VNC: Ignore client framebuffer updates if nothing has changed (we can does this because client requests incremental updates

This commit is contained in:
Gregory Nutt 2016-04-23 10:22:54 -06:00
parent f3499b173a
commit 47a33cbb64
5 changed files with 51 additions and 15 deletions

View file

@ -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);

View file

@ -521,5 +521,6 @@ int vnc_client_pixelformat(FAR struct vnc_session_s *session,
return -ENOSYS;
}
session->change = true;
return OK;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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 */