diff --git a/graphics/vnc/server/vnc_negotiate.c b/graphics/vnc/server/vnc_negotiate.c index bb6aff34f4a..5014e9a83d2 100644 --- a/graphics/vnc/server/vnc_negotiate.c +++ b/graphics/vnc/server/vnc_negotiate.c @@ -466,37 +466,43 @@ int vnc_client_pixelformat(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; + session->colorfmt = FB_FMT_RGB8_222; + session->bpp = 8; + session->bigendian = false; } 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; + session->colorfmt = FB_FMT_RGB8_332; + session->bpp = 8; + session->bigendian = false; } 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; + session->colorfmt = FB_FMT_RGB16_555; + session->bpp = 16; + session->bigendian = (pixelfmt->bigendian != 0) ? true : false; } 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; + session->colorfmt = FB_FMT_RGB16_565; + session->bpp = 16; + session->bigendian = (pixelfmt->bigendian != 0) ? true : false; } 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; + session->colorfmt = FB_FMT_RGB32; + session->bpp = 32; + session->bigendian = (pixelfmt->bigendian != 0) ? true : false; } else if (pixelfmt->bpp == 32 && pixelfmt->depth == 32) { - session->colorfmt = FB_FMT_RGB32; - session->bpp = 32; + session->colorfmt = FB_FMT_RGB32; + session->bpp = 32; + session->bigendian = (pixelfmt->bigendian != 0) ? true : false; } else { diff --git a/graphics/vnc/server/vnc_raw.c b/graphics/vnc/server/vnc_raw.c index f54428df429..64cfee779e6 100644 --- a/graphics/vnc/server/vnc_raw.c +++ b/graphics/vnc/server/vnc_raw.c @@ -135,14 +135,16 @@ static size_t vnc_copy16(FAR struct vnc_session_s *session, FAR struct rfb_framebufferupdate_s *update; FAR const lfb_color_t *srcleft; FAR const lfb_color_t *src; - FAR uint16_t *dest; + FAR uint8_t *dest; + uint16_t pixel; nxgl_coord_t x; nxgl_coord_t y; + bool bigendian; /* Destination rectangle start address */ update = (FAR struct rfb_framebufferupdate_s *)session->outbuf; - dest = (FAR uint16_t *)update->rect[0].data; + dest = (FAR uint8_t *)update->rect[0].data; /* Source rectangle start address (left/top)*/ @@ -150,12 +152,24 @@ static size_t vnc_copy16(FAR struct vnc_session_s *session, /* Transfer each row from the source buffer into the update buffer */ + bigendian = session->bigendian; for (y = 0; y < height; y++) { src = srcleft; for (x = 0; x < width; x++) { - *dest++ = convert(*src); + pixel = convert(*src); + + if (bigendian) + { + rfb_putbe16(dest, pixel); + } + else + { + rfb_putle16(dest, pixel); + } + + dest += sizeof(uint16_t); src++; } @@ -192,14 +206,16 @@ static size_t vnc_copy32(FAR struct vnc_session_s *session, FAR struct rfb_framebufferupdate_s *update; FAR const lfb_color_t *srcleft; FAR const lfb_color_t *src; - FAR uint32_t *dest; + FAR uint8_t *dest; nxgl_coord_t x; nxgl_coord_t y; + uint32_t pixel; + bool bigendian; /* Destination rectangle start address */ update = (FAR struct rfb_framebufferupdate_s *)session->outbuf; - dest = (FAR uint32_t *)update->rect[0].data; + dest = (FAR uint8_t *)update->rect[0].data; /* Source rectangle start address (left/top)*/ @@ -207,12 +223,24 @@ static size_t vnc_copy32(FAR struct vnc_session_s *session, /* Transfer each row from the source buffer into the update buffer */ + bigendian = session->bigendian; for (y = 0; y < height; y++) { src = srcleft; for (x = 0; x < width; x++) { - *dest++ = convert(*src); + pixel = convert(*src); + + if (bigendian) + { + rfb_putbe32(dest, pixel); + } + else + { + rfb_putle32(dest, pixel); + } + + dest += sizeof(uint32_t); src++; } diff --git a/graphics/vnc/server/vnc_server.h b/graphics/vnc/server/vnc_server.h index f17dd752552..7ed5317c2b9 100644 --- a/graphics/vnc/server/vnc_server.h +++ b/graphics/vnc/server/vnc_server.h @@ -253,6 +253,7 @@ struct vnc_session_s 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 */ FAR uint8_t *fb; /* Allocated local frame buffer */ diff --git a/include/nuttx/video/rfb.h b/include/nuttx/video/rfb.h index 73f5477611d..a8f68c45eb5 100644 --- a/include/nuttx/video/rfb.h +++ b/include/nuttx/video/rfb.h @@ -1131,6 +1131,48 @@ struct rfb_palettendx_s ((uint32_t)((s)[2]) << 8) | \ (uint32_t)((s)[3])) +/* There are also cases where the client may request pixel data in its + * little-endian format. + */ + +/* void rfb_putle16(FAR uint8_t *dest, uint16_t value) */ + +#define rfb_putle16(d,v) \ + do \ + { \ + register FAR uint8_t *__d = (FAR uint8_t *)(d); \ + *__d++ = ((uint16_t)(v) & 0xff); \ + *__d = ((uint16_t)(v) >> 8); \ + } \ + while (0) + +/* uin16_t rfb_getle16(FAR const uint8_t *src) */ + +#define rfb_getle16(s) \ + (((uint16_t)((s)[1]) << 8) | \ + (uint16_t)((s)[0])) + +/* void rfb_putle32(FAR uint8_t *dest, uint32_t value) */ + +#define rfb_putle32(d,v) \ + do \ + { \ + register FAR uint8_t *__d = (FAR uint8_t *)(d); \ + *__d++ = ((uint32_t)(v) & 0xff); \ + *__d++ = ((uint32_t)(v) >> 8) & 0xff; \ + *__d++ = ((uint32_t)(v) >> 16) & 0xff; \ + *__d = ((uint32_t)(v) >> 24); \ + } \ + while (0) + +/* uint32_t rfb_getle32(FAR const uint8_t *src) */ + +#define rfb_getle32(s) \ + (((uint32_t)((s)[3]) << 24) | \ + ((uint32_t)((s)[2]) << 16) | \ + ((uint32_t)((s)[1]) << 8) | \ + (uint32_t)((s)[0])) + /**************************************************************************** * Public Function Prototypes ****************************************************************************/