VNC: Correct pixel width in RRE encoding

This commit is contained in:
Gregory Nutt 2016-04-21 08:16:33 -06:00
parent 79e577eae1
commit eb8c7f1641
4 changed files with 219 additions and 59 deletions

View File

@ -384,12 +384,13 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
} }
else if (setformat->msgtype != RFB_SETPIXELFMT_MSG) else if (setformat->msgtype != RFB_SETPIXELFMT_MSG)
{ {
gdbg("ERROR: Not a SetPixelFormat message: %d\n", (int)setformat->msgtype); gdbg("ERROR: Not a SetPixelFormat message: %d\n",
(int)setformat->msgtype);
return -EPROTO; return -EPROTO;
} }
/* Instantiate the client pixel format, verifying that the client request format /* Instantiate the client pixel format, verifying that the client request
* is one that we can handle. * format is one that we can handle.
*/ */
ret = vnc_client_pixelformat(session, &setformat->format); ret = vnc_client_pixelformat(session, &setformat->format);
@ -408,7 +409,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
encodings = (FAR struct rfb_setencodings_s *)session->inbuf; encodings = (FAR struct rfb_setencodings_s *)session->inbuf;
nrecvd = psock_recv(&session->connect, encodings, nrecvd = psock_recv(&session->connect, encodings,
CONFIG_VNCSERVER_INBUFFER_SIZE, 0); CONFIG_VNCSERVER_INBUFFER_SIZE, 0);
if (nrecvd < 0) if (nrecvd < 0)
{ {
errcode = get_errno(); errcode = get_errno();
@ -419,7 +420,7 @@ int vnc_negotiate(FAR struct vnc_session_s *session)
if (nrecvd > 0 && encodings->msgtype == RFB_SETENCODINGS_MSG) if (nrecvd > 0 && encodings->msgtype == RFB_SETENCODINGS_MSG)
{ {
DEBUGASSERT(nrecvd >= SIZEOF_RFB_SETENCODINGS_S(0)); DEBUGASSERT(nrecvd >= SIZEOF_RFB_SETENCODINGS_S(0));
/* Pick out any mutually supported encodings */ /* Pick out any mutually supported encodings */

View File

@ -50,35 +50,119 @@
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
struct rre_data_s struct rre_encode8_s
{ {
#if RFB_BITSPERPIXEL == 16 struct rfb_rrehdr8_s hdr;
struct rfb_rrehdr16_s hdr; /* Header with background pixel */ struct rfb_rrerect8_s rect;
struct rfb_rrerect16_s srect; /* Sub-rectangle */
#elif RFB_BITSPERPIXEL == 32
struct rfb_rrehdr32_s hdr; /* Header with background pixel */
struct rfb_rrerect32_s srect; /* Sub-rectangle */
#endif
}; };
struct rre_rectangle_s struct rre_encode16_s
{ {
uint8_t xpos[2]; /* U16 X position */ struct rfb_rrehdr16_s hdr;
uint8_t ypos[2]; /* U16 Y position */ struct rfb_rrerect16_s rect;
uint8_t width[2]; /* U16 Width */
uint8_t height[2]; /* U16 Height */
uint8_t encoding[4]; /* S32 Encoding type = RFB_ENCODING_RRE */
struct rre_data_s data; /* Pixel data, actual size varies */
}; };
struct rre_framebufferupdate_s struct rre_encode32_s
{ {
uint8_t msgtype; /* U8 Message type = RFB_FBUPDATE_MSG*/ struct rfb_rrehdr32_s hdr;
uint8_t padding; struct rfb_rrerect32_s rect;
uint8_t nrect[2]; /* U16 Number of rectangles = 1*/
struct rre_rectangle_s rect; /* RRE encoded rectangle */
}; };
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: vnc_rreNN
*
* Description:
* Encode a single RRE sub-rectangle, NN=bits-per-pixel
*
* Input Parameters:
* session - An instance of the session structure.
* dest - The locate to save the RRE encoded data
* rect - Describes the rectangle in the local framebuffer.
* bgcolor - The local color of the pixel data
*
* Returned Value:
* The size of the framebuffer update message is returned..
*
****************************************************************************/
ssize_t vnc_rre8(FAR struct vnc_session_s *session,
FAR struct rre_encode8_s *dest,
FAR struct nxgl_rect_s *rect,
uint8_t bgcolor)
{
nxgl_coord_t width;
nxgl_coord_t height;
rfb_putbe32(dest->hdr.nsubrects, 1);
dest->hdr.pixel = bgcolor;
dest->rect.pixel = bgcolor;
rfb_putbe16(dest->rect.xpos, rect->pt1.x);
rfb_putbe16(dest->rect.ypos, rect->pt1.y);
width = rect->pt2.x - rect->pt1.x + 1;
height = rect->pt2.y - rect->pt1.y + 1;
rfb_putbe16(dest->rect.width, width);
rfb_putbe16(dest->rect.height, height);
return sizeof(struct rre_encode8_s);
}
ssize_t vnc_rre16(FAR struct vnc_session_s *session,
FAR struct rre_encode16_s *dest,
FAR struct nxgl_rect_s *rect,
uint16_t bgcolor)
{
nxgl_coord_t width;
nxgl_coord_t height;
rfb_putbe32(dest->hdr.nsubrects, 1);
rfb_putbe16(dest->hdr.pixel, bgcolor);
rfb_putbe16(dest->rect.pixel, bgcolor);
rfb_putbe16(dest->rect.xpos, rect->pt1.x);
rfb_putbe16(dest->rect.xpos, rect->pt1.x);
rfb_putbe16(dest->rect.ypos, rect->pt1.y);
width = rect->pt2.x - rect->pt1.x + 1;
height = rect->pt2.y - rect->pt1.y + 1;
rfb_putbe16(dest->rect.width, width);
rfb_putbe16(dest->rect.height, height);
return sizeof(struct rre_encode16_s);
}
ssize_t vnc_rre32(FAR struct vnc_session_s *session,
FAR struct rre_encode32_s *dest,
FAR struct nxgl_rect_s *rect,
uint32_t bgcolor)
{
nxgl_coord_t width;
nxgl_coord_t height;
rfb_putbe32(dest->hdr.nsubrects, 1);
rfb_putbe32(dest->hdr.pixel, bgcolor);
rfb_putbe32(dest->rect.pixel, bgcolor);
rfb_putbe16(dest->rect.xpos, rect->pt1.x);
rfb_putbe16(dest->rect.xpos, rect->pt1.x);
rfb_putbe16(dest->rect.ypos, rect->pt1.y);
width = rect->pt2.x - rect->pt1.x + 1;
height = rect->pt2.y - rect->pt1.y + 1;
rfb_putbe16(dest->rect.width, width);
rfb_putbe16(dest->rect.height, height);
return sizeof(struct rre_encode32_s);
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@ -97,22 +181,21 @@ struct rre_framebufferupdate_s
* *
* Returned Value: * Returned Value:
* Zero is returned if RRE coding was not performed (but not error was) * Zero is returned if RRE coding was not performed (but not error was)
* encountered. Otherwise, eith the size of the framebuffer update * encountered. Otherwise, the size of the framebuffer update message
* message is returned on success or a negated errno value is returned on * is returned on success or a negated errno value is returned on failure
* failure that indicates the the nature of the failure. A failure is * that indicates the the nature of the failure. A failure is only
* only returned in cases of a network failure and unexpected internal * returned in cases of a network failure and unexpected internal failures.
* failures.
* *
****************************************************************************/ ****************************************************************************/
int vnc_rre(FAR struct vnc_session_s *session, FAR struct nxgl_rect_s *rect) int vnc_rre(FAR struct vnc_session_s *session, FAR struct nxgl_rect_s *rect)
{ {
FAR struct rre_framebufferupdate_s *rre; FAR struct rfb_framebufferupdate_s *rre;
FAR struct rre_rectangle_s *rrect; FAR struct rfb_rectangle_s *rrect;
FAR struct rre_data_s *rdata;
lfb_color_t bgcolor; lfb_color_t bgcolor;
nxgl_coord_t width; nxgl_coord_t width;
nxgl_coord_t height; nxgl_coord_t height;
size_t nbytes;
ssize_t nsent; ssize_t nsent;
int ret; int ret;
@ -125,38 +208,66 @@ int vnc_rre(FAR struct vnc_session_s *session, FAR struct nxgl_rect_s *rect)
ret = vnc_colors(session, rect, 1, &bgcolor); ret = vnc_colors(session, rect, 1, &bgcolor);
if (ret == 1) if (ret == 1)
{ {
width = rect->pt2.x - rect->pt1.x + 1; width = rect->pt2.x - rect->pt1.x + 1;
height = rect->pt2.y - rect->pt1.y + 1; height = rect->pt2.y - rect->pt1.y + 1;
/* Format the FrameBuffer Update with a single RRE encoded /* Format the FrameBuffer Update with a single RRE encoded
* rectangle. * rectangle.
*/ */
rre = (FAR struct rre_framebufferupdate_s *)session->outbuf; rre = (FAR struct rfb_framebufferupdate_s *)session->outbuf;
rre->msgtype = RFB_FBUPDATE_MSG; rre->msgtype = RFB_FBUPDATE_MSG;
rre->padding = 0; rre->padding = 0;
rfb_putbe16(rre->nrect, 1); rfb_putbe16(rre->nrect, 1);
rrect = (FAR struct rre_rectangle_s *)&rre->rect; rrect = (FAR struct rfb_rectangle_s *)&rre->rect;
rfb_putbe16(rrect->xpos, rect->pt1.x); rfb_putbe16(rrect->xpos, rect->pt1.x);
rfb_putbe16(rrect->ypos, rect->pt1.y); rfb_putbe16(rrect->ypos, rect->pt1.y);
rfb_putbe16(rrect->width, width); rfb_putbe16(rrect->width, width);
rfb_putbe16(rrect->height, height); rfb_putbe16(rrect->height, height);
rfb_putbe32(rrect->encoding, RFB_ENCODING_RRE); rfb_putbe32(rrect->encoding, RFB_ENCODING_RRE);
rdata = (FAR struct rre_data_s *)&rrect->data; /* The sub-rectangle encoding depends of the remote pixel width */
rfb_putbe32(rdata->hdr.nsubrects, 1);
#if RFB_BITSPERPIXEL == 16 nbytes = SIZEOF_RFB_FRAMEBUFFERUPDATE_S(SIZEOF_RFB_RECTANGE_S(0));
rfb_putbe16(rdata->hdr.pixel, bgcolor);
rfb_putbe16(rdata->srect.pixel, bgcolor); switch (session->colorfmt)
#elif RFB_BITSPERPIXEL == 32 {
rfb_putbe32(rdata->hdr.pixel, bgcolor); case FB_FMT_RGB8_222:
rfb_putbe32(rdata->srect.pixel, bgcolor); nbytes += vnc_rre8(session,
#endif (FAR struct rre_encode8_s *)rrect->data,
rfb_putbe16(rdata->srect.xpos, rect->pt1.x); rect, vnc_convert_rgb8_222(bgcolor));
rfb_putbe16(rdata->srect.ypos, rect->pt1.y); break;
rfb_putbe16(rdata->srect.width, width);
rfb_putbe16(rdata->srect.height, height); case FB_FMT_RGB8_332:
nbytes += vnc_rre8(session,
(FAR struct rre_encode8_s *)rrect->data,
rect, vnc_convert_rgb8_332(bgcolor));
break;
case FB_FMT_RGB16_555:
nbytes += vnc_rre16(session,
(FAR struct rre_encode16_s *)rrect->data,
rect, vnc_convert_rgb16_555(bgcolor));
break;
case FB_FMT_RGB16_565:
nbytes += vnc_rre16(session,
(FAR struct rre_encode16_s *)rrect->data,
rect, vnc_convert_rgb16_565(bgcolor));
break;
case FB_FMT_RGB32:
nbytes += vnc_rre32(session,
(FAR struct rre_encode32_s *)rrect->data,
rect, vnc_convert_rgb32_888(bgcolor));
break;
default:
gdbg("ERROR: Unrecognized color format: %d\n",
session->colorfmt);
return -EINVAL;
}
/* At the very last most, make certain that the supported encoding /* At the very last most, make certain that the supported encoding
* has not changed asynchronously. * has not changed asynchronously.
@ -169,8 +280,7 @@ int vnc_rre(FAR struct vnc_session_s *session, FAR struct nxgl_rect_s *rect)
* and there are a limited number of IOBs available. * and there are a limited number of IOBs available.
*/ */
nsent = psock_send(&session->connect, rre, nsent = psock_send(&session->connect, rre, nbytes, 0);
sizeof(struct rre_framebufferupdate_s), 0);
if (nsent < 0) if (nsent < 0)
{ {
int errcode = get_errno(); int errcode = get_errno();
@ -180,8 +290,8 @@ int vnc_rre(FAR struct vnc_session_s *session, FAR struct nxgl_rect_s *rect)
return -errcode; return -errcode;
} }
DEBUGASSERT(nsent == sizeof(struct rre_framebufferupdate_s)); DEBUGASSERT(nsent == nbytes);
return sizeof(struct rre_framebufferupdate_s); return nbytes;
} }
return -EINVAL; return -EINVAL;

View File

@ -455,11 +455,10 @@ int vnc_receiver(FAR struct vnc_session_s *session);
* *
* Returned Value: * Returned Value:
* Zero is returned if RRE coding was not performed (but not error was) * Zero is returned if RRE coding was not performed (but not error was)
* encountered. Otherwise, eith the size of the framebuffer update * encountered. Otherwise, the size of the framebuffer update message
* message is returned on success or a negated errno value is returned on * is returned on success or a negated errno value is returned on failure
* failure that indicates the the nature of the failure. A failure is * that indicates the the nature of the failure. A failure is only
* only returned in cases of a network failure and unexpected internal * returned in cases of a network failure and unexpected internal failures.
* failures.
* *
****************************************************************************/ ****************************************************************************/

View File

@ -691,6 +691,12 @@ struct rfb_copyrect_encoding_s
* the header:" * the header:"
*/ */
struct rfb_rrehdr8_s
{
uint8_t nsubrects[4]; /* U32 Number of sub-rectangle */
uint8_t pixel; /* U8 Background pixel */
};
struct rfb_rrehdr16_s struct rfb_rrehdr16_s
{ {
uint8_t nsubrects[4]; /* U32 Number of sub-rectangle */ uint8_t nsubrects[4]; /* U32 Number of sub-rectangle */
@ -707,6 +713,15 @@ struct rfb_rrehdr32_s
* structure:" * structure:"
*/ */
struct rfb_rrerect8_s
{
uint8_t pixel; /* U8 sub-rect pixel value */
uint8_t xpos[2]; /* U16 X position */
uint8_t ypos[2]; /* U16 Y position */
uint8_t width[2]; /* U16 Width */
uint8_t height[2]; /* U16 Height */
};
struct rfb_rrerect16_s struct rfb_rrerect16_s
{ {
uint8_t pixel[2]; /* U16 sub-rect pixel value */ uint8_t pixel[2]; /* U16 sub-rect pixel value */
@ -771,6 +786,11 @@ struct rfb_rrerect32_s
* background colour for this tile:" * background colour for this tile:"
*/ */
struct rfb_backpixel8_s
{
uint8_t pixel; /* U8 Background pixel value */
};
struct rfb_backpixel16_s struct rfb_backpixel16_s
{ {
uint8_t pixel[2]; /* U16 Background pixel value */ uint8_t pixel[2]; /* U16 Background pixel value */
@ -788,6 +808,11 @@ struct rfb_backpixel32_s
* foreground colour to be used for all subrectangles in this tile:" * foreground colour to be used for all subrectangles in this tile:"
*/ */
struct rfb_forepixel8_s
{
uint8_t pixel; /* U8 Foreground pixel value */
};
struct rfb_forepixel16_s struct rfb_forepixel16_s
{ {
uint8_t pixel[2]; /* U16 Foreground pixel value */ uint8_t pixel[2]; /* U16 Foreground pixel value */
@ -816,6 +841,13 @@ struct rfb_nrects_s
* value giving the colour of that subrectangle, so a subrectangle is:" * value giving the colour of that subrectangle, so a subrectangle is:"
*/ */
struct rfb_subrectscolored8_s
{
uint8_t pixel; /* U8 Sub-rect pixel value */
uint8_t xy; /* U8 X and y position */
uint8_t wh; /* U8 Width and height */
};
struct rfb_subrectscolored16_s struct rfb_subrectscolored16_s
{ {
uint8_t pixel[2]; /* U16 Sub-rect pixel value */ uint8_t pixel[2]; /* U16 Sub-rect pixel value */
@ -916,6 +948,14 @@ struct rfb_srle_s
* height are the width and height of the tile):" * height are the width and height of the tile):"
*/ */
struct rfb_rawpixel8_s
{
uint8_t pixels[1]; /* Actual size is w*h */
};
#define SIZEOF_RFB_RAWPIXEL8_S(n,r) \
(sizeof(struct rfb_rawpixel8_s) + (n) - 1)
struct rfb_rawpixel16_s struct rfb_rawpixel16_s
{ {
uint8_t pixels[2]; /* Actual size is 2*w*h */ uint8_t pixels[2]; /* Actual size is 2*w*h */
@ -934,6 +974,11 @@ struct rfb_rawpixel32_s
/* "A solid tile consisting of a single colour. The pixel value follows:" */ /* "A solid tile consisting of a single colour. The pixel value follows:" */
struct rfb_solid8_s
{
uint8_t pixels; /* Pixel value */
};
struct rfb_solid16_s struct rfb_solid16_s
{ {
uint8_t pixels[2]; /* Pixel value */ uint8_t pixels[2]; /* Pixel value */
@ -977,6 +1022,11 @@ struct rfb_solid32_s
* (subencoding 128) pixel values:" * (subencoding 128) pixel values:"
*/ */
struct rfb_palette8_s
{
uint8_t palette[1]; /* Actual size is palleteSize */
};
struct rfb_palette16_s struct rfb_palette16_s
{ {
uint8_t palette[2]; /* Actual size is 2*palleteSize */ uint8_t palette[2]; /* Actual size is 2*palleteSize */