[gtk-vnc] Convert VncConnection over to use VncFramebuffer object
- From: Daniel P. Berrange <dberrange src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk-vnc] Convert VncConnection over to use VncFramebuffer object
- Date: Sat, 20 Mar 2010 21:29:38 +0000 (UTC)
commit 37fc69f2da557669b14728e2b4af5147f98a3b3c
Author: Daniel P. Berrange <berrange redhat com>
Date: Thu Nov 19 19:06:00 2009 +0000
Convert VncConnection over to use VncFramebuffer object
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(-)
---
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 dabe2d4..65bd576 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;
@@ -1070,6 +1047,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};
@@ -1215,59 +1197,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) |
@@ -1276,62 +1236,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,
@@ -1339,12 +1298,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,
@@ -1357,52 +1310,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,
@@ -1410,28 +1350,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)
@@ -1448,22 +1420,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)
@@ -1474,7 +1438,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];
@@ -1486,8 +1450,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);
}
}
@@ -1536,7 +1500,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)
@@ -1579,8 +1543,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);
}
}
}
@@ -1611,7 +1575,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;
}
}
@@ -1640,7 +1604,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;
}
}
@@ -1658,7 +1622,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,
@@ -1715,12 +1679,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;
@@ -1779,7 +1737,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);
}
}
}
@@ -1810,8 +1768,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);
}
}
}
@@ -1874,7 +1831,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;
@@ -1891,7 +1848,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,
@@ -1995,7 +1952,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;
@@ -2018,6 +1975,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;
@@ -2198,8 +2156,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:
@@ -3448,6 +3406,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;
}
@@ -3898,86 +3859,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 1af3e23..33c310f 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(gtk_widget_get_window(widget), &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_get_window(GTK_WIDGET(obj)));
@@ -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 */
@@ -833,10 +841,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(gtk_widget_get_window(widget), &ww, &wh);
@@ -846,8 +859,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;
@@ -857,10 +870,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;
@@ -871,42 +884,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_get_window(GTK_WIDGET(obj)));
-
- priv->image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
- priv->pixmap = gdk_pixmap_new(gtk_widget_get_window(GTK_WIDGET(obj)), 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)
{
@@ -969,18 +946,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);
@@ -997,9 +977,18 @@ static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
priv->gc = gdk_gc_new(gtk_widget_get_window(GTK_WIDGET(obj)));
}
- setup_gdk_image(obj, width, height);
+ visual = gdk_drawable_get_visual(gtk_widget_get_window(GTK_WIDGET(obj)));
+ 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_get_window(GTK_WIDGET(obj)), 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;
@@ -1012,16 +1001,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,
@@ -1351,9 +1348,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);
@@ -1431,13 +1428,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;
}
@@ -1625,9 +1625,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) {
@@ -2144,20 +2144,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;
@@ -2346,11 +2349,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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]