[PATCH 06/25] Add a VncFrameBuffer interface and basic implementation



Define the interface for a framebuffer and rendering into it
between local & remote pixel formats.

Provide a basic implementation of the interface using simple
blt functions for a local memory region
---
 src/Makefile.am             |    3 +
 src/vncbaseframebuffer.c    |  727 +++++++++++++++++++++++++++++++++++++++++++
 src/vncbaseframebuffer.h    |   77 +++++
 src/vncbaseframebufferblt.h |  196 ++++++++++++
 src/vncframebuffer.c        |  127 ++++++++
 src/vncframebuffer.h        |  125 ++++++++
 6 files changed, 1255 insertions(+), 0 deletions(-)
 create mode 100644 src/vncbaseframebuffer.c
 create mode 100644 src/vncbaseframebuffer.h
 create mode 100644 src/vncbaseframebufferblt.h
 create mode 100644 src/vncframebuffer.c
 create mode 100644 src/vncframebuffer.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 84c9ddf..5c0dbdb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,9 @@ libgtk_vnc_1_0_la_SOURCES = blt.h blt1.h \
 	d3des.h d3des.c \
 	dh.h dh.c \
 	vncpixelformat.h \
+	vncframebuffer.h vncframebuffer.c \
+	vncbaseframebufferblt.h \
+	vncbaseframebuffer.h vncbaseframebuffer.c \
 	vncconnection.h vncconnection.c \
 	vncdisplay.h vncdisplay.c \
         vncmarshal.h vncmarshal.c \
