diff --git a/graphics/vnc/server/vnc_fbdev.c b/graphics/vnc/server/vnc_fbdev.c index 1df96cd9b6..36337cf273 100644 --- a/graphics/vnc/server/vnc_fbdev.c +++ b/graphics/vnc/server/vnc_fbdev.c @@ -877,7 +877,7 @@ void nx_notify_rectangle(FAR NX_PLANEINFOTYPE *pinfo, { /* Queue the rectangular update */ - ret = vnc_update_rectangle(session, rect); + ret = vnc_update_rectangle(session, rect, true); if (ret < 0) { gdbg("ERROR: vnc_update_rectangle failed: %d\n", ret); diff --git a/graphics/vnc/server/vnc_negotiate.c b/graphics/vnc/server/vnc_negotiate.c index 8b4f6955ed..7b4bb67c1a 100644 --- a/graphics/vnc/server/vnc_negotiate.c +++ b/graphics/vnc/server/vnc_negotiate.c @@ -521,5 +521,6 @@ int vnc_client_pixelformat(FAR struct vnc_session_s *session, return -ENOSYS; } + session->change = true; return OK; } diff --git a/graphics/vnc/server/vnc_receiver.c b/graphics/vnc/server/vnc_receiver.c index 2bc3359a50..481f6bed0c 100644 --- a/graphics/vnc/server/vnc_receiver.c +++ b/graphics/vnc/server/vnc_receiver.c @@ -176,6 +176,10 @@ int vnc_receiver(FAR struct vnc_session_s *session) return -errcode; } + /* REVISIT: This assertion sometimes fires when there is a client + * disconnection. + */ + DEBUGASSERT(nrecvd == 1); /* The single byte received should be the message type. Handle the @@ -218,7 +222,7 @@ int vnc_receiver(FAR struct vnc_session_s *session) case RFB_SETENCODINGS_MSG: /* SetEncodings */ { FAR struct rfb_setencodings_s *encodings; - uint32_t nencodings; + unsigned int nencodings; gvdbg("Received SetEncodings\n"); @@ -239,7 +243,7 @@ int vnc_receiver(FAR struct vnc_session_s *session) /* Read the following encodings */ encodings = (FAR struct rfb_setencodings_s *)session->inbuf; - nencodings = rfb_getbe32(encodings->nencodings); + nencodings = rfb_getbe16(encodings->nencodings); ret = vnc_read_remainder(session, nencodings * sizeof(uint32_t), @@ -291,7 +295,7 @@ int vnc_receiver(FAR struct vnc_session_s *session) rect.pt2.x = rect.pt1.x + rfb_getbe16(update->width); rect.pt2.y = rect.pt1.y + rfb_getbe16(update->height); - ret = vnc_update_rectangle(session, &rect); + ret = vnc_update_rectangle(session, &rect, false); if (ret < 0) { gdbg("ERROR: Failed to queue update: %d\n", ret); @@ -463,7 +467,7 @@ int vnc_client_encodings(FAR struct vnc_session_s *session, /* Loop for each client supported encoding */ - nencodings = rfb_getbe32(encodings->nencodings); + nencodings = rfb_getbe16(encodings->nencodings); for (i = 0; i < nencodings; i++) { /* Get the next encoding */ @@ -475,10 +479,10 @@ int vnc_client_encodings(FAR struct vnc_session_s *session, if (encoding == RFB_ENCODING_RRE) { session->rre = true; - return OK; } } + session->change = true; return OK; } diff --git a/graphics/vnc/server/vnc_server.h b/graphics/vnc/server/vnc_server.h index 077bc0d6b4..45d34b5260 100644 --- a/graphics/vnc/server/vnc_server.h +++ b/graphics/vnc/server/vnc_server.h @@ -246,14 +246,15 @@ struct vnc_session_s struct socket connect; /* Connected socket */ volatile uint8_t state; /* See enum vnc_server_e */ volatile uint8_t nwhupd; /* Number of whole screen updates queued */ + volatile bool change; /* True: Frambebuffer data change since last whole screen update */ /* Display geometry and color characteristics */ uint8_t display; /* Display number (for debug) */ volatile uint8_t colorfmt; /* Remote color format (See include/nuttx/fb.h) */ volatile uint8_t bpp; /* Remote bits per pixel */ - volatile bool bigendian; /* Remote expect data in big-endian format */ - volatile bool rre; /* Remote supports RRE encoding */ + volatile bool bigendian; /* True: Remote expect data in big-endian format */ + volatile bool rre; /* True: Remote supports RRE encoding */ FAR uint8_t *fb; /* Allocated local frame buffer */ /* VNC client input support */ @@ -450,6 +451,7 @@ int vnc_stop_updater(FAR struct vnc_session_s *session); * Input Parameters: * session - An instance of the session structure. * rect - The rectanglular region to be updated. + * change - True: Frame buffer data has changed * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on @@ -458,7 +460,8 @@ int vnc_stop_updater(FAR struct vnc_session_s *session); ****************************************************************************/ int vnc_update_rectangle(FAR struct vnc_session_s *session, - FAR const struct nxgl_rect_s *rect); + FAR const struct nxgl_rect_s *rect, + bool change); /**************************************************************************** * Name: vnc_receiver diff --git a/graphics/vnc/server/vnc_updater.c b/graphics/vnc/server/vnc_updater.c index 1ac9d4bf6a..0368e46f42 100644 --- a/graphics/vnc/server/vnc_updater.c +++ b/graphics/vnc/server/vnc_updater.c @@ -490,6 +490,7 @@ int vnc_stop_updater(FAR struct vnc_session_s *session) * Input Parameters: * session - An instance of the session structure. * rect - The rectanglular region to be updated. + * change - True: Frame buffer data has changed * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on @@ -498,7 +499,7 @@ int vnc_stop_updater(FAR struct vnc_session_s *session) ****************************************************************************/ int vnc_update_rectangle(FAR struct vnc_session_s *session, - FAR const struct nxgl_rect_s *rect) + FAR const struct nxgl_rect_s *rect, bool change) { FAR struct vnc_fbupdate_s *update; struct nxgl_rect_s intersection; @@ -506,7 +507,7 @@ int vnc_update_rectangle(FAR struct vnc_session_s *session, /* Clip rectangle to the screen dimensions */ - nxgl_rectintersect(&intersection, rect, &g_wholescreen); + nxgl_rectintersect(&intersection, rect, &g_wholescreen); /* Make sure that the clipped rectangle has a area */ @@ -519,20 +520,34 @@ int vnc_update_rectangle(FAR struct vnc_session_s *session, whupd = (memcmp(&intersection, &g_wholescreen, sizeof(struct nxgl_rect_s)) == 0); - /* Ignore all updates if there is a queue whole screen update */ + /* Ignore any client update requests if there have been no changes to + * the framebuffer since the last whole screen update. + */ sched_lock(); + if (!change && !session->change) + { + /* No.. ignore the client update. We have nothing new to report. */ + + sched_unlock(); + return OK; + } + + /* Ignore all updates if there is a queued whole screen update */ + if (session->nwhupd == 0) { - /* Is this a new whole screen update */ + /* No whole screen updates in the queue. Is this a new whole + * screen update? + */ if (whupd) { + /* Yes.. Discard all of the previously queued updates */ + FAR struct vnc_fbupdate_s *curr; FAR struct vnc_fbupdate_s *next; - /* Yes.. discard all of the previously queued updates */ - updvdbg("New whole screen update...\n"); curr = (FAR struct vnc_fbupdate_s *)session->updqueue.head; @@ -545,7 +560,20 @@ int vnc_update_rectangle(FAR struct vnc_session_s *session, vnc_free_update(session, curr); } + /* One whole screen update will be queued. There have been + * no frame buffer data changes since this update was queued. + */ + session->nwhupd = 1; + session->change = false; + } + else + { + /* We are not updating the whole screen. Remember if this + * update (OR a preceding update) was due to a data change. + */ + + session->change |= change; } /* Allocate an update structure... waiting if necessary */