[PATCH 08/25] Convert VncConnection over to use VncFramebuffer object
- From: "Daniel P. Berrange" <berrange redhat com>
- To: gtk-vnc-list gnome org
- Cc: "Daniel P. Berrange" <berrange redhat com>
- Subject: [PATCH 08/25] Convert VncConnection over to use VncFramebuffer object
- Date: Sat, 21 Nov 2009 13:27:57 +0000
Remove the vnc_framebuffer struct, and make VncConnection use the
new VncFramebuffer object.
VncDisplay is changed to use the VncImageFramebuffer object
type as its implementation of VncFramebuffer
---
src/blt.h | 334 ------------------------------------
src/blt1.h | 31 ----
src/vncbaseframebuffer.c | 10 +
src/vncconnection.c | 423 ++++++++++++++++++----------------------------
src/vncconnection.h | 29 +---
src/vncconnectionblt.h | 163 ++++++++++++++++++
src/vncdisplay.c | 195 +++++++++++-----------
7 files changed, 440 insertions(+), 745 deletions(-)
delete mode 100644 src/blt.h
delete mode 100644 src/blt1.h
create mode 100644 src/vncconnectionblt.h
diff --git a/src/blt.h b/src/blt.h
deleted file mode 100644
index 66ce688..0000000
--- a/src/blt.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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
- */
-#define src_pixel_t SPLICE(SPLICE(uint, SRC), _t)
-#define ssrc_pixel_t SPLICE(SPLICE(int, SRC), _t)
-#define dst_pixel_t SPLICE(SPLICE(uint, DST), _t)
-#define SUFFIX() SPLICE(SRC,SPLICE(x,DST))
-#define SET_PIXEL SPLICE(vnc_connection_set_pixel_, SUFFIX())
-#define SET_PIXEL_AT SPLICE(vnc_connection_set_pixel_at_, SUFFIX())
-#define BLIT SPLICE(vnc_connection_blt_, SUFFIX())
-#define FILL SPLICE(vnc_connection_fill_, SUFFIX())
-#define FAST_FILL SPLICE(vnc_connection_fill_fast_, SUFFIX())
-#define HEXTILE SPLICE(vnc_connection_hextile_, SUFFIX())
-#define RRE SPLICE(vnc_connection_rre_, SUFFIX())
-#define RICH_CURSOR_BLIT SPLICE(vnc_connection_rich_cursor_blt_, SUFFIX())
-#define RGB24_BLIT SPLICE(vnc_connection_rgb24_blt_, SUFFIX())
-#define TIGHT_COMPUTE_PREDICTED SPLICE(vnc_connection_tight_compute_predicted_, SUFFIX())
-#define TIGHT_SUM_PIXEL SPLICE(vnc_connection_tight_sum_pixel_, SUFFIX())
-#define SWAP_RFB(conn, pixel) SPLICE(vnc_connection_swap_rfb_, SRC)(conn, pixel)
-#define SWAP_IMG(conn, pixel) SPLICE(vnc_connection_swap_img_, DST)(conn, pixel)
-#define COMPONENT(color, pixel) ((SWAP_RFB(conn, pixel) >> conn->fmt.SPLICE(color, _shift) & conn->fmt.SPLICE(color, _max)))
-
-static void FAST_FILL(VncConnection *conn, src_pixel_t *sp,
- int x, int y, int width, int height)
-{
- guint8 *dst = vnc_connection_get_local(conn, 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 += conn->local.linesize;
- }
- for (i = 1; i < height; i++) {
- memcpy(dst, dst - conn->local.linesize, width * sizeof(*sp));
- dst += conn->local.linesize;
- }
-}
-
-static void SET_PIXEL(VncConnection *conn, dst_pixel_t *dp, src_pixel_t sp)
-{
- *dp = SWAP_IMG(conn, ((sp >> conn->rrs) & conn->rm) << conn->rls
- | ((sp >> conn->grs) & conn->gm) << conn->gls
- | ((sp >> conn->brs) & conn->bm) << conn->bls);
-}
-
-static void SET_PIXEL_AT(VncConnection *conn, int x, int y, src_pixel_t *sp)
-{
- dst_pixel_t *dp = (dst_pixel_t *)vnc_connection_get_local(conn, x, y);
-
- SET_PIXEL(conn, dp, SWAP_RFB(conn, *sp));
-}
-
-static void FILL(VncConnection *conn, src_pixel_t *sp,
- int x, int y, int width, int height)
-{
- guint8 *dst = vnc_connection_get_local(conn, 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(conn, dp, SWAP_RFB(conn, *sp));
- dp++;
- }
- dst += conn->local.linesize;
- }
- for (i = 1; i < height; i++) {
- memcpy(dst, dst - conn->local.linesize, width * sizeof(dst_pixel_t));
- dst += conn->local.linesize;
- }
-}
-
-static void BLIT(VncConnection *conn, guint8 *src, int pitch, int x, int y, int w, int h)
-{
- guint8 *dst = vnc_connection_get_local(conn, x, y);
- int i;
-
- for (i = 0; i < h; i++) {
- dst_pixel_t *dp = (dst_pixel_t *)dst;
- src_pixel_t *sp = (src_pixel_t *)src;
- int j;
-
- for (j = 0; j < w; j++) {
- SET_PIXEL(conn, dp, SWAP_RFB(conn, *sp));
- dp++;
- sp++;
- }
- dst += conn->local.linesize;
- src += pitch;
- }
-}
-
-static void HEXTILE(VncConnection *conn, guint8 flags, guint16 x, guint16 y,
- guint16 width, guint16 height, src_pixel_t *fg, src_pixel_t *bg)
-{
- int stride = width * sizeof(src_pixel_t);
- int i;
-
- if (flags & 0x01) {
- /* Raw tile */
- if (conn->perfect_match) {
- guint8 *dst = vnc_connection_get_local(conn, x, y);
-
- for (i = 0; i < height; i++) {
- vnc_connection_read(conn, dst, stride);
- dst += conn->local.linesize;
- }
- } else {
- guint8 data[16 * 16 * sizeof(src_pixel_t)];
-
- vnc_connection_read(conn, data, stride * height);
- BLIT(conn, data, stride, x, y, width, height);
- }
- } else {
- /* Background Specified */
- if (flags & 0x02)
- vnc_connection_read(conn, bg, sizeof(*bg));
-
- /* Foreground Specified */
- if (flags & 0x04)
- vnc_connection_read(conn, fg, sizeof(*fg));
-
- if (conn->perfect_match)
- FAST_FILL(conn, bg, x, y, width, height);
- else
- FILL(conn, bg, x, y, width, height);
-
-
- /* AnySubrects */
- if (flags & 0x08) {
- guint8 n_rects = vnc_connection_read_u8(conn);
-
- for (i = 0; i < n_rects; i++) {
- guint8 xy, wh;
-
- /* SubrectsColored */
- if (flags & 0x10)
- vnc_connection_read(conn, fg, sizeof(*fg));
-
- xy = vnc_connection_read_u8(conn);
- wh = vnc_connection_read_u8(conn);
-
-
- if (conn->perfect_match)
- FAST_FILL(conn, fg,
- x + nibhi(xy), y + niblo(xy),
- nibhi(wh) + 1, niblo(wh) + 1);
- else
- FILL(conn, fg,
- x + nibhi(xy), y + niblo(xy),
- nibhi(wh) + 1, niblo(wh) + 1);
- }
- }
- }
-}
-
-/* We need to convert to a GdkPixbuf which is always 32-bit */
-#if DST == 32
-static void RICH_CURSOR_BLIT(VncConnection *conn, guint8 *pixbuf,
- guint8 *image, guint8 *mask, int pitch,
- guint16 width, guint16 height)
-{
- int x1, y1;
- guint32 *dst = (guint32 *)pixbuf;
- guint8 *src = image;
- guint8 *alpha = mask;
- int as, rs, gs, bs, n;
-
- /*
- * GdkPixbuf is always 32-bit RGB, so we can't use the precomputed
- * left / right shift data from conn->{r,g,b}{r,l}s. The latter
- * is set for the local display depth, which may be different
- * to GdkPixbuf's fixed 32-bit RGBA
- *
- * This function isn't called often, so just re-compute them now
- */
-
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- as = 0;
- rs = 8;
- gs = 16;
- bs = 24;
-#else
- as = 24;
- rs = 16;
- gs = 8;
- bs = 0;
-#endif
-
- /* Then this adjusts for remote having less bpp than 32 */
- for (n = 255 ; n > conn->fmt.red_max ; n>>= 1)
- rs++;
- for (n = 255 ; n > conn->fmt.green_max ; n>>= 1)
- gs++;
- for (n = 255 ; n > conn->fmt.blue_max ; n>>= 1)
- bs++;
-
- for (y1 = 0; y1 < height; y1++) {
- src_pixel_t *sp = (src_pixel_t *)src;
- guint8 *mp = alpha;
- for (x1 = 0; x1 < width; x1++) {
- *dst = (COMPONENT(red, *sp) << rs)
- | (COMPONENT(green, *sp) << gs)
- | (COMPONENT(blue, *sp) << bs);
-
- if ((mp[x1 / 8] >> (7 - (x1 % 8))) & 1)
- *dst |= (0xFF << as);
-
- dst++;
- sp++;
- }
- src += pitch;
- alpha += ((width + 7) / 8);
- }
-}
-#endif
-
-#if SRC == 32
-static void RGB24_BLIT(VncConnection *conn, int x, int y, int width, int height,
- guint8 *data, int pitch)
-{
- guint8 *dst = vnc_connection_get_local(conn, x, y);
- int i, j;
-
- for (j = 0; j < height; j++) {
- dst_pixel_t *dp = (dst_pixel_t *)dst;
- guint8 *sp = data;
-
- for (i = 0; i < width; i++) {
- /*
- * We use conn->fmt.XXX_shift instead of usual conn->Xls
- * because the source pixel component is a full 8 bits in
- * size, and so doesn't need the adjusted shift
- */
- *dp = (((sp[0] * conn->fmt.red_max) / 255) << conn->fmt.red_shift) |
- (((sp[1] * conn->fmt.green_max) / 255) << conn->fmt.green_shift) |
- (((sp[2] * conn->fmt.blue_max) / 255) << conn->fmt.blue_shift);
- dp++;
- sp += 3;
- }
-
- dst += conn->local.linesize;
- data += pitch;
- }
-}
-#endif
-
-#if SRC == DST
-
-static void TIGHT_COMPUTE_PREDICTED(VncConnection *conn, src_pixel_t *ppixel,
- src_pixel_t *lp, src_pixel_t *cp,
- src_pixel_t *llp)
-{
- ssrc_pixel_t red, green, blue;
-
- red = COMPONENT(red, *lp) + COMPONENT(red, *cp) - COMPONENT(red, *llp);
- red = MAX(red, 0);
- red = MIN(red, conn->fmt.red_max);
-
- green = COMPONENT(green, *lp) + COMPONENT(green, *cp) - COMPONENT(green, *llp);
- green = MAX(green, 0);
- green = MIN(green, conn->fmt.green_max);
-
- blue = COMPONENT(blue, *lp) + COMPONENT(blue, *cp) - COMPONENT(blue, *llp);
- blue = MAX(blue, 0);
- blue = MIN(blue, conn->fmt.blue_max);
-
- *ppixel = SWAP_RFB(conn,
- (red << conn->fmt.red_shift) |
- (green << conn->fmt.green_shift) |
- (blue << conn->fmt.blue_shift));
-}
-
-static void TIGHT_SUM_PIXEL(VncConnection *conn,
- src_pixel_t *lhs, src_pixel_t *rhs)
-{
- src_pixel_t red, green, blue;
-
- red = COMPONENT(red, *lhs) + COMPONENT(red, *rhs);
- green = COMPONENT(green, *lhs) + COMPONENT(green, *rhs);
- blue = COMPONENT(blue, *lhs) + COMPONENT(blue, *rhs);
-
- *lhs = SWAP_RFB(conn,
- ((red & conn->fmt.red_max) << conn->fmt.red_shift) |
- ((green & conn->fmt.green_max) << conn->fmt.green_shift) |
- ((blue & conn->fmt.blue_max) << conn->fmt.blue_shift));
-}
-
-#endif
-
-#undef COMPONENT
-#undef HEXTILE
-#undef FILL
-#undef FAST_FILL
-#undef BLIT
-#undef dst_pixel_t
-#undef src_pixel_t
-
-
-/*
- * Local variables:
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
diff --git a/src/blt1.h b/src/blt1.h
deleted file mode 100644
index 9bdda04..0000000
--- a/src/blt1.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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
- */
-
-#define DST 8
-#include "blt.h"
-#undef DST
-
-#define DST 16
-#include "blt.h"
-#undef DST
-
-#define DST 32
-#include "blt.h"
-#undef DST
diff --git a/src/vncbaseframebuffer.c b/src/vncbaseframebuffer.c
index f7dab3b..1651870 100644
--- a/src/vncbaseframebuffer.c
+++ b/src/vncbaseframebuffer.c
@@ -351,6 +351,15 @@ static const VncPixelFormat *vnc_base_framebuffer_get_remote_format(VncFramebuff
}
+static gboolean vnc_base_framebuffer_perfect_format_match(VncFramebuffer *iface)
+{
+ VncBaseFramebuffer *fb = VNC_BASE_FRAMEBUFFER(iface);
+ VncBaseFramebufferPrivate *priv = fb->priv;
+
+ return priv->perfect_match;
+}
+
+
static guint8 vnc_base_framebuffer_swap_img_8(VncBaseFramebufferPrivate *priv G_GNUC_UNUSED, guint8 pixel)
{
return pixel;
@@ -710,6 +719,7 @@ static void vnc_base_framebuffer_interface_init(gpointer g_iface,
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->perfect_format_match = vnc_base_framebuffer_perfect_format_match;
iface->set_pixel_at = vnc_base_framebuffer_set_pixel_at;
iface->fill = vnc_base_framebuffer_fill;
diff --git a/src/vncconnection.c b/src/vncconnection.c
index 6b0f465..35e54da 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -71,23 +71,9 @@ struct wait_queue
};
-typedef void vnc_connection_blt_func(VncConnection *conn, guint8 *, int, int, int, int, int);
-
-typedef void vnc_connection_fill_func(VncConnection *conn, guint8 *, int, int, int, int);
-
-typedef void vnc_connection_set_pixel_at_func(VncConnection *conn, int, int, guint8 *);
-
-typedef void vnc_connection_hextile_func(VncConnection *conn, guint8 flags,
- guint16 x, guint16 y,
- guint16 width, guint16 height,
- guint8 *fg, guint8 *bg);
-
typedef void vnc_connection_rich_cursor_blt_func(VncConnection *conn, guint8 *, guint8 *,
guint8 *, int, guint16, guint16);
-typedef void vnc_connection_rgb24_blt_func(VncConnection *conn, int, int, int, int,
- guint8 *, int);
-
typedef void vnc_connection_tight_compute_predicted_func(VncConnection *conn, guint8 *,
guint8 *, guint8 *,
guint8 *);
@@ -156,19 +142,10 @@ struct _VncConnection
char write_buffer[4096];
size_t write_offset;
- gboolean perfect_match;
- struct vnc_framebuffer local;
-
- int rm, gm, bm;
- int rrs, grs, brs;
- int rls, gls, bls;
+ VncFramebuffer *fb;
+ gboolean fbSwapRemote;
- vnc_connection_blt_func *blt;
- vnc_connection_fill_func *fill;
- vnc_connection_set_pixel_at_func *set_pixel_at;
- vnc_connection_hextile_func *hextile;
vnc_connection_rich_cursor_blt_func *rich_cursor_blt;
- vnc_connection_rgb24_blt_func *rgb24_blt;
vnc_connection_tight_compute_predicted_func *tight_compute_predicted;
vnc_connection_tight_sum_pixel_func *tight_sum_pixel;
@@ -1025,6 +1002,11 @@ gboolean vnc_connection_set_pixel_format(VncConnection *conn,
}
+const VncPixelFormat *vnc_connection_get_pixel_format(VncConnection *conn)
+{
+ return &conn->fmt;
+}
+
gboolean vnc_connection_set_encodings(VncConnection *conn, int n_encoding, gint32 *encoding)
{
guint8 pad[1] = {0};
@@ -1170,59 +1152,37 @@ gboolean vnc_connection_client_cut_text(VncConnection *conn,
return !vnc_connection_has_error(conn);
}
+
static inline guint8 *vnc_connection_get_local(VncConnection *conn, int x, int y)
{
- return conn->local.data +
- (y * conn->local.linesize) +
- (x * conn->local.bpp);
-}
+ const VncPixelFormat *local = vnc_framebuffer_get_local_format(conn->fb);
+ int rowstride = vnc_framebuffer_get_rowstride(conn->fb);
-static guint8 vnc_connection_swap_img_8(VncConnection *conn G_GNUC_UNUSED, guint8 pixel)
-{
- return pixel;
+ return vnc_framebuffer_get_buffer(conn->fb) +
+ (y * rowstride) +
+ (x * (local->bits_per_pixel / 8));
}
+
static guint8 vnc_connection_swap_rfb_8(VncConnection *conn G_GNUC_UNUSED, guint8 pixel)
{
return pixel;
}
-/* local host native format -> X server image format */
-static guint16 vnc_connection_swap_img_16(VncConnection *conn, guint16 pixel)
-{
- if (G_BYTE_ORDER != conn->local.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_connection_swap_rfb_16(VncConnection *conn, guint16 pixel)
{
- if (conn->fmt.byte_order != G_BYTE_ORDER)
+ if (conn->fbSwapRemote)
return (((pixel >> 8) & 0xFF) << 0) |
(((pixel >> 0) & 0xFF) << 8);
else
return pixel;
}
-/* local host native format -> X server image format */
-static guint32 vnc_connection_swap_img_32(VncConnection *conn, guint32 pixel)
-{
- if (G_BYTE_ORDER != conn->local.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_connection_swap_rfb_32(VncConnection *conn, guint32 pixel)
{
- if (conn->fmt.byte_order != G_BYTE_ORDER)
+ if (conn->fbSwapRemote)
return (((pixel >> 24) & 0xFF) << 0) |
(((pixel >> 16) & 0xFF) << 8) |
(((pixel >> 8) & 0xFF) << 16) |
@@ -1231,62 +1191,61 @@ static guint32 vnc_connection_swap_rfb_32(VncConnection *conn, guint32 pixel)
return pixel;
}
-#define SPLICE_I(a, b) a ## b
-#define SPLICE(a, b) SPLICE_I(a, b)
+#define SRC 8
+#define DST 8
+#include "vncconnectionblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 8
+#define DST 16
+#include "vncconnectionblt.h"
+#undef SRC
+#undef DST
#define SRC 8
-#include "blt1.h"
+#define DST 32
+#include "vncconnectionblt.h"
#undef SRC
+#undef DST
+
#define SRC 16
-#include "blt1.h"
+#define DST 8
+#include "vncconnectionblt.h"
#undef SRC
+#undef DST
-#define SRC 32
-#include "blt1.h"
+#define SRC 16
+#define DST 16
+#include "vncconnectionblt.h"
#undef SRC
+#undef DST
-static vnc_connection_blt_func *vnc_connection_blt_table[3][3] = {
- { vnc_connection_blt_8x8, vnc_connection_blt_8x16, vnc_connection_blt_8x32 },
- { vnc_connection_blt_16x8, vnc_connection_blt_16x16, vnc_connection_blt_16x32 },
- { vnc_connection_blt_32x8, vnc_connection_blt_32x16, vnc_connection_blt_32x32 },
-};
+#define SRC 16
+#define DST 32
+#include "vncconnectionblt.h"
+#undef SRC
+#undef DST
-static vnc_connection_hextile_func *vnc_connection_hextile_table[3][3] = {
- { (vnc_connection_hextile_func *)vnc_connection_hextile_8x8,
- (vnc_connection_hextile_func *)vnc_connection_hextile_8x16,
- (vnc_connection_hextile_func *)vnc_connection_hextile_8x32 },
- { (vnc_connection_hextile_func *)vnc_connection_hextile_16x8,
- (vnc_connection_hextile_func *)vnc_connection_hextile_16x16,
- (vnc_connection_hextile_func *)vnc_connection_hextile_16x32 },
- { (vnc_connection_hextile_func *)vnc_connection_hextile_32x8,
- (vnc_connection_hextile_func *)vnc_connection_hextile_32x16,
- (vnc_connection_hextile_func *)vnc_connection_hextile_32x32 },
-};
-static vnc_connection_set_pixel_at_func *vnc_connection_set_pixel_at_table[3][3] = {
- { (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_8x8,
- (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_8x16,
- (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_8x32 },
- { (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_16x8,
- (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_16x16,
- (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_16x32 },
- { (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_32x8,
- (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_32x16,
- (vnc_connection_set_pixel_at_func *)vnc_connection_set_pixel_at_32x32 },
-};
+#define SRC 32
+#define DST 8
+#include "vncconnectionblt.h"
+#undef SRC
+#undef DST
-static vnc_connection_fill_func *vnc_connection_fill_table[3][3] = {
- { (vnc_connection_fill_func *)vnc_connection_fill_8x8,
- (vnc_connection_fill_func *)vnc_connection_fill_8x16,
- (vnc_connection_fill_func *)vnc_connection_fill_8x32 },
- { (vnc_connection_fill_func *)vnc_connection_fill_16x8,
- (vnc_connection_fill_func *)vnc_connection_fill_16x16,
- (vnc_connection_fill_func *)vnc_connection_fill_16x32 },
- { (vnc_connection_fill_func *)vnc_connection_fill_32x8,
- (vnc_connection_fill_func *)vnc_connection_fill_32x16,
- (vnc_connection_fill_func *)vnc_connection_fill_32x32 },
-};
+#define SRC 32
+#define DST 16
+#include "vncconnectionblt.h"
+#undef SRC
+#undef DST
+
+#define SRC 32
+#define DST 32
+#include "vncconnectionblt.h"
+#undef SRC
+#undef DST
static vnc_connection_rich_cursor_blt_func *vnc_connection_rich_cursor_blt_table[3] = {
vnc_connection_rich_cursor_blt_8x32,
@@ -1294,12 +1253,6 @@ static vnc_connection_rich_cursor_blt_func *vnc_connection_rich_cursor_blt_table
vnc_connection_rich_cursor_blt_32x32,
};
-static vnc_connection_rgb24_blt_func *vnc_connection_rgb24_blt_table[3] = {
- (vnc_connection_rgb24_blt_func *)vnc_connection_rgb24_blt_32x8,
- (vnc_connection_rgb24_blt_func *)vnc_connection_rgb24_blt_32x16,
- (vnc_connection_rgb24_blt_func *)vnc_connection_rgb24_blt_32x32,
-};
-
static vnc_connection_tight_compute_predicted_func *vnc_connection_tight_compute_predicted_table[3] = {
(vnc_connection_tight_compute_predicted_func *)vnc_connection_tight_compute_predicted_8x8,
(vnc_connection_tight_compute_predicted_func *)vnc_connection_tight_compute_predicted_16x16,
@@ -1312,52 +1265,39 @@ static vnc_connection_tight_sum_pixel_func *vnc_connection_tight_sum_pixel_table
(vnc_connection_tight_sum_pixel_func *)vnc_connection_tight_sum_pixel_32x32,
};
-/* a fast blit for the perfect match scenario */
-static void vnc_connection_blt_fast(VncConnection *conn, guint8 *src, int pitch,
- int x, int y, int width, int height)
-{
- guint8 *dst = vnc_connection_get_local(conn, x, y);
- int i;
- for (i = 0; i < height; i++) {
- memcpy(dst, src, width * conn->local.bpp);
- dst += conn->local.linesize;
- src += pitch;
- }
-}
-
-static void vnc_connection_blt(VncConnection *conn, guint8 *src, int pitch,
- int x, int y, int width, int height)
-{
- conn->blt(conn, src, pitch, x, y, width, height);
-}
static void vnc_connection_raw_update(VncConnection *conn,
guint16 x, guint16 y,
guint16 width, guint16 height)
{
- guint8 *dst;
- int i;
-
/* optimize for perfect match between server/client
FWIW, in the local case, we ought to be doing a write
directly from the source framebuffer and a read directly
into the client framebuffer
*/
- if (conn->perfect_match) {
- dst = vnc_connection_get_local(conn, x, y);
+ if (vnc_framebuffer_perfect_format_match(conn->fb)) {
+ int i;
+ int rowstride = vnc_framebuffer_get_rowstride(conn->fb);
+ guint8 *dst = vnc_framebuffer_get_buffer(conn->fb);
+
+ dst += (y * rowstride) + (x * (conn->fmt.bits_per_pixel/8));
+
for (i = 0; i < height; i++) {
- vnc_connection_read(conn, dst, width * conn->local.bpp);
- dst += conn->local.linesize;
+ vnc_connection_read(conn, dst,
+ width * (conn->fmt.bits_per_pixel/8));
+ dst += rowstride;
}
- return;
- }
+ } else {
+ guint8 *dst;
+ int i;
- dst = g_malloc(width * (conn->fmt.bits_per_pixel / 8));
- for (i = 0; i < height; i++) {
- vnc_connection_read(conn, dst, width * (conn->fmt.bits_per_pixel / 8));
- vnc_connection_blt(conn, dst, 0, x, y + i, width, 1);
+ dst = g_malloc(width * (conn->fmt.bits_per_pixel / 8));
+ for (i = 0; i < height; i++) {
+ vnc_connection_read(conn, dst, width * (conn->fmt.bits_per_pixel / 8));
+ vnc_framebuffer_blt(conn->fb, dst, 0, x, y + i, width, 1);
+ }
+ g_free(dst);
}
- g_free(dst);
}
static void vnc_connection_copyrect_update(VncConnection *conn,
@@ -1365,28 +1305,60 @@ static void vnc_connection_copyrect_update(VncConnection *conn,
guint16 width, guint16 height)
{
int src_x, src_y;
- guint8 *dst, *src;
- int pitch = conn->local.linesize;
- int i;
src_x = vnc_connection_read_u16(conn);
src_y = vnc_connection_read_u16(conn);
- if (src_y < dst_y) {
- pitch = -pitch;
- src_y += (height - 1);
- dst_y += (height - 1);
- }
+ vnc_framebuffer_copyrect(conn->fb,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height);
+}
+
+static void vnc_connection_hextile_rect(VncConnection *conn,
+ guint8 flags,
+ guint16 x, guint16 y,
+ guint16 width, guint16 height,
+ guint8 *fg, guint8 *bg)
+{
+ int i;
+
+ if (flags & 0x01) {
+ vnc_connection_raw_update(conn, x, y, width, height);
+ } else {
+ /* Background Specified */
+ if (flags & 0x02)
+ vnc_connection_read_pixel(conn, bg);
+
+ /* Foreground Specified */
+ if (flags & 0x04)
+ vnc_connection_read_pixel(conn, fg);
+
+ vnc_framebuffer_fill(conn->fb, bg, x, y, width, height);
+
+ /* AnySubrects */
+ if (flags & 0x08) {
+ guint8 n_rects = vnc_connection_read_u8(conn);
+
+ for (i = 0; i < n_rects; i++) {
+ guint8 xy, wh;
+
+ /* SubrectsColored */
+ if (flags & 0x10)
+ vnc_connection_read_pixel(conn, fg);
+
+ xy = vnc_connection_read_u8(conn);
+ wh = vnc_connection_read_u8(conn);
- dst = vnc_connection_get_local(conn, dst_x, dst_y);
- src = vnc_connection_get_local(conn, src_x, src_y);
- for (i = 0; i < height; i++) {
- memmove(dst, src, width * conn->local.bpp);
- dst += pitch;
- src += pitch;
+ vnc_framebuffer_fill(conn->fb, fg,
+ x + nibhi(xy), y + niblo(xy),
+ nibhi(wh) + 1, niblo(wh) + 1);
+ }
+ }
}
}
+
static void vnc_connection_hextile_update(VncConnection *conn,
guint16 x, guint16 y,
guint16 width, guint16 height)
@@ -1403,22 +1375,14 @@ static void vnc_connection_hextile_update(VncConnection *conn,
int h = MIN(16, height - j);
flags = vnc_connection_read_u8(conn);
- conn->hextile(conn, flags, x + i, y + j, w, h, fg, bg);
+ vnc_connection_hextile_rect(conn, flags,
+ x + i, y + j,
+ w, h,
+ fg, bg);
}
}
}
-static void vnc_connection_fill(VncConnection *conn, guint8 *color,
- guint16 x, guint16 y, guint16 width, guint16 height)
-{
- conn->fill(conn, color, x, y, width, height);
-}
-
-static void vnc_connection_set_pixel_at(VncConnection *conn, int x, int y, guint8 *pixel)
-{
- conn->set_pixel_at(conn, x, y, pixel);
-}
-
static void vnc_connection_rre_update(VncConnection *conn,
guint16 x, guint16 y,
guint16 width, guint16 height)
@@ -1429,7 +1393,7 @@ static void vnc_connection_rre_update(VncConnection *conn,
num = vnc_connection_read_u32(conn);
vnc_connection_read_pixel(conn, bg);
- vnc_connection_fill(conn, bg, x, y, width, height);
+ vnc_framebuffer_fill(conn->fb, bg, x, y, width, height);
for (i = 0; i < num; i++) {
guint8 fg[4];
@@ -1441,8 +1405,8 @@ static void vnc_connection_rre_update(VncConnection *conn,
sub_w = vnc_connection_read_u16(conn);
sub_h = vnc_connection_read_u16(conn);
- vnc_connection_fill(conn, fg,
- x + sub_x, y + sub_y, sub_w, sub_h);
+ vnc_framebuffer_fill(conn->fb, fg,
+ x + sub_x, y + sub_y, sub_w, sub_h);
}
}
@@ -1491,7 +1455,7 @@ static void vnc_connection_zrle_update_tile_blit(VncConnection *conn,
for (i = 0; i < width * height; i++)
vnc_connection_read_cpixel(conn, blit_data + (i * bpp));
- vnc_connection_blt(conn, blit_data, width * bpp, x, y, width, height);
+ vnc_framebuffer_blt(conn->fb, blit_data, width * bpp, x, y, width, height);
}
static guint8 vnc_connection_read_zrle_pi(VncConnection *conn, int palette_size)
@@ -1534,8 +1498,8 @@ static void vnc_connection_zrle_update_tile_palette(VncConnection *conn,
for (i = 0; i < width; i++) {
int ind = vnc_connection_read_zrle_pi(conn, palette_size);
- vnc_connection_set_pixel_at(conn, x + i, y + j,
- palette[ind & 0x7F]);
+ vnc_framebuffer_set_pixel_at(conn->fb, palette[ind & 0x7F],
+ x + i, y + j);
}
}
}
@@ -1566,7 +1530,7 @@ static void vnc_connection_zrle_update_tile_rle(VncConnection *conn,
vnc_connection_read_cpixel(conn, pixel);
rl = vnc_connection_read_zrle_rl(conn);
}
- vnc_connection_set_pixel_at(conn, x + i, y + j, pixel);
+ vnc_framebuffer_set_pixel_at(conn->fb, pixel, x + i, y + j);
rl -= 1;
}
}
@@ -1595,7 +1559,7 @@ static void vnc_connection_zrle_update_tile_prle(VncConnection *conn,
rl = 1;
}
- vnc_connection_set_pixel_at(conn, x + i, y + j, palette[pi]);
+ vnc_framebuffer_set_pixel_at(conn->fb, palette[pi], x + i, y + j);
rl -= 1;
}
}
@@ -1613,7 +1577,7 @@ static void vnc_connection_zrle_update_tile(VncConnection *conn, guint16 x, guin
} else if (subencoding == 1) {
/* Solid tile of a single color */
vnc_connection_read_cpixel(conn, pixel);
- vnc_connection_fill(conn, pixel, x, y, width, height);
+ vnc_framebuffer_fill(conn->fb, pixel, x, y, width, height);
} else if ((subencoding >= 2) && (subencoding <= 16)) {
/* Packed palette types */
vnc_connection_zrle_update_tile_palette(conn, subencoding,
@@ -1670,12 +1634,6 @@ static void vnc_connection_zrle_update(VncConnection *conn,
g_free(zlib_data);
}
-static void vnc_connection_rgb24_blt(VncConnection *conn, int x, int y,
- int width, int height, guint8 *data, int pitch)
-{
- conn->rgb24_blt(conn, x, y, width, height, data, pitch);
-}
-
static guint32 vnc_connection_read_cint(VncConnection *conn)
{
guint32 value = 0;
@@ -1734,7 +1692,7 @@ static void vnc_connection_tight_update_copy(VncConnection *conn,
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
vnc_connection_read_tpixel(conn, pixel);
- vnc_connection_set_pixel_at(conn, x + i, y + j, pixel);
+ vnc_framebuffer_set_pixel_at(conn->fb, pixel, x + i, y + j);
}
}
}
@@ -1765,8 +1723,7 @@ static void vnc_connection_tight_update_palette(VncConnection *conn,
guint8 ind;
ind = vnc_connection_tight_get_pi(conn, &ra, i, palette_size);
- vnc_connection_set_pixel_at(conn, x + i, y + j,
- &palette[ind * 4]);
+ vnc_framebuffer_set_pixel_at(conn->fb, &palette[ind * 4], x + i, y + j);
}
}
}
@@ -1829,7 +1786,7 @@ static void vnc_connection_tight_update_gradient(VncConnection *conn,
}
/* write out row of pixel data */
- vnc_connection_blt(conn, row, width * bpp, x, y + j, width, 1);
+ vnc_framebuffer_blt(conn->fb, row, width * bpp, x, y + j, width, 1);
/* swap last row and current row */
tmp_row = last_row;
@@ -1846,7 +1803,7 @@ static void jpeg_draw(void *opaque, int x, int y, int w, int h,
{
VncConnection *conn = opaque;
- vnc_connection_rgb24_blt(conn, x, y, w, h, data, stride);
+ vnc_framebuffer_rgb24_blt(conn->fb, data, stride, x, y, w, h);
}
static void vnc_connection_tight_update_jpeg(VncConnection *conn, guint16 x, guint16 y,
@@ -1950,7 +1907,7 @@ static void vnc_connection_tight_update(VncConnection *conn,
/* fill */
/* FIXME check each width; endianness */
vnc_connection_read_tpixel(conn, pixel);
- vnc_connection_fill(conn, pixel, x, y, width, height);
+ vnc_framebuffer_fill(conn->fb, pixel, x, y, width, height);
} else if (ccontrol == 9) {
/* jpeg */
guint32 length;
@@ -1973,6 +1930,7 @@ static void vnc_connection_update(VncConnection *conn, int x, int y, int width,
{
if (conn->has_error || !conn->ops.update)
return;
+ GVNC_DEBUG("Notify update area (%dx%d) at location %d,%d", width, height, x, y);
if (!conn->ops.update(conn->ops_data, x, y, width, height)) {
GVNC_DEBUG("Closing the connection: vnc_connection_update");
conn->has_error = TRUE;
@@ -2153,8 +2111,8 @@ static void vnc_connection_framebuffer_update(VncConnection *conn, gint32 etype,
guint16 x, guint16 y,
guint16 width, guint16 height)
{
- GVNC_DEBUG("FramebufferUpdate(%d, %d, %d, %d, %d)",
- etype, x, y, width, height);
+ GVNC_DEBUG("FramebufferUpdate type=%d area (%dx%d) at location %d,%d",
+ etype, width, height, x, y);
switch (etype) {
case GVNC_ENCODING_RAW:
@@ -3403,6 +3361,9 @@ void vnc_connection_free(VncConnection *conn)
if (vnc_connection_is_open(conn))
vnc_connection_close(conn);
+ if (conn->fb)
+ g_object_unref(G_OBJECT(conn->fb));
+
g_free(conn);
conn = NULL;
}
@@ -3853,86 +3814,28 @@ gboolean vnc_connection_set_credential_x509_cert(VncConnection *conn, const char
}
-gboolean vnc_connection_set_local(VncConnection *conn, struct vnc_framebuffer *fb)
+gboolean vnc_connection_set_framebuffer(VncConnection *conn, VncFramebuffer *fb)
{
- int i, j, n;
- int depth;
+ const VncPixelFormat *remote;
+ int i;
- memcpy(&conn->local, fb, sizeof(*fb));
+ if (conn->fb)
+ g_object_unref(G_OBJECT(conn->fb));
+ conn->fb = fb;
+ g_object_ref(G_OBJECT(conn->fb));
+
+ remote = vnc_framebuffer_get_remote_format(conn->fb);
+
+ conn->fbSwapRemote = remote->byte_order != G_BYTE_ORDER;
+
+ i = conn->fmt.bits_per_pixel / 8;
+
+ if (i == 4) i = 3;
- if (fb->bpp == (conn->fmt.bits_per_pixel / 8) &&
- fb->red_mask == conn->fmt.red_max &&
- fb->green_mask == conn->fmt.green_max &&
- fb->blue_mask == conn->fmt.blue_max &&
- fb->red_shift == conn->fmt.red_shift &&
- fb->green_shift == conn->fmt.green_shift &&
- fb->blue_shift == conn->fmt.blue_shift &&
- fb->byte_order == G_BYTE_ORDER &&
- conn->fmt.byte_order == G_BYTE_ORDER)
- conn->perfect_match = TRUE;
- else
- conn->perfect_match = FALSE;
-
- depth = conn->fmt.depth;
- if (depth == 32)
- depth = 24;
-
- conn->rm = conn->local.red_mask & conn->fmt.red_max;
- conn->gm = conn->local.green_mask & conn->fmt.green_max;
- conn->bm = conn->local.blue_mask & conn->fmt.blue_max;
- GVNC_DEBUG("Mask local: %3d %3d %3d\n"
- " remote: %3d %3d %3d\n"
- " merged: %3d %3d %3d",
- conn->local.red_mask, conn->local.green_mask, conn->local.blue_mask,
- conn->fmt.red_max, conn->fmt.green_max, conn->fmt.blue_max,
- conn->rm, conn->gm, conn->bm);
-
- /* Setup shifts assuming matched bpp (but not necessarily match rgb order)*/
- conn->rrs = conn->fmt.red_shift;
- conn->grs = conn->fmt.green_shift;
- conn->brs = conn->fmt.blue_shift;
-
- conn->rls = conn->local.red_shift;
- conn->gls = conn->local.green_shift;
- conn->bls = conn->local.blue_shift;
-
- /* This adjusts for remote having more bpp than local */
- for (n = conn->fmt.red_max; n > conn->local.red_mask ; n>>= 1)
- conn->rrs++;
- for (n = conn->fmt.green_max; n > conn->local.green_mask ; n>>= 1)
- conn->grs++;
- for (n = conn->fmt.blue_max; n > conn->local.blue_mask ; n>>= 1)
- conn->brs++;
-
- /* This adjusts for remote having less bpp than remote */
- for (n = conn->local.red_mask ; n > conn->fmt.red_max ; n>>= 1)
- conn->rls++;
- for (n = conn->local.green_mask ; n > conn->fmt.green_max ; n>>= 1)
- conn->gls++;
- for (n = conn->local.blue_mask ; n > conn->fmt.blue_max ; n>>= 1)
- conn->bls++;
- GVNC_DEBUG("Pixel shifts\n right: %3d %3d %3d\n left: %3d %3d %3d",
- conn->rrs, conn->grs, conn->brs,
- conn->rls, conn->gls, conn->bls);
-
- i = conn->fmt.bits_per_pixel / 8;
- j = conn->local.bpp;
-
- if (i == 4) i = 3;
- if (j == 4) j = 3;
-
- conn->blt = vnc_connection_blt_table[i - 1][j - 1];
- conn->fill = vnc_connection_fill_table[i - 1][j - 1];
- conn->set_pixel_at = vnc_connection_set_pixel_at_table[i - 1][j - 1];
- conn->hextile = vnc_connection_hextile_table[i - 1][j - 1];
conn->rich_cursor_blt = vnc_connection_rich_cursor_blt_table[i - 1];
- conn->rgb24_blt = vnc_connection_rgb24_blt_table[i - 1];
conn->tight_compute_predicted = vnc_connection_tight_compute_predicted_table[i - 1];
conn->tight_sum_pixel = vnc_connection_tight_sum_pixel_table[i - 1];
- if (conn->perfect_match)
- conn->blt = vnc_connection_blt_fast;
-
return !vnc_connection_has_error(conn);
}
diff --git a/src/vncconnection.h b/src/vncconnection.h
index 1c8ef27..9c3de73 100644
--- a/src/vncconnection.h
+++ b/src/vncconnection.h
@@ -23,7 +23,7 @@
#include <glib.h>
-#include "vncpixelformat.h"
+#include "vncframebuffer.h"
typedef struct _VncConnection VncConnection;
@@ -50,28 +50,6 @@ struct vnc_connection_ops
};
-struct vnc_framebuffer
-{
- guint8 *data;
-
- int width;
- int height;
-
- int linesize;
-
- guint16 byte_order;
- int depth;
- int bpp;
-
- int red_mask;
- int green_mask;
- int blue_mask;
-
- int red_shift;
- int blue_shift;
- int green_shift;
-};
-
typedef enum {
GVNC_ENCODING_RAW = 0,
GVNC_ENCODING_COPY_RECT = 1,
@@ -180,9 +158,12 @@ gboolean vnc_connection_set_encodings(VncConnection *conn, int n_encoding, gint3
gboolean vnc_connection_set_pixel_format(VncConnection *conn,
const VncPixelFormat *fmt);
+const VncPixelFormat *vnc_connection_get_pixel_format(VncConnection *conn);
+
gboolean vnc_connection_has_error(VncConnection *conn);
-gboolean vnc_connection_set_local(VncConnection *conn, struct vnc_framebuffer *fb);
+gboolean vnc_connection_set_framebuffer(VncConnection *conn,
+ VncFramebuffer *fb);
const char *vnc_connection_get_name(VncConnection *conn);
int vnc_connection_get_width(VncConnection *conn);
diff --git a/src/vncconnectionblt.h b/src/vncconnectionblt.h
new file mode 100644
index 0000000..031fcf2
--- /dev/null
+++ b/src/vncconnectionblt.h
@@ -0,0 +1,163 @@
+/*
+ * 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
+ */
+#define SPLICE_I(a, b) a ## b
+#define SPLICE(a, b) SPLICE_I(a, b)
+#define src_pixel_t SPLICE(SPLICE(uint, SRC), _t)
+#define ssrc_pixel_t SPLICE(SPLICE(int, SRC), _t)
+#define dst_pixel_t SPLICE(SPLICE(uint, DST), _t)
+#define SUFFIX() SPLICE(SRC,SPLICE(x,DST))
+#define RICH_CURSOR_BLIT SPLICE(vnc_connection_rich_cursor_blt_, SUFFIX())
+#define TIGHT_COMPUTE_PREDICTED SPLICE(vnc_connection_tight_compute_predicted_, SUFFIX())
+#define TIGHT_SUM_PIXEL SPLICE(vnc_connection_tight_sum_pixel_, SUFFIX())
+#define SWAP_RFB(conn, pixel) SPLICE(vnc_connection_swap_rfb_, SRC)(conn, pixel)
+#define SWAP_IMG(conn, pixel) SPLICE(vnc_connection_swap_img_, DST)(conn, pixel)
+#define COMPONENT(color, pixel) ((SWAP_RFB(conn, pixel) >> conn->fmt.SPLICE(color, _shift) & conn->fmt.SPLICE(color, _max)))
+
+
+/* We need to convert to a GdkPixbuf which is always 32-bit */
+#if DST == 32
+static void RICH_CURSOR_BLIT(VncConnection *conn, guint8 *pixbuf,
+ guint8 *image, guint8 *mask, int pitch,
+ guint16 width, guint16 height)
+{
+ int x1, y1;
+ guint32 *dst = (guint32 *)pixbuf;
+ guint8 *src = image;
+ guint8 *alpha = mask;
+ int as, rs, gs, bs, n;
+
+ /*
+ * GdkPixbuf is always 32-bit RGB, so we can't use the precomputed
+ * left / right shift data from conn->{r,g,b}{r,l}s. The latter
+ * is set for the local display depth, which may be different
+ * to GdkPixbuf's fixed 32-bit RGBA
+ *
+ * This function isn't called often, so just re-compute them now
+ */
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ as = 0;
+ rs = 8;
+ gs = 16;
+ bs = 24;
+#else
+ as = 24;
+ rs = 16;
+ gs = 8;
+ bs = 0;
+#endif
+
+ /* Then this adjusts for remote having less bpp than 32 */
+ for (n = 255 ; n > conn->fmt.red_max ; n>>= 1)
+ rs++;
+ for (n = 255 ; n > conn->fmt.green_max ; n>>= 1)
+ gs++;
+ for (n = 255 ; n > conn->fmt.blue_max ; n>>= 1)
+ bs++;
+
+ for (y1 = 0; y1 < height; y1++) {
+ src_pixel_t *sp = (src_pixel_t *)src;
+ guint8 *mp = alpha;
+ for (x1 = 0; x1 < width; x1++) {
+ *dst = (COMPONENT(red, *sp) << rs)
+ | (COMPONENT(green, *sp) << gs)
+ | (COMPONENT(blue, *sp) << bs);
+
+ if ((mp[x1 / 8] >> (7 - (x1 % 8))) & 1)
+ *dst |= (0xFF << as);
+
+ dst++;
+ sp++;
+ }
+ src += pitch;
+ alpha += ((width + 7) / 8);
+ }
+}
+#endif
+
+
+#if SRC == DST
+
+static void TIGHT_COMPUTE_PREDICTED(VncConnection *conn, src_pixel_t *ppixel,
+ src_pixel_t *lp, src_pixel_t *cp,
+ src_pixel_t *llp)
+{
+ ssrc_pixel_t red, green, blue;
+
+ red = COMPONENT(red, *lp) + COMPONENT(red, *cp) - COMPONENT(red, *llp);
+ red = MAX(red, 0);
+ red = MIN(red, conn->fmt.red_max);
+
+ green = COMPONENT(green, *lp) + COMPONENT(green, *cp) - COMPONENT(green, *llp);
+ green = MAX(green, 0);
+ green = MIN(green, conn->fmt.green_max);
+
+ blue = COMPONENT(blue, *lp) + COMPONENT(blue, *cp) - COMPONENT(blue, *llp);
+ blue = MAX(blue, 0);
+ blue = MIN(blue, conn->fmt.blue_max);
+
+ *ppixel = SWAP_RFB(conn,
+ (red << conn->fmt.red_shift) |
+ (green << conn->fmt.green_shift) |
+ (blue << conn->fmt.blue_shift));
+}
+
+static void TIGHT_SUM_PIXEL(VncConnection *conn,
+ src_pixel_t *lhs, src_pixel_t *rhs)
+{
+ src_pixel_t red, green, blue;
+
+ red = COMPONENT(red, *lhs) + COMPONENT(red, *rhs);
+ green = COMPONENT(green, *lhs) + COMPONENT(green, *rhs);
+ blue = COMPONENT(blue, *lhs) + COMPONENT(blue, *rhs);
+
+ *lhs = SWAP_RFB(conn,
+ ((red & conn->fmt.red_max) << conn->fmt.red_shift) |
+ ((green & conn->fmt.green_max) << conn->fmt.green_shift) |
+ ((blue & conn->fmt.blue_max) << conn->fmt.blue_shift));
+}
+
+#endif
+
+#undef SPLICE
+#undef SPLICE_T
+#undef SUFFIX
+#undef RICH_CURSOR_BLIT
+#undef TIGHT_SUM_PIXEL
+#undef TIGHT_COMPUTE_PREDICTED
+#undef SWAP_RFB
+#undef SWAP_IMG
+#undef COMPONENT
+#undef dst_pixel_t
+#undef src_pixel_t
+#undef ssrc_pixel_t
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index c923efe..157b7ee 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -24,6 +24,7 @@
#include "vncdisplay.h"
#include "coroutine.h"
#include "vncconnection.h"
+#include "vncimageframebuffer.h"
#include "utils.h"
#include "vncmarshal.h"
#include "config.h"
@@ -59,14 +60,13 @@ struct _VncDisplayPrivate
char *host;
char *port;
GdkGC *gc;
- GdkImage *image;
GdkPixmap *pixmap;
GdkCursor *null_cursor;
GdkCursor *remote_cursor;
- struct vnc_framebuffer fb;
struct coroutine coroutine;
VncConnection *conn;
+ VncImageFramebuffer *fb;
guint open_id;
VncDisplayDepthColor depth;
@@ -304,19 +304,23 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
GdkRectangle drawn;
GdkRegion *clear, *copy;
#endif
+ int fbw, fbh;
- GVNC_DEBUG("Expose %dx%d @ %d,%d",
- expose->area.x,
- expose->area.y,
+ fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
+ fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
+
+ GVNC_DEBUG("Expose area %dx%d at location %d,%d",
expose->area.width,
- expose->area.height);
+ expose->area.height,
+ expose->area.x,
+ expose->area.y);
gdk_drawable_get_size(widget->window, &ww, &wh);
- if (ww > priv->fb.width)
- mx = (ww - priv->fb.width) / 2;
- if (wh > priv->fb.height)
- my = (wh - priv->fb.height) / 2;
+ if (ww > fbw)
+ mx = (ww - fbw) / 2;
+ if (wh > fbh)
+ my = (wh - fbh) / 2;
#if WITH_GTK_CAIRO
cr = gdk_cairo_create(GTK_WIDGET(obj)->window);
@@ -338,8 +342,8 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
behaviour of drawing the rectangle from right to left
to cut out the whole */
if (priv->pixmap)
- cairo_rectangle(cr, mx + priv->fb.width, my,
- -1 * priv->fb.width, priv->fb.height);
+ cairo_rectangle(cr, mx + fbw, my,
+ -1 * fbw, fbh);
cairo_fill(cr);
}
@@ -348,8 +352,8 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
if (priv->allow_scaling) {
double sx, sy;
/* Scale to fill window */
- sx = (double)ww / (double)priv->fb.width;
- sy = (double)wh / (double)priv->fb.height;
+ sx = (double)ww / (double)fbw;
+ sy = (double)wh / (double)fbh;
cairo_scale(cr, sx, sy);
gdk_cairo_set_source_pixmap(cr,
priv->pixmap,
@@ -364,10 +368,10 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
cairo_destroy(cr);
#else
- x = MIN(expose->area.x - mx, priv->fb.width);
- y = MIN(expose->area.y - my, priv->fb.height);
- w = MIN(expose->area.x + expose->area.width - mx, priv->fb.width);
- h = MIN(expose->area.y + expose->area.height - my, priv->fb.height);
+ x = MIN(expose->area.x - mx, fbw);
+ y = MIN(expose->area.y - my, fbh);
+ w = MIN(expose->area.x + expose->area.width - mx, fbw);
+ h = MIN(expose->area.y + expose->area.height - my, fbh);
x = MAX(0, x);
y = MAX(0, y);
w = MAX(0, w);
@@ -590,6 +594,10 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
{
VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
int ww, wh;
+ int fbw, fbh;
+
+ fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
+ fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
if (priv->conn == NULL || !vnc_connection_is_initialized(priv->conn))
return FALSE;
@@ -607,8 +615,8 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
/* First apply adjustments to the coords in the motion event */
if (priv->allow_scaling) {
double sx, sy;
- sx = (double)priv->fb.width / (double)ww;
- sy = (double)priv->fb.height / (double)wh;
+ sx = (double)fbw / (double)ww;
+ sy = (double)fbh / (double)wh;
/* Scaling the desktop, so scale the mouse coords
* by same ratio */
@@ -617,10 +625,10 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
} else {
int mw = 0, mh = 0;
- if (ww > priv->fb.width)
- mw = (ww - priv->fb.width) / 2;
- if (wh > priv->fb.height)
- mh = (wh - priv->fb.height) / 2;
+ if (ww > fbw)
+ mw = (ww - fbw) / 2;
+ if (wh > fbh)
+ mh = (wh - fbh) / 2;
/* Not scaling, drawing the desktop centered
* in the larger window, so offset the mouse
@@ -666,8 +674,8 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
/* Drop out of bounds motion to avoid upsetting
* the server */
- if (dx < 0 || dx >= priv->fb.width ||
- dy < 0 || dy >= priv->fb.height)
+ if (dx < 0 || dx >= fbw ||
+ dy < 0 || dy >= fbh)
return FALSE;
} else {
/* Just send the delta since last motion event */
@@ -830,10 +838,15 @@ static gboolean on_update(void *opaque, int x, int y, int w, int h)
VncDisplayPrivate *priv = obj->priv;
int ww, wh;
GdkRectangle r = { x, y, w, h };
+ int fbw, fbh;
+
+ fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
+ fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
/* Copy pixbuf to pixmap */
gdk_gc_set_clip_rectangle(priv->gc, &r);
- gdk_draw_image(priv->pixmap, priv->gc, priv->image,
+ gdk_draw_image(priv->pixmap, priv->gc,
+ vnc_image_framebuffer_get_image(priv->fb),
x, y, x, y, w, h);
gdk_drawable_get_size(widget->window, &ww, &wh);
@@ -843,8 +856,8 @@ static gboolean on_update(void *opaque, int x, int y, int w, int h)
/* Scale the VNC region to produce expose region */
- sx = (double)ww / (double)priv->fb.width;
- sy = (double)wh / (double)priv->fb.height;
+ sx = (double)ww / (double)fbw;
+ sy = (double)wh / (double)fbh;
x *= sx;
y *= sy;
w *= sx;
@@ -854,10 +867,10 @@ static gboolean on_update(void *opaque, int x, int y, int w, int h)
/* Offset the VNC region to produce expose region */
- if (ww > priv->fb.width)
- mw = (ww - priv->fb.width) / 2;
- if (wh > priv->fb.height)
- mh = (wh - priv->fb.height) / 2;
+ if (ww > fbw)
+ mw = (ww - fbw) / 2;
+ if (wh > fbh)
+ mh = (wh - fbh) / 2;
x += mw;
y += mh;
@@ -868,42 +881,6 @@ static gboolean on_update(void *opaque, int x, int y, int w, int h)
return TRUE;
}
-static void setup_gdk_image(VncDisplay *obj, gint width, gint height)
-{
- VncDisplayPrivate *priv = obj->priv;
- GdkVisual *visual;
-
- visual = gdk_drawable_get_visual(GTK_WIDGET(obj)->window);
-
- priv->image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
- priv->pixmap = gdk_pixmap_new(GTK_WIDGET(obj)->window, width, height, -1);
-
- GVNC_DEBUG("Visual mask: %3d %3d %3d\n shift: %3d %3d %3d",
- visual->red_mask,
- visual->green_mask,
- visual->blue_mask,
- visual->red_shift,
- visual->green_shift,
- visual->blue_shift);
-
- priv->fb.red_mask = visual->red_mask >> visual->red_shift;
- priv->fb.green_mask = visual->green_mask >> visual->green_shift;
- priv->fb.blue_mask = visual->blue_mask >> visual->blue_shift;
- priv->fb.red_shift = visual->red_shift;
- priv->fb.green_shift = visual->green_shift;
- priv->fb.blue_shift = visual->blue_shift;
- priv->fb.depth = priv->image->depth;
- priv->fb.bpp = priv->image->bpp;
- priv->fb.width = priv->image->width;
- priv->fb.height = priv->image->height;
- priv->fb.linesize = priv->image->bpl;
- priv->fb.data = (guint8 *)priv->image->mem;
- priv->fb.byte_order = priv->image->byte_order == GDK_LSB_FIRST ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
-
- if (priv->force_size)
- gtk_widget_set_size_request(GTK_WIDGET(obj), width, height);
-}
-
static gboolean emit_signal_auth_cred(gpointer opaque)
{
@@ -966,18 +943,21 @@ static void emit_signal_delayed(VncDisplay *obj, int signum,
coroutine_yield(NULL);
}
-static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
+static gboolean do_framebuffer_init(VncDisplay *obj,
+ const VncPixelFormat *remoteFormat,
+ int width, int height, gboolean quiet)
{
- VncDisplay *obj = VNC_DISPLAY(opaque);
VncDisplayPrivate *priv = obj->priv;
struct signal_data s;
+ GdkVisual *visual;
+ GdkImage *image;
if (priv->conn == NULL || !vnc_connection_is_initialized(priv->conn))
return TRUE;
- if (priv->image) {
- g_object_unref(priv->image);
- priv->image = NULL;
+ if (priv->fb) {
+ g_object_unref(priv->fb);
+ priv->fb = NULL;
}
if (priv->pixmap) {
g_object_unref(priv->pixmap);
@@ -994,9 +974,18 @@ static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
priv->gc = gdk_gc_new(GTK_WIDGET(obj)->window);
}
- setup_gdk_image(obj, width, height);
+ visual = gdk_drawable_get_visual(GTK_WIDGET(obj)->window);
+ image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
- vnc_connection_set_local(priv->conn, &priv->fb);
+ priv->fb = vnc_image_framebuffer_new(image, remoteFormat);
+ priv->pixmap = gdk_pixmap_new(GTK_WIDGET(obj)->window, width, height, -1);
+
+ g_object_unref(G_OBJECT(image));
+
+ vnc_connection_set_framebuffer(priv->conn, VNC_FRAMEBUFFER(priv->fb));
+
+ if (priv->force_size)
+ gtk_widget_set_size_request(GTK_WIDGET(obj), width, height);
if (!quiet) {
s.width = width;
@@ -1009,16 +998,24 @@ static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
static gboolean on_resize(void *opaque, int width, int height)
{
- return do_resize(opaque, width, height, FALSE);
+ VncDisplay *obj = VNC_DISPLAY(opaque);
+ VncDisplayPrivate *priv = obj->priv;
+ const VncPixelFormat *remoteFormat;
+
+ remoteFormat = vnc_connection_get_pixel_format(priv->conn);
+
+ return do_framebuffer_init(opaque, remoteFormat, width, height, FALSE);
}
static gboolean on_pixel_format(void *opaque,
- VncPixelFormat *fmt G_GNUC_UNUSED)
+ VncPixelFormat *remoteFormat)
{
VncDisplay *obj = VNC_DISPLAY(opaque);
VncDisplayPrivate *priv = obj->priv;
+ gint16 width = vnc_connection_get_width(priv->conn);
+ gint16 height = vnc_connection_get_height(priv->conn);
- return do_resize(opaque, priv->fb.width, priv->fb.height, TRUE);
+ return do_framebuffer_init(opaque, remoteFormat, width, height, TRUE);
}
static gboolean on_get_preferred_pixel_format(void *opaque,
@@ -1348,9 +1345,9 @@ static gboolean delayed_unref_object(gpointer data)
g_assert(obj->priv->coroutine.exited == TRUE);
- if (obj->priv->image) {
- g_object_unref(obj->priv->image);
- obj->priv->image = NULL;
+ if (obj->priv->fb) {
+ g_object_unref(obj->priv->fb);
+ obj->priv->fb = NULL;
}
if (obj->priv->pixmap) {
g_object_unref(obj->priv->pixmap);
@@ -1428,13 +1425,16 @@ static void *vnc_coroutine(void *opaque)
if (!vnc_connection_set_encodings(priv->conn, n_encodings, encodingsp))
goto cleanup;
- if (!vnc_connection_framebuffer_update_request(priv->conn, 0, 0, 0, priv->fb.width, priv->fb.height))
+ if (!vnc_connection_framebuffer_update_request(priv->conn, 0, 0, 0,
+ vnc_connection_get_width(priv->conn),
+ vnc_connection_get_height(priv->conn)))
goto cleanup;
GVNC_DEBUG("Running main loop");
while ((ret = vnc_connection_server_message(priv->conn))) {
if (!vnc_connection_framebuffer_update_request(priv->conn, 1, 0, 0,
- priv->fb.width, priv->fb.height))
+ vnc_connection_get_width(priv->conn),
+ vnc_connection_get_height(priv->conn)))
goto cleanup;
}
@@ -1622,9 +1622,9 @@ static void vnc_display_finalize (GObject *obj)
vnc_connection_free(priv->conn);
display->priv->conn = NULL;
- if (priv->image) {
- g_object_unref(priv->image);
- priv->image = NULL;
+ if (priv->fb) {
+ g_object_unref(priv->fb);
+ priv->fb = NULL;
}
if (priv->null_cursor) {
@@ -2136,20 +2136,23 @@ GdkPixbuf *vnc_display_get_pixbuf(VncDisplay *obj)
{
VncDisplayPrivate *priv = obj->priv;
GdkPixbuf *pixbuf;
+ GdkImage *image;
if (!priv->conn ||
!vnc_connection_is_initialized(priv->conn))
return NULL;
+ image = vnc_image_framebuffer_get_image(priv->fb);
+
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
- priv->image->width, priv->image->height);
+ image->width, image->height);
if (!gdk_pixbuf_get_from_image(pixbuf,
- priv->image,
+ image,
gdk_colormap_get_system(),
0, 0, 0, 0,
- priv->image->width,
- priv->image->height))
+ image->width,
+ image->height))
return NULL;
return pixbuf;
@@ -2338,11 +2341,11 @@ vnc_display_request_update(VncDisplay *obj)
GVNC_DEBUG ("Requesting a full update");
return vnc_connection_framebuffer_update_request(obj->priv->conn,
- 0,
- 0,
- 0,
- obj->priv->fb.width,
- obj->priv->fb.height);
+ 0,
+ 0,
+ 0,
+ vnc_connection_get_width(obj->priv->conn),
+ vnc_connection_get_width(obj->priv->conn));
}
#ifdef WIN32
--
1.6.5.2
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]