VNC: Fixes from debug. One issues is that VNC client is changing color formats after starting. That is now handled.

This commit is contained in:
Gregory Nutt 2016-04-20 09:47:02 -06:00
parent 2cb52786b6
commit 7134652fea
6 changed files with 141 additions and 55 deletions

View File

@ -2323,3 +2323,19 @@ Configuration sub-directories
2. The default (local) framebuffer configuration is 320x240 with 16-bit
RGB color.
3. There are complicated interactions between VNC and the network
configuration. The CONFIG_VNCSERVER_UPDATE_BUFSIZE determines the
size of update messages. That is 1024 bytes in that configuration
(the full message with the header will be a little larger). The
MTU (CONFIG_NET_ETH_MTU) is set to 590 so that a full update will
require several packets.i
Write buffering also effects network performance. This will break
up the large updates into small (196 byte) groups. When we run out
of read-ahead buffers, then partial updates may be sent causing a
loss of synchronization.
4. Hint: If you are debugging using the RealVNC clint, turn off all
mouse/keyboard inputs in the options/input menu. That will make
things a little clearer.

View File

@ -741,8 +741,8 @@ CONFIG_NET_NOINTS=y
# Driver buffer configuration
#
# CONFIG_NET_MULTIBUFFER is not set
CONFIG_NET_ETH_MTU=1508
CONFIG_NET_ETH_TCP_RECVWNDO=1454
CONFIG_NET_ETH_MTU=590
CONFIG_NET_ETH_TCP_RECVWNDO=536
CONFIG_NET_GUARDSIZE=2
#

View File

@ -383,10 +383,51 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
return -EPROTO;
}
/* Check if the client request format is one that we can handle. */
/* Instantiate the client pixel format, verifying that the client request format
* is one that we can handle.
*/
pixelfmt = &setformat->format;
ret = vnc_client_pixelformat(session, &setformat->format);
if (ret < 0)
{
/* We do not support this pixel format */
gdbg("ERROR: PixelFormat not supported\n");
return ret;
}
/* Receive supported encoding types from client, but ignore them.
* we will do only raw format.
*/
gvdbg("Receive encoding types\n");
(void)psock_recv(&session->connect, session->inbuf,
CONFIG_VNCSERVER_INBUFFER_SIZE, 0);
session->state = VNCSERVER_CONFIGURED;
return OK;
}
/****************************************************************************
* Name: vnc_client_pixelformat
*
* Description:
* A Client-to-Sever SetPixelFormat message has been received. We need to
* immediately switch the output color format that we generate.
*
* Input Parameters:
* session - An instance of the session structure.
* pixelfmt - The pixel from from the received SetPixelFormat message
*
* Returned Value:
* Returns zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int vnc_client_pixelformat(FAR struct vnc_session_s *session,
FAR struct rfb_pixelfmt_s *pixelfmt)
{
if (pixelfmt->truecolor == 0)
{
/* At present, we support only TrueColor formats */
@ -397,26 +438,31 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
if (pixelfmt->bpp == 8 && pixelfmt->depth == 6)
{
gvdbg("Client pixel format: RGB8 2:2:2\n");
session->colorfmt = FB_FMT_RGB8_222;
session->bpp = 8;
}
else if (pixelfmt->bpp == 8 && pixelfmt->depth == 8)
{
gvdbg("Client pixel format: RGB8 3:3:2\n");
session->colorfmt = FB_FMT_RGB8_332;
session->bpp = 8;
}
else if (pixelfmt->bpp == 16 && pixelfmt->depth == 15)
{
gvdbg("Client pixel format: RGB16 5:5:5\n");
session->colorfmt = FB_FMT_RGB16_555;
session->bpp = 16;
}
else if (pixelfmt->bpp == 16 && pixelfmt->depth == 16)
{
gvdbg("Client pixel format: RGB16 5:6:5\n");
session->colorfmt = FB_FMT_RGB16_565;
session->bpp = 16;
}
else if (pixelfmt->bpp == 32 && pixelfmt->depth == 24)
{
gvdbg("Client pixel format: RGB32 8:8:8\n");
session->colorfmt = FB_FMT_RGB32;
session->bpp = 32;
}
@ -434,15 +480,5 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
return -ENOSYS;
}
/* Receive supported encoding types from client, but ignore them.
* we will do only raw format.
*/
gvdbg("Receive encoding types\n");
(void)psock_recv(&session->connect, session->inbuf,
CONFIG_VNCSERVER_INBUFFER_SIZE, 0);
session->state = VNCSERVER_CONFIGURED;
return OK;
}

View File

@ -189,7 +189,17 @@ int vnc_receiver(FAR struct vnc_session_s *session)
}
else
{
/* REVISIT: SetPixelFormat is currently ignored */
FAR struct rfb_setpixelformat_s *setformat =
(FAR struct rfb_setpixelformat_s *)session->inbuf;
ret = vnc_client_pixelformat(session, &setformat->format);
if (ret < 0)
{
/* We do not support this pixel format */
/* REVISIT: We are going to be putting garbage on the RFB */
gdbg("ERROR: PixelFormat not supported\n");
}
}
}
break;

