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
+16
View File
@@ -2323,3 +2323,19 @@ Configuration sub-directories
2. The default (local) framebuffer configuration is 320x240 with 16-bit 2. The default (local) framebuffer configuration is 320x240 with 16-bit
RGB color. 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.
+2 -2
View File
@@ -741,8 +741,8 @@ CONFIG_NET_NOINTS=y
# Driver buffer configuration # Driver buffer configuration
# #
# CONFIG_NET_MULTIBUFFER is not set # CONFIG_NET_MULTIBUFFER is not set
CONFIG_NET_ETH_MTU=1508 CONFIG_NET_ETH_MTU=590
CONFIG_NET_ETH_TCP_RECVWNDO=1454 CONFIG_NET_ETH_TCP_RECVWNDO=536
CONFIG_NET_GUARDSIZE=2 CONFIG_NET_GUARDSIZE=2
# #
+48 -12
View File
@@ -383,10 +383,51 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
return -EPROTO; 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) if (pixelfmt->truecolor == 0)
{ {
/* At present, we support only TrueColor formats */ /* 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) if (pixelfmt->bpp == 8 && pixelfmt->depth == 6)
{ {
gvdbg("Client pixel format: RGB8 2:2:2\n");
session->colorfmt = FB_FMT_RGB8_222; session->colorfmt = FB_FMT_RGB8_222;
session->bpp = 8; session->bpp = 8;
} }
else if (pixelfmt->bpp == 8 && pixelfmt->depth == 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->colorfmt = FB_FMT_RGB8_332;
session->bpp = 8; session->bpp = 8;
} }
else if (pixelfmt->bpp == 16 && pixelfmt->depth == 15) else if (pixelfmt->bpp == 16 && pixelfmt->depth == 15)
{ {
gvdbg("Client pixel format: RGB16 5:5:5\n");
session->colorfmt = FB_FMT_RGB16_555; session->colorfmt = FB_FMT_RGB16_555;
session->bpp = 16; session->bpp = 16;
} }
else if (pixelfmt->bpp == 16 && pixelfmt->depth == 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->colorfmt = FB_FMT_RGB16_565;
session->bpp = 16; session->bpp = 16;
} }
else if (pixelfmt->bpp == 32 && pixelfmt->depth == 24) else if (pixelfmt->bpp == 32 && pixelfmt->depth == 24)
{ {
gvdbg("Client pixel format: RGB32 8:8:8\n");
session->colorfmt = FB_FMT_RGB32; session->colorfmt = FB_FMT_RGB32;
session->bpp = 32; session->bpp = 32;
} }
@@ -434,15 +480,5 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
return -ENOSYS; 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; return OK;
} }
+11 -1
View File
@@ -189,7 +189,17 @@ int vnc_receiver(FAR struct vnc_session_s *session)
} }
else 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; break;
+19
View File
@@ -300,6 +300,25 @@ int vnc_server(int argc, FAR char *argv[]);
int vnc_negotiate(FAR struct vnc_session_s *session); 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 * Name: vnc_start_updater
* *
+26 -21
View File
@@ -770,9 +770,26 @@ static FAR void *vnc_updater(FAR void *arg)
DEBUGASSERT(session != NULL); DEBUGASSERT(session != NULL);
gvdbg("Updater running for Display %d\n", session->display); gvdbg("Updater running for Display %d\n", session->display);
/* Set up some constant pointers and values for convenience */ /* 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?
*/
while (session->state == VNCSERVER_RUNNING)
{
/* Get the next queued rectangle update. This call will block until an
* upate is available for the case where the update queue is empty.
*/
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.
*/
update = (FAR struct rfb_framebufferupdate_s *)session->outbuf;
bytesperpixel = (session->bpp + 7) >> 3; bytesperpixel = (session->bpp + 7) >> 3;
maxwidth = CONFIG_VNCSERVER_UPDATE_BUFSIZE / bytesperpixel; maxwidth = CONFIG_VNCSERVER_UPDATE_BUFSIZE / bytesperpixel;
@@ -805,21 +822,6 @@ static FAR void *vnc_updater(FAR void *arg)
goto errout; goto errout;
} }
/* Then 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?
*/
while (session->state == VNCSERVER_RUNNING)
{
/* Get the next queued rectangle update. This call will block until an
* upate is available for the case where the update queue is empty.
*/
srcrect = vnc_remove_queue(session);
DEBUGASSERT(srcrect != NULL);
/* Get with width and height of the source and destination rectangles. /* Get with width and height of the source and destination rectangles.
* The source rectangle many be larger than the destination rectangle. * The source rectangle many be larger than the destination rectangle.
* In that case, we will have to emit multiple rectangles. * 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. * performing the necessary color conversions.
*/ */
if (session->bpp == 8) if (bytesperpixel == 1)
{ {
size = vnc_copy8(session, y, x, updheight, updwidth, size = vnc_copy8(session, y, x, updheight, updwidth,
convert.bpp8); convert.bpp8);
} }
else if (session->bpp == 16) else if (bytesperpixel == 2)
{ {
size = vnc_copy16(session, y, x, updheight, updwidth, size = vnc_copy16(session, y, x, updheight, updwidth,
convert.bpp16); convert.bpp16);
} }
else else /* bytesperpixel == 4 */
{ {
size = vnc_copy32(session, y, x, updheight, updwidth, size = vnc_copy32(session, y, x, updheight, updwidth,
convert.bpp32); convert.bpp32);
@@ -913,6 +915,7 @@ static FAR void *vnc_updater(FAR void *arg)
/* Format the FramebufferUpdate message */ /* Format the FramebufferUpdate message */
update = (FAR struct rfb_framebufferupdate_s *)session->outbuf;
update->msgtype = RFB_FBUPDATE_MSG; update->msgtype = RFB_FBUPDATE_MSG;
update->padding = 0; update->padding = 0;
rfb_putbe16(update->nrect, 1); rfb_putbe16(update->nrect, 1);
@@ -930,7 +933,7 @@ static FAR void *vnc_updater(FAR void *arg)
size += SIZEOF_RFB_FRAMEBUFFERUPDATE_S(0); size += SIZEOF_RFB_FRAMEBUFFERUPDATE_S(0);
src = session->outbuf; src = session->outbuf;
while (size > 0) do
{ {
nsent = psock_send(&session->connect, src, size, 0); nsent = psock_send(&session->connect, src, size, 0);
if (nsent < 0) if (nsent < 0)
@@ -940,9 +943,11 @@ static FAR void *vnc_updater(FAR void *arg)
goto errout; goto errout;
} }
DEBUGASSERT(nsent <= size);
src += nsent; src += nsent;
size -= nsent; size -= nsent;
} }
while (size > 0);
} }
} }