[gtk-vnc] Add support for colourmap based pixel formats



commit 7fab4a7abb85451f2ebb2d95ce0ec46dd6a9cccb
Author: Daniel P. Berrange <dan berrange com>
Date:   Wed Jun 16 22:43:17 2010 +0100

    Add support for colourmap based pixel formats
    
    The current code will force the server to use the native
    client's pixel format if it ever sees a pixel format
    with true_color_flag==0 (ie colourmap).  This is bad because
    the client native pixel format is almost always 32bpp while
    the main reason for using a colourmap is to get bandwidth
    friendly 8bpp format. This makes GTK-VNC look bad in any
    performance comparisons.
    
    This patch implements full support for rendering from
    colourmaps. It introduces a boxed data type to store the
    colour map entries and wires this upto the framebuffer
    interface.
    
    For rendering, the BLT functions for the VncBaseFramebuffer
    are enhanced to cope with colourmaps. Since colour maps
    provide 16bit r,g,b triples, the BLT code is enhanced to
    cope with 64-bit bpp pixels. This is technically required
    even for non-colourmap entries since the VNC pixel format
    protocol message allows for 16 bit r,g,b masks which
    results in a 64-bit true colour pixel.
    
    * src/vnccolormap.h, src/vnccolormap.c, src/Makefile.am: Add
      a VncColorMap boxed data type to hold the colour map entries.
    * src/vncframebuffer.h, src/vncframebuffer.c: Add an API to
      the VncFrameBuffer interface to allow the colour map to be
      updated.
    * src/vncconnection.h, src/vncconnection.c: Remove last case
      of vnc_ops and replace with new VncColorMap object
    * src/vncdisplay.c: Don't override the default server pixel
      format, allow use of colour maps
    * src/vncbaseframebuffer.c, src/vncbaseframebufferblt.h: Add
      support for rendering pixels using a colourmap

 src/Makefile.am             |    3 +
 src/libgvnc_sym.version     |    6 +
 src/vncbaseframebuffer.c    |  277 ++++++++++++++++++++++++++++++++++++++++---
 src/vncbaseframebufferblt.h |   26 ++++-
 src/vnccolormap.c           |  113 ++++++++++++++++++
 src/vnccolormap.h           |   77 ++++++++++++
 src/vncconnection.c         |   31 ++---
 src/vncconnection.h         |    5 -
 src/vncdisplay.c            |   22 ++--
 src/vncframebuffer.c        |    7 +
 src/vncframebuffer.h        |    6 +-
 11 files changed, 522 insertions(+), 51 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 6e1f5d4..393d76a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ gvnc_include_HEADERS = \
 			vncframebuffer.h \
 			vncbaseframebuffer.h \
 			vnccursor.h \
+			vnccolormap.h \
 			vncconnection.h \
 			vncconnectionenums.h \
 			vncutil.h
@@ -45,6 +46,7 @@ libgvnc_1_0_la_SOURCES = \
 			vncbaseframebufferblt.h \
 			vncbaseframebuffer.h vncbaseframebuffer.c \
 			vnccursor.h vnccursor.c \
+			vnccolormap.h vnccolormap.c \
 			vncconnection.h vncconnection.c \
 			vncconnectionblt.h \
 			vncconnectionenums.h vncconnectionenums.c \
@@ -193,6 +195,7 @@ GVNC_INTROSPECTION_SRCS = \
 			$(srcdir)/vncpixelformat.h \
 			$(srcdir)/vncframebuffer.h $(srcdir)/vncframebuffer.c \
 			$(srcdir)/vncbaseframebuffer.h $(srcdir)/vncbaseframebuffer.c \
+			$(srcdir)/vnccolormap.h $(srcdir)/vnccolormap.c \
 			$(srcdir)/vnccursor.h $(srcdir)/vnccursor.c \
 			$(srcdir)/vncconnection.h $(srcdir)/vncconnection.c \
 			$(builddir)/vncconnectionenums.h $(builddir)/vncconnectionenums.c \
diff --git a/src/libgvnc_sym.version b/src/libgvnc_sym.version
index 47c474d..8f0ea44 100644
--- a/src/libgvnc_sym.version
+++ b/src/libgvnc_sym.version
@@ -8,6 +8,12 @@
 	vnc_cursor_get_width;
 	vnc_cursor_get_height;
 
