[gtk-vnc] Remove the server side framebuffer cached in GdkPixmap
- From: Daniel P. Berrange <dberrange src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk-vnc] Remove the server side framebuffer cached in GdkPixmap
- Date: Thu, 28 Oct 2010 15:41:08 +0000 (UTC)
commit 693d51118fc3775ef71f6f07e5b55839beacecdb
Author: Daniel P. Berrange <berrange redhat com>
Date: Wed Oct 27 21:34:28 2010 +0100
Remove the server side framebuffer cached in GdkPixmap
For rendering efficiency a GdkPixmap was kept on the server
duplicating what was in the old GdkImage object on the client
side. The client was changed to use a cairo image surface.
This can easily be rendered straight to the window and does
not appear to have any performance degradation. Thus the
GdkPixmap can be eliminated, avoiding the extra memory usage
that entails
* src/vncdisplay.c: Remove the GdkPixmap copy of the framebuffer
src/vncdisplay.c | 94 ++++++++++++++++++++++++++++-------------------------
1 files changed, 50 insertions(+), 44 deletions(-)
---
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index d754fb6..d0a04dc 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -45,7 +45,6 @@
struct _VncDisplayPrivate
{
- GdkPixmap *pixmap;
GdkCursor *null_cursor;
GdkCursor *remote_cursor;
@@ -300,7 +299,7 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
/* If we don't have a pixmap, or we're not scaling, then
we need to fill with background color */
- if (!priv->pixmap ||
+ if (!priv->fb ||
!priv->allow_scaling) {
cairo_rectangle(cr, 0, 0, ww, wh);
/* Optionally cut out the inner area where the pixmap
@@ -308,27 +307,29 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
not double-buffering. Note we're using the undocumented
behaviour of drawing the rectangle from right to left
to cut out the whole */
- if (priv->pixmap)
+ if (priv->fb)
cairo_rectangle(cr, mx + fbw, my,
-1 * fbw, fbh);
cairo_fill(cr);
}
/* Draw the VNC display */
- if (priv->pixmap) {
+ if (priv->fb) {
if (priv->allow_scaling) {
double sx, sy;
/* Scale to fill window */
sx = (double)ww / (double)fbw;
sy = (double)wh / (double)fbh;
cairo_scale(cr, sx, sy);
- gdk_cairo_set_source_pixmap(cr,
- priv->pixmap,
- 0, 0);
+ cairo_set_source_surface(cr,
+ vnc_cairo_framebuffer_get_surface(priv->fb),
+ 0,
+ 0);
} else {
- gdk_cairo_set_source_pixmap(cr,
- priv->pixmap,
- mx, my);
+ cairo_set_source_surface(cr,
+ vnc_cairo_framebuffer_get_surface(priv->fb),
+ mx,
+ my);
}
cairo_paint(cr);
}
@@ -811,22 +812,10 @@ static void on_framebuffer_update(VncConnection *conn G_GNUC_UNUSED,
VncDisplayPrivate *priv = obj->priv;
int ww, wh;
int fbw, fbh;
- cairo_surface_t *surface;
- cairo_t *cr;
fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
- cr = gdk_cairo_create(priv->pixmap);
- cairo_rectangle(cr, x, y, w, h);
- cairo_clip(cr);
-
- surface = vnc_cairo_framebuffer_get_surface(priv->fb);
- cairo_set_source_surface(cr, surface, 0, 0);
- cairo_paint(cr);
-
- cairo_destroy(cr);
-
gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh);
if (priv->allow_scaling) {
@@ -876,10 +865,6 @@ static void do_framebuffer_init(VncDisplay *obj,
g_object_unref(priv->fb);
priv->fb = NULL;
}
- if (priv->pixmap) {
- g_object_unref(priv->pixmap);
- priv->pixmap = NULL;
- }
if (priv->null_cursor == NULL) {
priv->null_cursor = create_null_cursor();
@@ -890,8 +875,6 @@ static void do_framebuffer_init(VncDisplay *obj,
}
priv->fb = vnc_cairo_framebuffer_new(width, height, remoteFormat);
- priv->pixmap = gdk_pixmap_new(gtk_widget_get_window(GTK_WIDGET(obj)), width, height, -1);
-
vnc_connection_set_framebuffer(priv->conn, VNC_FRAMEBUFFER(priv->fb));
if (priv->force_size)
@@ -1990,31 +1973,54 @@ void vnc_display_set_read_only(VncDisplay *obj, gboolean enable)
obj->priv->read_only = enable;
}
+static void vnc_display_convert_data(GdkPixbuf *pixbuf,
+ cairo_surface_t *surface,
+ int width,
+ int height)
+{
+ int x, y;
+ guchar *dest_data = gdk_pixbuf_get_pixels(pixbuf);
+ int dest_stride = gdk_pixbuf_get_rowstride(pixbuf);
+ guchar *src_data = cairo_image_surface_get_data(surface);
+ int src_stride = cairo_image_surface_get_stride(surface);
+
+ for (y = 0; y < height; y++) {
+ guint32 *src = (guint32 *) src_data;
+ for (x = 0; x < width; x++) {
+ dest_data[x * 3 + 0] = src[x] >> 16;
+ dest_data[x * 3 + 1] = src[x] >> 8;
+ dest_data[x * 3 + 2] = src[x];
+ }
+
+ src_data += src_stride;
+ dest_data += dest_stride;
+ }
+}
+
GdkPixbuf *vnc_display_get_pixbuf(VncDisplay *obj)
{
VncDisplayPrivate *priv = obj->priv;
- GdkPixbuf *pixbuf;
+ VncFramebuffer *fb;
+ cairo_content_t content;
cairo_surface_t *surface;
- gint w, h;
+ GdkPixbuf *pixbuf;
if (!priv->conn ||
!vnc_connection_is_initialized(priv->conn))
return NULL;
+ fb = VNC_FRAMEBUFFER(priv->fb);
surface = vnc_cairo_framebuffer_get_surface(priv->fb);
- w = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
- h = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
-
- pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
- w,
- h);
-
- if (!gdk_pixbuf_get_from_drawable(pixbuf,
- priv->pixmap,
- NULL,
- 0, 0, 0, 0,
- w, h))
- return NULL;
+ content = cairo_surface_get_content(surface) | CAIRO_CONTENT_COLOR;
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+ !!(content & CAIRO_CONTENT_ALPHA),
+ 8,
+ vnc_framebuffer_get_width(fb),
+ vnc_framebuffer_get_height(fb));
+
+ vnc_display_convert_data(pixbuf, surface,
+ vnc_framebuffer_get_width(fb),
+ vnc_framebuffer_get_height(fb));
return pixbuf;
}
@@ -2068,7 +2074,7 @@ gboolean vnc_display_set_scaling(VncDisplay *obj,
obj->priv->allow_scaling = enable;
- if (obj->priv->pixmap != NULL) {
+ if (obj->priv->fb != NULL) {
gdk_drawable_get_size(gtk_widget_get_window(GTK_WIDGET(obj)), &ww, &wh);
gtk_widget_queue_draw_area(GTK_WIDGET(obj), 0, 0, ww, wh);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]