[PATCH] Add support for colourmap based pixel formats
- From: "Daniel P. Berrange" <dan berrange com>
- To: gtk-vnc-list gnome org
- Subject: [PATCH] Add support for colourmap based pixel formats
- Date: Thu, 17 Jun 2010 21:49:29 +0100
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(-)
create mode 100644 src/vnccolormap.c
create mode 100644 src/vnccolormap.h
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 4b782ef..0a0c626 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -1034,14 +1034,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;
@@ -1349,9 +1353,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
--
1.7.0.1
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]