+	vnc_color_map_get_type;
+	vnc_color_map_new;
+	vnc_color_map_copy;
+	vnc_color_map_free;
+	vnc_color_map_set;
+
 	vnc_framebuffer_get_type;
 	vnc_framebuffer_get_width;
 	vnc_framebuffer_get_height;
diff --git a/src/vncbaseframebuffer.c b/src/vncbaseframebuffer.c
index d689e84..99fc5ef 100644
--- a/src/vncbaseframebuffer.c
+++ b/src/vncbaseframebuffer.c
@@ -56,6 +56,8 @@ struct _VncBaseFramebufferPrivate {
 	VncPixelFormat *localFormat;
 	VncPixelFormat *remoteFormat;
 
+	VncColorMap *colorMap;
+
 	/* TRUE if the following derived data needs reinitializing */
 	gboolean reinitRenderFuncs;
 
@@ -93,6 +95,7 @@ enum {
 	PROP_ROWSTRIDE,
 	PROP_LOCAL_FORMAT,
 	PROP_REMOTE_FORMAT,
+	PROP_COLOR_MAP,
 };
 
 
@@ -129,6 +132,10 @@ static void vnc_base_framebuffer_get_property(GObject *object,
 		g_value_set_boxed(value, priv->remoteFormat);
 		break;
 
+	case PROP_COLOR_MAP:
+		g_value_set_boxed(value, priv->colorMap);
+		break;
+
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 	}
@@ -177,6 +184,13 @@ static void vnc_base_framebuffer_set_property(GObject *object,
 		priv->reinitRenderFuncs = TRUE;
 		break;
 
+	case PROP_COLOR_MAP:
+		if (priv->colorMap)
+			vnc_color_map_free(priv->colorMap);
+		priv->colorMap = g_value_dup_boxed(value);
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         }
@@ -194,6 +208,8 @@ static void vnc_base_framebuffer_finalize(GObject *object)
 		vnc_pixel_format_free(priv->localFormat);
 	if (priv->remoteFormat)
 		vnc_pixel_format_free(priv->remoteFormat);
+	if (priv->colorMap)
+		vnc_color_map_free(priv->colorMap);
 
 	G_OBJECT_CLASS(vnc_base_framebuffer_parent_class)->finalize (object);
 }
@@ -284,6 +300,18 @@ static void vnc_base_framebuffer_class_init(VncBaseFramebufferClass *klass)
 							   G_PARAM_STATIC_NICK |
 							   G_PARAM_STATIC_BLURB));
 
+	g_object_class_install_property(object_class,
+					PROP_COLOR_MAP,
+					g_param_spec_boxed("color-map",
+							   "Color map",
+							   "The color map",
+							   VNC_TYPE_COLOR_MAP,
+							   G_PARAM_READABLE |
+							   G_PARAM_WRITABLE |
+							   G_PARAM_STATIC_NAME |
+							   G_PARAM_STATIC_NICK |
+							   G_PARAM_STATIC_BLURB));
+
 	g_type_class_add_private(klass, sizeof(VncBaseFramebufferPrivate));
 }
 
@@ -430,6 +458,23 @@ static guint32 vnc_base_framebuffer_swap_img_32(VncBaseFramebufferPrivate *priv,
 }
 
 