View File

@ -300,6 +300,25 @@ int vnc_server(int argc, FAR char *argv[]);
int vnc_negotiate(FAR struct vnc_session_s *session);
/****************************************************************************
* Name: vnc_client_pixelformat
*
* Description:
* A Client-to-Sever SetPixelFormat message has been received. We need to
* immediately switch the output color format that we generate.
*
* Input Parameters:
* session - An instance of the session structure.
* pixelfmt - The pixel from from the received SetPixelFormat message
*
* Returned Value:
* Returns zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int vnc_client_pixelformat(FAR struct vnc_session_s *session,
FAR struct rfb_pixelfmt_s *pixelfmt);
/****************************************************************************
* Name: vnc_start_updater
*

View File

@ -770,42 +770,7 @@ static FAR void *vnc_updater(FAR void *arg)
DEBUGASSERT(session != NULL);
gvdbg("Updater running for Display %d\n", session->display);
/* Set up some constant pointers and values for convenience */
update = (FAR struct rfb_framebufferupdate_s *)session->outbuf;
bytesperpixel = (session->bpp + 7) >> 3;
maxwidth = CONFIG_VNCSERVER_UPDATE_BUFSIZE / bytesperpixel;
/* Set up the color conversion */
switch (session->colorfmt)
{
case FB_FMT_RGB8_222:
convert.bpp8 = vnc_convert_rgb8_222;
break;
case FB_FMT_RGB8_332:
convert.bpp8 = vnc_convert_rgb8_332;
break;
case FB_FMT_RGB16_555:
convert.bpp16 = vnc_convert_rgb16_555;
break;
case FB_FMT_RGB16_565:
convert.bpp16 = vnc_convert_rgb16_565;
break;
case FB_FMT_RGB32:
convert.bpp32 = vnc_convert_rgb32_888;
break;
default:
gdbg("ERROR: Unrecognized color format: %d\n", session->colorfmt);
goto errout;
}
/* Then loop, processing updates until we are asked to stop.
/* Loop, processing updates until we are asked to stop.
* REVISIT: Probably need some kind of signal mechanism to wake up
* vnc_remove_queue() in order to stop. Or perhaps a special STOP
* message in the queue?
@ -820,6 +785,43 @@ static FAR void *vnc_updater(FAR void *arg)
srcrect = vnc_remove_queue(session);
DEBUGASSERT(srcrect != NULL);
/* Set up characteristics of the client pixel format to use on this
* update. These can change at any time if a SetPixelFormat is
* received asynchronously.
*/
bytesperpixel = (session->bpp + 7) >> 3;
maxwidth = CONFIG_VNCSERVER_UPDATE_BUFSIZE / bytesperpixel;
/* Set up the color conversion */
switch (session->colorfmt)
{
case FB_FMT_RGB8_222:
convert.bpp8 = vnc_convert_rgb8_222;
break;
case FB_FMT_RGB8_332:
convert.bpp8 = vnc_convert_rgb8_332;
break;
case FB_FMT_RGB16_555:
convert.bpp16 = vnc_convert_rgb16_555;
break;
case FB_FMT_RGB16_565:
convert.bpp16 = vnc_convert_rgb16_565;
break;
case FB_FMT_RGB32:
convert.bpp32 = vnc_convert_rgb32_888;
break;
default:
gdbg("ERROR: Unrecognized color format: %d\n", session->colorfmt);
goto errout;
}
/* Get with width and height of the source and destination rectangles.
* The source rectangle many be larger than the destination rectangle.
* In that case, we will have to emit multiple rectangles.
@ -895,17 +897,17 @@ static FAR void *vnc_updater(FAR void *arg)
* performing the necessary color conversions.
*/
if (session->bpp == 8)
if (bytesperpixel == 1)
{
size = vnc_copy8(session, y, x, updheight, updwidth,
convert.bpp8);
}
else if (session->bpp == 16)
else if (bytesperpixel == 2)
{
size = vnc_copy16(session, y, x, updheight, updwidth,
convert.bpp16);
}
else
else /* bytesperpixel == 4 */
{
size = vnc_copy32(session, y, x, updheight, updwidth,
convert.bpp32);
@ -913,6 +915,7 @@ static FAR void *vnc_updater(FAR void *arg)
/* Format the FramebufferUpdate message */
update = (FAR struct rfb_framebufferupdate_s *)session->outbuf;
update->msgtype = RFB_FBUPDATE_MSG;
update->padding = 0;
rfb_putbe16(update->nrect, 1);
@ -930,7 +933,7 @@ static FAR void *vnc_updater(FAR void *arg)
size += SIZEOF_RFB_FRAMEBUFFERUPDATE_S(0);
src = session->outbuf;
while (size > 0)
do
{
nsent = psock_send(&session->connect, src, size, 0);
if (nsent < 0)
@ -940,9 +943,11 @@ static FAR void *vnc_updater(FAR void *arg)
goto errout;
}
DEBUGASSERT(nsent <= size);
src += nsent;
size -= nsent;
}
while (size > 0);
}
}