diff --git a/graphics/vnc/server/vnc_negotiate.c b/graphics/vnc/server/vnc_negotiate.c index 0d8362fd1c..d50798f6f1 100644 --- a/graphics/vnc/server/vnc_negotiate.c +++ b/graphics/vnc/server/vnc_negotiate.c @@ -310,7 +310,13 @@ int vnc_negotiate(FAR struct vnc_session_s *session) * * "After receiving the ClientInit message, the server sends a ServerInit * message. This tells the client the width and height of the server’s - * framebuffer, its pixel format and the name associated with the desktop: + * framebuffer, its pixel format and the name associated with the desktop:" + * + * RealVNC client supports this resolutions: + * Full (all availlable colors) - Max resolution of the platform (TrueColor) + * Medium (256 colors) - 256 colors (Paletted) + * Low (64 colors) - RGB8 2:2:2 (default, TrueColor) + * Very Low (8 colors) - RGB3 1:1:1 (TrueColor) */ gvdbg("Send ServerInit\n"); @@ -389,7 +395,17 @@ int vnc_negotiate(FAR struct vnc_session_s *session) return -ENOSYS; } - if (pixelfmt->bpp == 16 && pixelfmt->depth == 15) + if (pixelfmt->bpp == 8 && pixelfmt->depth == 6) + { + session->colorfmt = FB_FMT_RGB8_222; + session->bpp = 8; + } + else if (pixelfmt->bpp == 8 && pixelfmt->depth == 8) + { + session->colorfmt = FB_FMT_RGB8_332; + session->bpp = 8; + } + else if (pixelfmt->bpp == 16 && pixelfmt->depth == 15) { session->colorfmt = FB_FMT_RGB16_555; session->bpp = 16; diff --git a/graphics/vnc/server/vnc_updater.c b/graphics/vnc/server/vnc_updater.c index 01e1046a96..d12bf5953c 100644 --- a/graphics/vnc/server/vnc_updater.c +++ b/graphics/vnc/server/vnc_updater.c @@ -58,9 +58,11 @@ /* Color conversion functions */ #if defined(CONFIG_VNCSERVER_COLORFMT_RGB16) +typedef CODE uint8_t(*vnc_convert8_t)(uint16_t rgb); typedef CODE uint16_t(*vnc_convert16_t)(uint16_t rgb); typedef CODE uint32_t(*vnc_convert32_t)(uint16_t rgb); #elif defined(CONFIG_VNCSERVER_COLORFMT_RGB32) +typedef CODE uint8_t(*vnc_convert8_t)(uint32_t rgb); typedef CODE uint16_t(*vnc_convert16_t)(uint32_t rgb); typedef CODE uint32_t(*vnc_convert32_t)(uint32_t rgb); #else @@ -244,6 +246,34 @@ static void vnc_add_queue(FAR struct vnc_session_s *session, #if defined(CONFIG_VNCSERVER_COLORFMT_RGB16) +uint8_t vnc_convert_rgb8_222(uint16_t rgb) +{ + /* 111111 + * 54321098 76543210 + * ----------------- + * RRRRRGGG GGGBBBBB + * ..RRGGBB + */ + + return (uint8_t)(((rgb >> 10) & 0x0030) | + ((rgb >> 7) & 0x000c) | + ((rgb >> 3) & 0x0003)); +} + +uint8_t vnc_convert_rgb8_332(uint16_t rgb) +{ + /* 111111 + * 54321098 76543210 + * ----------------- + * RRRRRGGG GGGBBBBB + * RRRGGGBB + */ + + return (uint8_t)(((rgb >> 8) & 0x0070) | + ((rgb >> 6) & 0x001c) | + ((rgb >> 3) & 0x0003)); +} + uint16_t vnc_convert_rgb16_555(uint16_t rgb) { /* 111111 @@ -278,12 +308,40 @@ uint32_t vnc_convert_rgb32_888(uint16_t rgb) } #elif defined(CONFIG_VNCSERVER_COLORFMT_RGB32) +uint8_t vnc_convert_rgb8_222(uint16_t rgb) +{ + /* 33222222 22221111 111111 + * 10987654 32109876 54321098 76543210 + * ----------------------------------- + * RRRRRRRR GGGGGGGG BBBBBBBB + * ..RRGGBB + */ + + return (uint8_t)(((rgb >> 18) & 0x0030) | + ((rgb >> 12) & 0x000c) | + (rgb >> 6) & 0x0003)); +} + +uint8_t vnc_convert_rgb8_332(uint16_t rgb) +{ + /* 33222222 22221111 111111 + * 10987654 32109876 54321098 76543210 + * ----------------------------------- + * RRRRRRRR GGGGGGGG BBBBBBBB + * RRRGGGBB + */ + + return (uint8_t)(((rgb >> 16) & 0x0070) | + ((rgb >> 11) & 0x001c) | + (rgb >> 6) & 0x0003)); +} + uint16_t vnc_convert_rgb16_555(uint32_t rgb) { /* 33222222 22221111 111111 * 10987654 32109876 54321098 76543210 - * ---------------------------------- - * RRRRR... GGGGG... BBBBB... + * ----------------------------------- + * RRRRRRRR GGGGGGGG BBBBBBBB * .RRRRRGG GGGBBBBB */ @@ -297,8 +355,8 @@ uint16_t vnc_convert_rgb16_565(uint32_t rgb) { /* 33222222 22221111 111111 * 10987654 32109876 54321098 76543210 - * ---------------------------------- - * RRRRR... GGGGGG.. BBBBB... + * ----------------------------------- + * RRRRRRRR GGGGGGGG BBBBBBBB * RRRRRGGG GGGBBBBB */ @@ -318,6 +376,96 @@ uint32_t vnc_convert_rgb32_888(uint32_t rgb) # error Unspecified/unsupported color format #endif +/**************************************************************************** + * Name: vnc_copy8 + * + * Description: + * Copy a 16/32-bit pixels from the source rectangle to a 8-bit pixel + * destination rectangle. + * + * Input Parameters: + * session - A reference to the VNC session structure. + * row,col - The upper left X/Y (pixel/row) position of the rectangle + * width,height - The width (pixels) and height (rows of the rectangle) + * convert - The function to use to convert from the local framebuffer + * color format to the remote framebuffer color format. + * + * Returned Value: + * The size of the transfer in bytes. + * + ****************************************************************************/ + +static size_t vnc_copy8(FAR struct vnc_session_s *session, + nxgl_coord_t row, nxgl_coord_t col, + nxgl_coord_t height, nxgl_coord_t width, + vnc_convert8_t convert) +{ +#if defined(CONFIG_VNCSERVER_COLORFMT_RGB16) + FAR struct rfb_framebufferupdate_s *update; + FAR const uint16_t *srcleft; + FAR const uint16_t *src; + FAR uint8_t *dest; + nxgl_coord_t x; + nxgl_coord_t y; + + /* Destination rectangle start address */ + + update = (FAR struct rfb_framebufferupdate_s *)session->outbuf; + dest = (FAR uint8_t *)update->rect[0].data; + + /* Source rectangle start address (left/top)*/ + + srcleft = (FAR uint16_t *)(session->fb + RFB_STRIDE * row + RFB_BYTESPERPIXEL * col); + + /* Transfer each row from the source buffer into the update buffer */ + + for (y = 0; y < height; y++) + { + src = srcleft; + for (x = 0; x < width; x++) + { + *dest++ = convert(*src); + src++; + } + + srcleft = (FAR uint16_t *)((uintptr_t)srcleft + RFB_STRIDE); + } + + return (size_t)((uintptr_t)dest - (uintptr_t)update->rect[0].data); + +#elif defined(CONFIG_VNCSERVER_COLORFMT_RGB32) + FAR struct rfb_framebufferupdate_s *update; + FAR const uint32_t *srcleft; + FAR const uint32_t *src; + FAR uint8_t *dest; + nxgl_coord_t x; + nxgl_coord_t y; + + /* Destination rectangle start address */ + + update = (FAR struct rfb_framebufferupdate_s *)session->outbuf; + dest = (FAR uint8_t *)update->rect[0].data; + + /* Source rectangle start address */ + + srcleft = (FAR uint32_t *)(session->fb + RFB_STRIDE * row + RFB_BYTESPERPIXEL * col); + + for (y = 0; y < height; y++) + { + src = srcleft; + for (x = 0; x < width; x++) + { + *dest++ = convert(*src); + src++; + } + + srcleft = (FAR uint32_t *)((uintptr_t)srcleft + RFB_STRIDE); + } + + return (size_t)((uintptr_t)dest - (uintptr_t)update->rect[0].data); +#endif +} + /**************************************************************************** * Name: vnc_copy16 * @@ -539,10 +687,11 @@ static FAR void *vnc_updater(FAR void *arg) union { + vnc_convert8_t bpp8; vnc_convert16_t bpp16; vnc_convert32_t bpp32; } convert; - bool color32 = false; + uint8_t bpp; DEBUGASSERT(session != NULL); gvdbg("Updater running for Display %d\n", session->display); @@ -559,17 +708,29 @@ static FAR void *vnc_updater(FAR void *arg) switch (session->colorfmt) { + case FB_FMT_RGB8_222: + convert.bpp8 = vnc_convert_rgb8_222; + bpp = 8; + break; + + case FB_FMT_RGB8_332: + convert.bpp8 = vnc_convert_rgb8_332; + bpp = 8; + break; + case FB_FMT_RGB16_555: convert.bpp16 = vnc_convert_rgb16_555; + bpp = 16; break; case FB_FMT_RGB16_565: convert.bpp16 = vnc_convert_rgb16_565; + bpp = 16; break; case FB_FMT_RGB32: convert.bpp32 = vnc_convert_rgb32_888; - color32 = true; + bpp = 32; break; default: @@ -672,16 +833,21 @@ static FAR void *vnc_updater(FAR void *arg) * performing the necessary color conversions. */ - if (color32) + if (bpp == 8) { - size = vnc_copy32(session, y, x, updheight, updwidth, - convert.bpp32); + size = vnc_copy8(session, y, x, updheight, updwidth, + convert.bpp8); } - else + else if (bpp == 16) { size = vnc_copy16(session, y, x, updheight, updwidth, convert.bpp16); } + else + { + size = vnc_copy32(session, y, x, updheight, updwidth, + convert.bpp32); + } /* Format the FramebufferUpdate message */ diff --git a/include/nuttx/video/fb.h b/include/nuttx/video/fb.h index da702b31fc..1264515ade 100644 --- a/include/nuttx/video/fb.h +++ b/include/nuttx/video/fb.h @@ -69,112 +69,113 @@ #define FB_FMT_RGB1 FB_FMT_Y1 /* BPP=1 */ #define FB_FMT_RGB4 4 /* BPP=4 */ #define FB_FMT_RGB8 5 /* BPP=8 RGB palette index */ -#define FB_FMT_RGB8_332 6 /* BPP=8 R=3, G=3, B=2 */ -#define FB_FMT_RGB12_444 7 /* BPP=12 R=4, G=4, B=4 */ -#define FB_FMT_RGB16_555 8 /* BPP=16 R=5, G=5, B=5 (1 unused bit) */ -#define FB_FMT_RGB16_565 9 /* BPP=16 R=6, G=6, B=5 */ -#define FB_FMT_RGB24 10 /* BPP=24 */ -#define FB_FMT_RGB32 11 /* BPP=32 */ +#define FB_FMT_RGB8_222 6 /* BPP=8 R=2, G=2, B=2 */ +#define FB_FMT_RGB8_332 7 /* BPP=8 R=3, G=3, B=2 */ +#define FB_FMT_RGB12_444 8 /* BPP=12 R=4, G=4, B=4 */ +#define FB_FMT_RGB16_555 9 /* BPP=16 R=5, G=5, B=5 (1 unused bit) */ +#define FB_FMT_RGB16_565 10 /* BPP=16 R=6, G=6, B=5 */ +#define FB_FMT_RGB24 11 /* BPP=24 */ +#define FB_FMT_RGB32 12 /* BPP=32 */ /* Run length encoded RGB */ -#define FB_FMT_RGBRLE4 12 /* BPP=4 */ -#define FB_FMT_RGBRLE8 13 /* BPP=8 */ +#define FB_FMT_RGBRLE4 13 /* BPP=4 */ +#define FB_FMT_RGBRLE8 14 /* BPP=8 */ /* Raw RGB */ -#define FB_FMT_RGBRAW 14 /* BPP=? */ +#define FB_FMT_RGBRAW 15 /* BPP=? */ /* Raw RGB with arbitrary sample packing within a pixel. Packing and precision * of R, G and B components is determined by bit masks for each. */ -#define FB_FMT_RGBBTFLD16 15 /* BPP=16 */ -#define FB_FMT_RGBBTFLD24 16 /* BPP=24 */ -#define FB_FMT_RGBBTFLD32 17 /* BPP=32 */ -#define FB_FMT_RGBA16 18 /* BPP=16 Raw RGB with alpha */ -#define FB_FMT_RGBA32 19 /* BPP=32 Raw RGB with alpha */ +#define FB_FMT_RGBBTFLD16 16 /* BPP=16 */ +#define FB_FMT_RGBBTFLD24 17 /* BPP=24 */ +#define FB_FMT_RGBBTFLD32 18 /* BPP=32 */ +#define FB_FMT_RGBA16 19 /* BPP=16 Raw RGB with alpha */ +#define FB_FMT_RGBA32 20 /* BPP=32 Raw RGB with alpha */ /* Raw RGB with a transparency field. Layout is as for standard RGB at 16 and * 32 bits per pixel but the msb in each pixel indicates whether the pixel is * transparent or not. */ -#define FB_FMT_RGBT16 20 /* BPP=16 */ -#define FB_FMT_RGBT32 21 /* BPP=32 */ +#define FB_FMT_RGBT16 21 /* BPP=16 */ +#define FB_FMT_RGBT32 22 /* BPP=32 */ #define FB_ISRGB(f) ((f) >= FB_FMT_RGB1) && (f) <= FB_FMT_RGBT32) /* Packed YUV Formats *******************************************************/ -#define FB_FMT_AYUV 22 /* BPP=32 Combined YUV and alpha */ -#define FB_FMT_CLJR 23 /* BPP=8 4 pixels packed into a uint32_t. +#define FB_FMT_AYUV 23 /* BPP=32 Combined YUV and alpha */ +#define FB_FMT_CLJR 24 /* BPP=8 4 pixels packed into a uint32_t. * YUV 4:1:1 with l< 8 bits * per YUV sample */ -#define FB_FMT_CYUV 24 /* BPP=16 UYVY except that height is +#define FB_FMT_CYUV 25 /* BPP=16 UYVY except that height is * reversed */ -#define FB_FMT_IRAW 25 /* BPP=? Intel uncompressed YUV */ -#define FB_FMT_IUYV 26 /* BPP=16 Interlaced UYVY (line order +#define FB_FMT_IRAW 26 /* BPP=? Intel uncompressed YUV */ +#define FB_FMT_IUYV 27 /* BPP=16 Interlaced UYVY (line order * 0,2,4,.., 1,3,5...) */ -#define FB_FMT_IY41 27 /* BPP=12 Interlaced Y41P (line order +#define FB_FMT_IY41 28 /* BPP=12 Interlaced Y41P (line order * 0,2,4,.., 1,3,5...) */ -#define FB_FMT_IYU2 28 /* BPP=24 */ -#define FB_FMT_HDYC 29 /* BPP=16 UYVY except uses the BT709 +#define FB_FMT_IYU2 29 /* BPP=24 */ +#define FB_FMT_HDYC 30 /* BPP=16 UYVY except uses the BT709 * color space */ -#define FB_FMT_UYVP 30 /* BPP=24? YCbCr 4:2:2, 10-bits per +#define FB_FMT_UYVP 31 /* BPP=24? YCbCr 4:2:2, 10-bits per * component in U0Y0V0Y1 order */ -#define FB_FMT_UYVY 31 /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_UYVY 32 /* BPP=16 YUV 4:2:2 */ #define FB_FMT_UYNV FB_FMT_UYVY /* BPP=16 */ #define FB_FMT_Y422 FB_FMT_UYVY /* BPP=16 */ -#define FB_FMT_V210 32 /* BPP=32 10-bit 4:2:2 YCrCb */ -#define FB_FMT_V422 33 /* BPP=16 Upside down version of UYVY */ -#define FB_FMT_V655 34 /* BPP=16? 16-bit YUV 4:2:2 */ -#define FB_FMT_VYUY 35 /* BPP=? ATI Packed YUV Data */ -#define FB_FMT_YUYV 36 /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_V210 33 /* BPP=32 10-bit 4:2:2 YCrCb */ +#define FB_FMT_V422 34 /* BPP=16 Upside down version of UYVY */ +#define FB_FMT_V655 35 /* BPP=16? 16-bit YUV 4:2:2 */ +#define FB_FMT_VYUY 36 /* BPP=? ATI Packed YUV Data */ +#define FB_FMT_YUYV 37 /* BPP=16 YUV 4:2:2 */ #define FB_FMT_YUY2 FB_FMT_YUYV /* BPP=16 YUV 4:2:2 */ #define FB_FMT_YUNV FB_FMT_YUYV /* BPP=16 YUV 4:2:2 */ -#define FB_FMT_YVYU 37 /* BPP=16 YUV 4:2:2 */ -#define FB_FMT_Y41P 38 /* BPP=12 YUV 4:1:1 */ -#define FB_FMT_Y411 39 /* BPP=12 YUV 4:1:1 */ -#define FB_FMT_Y211 40 /* BPP=8 */ -#define FB_FMT_Y41T 41 /* BPP=12 Y41P LSB for transparency */ -#define FB_FMT_Y42T 42 /* BPP=16 UYVY LSB for transparency */ -#define FB_FMT_YUVP 43 /* BPP=24? YCbCr 4:2:2 Y0U0Y1V0 order */ +#define FB_FMT_YVYU 38 /* BPP=16 YUV 4:2:2 */ +#define FB_FMT_Y41P 39 /* BPP=12 YUV 4:1:1 */ +#define FB_FMT_Y411 40 /* BPP=12 YUV 4:1:1 */ +#define FB_FMT_Y211 41 /* BPP=8 */ +#define FB_FMT_Y41T 42 /* BPP=12 Y41P LSB for transparency */ +#define FB_FMT_Y42T 43 /* BPP=16 UYVY LSB for transparency */ +#define FB_FMT_YUVP 44 /* BPP=24? YCbCr 4:2:2 Y0U0Y1V0 order */ #define FB_ISYUVPACKED(f) ((f) >= FB_FMT_AYUV) && (f) <= FB_FMT_YUVP) /* Packed Planar YUV Formats ************************************************/ -#define FB_FMT_YVU9 44 /* BPP=9 8-bit Y followed by 8-bit +#define FB_FMT_YVU9 45 /* BPP=9 8-bit Y followed by 8-bit * 4x4 VU */ -#define FB_FMT_YUV9 45 /* BPP=9? */ -#define FB_FMT_IF09 46 /* BPP=9.5 YVU9 + 4x4 plane of delta +#define FB_FMT_YUV9 46 /* BPP=9? */ +#define FB_FMT_IF09 47 /* BPP=9.5 YVU9 + 4x4 plane of delta * relative to tframe. */ -#define FB_FMT_YV16 47 /* BPP=16 8-bit Y followed by 8-bit +#define FB_FMT_YV16 48 /* BPP=16 8-bit Y followed by 8-bit * 2x1 VU */ -#define FB_FMT_YV12 48 /* BPP=12 8-bit Y followed by 8-bit +#define FB_FMT_YV12 49 /* BPP=12 8-bit Y followed by 8-bit * 2x2 VU */ -#define FB_FMT_I420 49 /* BPP=12 8-bit Y followed by 8-bit +#define FB_FMT_I420 50 /* BPP=12 8-bit Y followed by 8-bit * 2x2 UV */ #define FB_FMT_IYUV FB_FMT_I420 /* BPP=12 */ -#define FB_FMT_NV12 50 /* BPP=12 8-bit Y followed by an +#define FB_FMT_NV12 51 /* BPP=12 8-bit Y followed by an * interleaved 2x2 UV */ -#define FB_FMT_NV21 51 /* BPP=12 NV12 with UV reversed */ -#define FB_FMT_IMC1 52 /* BPP=12 YV12 except UV planes same +#define FB_FMT_NV21 52 /* BPP=12 NV12 with UV reversed */ +#define FB_FMT_IMC1 53 /* BPP=12 YV12 except UV planes same * stride as Y */ -#define FB_FMT_IMC2 53 /* BPP=12 IMC1 except UV lines +#define FB_FMT_IMC2 54 /* BPP=12 IMC1 except UV lines * interleaved at half stride * boundaries */ -#define FB_FMT_IMC3 54 /* BPP=12 As IMC1 except that UV +#define FB_FMT_IMC3 55 /* BPP=12 As IMC1 except that UV * swapped */ -#define FB_FMT_IMC4 55 /* BPP=12 As IMC2 except that UV +#define FB_FMT_IMC4 56 /* BPP=12 As IMC2 except that UV * swapped */ -#define FB_FMT_CLPL 56 /* BPP=12 YV12 but including a level +#define FB_FMT_CLPL 57 /* BPP=12 YV12 but including a level * of indirection. */ -#define FB_FMT_Y41B 57 /* BPP=12? 4:1:1 planar. */ -#define FB_FMT_Y42B 58 /* BPP=16? YUV 4:2:2 planar. */ -#define FB_FMT_CXY1 59 /* BPP=12 */ -#define FB_FMT_CXY2 60 /* BPP=16 */ +#define FB_FMT_Y41B 58 /* BPP=12? 4:1:1 planar. */ +#define FB_FMT_Y42B 59 /* BPP=16? YUV 4:2:2 planar. */ +#define FB_FMT_CXY1 60 /* BPP=12 */ +#define FB_FMT_CXY2 61 /* BPP=16 */ #define FB_ISYUVPLANAR(f) ((f) >= FB_FMT_AYUV) && (f) <= FB_FMT_YUVP) #define FB_ISYUV(f) (FB_ISYUVPACKED(f) || FB_ISYUVPLANAR(f))