+/* local host native format -> X server image format */
+static guint32 vnc_base_framebuffer_swap_img_64(VncBaseFramebufferPrivate *priv, guint64 pixel)
+{
+	if (G_BYTE_ORDER != priv->localFormat->byte_order)
+		return  (((pixel >> 56) & 0xFF) <<  0) |
+			(((pixel >> 48) & 0xFF) <<  8) |
+			(((pixel >> 40) & 0xFF) << 16) |
+			(((pixel >> 32) & 0xFF) << 24) |
+			(((pixel >> 24) & 0xFF) << 32) |
+			(((pixel >> 16) & 0xFF) << 40) |
+			(((pixel >>  8) & 0xFF) << 48) |
+			(((pixel >>  0) & 0xFF) << 56);
+	else
+		return pixel;
+}
+
+
 /* VNC server RFB  format ->  local host native format */
 static guint32 vnc_base_framebuffer_swap_rfb_32(VncBaseFramebufferPrivate *priv, guint32 pixel)
 {
@@ -442,6 +487,22 @@ static guint32 vnc_base_framebuffer_swap_rfb_32(VncBaseFramebufferPrivate *priv,
 		return pixel;
 }
 
+/* VNC server RFB  format ->  local host native format */
+static guint32 vnc_base_framebuffer_swap_rfb_64(VncBaseFramebufferPrivate *priv, guint64 pixel)
+{
+	if (priv->remoteFormat->byte_order != G_BYTE_ORDER)
+		return  (((pixel >> 56) & 0xFF) <<  0) |
+			(((pixel >> 48) & 0xFF) <<  8) |
+			(((pixel >> 40) & 0xFF) << 16) |
+			(((pixel >> 32) & 0xFF) << 24) |
+			(((pixel >> 24) & 0xFF) << 32) |
+			(((pixel >> 16) & 0xFF) << 40) |
+			(((pixel >>  8) & 0xFF) << 48) |
+			(((pixel >>  0) & 0xFF) << 56);
+	else
+		return pixel;
+}
+
 #define SRC 8
 #define DST 8
 #include "vncbaseframebufferblt.h"
@@ -460,6 +521,12 @@ static guint32 vnc_base_framebuffer_swap_rfb_32(VncBaseFramebufferPrivate *priv,
 #undef SRC
 #undef DST
 
+#define SRC 8
+#define DST 64
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
 
 #define SRC 16
 #define DST 8
@@ -479,6 +546,12 @@ static guint32 vnc_base_framebuffer_swap_rfb_32(VncBaseFramebufferPrivate *priv,
 #undef SRC
 #undef DST
 
+#define SRC 16
+#define DST 64
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
 
 #define SRC 32
 #define DST 8
@@ -498,46 +571,186 @@ static guint32 vnc_base_framebuffer_swap_rfb_32(VncBaseFramebufferPrivate *priv,
 #undef SRC
 #undef DST
 
-static vnc_base_framebuffer_set_pixel_at_func *vnc_base_framebuffer_set_pixel_at_table[3][3] = {
+#define SRC 32
+#define DST 64
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+
+
+#define SRC 64
+#define DST 8
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 64
+#define DST 16
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 64
+#define DST 32
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 64
+#define DST 64
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+
+#define COLORMAP
+#define SRC 8
+#define DST 8
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 8
+#define DST 16
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 8
+#define DST 32
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 8
+#define DST 64
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+#undef COLORMAP
+
+
+
+#define COLORMAP
+#define SRC 16
+#define DST 8
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 16
+#define DST 16
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 16
+#define DST 32
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 16
+#define DST 64
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+#undef COLORMAP
+
+static vnc_base_framebuffer_set_pixel_at_func *vnc_base_framebuffer_set_pixel_at_table[6][4] = {
         { (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_8x8,
           (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_8x16,
-          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_8x32 },
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_8x32,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_8x64 },
         { (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_16x8,
           (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_16x16,
-          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_16x32 },
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_16x32,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_16x64 },
         { (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_32x8,
           (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_32x16,
-          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_32x32 },
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_32x32,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_32x64 },
+        { (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_64x8,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_64x16,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_64x32,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_64x64 },
+        { (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap8x8,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap8x16,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap8x32,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap8x64 },
+        { (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap16x8,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap16x16,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap16x32,
+          (vnc_base_framebuffer_set_pixel_at_func *)vnc_base_framebuffer_set_pixel_at_cmap16x64 },
 };
 
-static vnc_base_framebuffer_fill_func *vnc_base_framebuffer_fill_table[3][3] = {
+static vnc_base_framebuffer_fill_func *vnc_base_framebuffer_fill_table[6][4] = {
         { (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_8x8,
           (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_8x16,
-          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_8x32 },
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_8x32,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_8x64 },
         { (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_16x8,
           (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_16x16,
-          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_16x32 },
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_16x32,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_16x64 },
         { (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x8,
           (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x16,
-          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x32 },
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x32,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x64 },
+        { (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_64x8,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_64x16,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_64x32,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_64x64 },
+        { (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap8x8,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap8x16,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap8x32,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap8x64 },
+        { (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap16x8,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap16x16,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap16x32,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_cmap16x64 },
 };
 
-static vnc_base_framebuffer_fill_func *vnc_base_framebuffer_fill_fast_table[3] = {
+static vnc_base_framebuffer_fill_func *vnc_base_framebuffer_fill_fast_table[4] = {
 	(vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_fast_8x8,
 	(vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_fast_16x16,
 	(vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_fast_32x32,
+	(vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_fast_64x64,
 };
 
-static vnc_base_framebuffer_blt_func *vnc_base_framebuffer_blt_table[3][3] = {
-        {  vnc_base_framebuffer_blt_8x8,  vnc_base_framebuffer_blt_8x16,  vnc_base_framebuffer_blt_8x32 },
-        { vnc_base_framebuffer_blt_16x8, vnc_base_framebuffer_blt_16x16, vnc_base_framebuffer_blt_16x32 },
-        { vnc_base_framebuffer_blt_32x8, vnc_base_framebuffer_blt_32x16, vnc_base_framebuffer_blt_32x32 },
+static vnc_base_framebuffer_blt_func *vnc_base_framebuffer_blt_table[6][4] = {
+        {  vnc_base_framebuffer_blt_8x8,
+	   vnc_base_framebuffer_blt_8x16,
+	   vnc_base_framebuffer_blt_8x32,
+	   vnc_base_framebuffer_blt_8x64 },
+        { vnc_base_framebuffer_blt_16x8,
+	  vnc_base_framebuffer_blt_16x16,
+	  vnc_base_framebuffer_blt_16x32,
+	  vnc_base_framebuffer_blt_16x64 },
+        { vnc_base_framebuffer_blt_32x8,
+	  vnc_base_framebuffer_blt_32x16,
+	  vnc_base_framebuffer_blt_32x32,
+	  vnc_base_framebuffer_blt_32x64 },
+        { vnc_base_framebuffer_blt_64x8,
+	  vnc_base_framebuffer_blt_64x16,
+	  vnc_base_framebuffer_blt_64x32,
+	  vnc_base_framebuffer_blt_64x64 },
+        { vnc_base_framebuffer_blt_cmap8x8,
+	  vnc_base_framebuffer_blt_cmap8x16,
+	  vnc_base_framebuffer_blt_cmap8x32,
+	  vnc_base_framebuffer_blt_cmap8x64 },
+        { vnc_base_framebuffer_blt_cmap16x8,
+	  vnc_base_framebuffer_blt_cmap16x16,
+	  vnc_base_framebuffer_blt_cmap16x32,
+	  vnc_base_framebuffer_blt_cmap16x64 },
 };
 
-static vnc_base_framebuffer_rgb24_blt_func *vnc_base_framebuffer_rgb24_blt_table[3] = {
+static vnc_base_framebuffer_rgb24_blt_func *vnc_base_framebuffer_rgb24_blt_table[4] = {
         (vnc_base_framebuffer_rgb24_blt_func *)vnc_base_framebuffer_rgb24_blt_32x8,
         (vnc_base_framebuffer_rgb24_blt_func *)vnc_base_framebuffer_rgb24_blt_32x16,
         (vnc_base_framebuffer_rgb24_blt_func *)vnc_base_framebuffer_rgb24_blt_32x32,
+        (vnc_base_framebuffer_rgb24_blt_func *)vnc_base_framebuffer_rgb24_blt_32x64,
 };
 
 
@@ -566,7 +779,18 @@ static void vnc_base_framebuffer_reinit_render_funcs(VncBaseFramebuffer *fb)
 	if (!priv->reinitRenderFuncs)
 		return;
 
-	if (priv->localFormat->bits_per_pixel == priv->remoteFormat->bits_per_pixel &&
+	if (!priv->remoteFormat->true_color_flag) {
+		priv->remoteFormat->red_max = ~(guint16)0;
+		priv->remoteFormat->green_max = ~(guint16)0;
+		priv->remoteFormat->blue_max = ~(guint16)0;
+		priv->remoteFormat->red_shift = 32;
+		priv->remoteFormat->green_shift = 16;
+		priv->remoteFormat->blue_shift = 0;
+		priv->remoteFormat->byte_order = G_BYTE_ORDER;
+	}
+
+	if (priv->remoteFormat->true_color_flag &&
+	    priv->localFormat->bits_per_pixel == priv->remoteFormat->bits_per_pixel &&
 	    priv->localFormat->red_max == priv->remoteFormat->red_max &&
 	    priv->localFormat->green_max == priv->remoteFormat->green_max &&
 	    priv->localFormat->blue_max == priv->remoteFormat->blue_max &&
@@ -623,9 +847,17 @@ static void vnc_base_framebuffer_reinit_render_funcs(VncBaseFramebuffer *fb)
 
 	i = priv->remoteFormat->bits_per_pixel / 8;
 	j = priv->localFormat->bits_per_pixel / 8;
-
 	if (i == 4) i = 3;
 	if (j == 4) j = 3;
+	if (i > 4) i = 4; /* XXX hardcoding int64 */
+	if (j > 4) j = 4; /* XXX hardcoding int64 */
+	if (!priv->remoteFormat->true_color_flag) {
+		if (priv->remoteFormat->bits_per_pixel == 8)
+			i = 5; /* 8bpp colourmap */
+		else
+			i = 6; /* 16bpp colourmap */
+		VNC_DEBUG("BPP i %d %d", priv->remoteFormat->bits_per_pixel, i);
+	}
 
 	priv->set_pixel_at = vnc_base_framebuffer_set_pixel_at_table[i - 1][j - 1];
 
@@ -731,6 +963,18 @@ static void vnc_base_framebuffer_rgb24_blt(VncFramebuffer *iface,
 }
 
 
+static void vnc_base_framebuffer_set_color_map(VncFramebuffer *iface,
+					       VncColorMap *map)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	if (priv->colorMap)
+		vnc_color_map_free(priv->colorMap);
+	priv->colorMap = vnc_color_map_copy(map);
+}
+
+
 static void vnc_base_framebuffer_interface_init(gpointer g_iface,
 						gpointer iface_data G_GNUC_UNUSED)
 {
@@ -749,6 +993,7 @@ static void vnc_base_framebuffer_interface_init(gpointer g_iface,
     iface->copyrect = vnc_base_framebuffer_copyrect;
     iface->blt = vnc_base_framebuffer_blt;
     iface->rgb24_blt = vnc_base_framebuffer_rgb24_blt;
+    iface->set_color_map = vnc_base_framebuffer_set_color_map;
 }
 
 /*
diff --git a/src/vncbaseframebufferblt.h b/src/vncbaseframebufferblt.h
index 398229d..1873cd1 100644
--- a/src/vncbaseframebufferblt.h
+++ b/src/vncbaseframebufferblt.h
@@ -27,7 +27,11 @@
 
 #define SPLICE_I(a, b) a ## b
 #define SPLICE(a, b) SPLICE_I(a, b)
+#ifdef COLORMAP
+#define SUFFIX() SPLICE(cmap,SPLICE(SRC,SPLICE(x,DST)))
+#else
 #define SUFFIX() SPLICE(SRC,SPLICE(x,DST))
+#endif
 
 #define src_pixel_t SPLICE(guint, SRC)
 #define ssrc_pixel_t SPLICE(gint, SRC)
@@ -43,7 +47,24 @@
 #define SWAP_RFB(priv, pixel) SPLICE(vnc_base_framebuffer_swap_rfb_, SRC)(priv, pixel)
 #define SWAP_IMG(priv, pixel) SPLICE(vnc_base_framebuffer_swap_img_, DST)(priv, pixel)
 #define COMPONENT(color, pixel) ((SWAP_RFB(priv, pixel) >> priv->remoteFormat->SPLICE(color, _shift) & priv->remoteFormat->SPLICE(color, _max)))
-
+#include <stdio.h>
+#ifdef COLORMAP
+static void SET_PIXEL(VncBaseFramebufferPrivate *priv,
+		      dst_pixel_t *dp, src_pixel_t spidx)
+{
+	guint64 sp;
+	guint16 red = 0;
+	guint16 green = 0;
+	guint16 blue = 0;
+	vnc_color_map_lookup(priv->colorMap,
+			     spidx,
+			     &red, &green, &blue);
+	sp = ((guint64)red << 32) | ((guint64)green << 16) | (guint64)blue;
+	*dp = SWAP_IMG(priv, ((sp >> priv->rrs) & priv->rm) << priv->rls
+		       | ((sp >> priv->grs) & priv->gm) << priv->gls
+		       | ((sp >> priv->brs) & priv->bm) << priv->bls);
+}
+#else
 static void SET_PIXEL(VncBaseFramebufferPrivate *priv,
 		      dst_pixel_t *dp, src_pixel_t sp)
 {
@@ -51,6 +72,7 @@ static void SET_PIXEL(VncBaseFramebufferPrivate *priv,
 		       | ((sp >> priv->grs) & priv->gm) << priv->gls
 		       | ((sp >> priv->brs) & priv->bm) << priv->bls);
 }
+#endif
 
 static void SET_PIXEL_AT(VncBaseFramebufferPrivate *priv,
 			 src_pixel_t *sp,
@@ -63,6 +85,7 @@ static void SET_PIXEL_AT(VncBaseFramebufferPrivate *priv,
 
 
 #if SRC == DST
+#ifndef COLORMAP
 static void FAST_FILL(VncBaseFramebufferPrivate *priv,
 		      src_pixel_t *sp,
 		      guint16 x, guint16 y,
@@ -87,6 +110,7 @@ static void FAST_FILL(VncBaseFramebufferPrivate *priv,
 	}
 }
 #endif
+#endif
 
 
 static void FILL(VncBaseFramebufferPrivate *priv,
diff --git a/src/vnccolormap.c b/src/vnccolormap.c
new file mode 100644
index 0000000..99f6894
--- /dev/null
+++ b/src/vnccolormap.c
@@ -0,0 +1,113 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2010 Daniel P. Berrange <dan berrange com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "vnccolormap.h"
+
+GType vnc_color_map_get_type(void)
+{
+	static GType color_map_type = 0;
+
+	if (G_UNLIKELY(color_map_type == 0)) {
+		color_map_type = g_boxed_type_register_static
+			("VncColorMap",
+			 (GBoxedCopyFunc)vnc_color_map_copy,
+			 (GBoxedFreeFunc)vnc_color_map_free);
+	}
+
+	return color_map_type;
+}
+
+
+VncColorMap *vnc_color_map_new(guint16 offset, guint16 size)
+{
+	VncColorMap *map;
+
+	map = g_slice_new0(VncColorMap);
+	map->offset = offset;
+	map->size = size;
+	map->colors = g_new0(VncColorMapEntry, size);
+
+	return map;
+}
+
+
+VncColorMap *vnc_color_map_copy(VncColorMap *srcMap)
+{
+	VncColorMap *map;
+
+	map = g_slice_dup(VncColorMap, srcMap);
+	map->colors = g_new0(VncColorMapEntry, srcMap->size);
+	memcpy(map->colors, srcMap->colors,
+	       sizeof(VncColorMapEntry) * map->size);
+
+	return map;
+}
+
+
+void vnc_color_map_free(VncColorMap *map)
+{
+	g_slice_free(VncColorMap, map);
+}
+
+
+gboolean vnc_color_map_set(VncColorMap *map,
+			   guint16 idx,
+			   guint16 red,
+			   guint16 green,
+			   guint16 blue)
+{
+	if (idx >= (map->size + map->offset))
+		return FALSE;
+
+	map->colors[idx - map->offset].red = red;
+	map->colors[idx - map->offset].green = green;
+	map->colors[idx - map->offset].blue = blue;
+
+	return TRUE;
+}
+
+
+gboolean vnc_color_map_lookup(VncColorMap *map,
+			      guint16 idx,
+			      guint16 *red,
+			      guint16 *green,
+			      guint16 *blue)
+{
+	if (idx >= (map->size + map->offset))
+		return FALSE;
+
+	*red = map->colors[idx - map->offset].red;
+	*green = map->colors[idx - map->offset].green;
+	*blue = map->colors[idx - map->offset].blue;
+
+	return TRUE;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/src/vnccolormap.h b/src/vnccolormap.h
new file mode 100644
index 0000000..fe1f1d5
--- /dev/null
+++ b/src/vnccolormap.h
@@ -0,0 +1,77 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony codemonkey ws>
+ * Copyright (C) 2009-2010 Daniel P. Berrange <dan berrange com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef VNC_COLOR_MAP_H
+#define VNC_COLOR_MAP_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define VNC_TYPE_COLOR_MAP            (vnc_color_map_get_type ())
+
+typedef struct _VncColorMap VncColorMap;
+typedef struct _VncColorMapEntry VncColorMapEntry;
+
+struct _VncColorMap {
+	guint16 offset;
+	guint16 size;
+	VncColorMapEntry *colors;
+};
+
+struct _VncColorMapEntry {
+	guint16 red;
+	guint16 green;
+	guint16 blue;
+};
+
+
+GType vnc_color_map_get_type(void);
+
+VncColorMap *vnc_color_map_new(guint16 offset, guint16 nentries);
+VncColorMap *vnc_color_map_copy(VncColorMap *map);
+void vnc_color_map_free(VncColorMap *map);
+
+gboolean vnc_color_map_set(VncColorMap *map,
+			   guint16 idx,
+			   guint16 red,
+			   guint16 green,
+			   guint16 blue);
+
+gboolean vnc_color_map_lookup(VncColorMap *map,
+			      guint16 idx,
+			      guint16 *red,
+			      guint16 *green,
+			      guint16 *blue);
+
+
+G_END_DECLS
+
+#endif /* VNC_COLOR_MAP_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/src/vncconnection.c b/src/vncconnection.c
index 40ec86b..76bb060 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -164,9 +164,6 @@ struct _VncConnectionPrivate
 	vnc_connection_tight_compute_predicted_func *tight_compute_predicted;
 	vnc_connection_tight_sum_pixel_func *tight_sum_pixel;
 
-	struct vnc_connection_ops ops;
-	gpointer ops_data;
-
 	int wait_interruptable;
 	struct wait_queue wait;
 
@@ -2367,20 +2364,6 @@ static void vnc_connection_update(VncConnection *conn, int x, int y, int width,
 	vnc_connection_emit_main_context(conn, VNC_FRAMEBUFFER_UPDATE, &sigdata);
 }
 
-static void vnc_connection_set_color_map_entry(VncConnection *conn, guint16 color,
-					       guint16 red, guint16 green,
-					       guint16 blue)
-{
-	VncConnectionPrivate *priv = conn->priv;
-
-	if (priv->has_error || !priv->ops.set_color_map_entry)
-		return;
-	if (!priv->ops.set_color_map_entry(priv->ops_data, color,
-					   red, green, blue)) {
-		VNC_DEBUG("Closing the connection: vnc_connection_set_color_map_entry");
-		priv->has_error = TRUE;
-	}
-}
 
 static void vnc_connection_bell(VncConnection *conn)
 {
@@ -2680,12 +2663,17 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
 		guint16 first_color;
 		guint16 n_colors;
 		guint8 pad[1];
+		VncColorMap *map;
 		int i;
 
 		vnc_connection_read(conn, pad, 1);
 		first_color = vnc_connection_read_u16(conn);
 		n_colors = vnc_connection_read_u16(conn);
 
+		VNC_DEBUG("Colour map from %d with %d entries",
+			  first_color, n_colors);
+		map = vnc_color_map_new(first_color, n_colors);
+
 		for (i = 0; i < n_colors; i++) {
 			guint16 red, green, blue;
 
@@ -2693,10 +2681,13 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
 			green = vnc_connection_read_u16(conn);
 			blue = vnc_connection_read_u16(conn);
 
-			vnc_connection_set_color_map_entry(conn,
-							   i + first_color,
-							   red, green, blue);
+			vnc_color_map_set(map, 
+					  i + first_color,
+					  red, green, blue);
 		}
+
+		vnc_framebuffer_set_color_map(priv->fb, map);
+		vnc_color_map_free(map);
 	}	break;
 	case 2: /* Bell */
 		vnc_connection_bell(conn);
diff --git a/src/vncconnection.h b/src/vncconnection.h
index e66f0e6..02262ec 100644
--- a/src/vncconnection.h
+++ b/src/vncconnection.h
@@ -70,11 +70,6 @@ struct _VncConnectionClass
 	void (*vnc_disconnected)(VncConnection *conn);
 };
 
-struct vnc_connection_ops
-{
-	gboolean (*set_color_map_entry)(void *, int, int, int, int);
-};
-
 
 typedef enum {
 	VNC_CONNECTION_ENCODING_RAW = 0,
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 4268b78..71e158b 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -967,14 +967,18 @@ static gboolean vnc_display_set_preferred_pixel_format(VncDisplay *display)
 
 	switch (priv->depth) {
 	case VNC_DISPLAY_DEPTH_COLOR_DEFAULT:
-		/* If current format is not true colour, then
-		 * fallthrough to next case
-		 */
-		if (currentFormat->true_color_flag == 1) {
-			VNC_DEBUG ("Using default colour depth %d (%d bpp)",
-				    currentFormat->depth, currentFormat->bits_per_pixel);
-			return TRUE;
-		}
+		VNC_DEBUG ("Using default colour depth %d (%d bpp) (true color? %d)",
+			   currentFormat->depth, currentFormat->bits_per_pixel,
+			   currentFormat->true_color_flag);
+#if 0
+		/* TigerVNC always sends back the encoding even if
+		   unchanged from what the server suggested. This
+		   does not appear to matter, so lets save the bytes */
+		memcpy(&fmt, currentFormat, sizeof(fmt));
+		break;
+#else
+		return TRUE;
+#endif
 
 	case VNC_DISPLAY_DEPTH_COLOR_FULL:
 		fmt.depth = 24;
@@ -1282,9 +1286,11 @@ static void on_initialized(VncConnection *conn G_GNUC_UNUSED,
 		n_encodings -= 2;
 	}
 
+	VNC_DEBUG("Sending %d encodings", n_encodings);
 	if (!vnc_connection_set_encodings(priv->conn, n_encodings, encodingsp))
 		goto error;
 
+	VNC_DEBUG("Requesting first framebuffer update");
 	if (!vnc_connection_framebuffer_update_request(priv->conn, 0, 0, 0,
 						       vnc_connection_get_width(priv->conn),
 						       vnc_connection_get_height(priv->conn)))
diff --git a/src/vncframebuffer.c b/src/vncframebuffer.c
index b670a0d..617f45a 100644
--- a/src/vncframebuffer.c
+++ b/src/vncframebuffer.c
@@ -101,6 +101,13 @@ void vnc_framebuffer_rgb24_blt(VncFramebuffer *fb,
 }
 
 
+void vnc_framebuffer_set_color_map(VncFramebuffer *fb,
+				   VncColorMap *map)
+{
+	VNC_FRAMEBUFFER_GET_INTERFACE(fb)->set_color_map(fb, map);
+}
+
+
 GType
 vnc_framebuffer_get_type (void)
 {
diff --git a/src/vncframebuffer.h b/src/vncframebuffer.h
index 1776b7a..ebef8de 100644
--- a/src/vncframebuffer.h
+++ b/src/vncframebuffer.h
@@ -25,6 +25,7 @@
 #include <glib-object.h>
 
 #include <vncpixelformat.h>
+#include <vnccolormap.h>
 
 G_BEGIN_DECLS
 
@@ -69,7 +70,8 @@ struct _VncFramebufferInterface {
 			  int rowstride,
 			  guint16 x, guint16 y,
 			  guint16 width, guint16 height);
-
+	void (*set_color_map)(VncFramebuffer *fb,
+			      VncColorMap *map);
 };
 
 GType vnc_framebuffer_get_type(void) G_GNUC_CONST;
@@ -111,6 +113,8 @@ void vnc_framebuffer_rgb24_blt(VncFramebuffer *fb,
 			       guint16 x, guint16 y,
 			       guint16 width, guint16 height);
 
+void vnc_framebuffer_set_color_map(VncFramebuffer *fb,
+				   VncColorMap *map);
 
 
 G_END_DECLS



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]