diff --git a/src/vncbaseframebuffer.c b/src/vncbaseframebuffer.c
new file mode 100644
index 0000000..f7dab3b
--- /dev/null
+++ b/src/vncbaseframebuffer.c
@@ -0,0 +1,727 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony codemonkey ws>
+ *
+ * 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 "vncbaseframebuffer.h"
+#include "utils.h"
+
+typedef void vnc_base_framebuffer_blt_func(VncBaseFramebufferPrivate *priv,
+					   guint8 *src,
+					   int rowstride,
+					   guint16 x, guint16 y,
+					   guint16 widht, guint16 width);
+typedef void vnc_base_framebuffer_fill_func(VncBaseFramebufferPrivate *priv,
+					    guint8 *src,
+					    guint16 x, guint16 y,
+					    guint16 widht, guint16 width);
+typedef void vnc_base_framebuffer_set_pixel_at_func(VncBaseFramebufferPrivate *priv,
+						    guint8 *src,
+						    guint16 x, guint16 y);
+typedef void vnc_base_framebuffer_rgb24_blt_func(VncBaseFramebufferPrivate *priv,
+						 guint8 *src, int rowstride,
+						 guint16 x, guint16 y,
+						 guint16 width, guint16 height);
+
+
+#define VNC_BASE_FRAMEBUFFER_GET_PRIVATE(obj)				\
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), VNC_TYPE_BASE_FRAMEBUFFER, VncBaseFramebufferPrivate))
+
+struct _VncBaseFramebufferPrivate {
+	guint8 *buffer; /* Owned by caller, so no need to free */
+	guint16 width;
+	guint16 height;
+	int rowstride;
+
+	VncPixelFormat localFormat;
+	VncPixelFormat remoteFormat;
+
+	/* TRUE if the following derived data needs reinitializing */
+	gboolean reinitRenderFuncs;
+
+	/* Derived from above data */
+	int rm, gm, bm;
+        int rrs, grs, brs;
+        int rls, gls, bls;
+
+	/* TRUE if localFormat == remoteFormat */
+        gboolean perfect_match;
+
+	/* Render function impls for this local+remote format pair */
+        vnc_base_framebuffer_set_pixel_at_func *set_pixel_at;
+        vnc_base_framebuffer_fill_func *fill;
+        vnc_base_framebuffer_blt_func *blt;
+        vnc_base_framebuffer_rgb24_blt_func *rgb24_blt;
+};
+
+#define VNC_BASE_FRAMEBUFFER_AT(priv, x, y) \
+	((priv)->buffer + ((y) * (priv)->rowstride) + ((x) * ((priv)->localFormat.bits_per_pixel/8)))
+
+
+static void vnc_base_framebuffer_interface_init (gpointer g_iface,
+                                                 gpointer iface_data);
+
+G_DEFINE_TYPE_EXTENDED(VncBaseFramebuffer, vnc_base_framebuffer, G_TYPE_OBJECT, 0,
+                       G_IMPLEMENT_INTERFACE(VNC_TYPE_FRAMEBUFFER, vnc_base_framebuffer_interface_init));
+
+
+enum {
+	PROP_0,
+	PROP_BUFFER,
+	PROP_WIDTH,
+	PROP_HEIGHT,
+	PROP_ROWSTRIDE,
+	PROP_LOCAL_FORMAT,
+	PROP_REMOTE_FORMAT,
+};
+
+
+static void vnc_base_framebuffer_get_property(GObject *object,
+					      guint prop_id,
+					      GValue *value,
+					      GParamSpec *pspec)
+{
+	VncBaseFramebuffer *framebuffer = VNC_BASE_FRAMEBUFFER(object);
+	VncBaseFramebufferPrivate *priv = framebuffer->priv;
+
+	switch (prop_id) {
+	case PROP_BUFFER:
+		g_value_set_pointer(value, priv->buffer);
+		break;
+
+	case PROP_WIDTH:
+		g_value_set_int(value, priv->width);
+		break;
+
+	case PROP_HEIGHT:
+		g_value_set_int(value, priv->height);
+		break;
+
+	case PROP_ROWSTRIDE:
+		g_value_set_int(value, priv->rowstride);
+		break;
+
+	case PROP_LOCAL_FORMAT:
+		g_value_set_pointer(value, &priv->localFormat);
+		break;
+
+	case PROP_REMOTE_FORMAT:
+		g_value_set_pointer(value, &priv->remoteFormat);
+		break;
+
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+	}
+}
+
+static void vnc_base_framebuffer_set_property(GObject *object,
+					      guint prop_id,
+					      const GValue *value,
+					      GParamSpec *pspec)
+{
+	VncBaseFramebuffer *framebuffer = VNC_BASE_FRAMEBUFFER(object);
+	VncBaseFramebufferPrivate *priv = framebuffer->priv;
+
+	switch (prop_id){
+	case PROP_BUFFER:
+		priv->buffer = g_value_get_pointer(value);
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
+	case PROP_WIDTH:
+		priv->width = g_value_get_int(value);
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
+	case PROP_HEIGHT:
+		priv->height = g_value_get_int(value);
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
+	case PROP_ROWSTRIDE:
+		priv->rowstride = g_value_get_int(value);
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
+	case PROP_LOCAL_FORMAT:
+		memcpy(&priv->localFormat,
+		       g_value_get_pointer(value),
+		       sizeof(priv->localFormat));
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
+	case PROP_REMOTE_FORMAT:
+		memcpy(&priv->remoteFormat,
+		       g_value_get_pointer(value),
+		       sizeof(priv->remoteFormat));
+		priv->reinitRenderFuncs = TRUE;
+		break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        }
+}
+
+
+static void vnc_base_framebuffer_class_init(VncBaseFramebufferClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->get_property = vnc_base_framebuffer_get_property;
+	object_class->set_property = vnc_base_framebuffer_set_property;
+
+	g_object_class_install_property(object_class,
+					PROP_BUFFER,
+					g_param_spec_pointer("buffer",
+							     "The framebuffer",
+							     "The framebuffer memory region",
+							     G_PARAM_READABLE |
+							     G_PARAM_WRITABLE |
+							     G_PARAM_CONSTRUCT_ONLY |
+							     G_PARAM_STATIC_NAME |
+							     G_PARAM_STATIC_NICK |
+							     G_PARAM_STATIC_BLURB));
+
+	g_object_class_install_property(object_class,
+					PROP_WIDTH,
+					g_param_spec_int("width",
+							 "Framebuffer width",
+							 "Width of the framebuffer in pixels",
+							 0, 1 << 16, 0,
+							 G_PARAM_READABLE |
+							 G_PARAM_WRITABLE |
+							 G_PARAM_CONSTRUCT_ONLY |
+							 G_PARAM_STATIC_NAME |
+							 G_PARAM_STATIC_NICK |
+							 G_PARAM_STATIC_BLURB));
+
+	g_object_class_install_property(object_class,
+					PROP_HEIGHT,
+					g_param_spec_int("height",
+							 "Framebuffer height",
+							 "Height of the framebuffer in pixels",
+							 0, 1 << 16, 0,
+							 G_PARAM_READABLE |
+							 G_PARAM_WRITABLE |
+							 G_PARAM_CONSTRUCT_ONLY |
+							 G_PARAM_STATIC_NAME |
+							 G_PARAM_STATIC_NICK |
+							 G_PARAM_STATIC_BLURB));
+
+	g_object_class_install_property(object_class,
+					PROP_ROWSTRIDE,
+					g_param_spec_int("rowstride",
+							 "Framebuffer rowstride",
+							 "Size of one framebuffer line in bytes",
+							 0, 1 << 30, 0,
+							 G_PARAM_READABLE |
+							 G_PARAM_WRITABLE |
+							 G_PARAM_CONSTRUCT_ONLY |
+							 G_PARAM_STATIC_NAME |
+							 G_PARAM_STATIC_NICK |
+							 G_PARAM_STATIC_BLURB));
+
+	g_object_class_install_property(object_class,
+					PROP_LOCAL_FORMAT,
+					g_param_spec_pointer("local-format",
+							     "Local pixel format",
+							     "The local pixel format of the framebuffer",
+							     G_PARAM_READABLE |
+							     G_PARAM_WRITABLE |
+							     G_PARAM_CONSTRUCT_ONLY |
+							     G_PARAM_STATIC_NAME |
+							     G_PARAM_STATIC_NICK |
+							     G_PARAM_STATIC_BLURB));
+
+	g_object_class_install_property(object_class,
+					PROP_REMOTE_FORMAT,
+					g_param_spec_pointer("remote-format",
+							     "Remote pixel format",
+							     "The remote pixel format of the framebuffer",
+							     G_PARAM_READABLE |
+							     G_PARAM_WRITABLE |
+							     G_PARAM_CONSTRUCT_ONLY |
+							     G_PARAM_STATIC_NAME |
+							     G_PARAM_STATIC_NICK |
+							     G_PARAM_STATIC_BLURB));
+
+	g_type_class_add_private(klass, sizeof(VncBaseFramebufferPrivate));
+}
+
+
+void vnc_base_framebuffer_init(VncBaseFramebuffer *fb)
+{
+	VncBaseFramebufferPrivate *priv;
+
+	priv = fb->priv = VNC_BASE_FRAMEBUFFER_GET_PRIVATE(fb);
+
+	memset(priv, 0, sizeof(*priv));
+	priv->reinitRenderFuncs = TRUE;
+}
+
+
+VncBaseFramebuffer *vnc_base_framebuffer_new(guint8 *buffer,
+					     guint16 width,
+					     guint16 height,
+					     int rowstride,
+					     const VncPixelFormat *localFormat,
+					     const VncPixelFormat *remoteFormat)
+{
+	return VNC_BASE_FRAMEBUFFER(g_object_new(VNC_TYPE_BASE_FRAMEBUFFER,
+						 "buffer", buffer,
+						 "width", width,
+						 "height", height,
+						 "rowstride", rowstride,
+						 "local-format", localFormat,
+						 "remote-format", remoteFormat,
+						 NULL));
+}
+
+
+static guint16 vnc_base_framebuffer_get_width(VncFramebuffer *iface)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	return priv->width;
+}
+
+
+static guint16 vnc_base_framebuffer_get_height(VncFramebuffer *iface)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	return priv->height;
+}
+
+
+static int vnc_base_framebuffer_get_rowstride(VncFramebuffer *iface)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	return priv->rowstride;
+}
+
+
+static guint8 *vnc_base_framebuffer_get_buffer(VncFramebuffer *iface)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	return priv->buffer;
+}
+
+
+static const VncPixelFormat *vnc_base_framebuffer_get_local_format(VncFramebuffer *iface)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	return &priv->localFormat;
+}
+
+
+static const VncPixelFormat *vnc_base_framebuffer_get_remote_format(VncFramebuffer *iface)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	return &priv->remoteFormat;
+}
+
+
+static guint8 vnc_base_framebuffer_swap_img_8(VncBaseFramebufferPrivate *priv G_GNUC_UNUSED, guint8 pixel)
+{
+	return pixel;
+}
+
+
+static guint8 vnc_base_framebuffer_swap_rfb_8(VncBaseFramebufferPrivate *priv G_GNUC_UNUSED, guint8 pixel)
+{
+	return pixel;
+}
+
+
+/* local host native format -> X server image format */
+static guint16 vnc_base_framebuffer_swap_img_16(VncBaseFramebufferPrivate *priv, guint16 pixel)
+{
+	if (G_BYTE_ORDER != priv->localFormat.byte_order)
+		return  (((pixel >> 8) & 0xFF) << 0) |
+			(((pixel >> 0) & 0xFF) << 8);
+	else
+		return pixel;
+}
+
+
+/* VNC server RFB  format ->  local host native format */
+static guint16 vnc_base_framebuffer_swap_rfb_16(VncBaseFramebufferPrivate *priv, guint16 pixel)
+{
+	if (priv->remoteFormat.byte_order != G_BYTE_ORDER)
+		return  (((pixel >> 8) & 0xFF) << 0) |
+			(((pixel >> 0) & 0xFF) << 8);
+	else
+		return pixel;
+}
+
+
+/* local host native format -> X server image format */
+static guint32 vnc_base_framebuffer_swap_img_32(VncBaseFramebufferPrivate *priv, guint32 pixel)
+{
+	if (G_BYTE_ORDER != priv->localFormat.byte_order)
+		return  (((pixel >> 24) & 0xFF) <<  0) |
+			(((pixel >> 16) & 0xFF) <<  8) |
+			(((pixel >>  8) & 0xFF) << 16) |
+			(((pixel >>  0) & 0xFF) << 24);
+	else
+		return pixel;
+}
+
+
+/* VNC server RFB  format ->  local host native format */
+static guint32 vnc_base_framebuffer_swap_rfb_32(VncBaseFramebufferPrivate *priv, guint32 pixel)
+{
+	if (priv->remoteFormat.byte_order != G_BYTE_ORDER)
+		return  (((pixel >> 24) & 0xFF) <<  0) |
+			(((pixel >> 16) & 0xFF) <<  8) |
+			(((pixel >>  8) & 0xFF) << 16) |
+			(((pixel >>  0) & 0xFF) << 24);
+	else
+		return pixel;
+}
+
+#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 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 32
+#define DST 8
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 32
+#define DST 16
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 32
+#define DST 32
+#include "vncbaseframebufferblt.h"
+#undef SRC
+#undef DST
+
+static vnc_base_framebuffer_set_pixel_at_func *vnc_base_framebuffer_set_pixel_at_table[3][3] = {
+        { (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_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_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 },
+};
+
+static vnc_base_framebuffer_fill_func *vnc_base_framebuffer_fill_table[3][3] = {
+        { (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_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_32x8,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x16,
+          (vnc_base_framebuffer_fill_func *)vnc_base_framebuffer_fill_32x32 },
+};
+
+static vnc_base_framebuffer_fill_func *vnc_base_framebuffer_fill_fast_table[3] = {
+	(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,
+};
+
+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_rgb24_blt_func *vnc_base_framebuffer_rgb24_blt_table[3] = {
+        (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,
+};
+
+
+/* a fast blit for the perfect match scenario */
+static void vnc_base_framebuffer_blt_fast(VncBaseFramebufferPrivate *priv,
+					  guint8 *src, int rowstride,
+					  guint16 x, guint16 y,
+					  guint16 width, guint16 height)
+{
+        guint8 *dst = VNC_BASE_FRAMEBUFFER_AT(priv, x, y);
+        guint16 i;
+        for (i = 0; i < height; i++) {
+                memcpy(dst, src, width * (priv->localFormat.bits_per_pixel / 8));
+                dst += priv->rowstride;
+                src += rowstride;
+        }
+}
+
+
+static void vnc_base_framebuffer_reinit_render_funcs(VncBaseFramebuffer *fb)
+{
+	VncBaseFramebufferPrivate *priv = fb->priv;
+	int i, j, n;
+	int depth;
+
+	if (!priv->reinitRenderFuncs)
+		return;
+
+	if (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 &&
+	    priv->localFormat.red_shift == priv->remoteFormat.red_shift &&
+	    priv->localFormat.green_shift == priv->remoteFormat.green_shift &&
+	    priv->localFormat.blue_shift == priv->remoteFormat.blue_shift &&
+	    priv->localFormat.byte_order == G_BYTE_ORDER &&
+	    priv->remoteFormat.byte_order == G_BYTE_ORDER)
+		priv->perfect_match = TRUE;
+	else
+		priv->perfect_match = FALSE;
+
+	depth = priv->remoteFormat.depth;
+	if (depth == 32)
+		depth = 24;
+
+	priv->rm = priv->localFormat.red_max & priv->remoteFormat.red_max;
+	priv->gm = priv->localFormat.green_max & priv->remoteFormat.green_max;
+	priv->bm = priv->localFormat.blue_max & priv->remoteFormat.blue_max;
+	GVNC_DEBUG("Mask local: %3d %3d %3d\n"
+		   "    remote: %3d %3d %3d\n"
+		   "    merged: %3d %3d %3d",
+		   priv->localFormat.red_max, priv->localFormat.green_max, priv->localFormat.blue_max,
+		   priv->remoteFormat.red_max, priv->remoteFormat.green_max, priv->remoteFormat.blue_max,
+		   priv->rm, priv->gm, priv->bm);
+
+	/* Setup shifts assuming matched bpp (but not necessarily match rgb order)*/
+	priv->rrs = priv->remoteFormat.red_shift;
+	priv->grs = priv->remoteFormat.green_shift;
+	priv->brs = priv->remoteFormat.blue_shift;
+
+	priv->rls = priv->localFormat.red_shift;
+	priv->gls = priv->localFormat.green_shift;
+	priv->bls = priv->localFormat.blue_shift;
+
+	/* This adjusts for remote having more bpp than local */
+	for (n = priv->remoteFormat.red_max; n > priv->localFormat.red_max ; n>>= 1)
+		priv->rrs++;
+	for (n = priv->remoteFormat.green_max; n > priv->localFormat.green_max ; n>>= 1)
+		priv->grs++;
+	for (n = priv->remoteFormat.blue_max; n > priv->localFormat.blue_max ; n>>= 1)
+		priv->brs++;
+
+	/* This adjusts for remote having less bpp than remote */
+	for (n = priv->localFormat.red_max ; n > priv->remoteFormat.red_max ; n>>= 1)
+		priv->rls++;
+	for (n = priv->localFormat.green_max ; n > priv->remoteFormat.green_max ; n>>= 1)
+		priv->gls++;
+	for (n = priv->localFormat.blue_max ; n > priv->remoteFormat.blue_max ; n>>= 1)
+		priv->bls++;
+	GVNC_DEBUG("Pixel shifts\n   right: %3d %3d %3d\n    left: %3d %3d %3d",
+		   priv->rrs, priv->grs, priv->brs,
+		   priv->rls, priv->gls, priv->bls);
+
+	i = priv->remoteFormat.bits_per_pixel / 8;
+	j = priv->localFormat.bits_per_pixel / 8;
+
+	if (i == 4) i = 3;
+	if (j == 4) j = 3;
+
+	priv->set_pixel_at = vnc_base_framebuffer_set_pixel_at_table[i - 1][j - 1];
+
+	if (priv->perfect_match)
+		priv->fill = vnc_base_framebuffer_fill_fast_table[i - 1];
+	else
+		priv->fill = vnc_base_framebuffer_fill_table[i - 1][j - 1];
+
+	if (priv->perfect_match)
+		priv->blt = vnc_base_framebuffer_blt_fast;
+	else
+		priv->blt = vnc_base_framebuffer_blt_table[i - 1][j - 1];
+
+	priv->rgb24_blt = vnc_base_framebuffer_rgb24_blt_table[i - 1];
+
+	priv->reinitRenderFuncs = FALSE;
+}
+
+
+static void vnc_base_framebuffer_set_pixel_at(VncFramebuffer *iface,
+					      guint8 *src,
+					      guint16 x, guint16 y)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	vnc_base_framebuffer_reinit_render_funcs(fb);
+
+	priv->set_pixel_at(priv, src, x, y);
+}
+
+
+static void vnc_base_framebuffer_fill(VncFramebuffer *iface,
+				      guint8 *src,
+				      guint16 x, guint16 y,
+				      guint16 width, guint16 height)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	vnc_base_framebuffer_reinit_render_funcs(fb);
+
+	priv->fill(priv, src, x, y, width, height);
+}
+
+
+static void vnc_base_framebuffer_copyrect(VncFramebuffer *iface,
+					  guint16 srcx, guint16 srcy,
+					  guint16 dstx, guint16 dsty,
+					  guint16 width, guint16 height)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+	guint8 *dst, *src;
+	int rowstride = priv->rowstride;
+	int i;
+
+	vnc_base_framebuffer_reinit_render_funcs(fb);
+
+	if (srcy < dsty) {
+		rowstride = -rowstride;
+		srcy += (height - 1);
+		dsty += (height - 1);
+	}
+
+	dst = VNC_BASE_FRAMEBUFFER_AT(priv, dstx, dsty);
+	src = VNC_BASE_FRAMEBUFFER_AT(priv, srcx, srcy);
+	for (i = 0; i < height; i++) {
+		memmove(dst, src, width * (priv->localFormat.bits_per_pixel  / 8));
+		dst += rowstride;
+		src += rowstride;
+	}
+}
+
+
+static void vnc_base_framebuffer_blt(VncFramebuffer *iface,
+				     guint8 *src,
+				     int rowstride,
+				     guint16 x, guint16 y,
+				     guint16 width, guint16 height)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	vnc_base_framebuffer_reinit_render_funcs(fb);
+
+	priv->blt(priv, src, rowstride, x, y, width, height);
+}
+
+
+static void vnc_base_framebuffer_rgb24_blt(VncFramebuffer *iface,
+					   guint8 *src,
+					   int rowstride,
+					   guint16 x, guint16 y,
+					   guint16 width, guint16 height)
+{
+	VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+	VncBaseFramebufferPrivate *priv = fb->priv;
+
+	vnc_base_framebuffer_reinit_render_funcs(fb);
+
+	priv->rgb24_blt(priv, src, rowstride, x, y, width, height);
+}
+
+
+static void vnc_base_framebuffer_interface_init(gpointer g_iface,
+						gpointer iface_data G_GNUC_UNUSED)
+{
+    VncFramebufferInterface *iface = g_iface;
+
+    iface->get_width = vnc_base_framebuffer_get_width;
+    iface->get_height = vnc_base_framebuffer_get_height;
+    iface->get_rowstride = vnc_base_framebuffer_get_rowstride;
+    iface->get_buffer = vnc_base_framebuffer_get_buffer;
+    iface->get_local_format = vnc_base_framebuffer_get_local_format;
+    iface->get_remote_format = vnc_base_framebuffer_get_remote_format;
+
+    iface->set_pixel_at = vnc_base_framebuffer_set_pixel_at;
+    iface->fill = vnc_base_framebuffer_fill;
+    iface->copyrect = vnc_base_framebuffer_copyrect;
+    iface->blt = vnc_base_framebuffer_blt;
+    iface->rgb24_blt = vnc_base_framebuffer_rgb24_blt;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/src/vncbaseframebuffer.h b/src/vncbaseframebuffer.h
new file mode 100644
index 0000000..529a347
--- /dev/null
+++ b/src/vncbaseframebuffer.h
@@ -0,0 +1,77 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony codemonkey ws>
+ *
+ * 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_BASE_FRAMEBUFFER_H
+#define VNC_BASE_FRAMEBUFFER_H
+
+#include <glib-object.h>
+
+#include <vncframebuffer.h>
+
+G_BEGIN_DECLS
+
+#define VNC_TYPE_BASE_FRAMEBUFFER            (vnc_base_framebuffer_get_type ())
+#define VNC_BASE_FRAMEBUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), VNC_TYPE_BASE_FRAMEBUFFER, VncBaseFramebuffer))
+#define VNC_BASE_FRAMEBUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), VNC_TYPE_BASE_FRAMEBUFFER, VncBaseFramebufferClass))
+#define VNC_IS_BASE_FRAMEBUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VNC_TYPE_BASE_FRAMEBUFFER))
+#define VNC_IS_BASE_FRAMEBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VNC_TYPE_BASE_FRAMEBUFFER))
+#define VNC_BASE_FRAMEBUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), VNC_TYPE_BASE_FRAMEBUFFER, VncBAseFramebufferClass))
+
+
+typedef struct _VncBaseFramebuffer VncBaseFramebuffer;
+typedef struct _VncBaseFramebufferPrivate VncBaseFramebufferPrivate;
+typedef struct _VncBaseFramebufferClass VncBaseFramebufferClass;
+
+struct _VncBaseFramebuffer
+{
+	GObject parent;
+
+	VncBaseFramebufferPrivate *priv;
+};
+
+struct _VncBaseFramebufferClass
+{
+	GObjectClass parent_class;
+
+};
+
+
+GType vnc_base_framebuffer_get_type(void) G_GNUC_CONST;
+
+VncBaseFramebuffer *vnc_base_framebuffer_new(guint8 *buffer,
+					     guint16 width,
+					     guint16 height,
+					     int rowstride,
+					     const VncPixelFormat *localFormat,
+					     const VncPixelFormat *remoteFormat);
+
+
+
+G_END_DECLS
+
+#endif /* VNC_BASE_FRAMEBUFFER_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/src/vncbaseframebufferblt.h b/src/vncbaseframebufferblt.h
new file mode 100644
index 0000000..101410f
--- /dev/null
+++ b/src/vncbaseframebufferblt.h
@@ -0,0 +1,196 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony codemonkey ws>
+ *
+ * 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
+ */
+
+/* Ordering of the SPLICE calls here is important to avoid
+ * a Solaris compiler/cpp  whitespace bug
+ */
+
+/* Everything here must be #undef'd at the end of the file */
+
+#define SPLICE_I(a, b) a ## b
+#define SPLICE(a, b) SPLICE_I(a, b)
+#define SUFFIX() SPLICE(SRC,SPLICE(x,DST))
+
+#define src_pixel_t SPLICE(guint, SRC)
+#define ssrc_pixel_t SPLICE(gint, SRC)
+#define dst_pixel_t SPLICE(guint, DST)
+
+#define SET_PIXEL SPLICE(vnc_base_framebuffer_set_pixel_, SUFFIX())
+#define SET_PIXEL_AT SPLICE(vnc_base_framebuffer_set_pixel_at_, SUFFIX())
+#define FAST_FILL SPLICE(vnc_base_framebuffer_fill_fast_, SUFFIX())
+#define FILL SPLICE(vnc_base_framebuffer_fill_, SUFFIX())
+#define BLT SPLICE(vnc_base_framebuffer_blt_, SUFFIX())
+#define RGB24_BLT SPLICE(vnc_base_framebuffer_rgb24_blt_, SUFFIX())
+
+#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)))
+
+static void SET_PIXEL(VncBaseFramebufferPrivate *priv,
+		      dst_pixel_t *dp, src_pixel_t sp)
+{
+	*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);
+}
+
+static void SET_PIXEL_AT(VncBaseFramebufferPrivate *priv,
+			 src_pixel_t *sp,
+			 guint16 x, guint16 y)
+{
+	dst_pixel_t *dp = (dst_pixel_t *)VNC_BASE_FRAMEBUFFER_AT(priv, x, y);
+
+	SET_PIXEL(priv, dp, SWAP_RFB(priv, *sp));
+}
+
+
+#if SRC == DST
+static void FAST_FILL(VncBaseFramebufferPrivate *priv,
+		      src_pixel_t *sp,
+		      guint16 x, guint16 y,
+		      guint16 width, guint16 height)
+{
+	guint8 *dst = VNC_BASE_FRAMEBUFFER_AT(priv, x, y);
+	int i;
+
+	for (i = 0; i < 1; i++) {
+		int j;
+		dst_pixel_t *dp = (dst_pixel_t *)dst;
+
+		for (j = 0; j < width; j++) {
+			*dp = *sp;
+			dp++;
+		}
+		dst += priv->rowstride;
+	}
+	for (i = 1; i < height; i++) {
+		memcpy(dst, dst - priv->rowstride, width * sizeof(*sp));
+		dst += priv->rowstride;
+	}
+}
+#endif
+
+
+static void FILL(VncBaseFramebufferPrivate *priv,
+		 src_pixel_t *sp,
+		 guint16 x, guint16 y,
+		 guint16 width, guint16 height)
+{
+	guint8 *dst = VNC_BASE_FRAMEBUFFER_AT(priv, x, y);
+	int i;
+
+	for (i = 0; i < 1; i++) {
+		dst_pixel_t *dp = (dst_pixel_t *)dst;
+		int j;
+
+		for (j = 0; j < width; j++) {
+			SET_PIXEL(priv, dp, SWAP_RFB(priv, *sp));
+			dp++;
+		}
+		dst += priv->rowstride;
+	}
+	for (i = 1; i < height; i++) {
+		memcpy(dst, dst - priv->rowstride, width * sizeof(dst_pixel_t));
+		dst += priv->rowstride;
+	}
+}
+
+static void BLT(VncBaseFramebufferPrivate *priv,
+		guint8 *src, int rowstride,
+		guint16 x, guint16 y,
+		guint16 width, guint16 height)
+{
+	guint8 *dst = VNC_BASE_FRAMEBUFFER_AT(priv, x, y);
+	int i;
+
+	for (i = 0; i < height; i++) {
+		dst_pixel_t *dp = (dst_pixel_t *)dst;
+		src_pixel_t *sp = (src_pixel_t *)src;
+		int j;
+
+		for (j = 0; j < width; j++) {
+			SET_PIXEL(priv, dp, SWAP_RFB(priv, *sp));
+			dp++;
+			sp++;
+		}
+		dst += priv->rowstride;
+		src += rowstride;
+	}
+}
+
+
+#if SRC == 32
+static void RGB24_BLT(VncBaseFramebufferPrivate *priv,
+		      guint8 *src, int rowstride,
+		      guint16 x, gint16 y,
+		      guint16 width, guint16 height)
+{
+	guint8 *dst = VNC_BASE_FRAMEBUFFER_AT(priv, x, y);
+	int i, j;
+
+	for (j = 0; j < height; j++) {
+		dst_pixel_t *dp = (dst_pixel_t *)dst;
+		guint8 *sp = src;
+
+		for (i = 0; i < width; i++) {
+			/*
+			 * We use priv->remoteFormat.XXX_shift instead of usual priv->Xls
+			 * because the source pixel component is a full 8 bits in
+			 * size, and so doesn't need the adjusted shift
+			 */
+			*dp = (((sp[0] * priv->remoteFormat.red_max) / 255) << priv->remoteFormat.red_shift) |
+				(((sp[1] * priv->remoteFormat.green_max) / 255) << priv->remoteFormat.green_shift) |
+				(((sp[2] * priv->remoteFormat.blue_max) / 255) << priv->remoteFormat.blue_shift);
+			dp++;
+			sp += 3;
+		}
+
+		dst += priv->rowstride;
+		src += rowstride;
+	}
+}
+#endif
+
+#undef COMPONENT
+#undef SWAP_IMG
+#undef SWAP_RGB
+
+#undef RGB24_BLT
+#undef BLT
+#undef FILL
+#undef FAST_FILL
+#undef SET_PIXEL_AT
+#undef SET_PIXEL
+
+#undef dst_pixel_t
+#undef ssrc_pixel_t
+#undef src_pixel_t
+
+#undef SUFFIX
+#undef SPLICE
+#undef SPLICE_I
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/src/vncframebuffer.c b/src/vncframebuffer.c
new file mode 100644
index 0000000..aa7c6cb
--- /dev/null
+++ b/src/vncframebuffer.c
@@ -0,0 +1,127 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony codemonkey ws>
+ *
+ * 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 "vncframebuffer.h"
+
+
+guint16 vnc_framebuffer_get_width(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->get_width(fb);
+}
+
+guint16 vnc_framebuffer_get_height(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->get_height(fb);
+}
+
+int vnc_framebuffer_get_rowstride(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->get_rowstride(fb);
+}
+
+guint8 *vnc_framebuffer_get_buffer(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->get_buffer(fb);
+}
+
+const VncPixelFormat *vnc_framebuffer_get_local_format(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->get_local_format(fb);
+}
+
+const VncPixelFormat *vnc_framebuffer_get_remote_format(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->get_remote_format(fb);
+}
+
+gboolean vnc_framebuffer_perfect_format_match(VncFramebuffer *fb)
+{
+	return VNC_FRAMEBUFFER_GET_INTERFACE(fb)->perfect_format_match(fb);
+}
+
+void vnc_framebuffer_set_pixel_at(VncFramebuffer *fb,
+				  guint8 *src,
+				  guint16 x, guint16 y)
+{
+	VNC_FRAMEBUFFER_GET_INTERFACE(fb)->set_pixel_at(fb, src, x, y);
+}
+
+void vnc_framebuffer_fill(VncFramebuffer *fb,
+			  guint8 *src,
+			  guint16 x, guint16 y,
+			  guint16 width, guint16 height)
+{
+	VNC_FRAMEBUFFER_GET_INTERFACE(fb)->fill(fb, src, x, y, width, height);
+}
+
+void vnc_framebuffer_copyrect(VncFramebuffer *fb,
+			      guint16 srcx, guint16 srcy,
+			      guint16 dstx, guint16 dsty,
+			      guint16 width, guint16 height)
+{
+	VNC_FRAMEBUFFER_GET_INTERFACE(fb)->copyrect(fb, srcx, srcy, dstx, dsty, width, height);
+}
+
+void vnc_framebuffer_blt(VncFramebuffer *fb,
+			 guint8 *src,
+			 int rowstride,
+			 guint16 x, guint16 y,
+			 guint16 width, guint16 height)
+{
+	VNC_FRAMEBUFFER_GET_INTERFACE(fb)->blt(fb, src, rowstride, x, y, width, height);
+}
+
+void vnc_framebuffer_rgb24_blt(VncFramebuffer *fb,
+			       guint8 *src,
+			       int rowstride,
+			       guint16 x, guint16 y,
+			       guint16 width, guint16 height)
+{
+	VNC_FRAMEBUFFER_GET_INTERFACE(fb)->rgb24_blt(fb, src, rowstride, x, y, width, height);
+}
+
+
+GType
+vnc_framebuffer_get_type (void)
+{
+	static GType framebuffer_type = 0;
+
+	if (!framebuffer_type) {
+		framebuffer_type =
+			g_type_register_static_simple (G_TYPE_INTERFACE, "VncFramebuffer",
+						       sizeof (VncFramebufferInterface),
+						       NULL, 0, NULL, 0);
+
+		g_type_interface_add_prerequisite (framebuffer_type, G_TYPE_OBJECT);
+	}
+
+	return framebuffer_type;
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/src/vncframebuffer.h b/src/vncframebuffer.h
new file mode 100644
index 0000000..12bf5a9
--- /dev/null
+++ b/src/vncframebuffer.h
@@ -0,0 +1,125 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006  Anthony Liguori <anthony codemonkey ws>
+ *
+ * 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_FRAMEBUFFER_H
+#define VNC_FRAMEBUFFER_H
+
+#include <glib-object.h>
+
+#include <vncpixelformat.h>
+
+G_BEGIN_DECLS
+
+#define VNC_TYPE_FRAMEBUFFER            (vnc_framebuffer_get_type ())
+#define VNC_FRAMEBUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), VNC_TYPE_FRAMEBUFFER, VncFramebuffer))
+#define VNC_IS_FRAMEBUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VNC_TYPE_FRAMEBUFFER))
+#define VNC_FRAMEBUFFER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), VNC_TYPE_FRAMEBUFFER, VncFramebufferInterface))
+
+
+typedef struct _VncFramebuffer VncFramebuffer; /* Dummy object */
+typedef struct _VncFramebufferInterface VncFramebufferInterface;
+
+struct _VncFramebufferInterface {
+	GTypeInterface parent;
+
+	guint16 (*get_width)(VncFramebuffer *fb);
+	guint16 (*get_height)(VncFramebuffer *fb);
+	int (*get_rowstride)(VncFramebuffer *fb);
+	guint8 *(*get_buffer)(VncFramebuffer *fb);
+	const VncPixelFormat *(*get_local_format)(VncFramebuffer *fb);
+	const VncPixelFormat *(*get_remote_format)(VncFramebuffer *fb);
+	gboolean (*perfect_format_match)(VncFramebuffer *fb);
+
+	void (*set_pixel_at)(VncFramebuffer *fb,
+			     guint8 *src, /* One remote pixel */
+			     guint16 x, guint16 y);
+	void (*fill)(VncFramebuffer *fb,
+		     guint8 *src, /* One remote pixel */
+		     guint16 x, guint16 y,
+		     guint16 width, guint16 height);
+	void (*copyrect)(VncFramebuffer *fb,
+			 guint16 srcx, guint16 srcy,
+			 guint16 dstx, guint16 dsty,
+			 guint16 width, guint16 height);
+	void (*blt)(VncFramebuffer *fb,
+		    guint8 *src, /* Remote pixel array */
+		    int rowstride,
+		    guint16 x, guint16 y,
+		    guint16 width, guint16 height);
+	void (*rgb24_blt)(VncFramebuffer *fb,
+			  guint8 *src, /* rgb24 pixel array */
+			  int rowstride,
+			  guint16 x, guint16 y,
+			  guint16 width, guint16 height);
+
+};
+
+GType vnc_framebuffer_get_type(void) G_GNUC_CONST;
+
+
+guint16 vnc_framebuffer_get_width(VncFramebuffer *fb);
+guint16 vnc_framebuffer_get_height(VncFramebuffer *fb);
+int vnc_framebuffer_get_rowstride(VncFramebuffer *fb);
+
+guint8 *vnc_framebuffer_get_buffer(VncFramebuffer *fb);
+
+const VncPixelFormat *vnc_framebuffer_get_local_format(VncFramebuffer *fb);
+const VncPixelFormat *vnc_framebuffer_get_remote_format(VncFramebuffer *fb);
+gboolean vnc_framebuffer_perfect_format_match(VncFramebuffer *fb);
+
+void vnc_framebuffer_set_pixel_at(VncFramebuffer *fb,
+				  guint8 *src, /* One remote pixel */
+				  guint16 x, guint16 y);
+
+void vnc_framebuffer_fill(VncFramebuffer *fb,
+			  guint8 *src, /* One remote pixel */
+			  guint16 x, guint16 y,
+			  guint16 width, guint16 height);
+
+void vnc_framebuffer_copyrect(VncFramebuffer *fb,
+			      guint16 srcx, guint16 srcy,
+			      guint16 dstx, guint16 dsty,
+			      guint16 width, guint16 height);
+
+void vnc_framebuffer_blt(VncFramebuffer *fb,
+			 guint8 *src, /* Remote pixel array */
+			 int rowstride,
+			 guint16 x, guint16 y,
+			 guint16 width, guint16 height);
+
+void vnc_framebuffer_rgb24_blt(VncFramebuffer *fb,
+			       guint8 *src, /* rgb24 pixel array */
+			       int rowstride,
+			       guint16 x, guint16 y,
+			       guint16 width, guint16 height);
+
+
+
+G_END_DECLS
+
+#endif /* VNC_FRAMEBUFFER_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
-- 
1.6.5.2



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