From 938e008c19e051922076001083d5da9a13907128 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 29 Nov 2010 16:37:05 +0000 Subject: [PATCH] Re-introduce a server side pixmap via cairo to cache framebuffer --- gtk-vnc-0.4.2-pixmap-cache.patch | 127 +++++++++++++++++++++++++++++++ gtk-vnc.spec | 9 ++- 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 gtk-vnc-0.4.2-pixmap-cache.patch diff --git a/gtk-vnc-0.4.2-pixmap-cache.patch b/gtk-vnc-0.4.2-pixmap-cache.patch new file mode 100644 index 0000000..319c334 --- /dev/null +++ b/gtk-vnc-0.4.2-pixmap-cache.patch @@ -0,0 +1,127 @@ +commit 20a8875df00d7e6d918fa7b94aca2baebe034cb5 +Author: Daniel P. Berrange +Date: Mon Nov 29 16:12:53 2010 +0000 + + Re-introduce a server side Pixmap to cache framebuffer + + Despite use of clipping during drawing, rendering directly + from the client side cairo image, to the window incurred + a serious performance penalty for some users' X servers. + Re-introduce a server side copy of the VNC desktop using + a cairo surface, backed by an X Pixmap. This uses cairo + APIs directly, avoiding any need for GdkPixmap. + +diff --git a/src/vncdisplay.c b/src/vncdisplay.c +index 0b7e800..33d2623 100644 +--- a/src/vncdisplay.c ++++ b/src/vncdisplay.c +@@ -50,6 +50,7 @@ struct _VncDisplayPrivate + + VncConnection *conn; + VncCairoFramebuffer *fb; ++ cairo_surface_t *fbCache; /* Cache on server display */ + + VncDisplayDepthColor depth; + +@@ -282,6 +283,32 @@ static GdkCursor *create_null_cursor(void) + return cursor; + } + ++ ++static void setup_surface_cache(VncDisplay *dpy, cairo_t *crWin, int w, int h) ++{ ++ VncDisplayPrivate *priv = dpy->priv; ++ cairo_surface_t *win = cairo_get_target(crWin); ++ cairo_t *crCache; ++ ++ if (priv->fbCache) ++ return; ++ ++ /* Creates a Pixmap on the X11 server matching the Window */ ++ priv->fbCache = cairo_surface_create_similar(win, ++ CAIRO_CONTENT_COLOR, ++ w, h); ++ crCache = cairo_create(priv->fbCache); ++ ++ /* Copy our local framebuffer contents to the Pixmap */ ++ cairo_set_source_surface(crCache, ++ vnc_cairo_framebuffer_get_surface(priv->fb), ++ 0, ++ 0); ++ cairo_paint(crCache); ++ ++ cairo_destroy(crCache); ++} ++ + static gboolean draw_event(GtkWidget *widget, cairo_t *cr) + { + VncDisplay *obj = VNC_DISPLAY(widget); +@@ -293,6 +320,8 @@ static gboolean draw_event(GtkWidget *widget, cairo_t *cr) + if (priv->fb) { + fbw = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb)); + fbh = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb)); ++ ++ setup_surface_cache(obj, cr, fbw, fbh); + } + + gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh); +@@ -327,12 +356,12 @@ static gboolean draw_event(GtkWidget *widget, cairo_t *cr) + sy = (double)wh / (double)fbh; + cairo_scale(cr, sx, sy); + cairo_set_source_surface(cr, +- vnc_cairo_framebuffer_get_surface(priv->fb), ++ priv->fbCache, + 0, + 0); + } else { + cairo_set_source_surface(cr, +- vnc_cairo_framebuffer_get_surface(priv->fb), ++ priv->fbCache, + mx, + my); + } +@@ -848,6 +877,22 @@ static void on_framebuffer_update(VncConnection *conn G_GNUC_UNUSED, + + gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh); + ++ /* If we have a pixmap, update the region which changed. ++ * If we don't have a pixmap, the entire thing will be ++ * created & rendered during the drawing handler ++ */ ++ if (priv->fbCache) { ++ cairo_t *cr = cairo_create(priv->fbCache); ++ cairo_surface_t *surface = vnc_cairo_framebuffer_get_surface(priv->fb); ++ ++ cairo_rectangle(cr, x, y, w, h); ++ cairo_clip(cr); ++ cairo_set_source_surface(cr, surface, 0, 0); ++ cairo_paint(cr); ++ ++ cairo_destroy(cr); ++ } ++ + if (priv->allow_scaling) { + double sx, sy; + +@@ -905,6 +950,10 @@ static void do_framebuffer_init(VncDisplay *obj, + g_object_unref(priv->fb); + priv->fb = NULL; + } ++ if (priv->fbCache) { ++ cairo_surface_destroy(priv->fbCache); ++ priv->fbCache = NULL; ++ } + + if (priv->null_cursor == NULL) { + priv->null_cursor = create_null_cursor(); +@@ -1496,6 +1545,10 @@ static void vnc_display_finalize (GObject *obj) + g_object_unref(priv->fb); + priv->fb = NULL; + } ++ if (priv->fbCache) { ++ cairo_surface_destroy(priv->fbCache); ++ priv->fbCache = NULL; ++ } + + if (priv->null_cursor) { + gdk_cursor_unref (priv->null_cursor); diff --git a/gtk-vnc.spec b/gtk-vnc.spec index 2f8cd06..0684812 100644 --- a/gtk-vnc.spec +++ b/gtk-vnc.spec @@ -11,20 +11,21 @@ %endif %define with_gtk3 0 -%if 0%{fedora} >= 15 +%if 0%{?fedora} >= 15 %define with_gtk3 1 %endif Summary: A GTK2 widget for VNC clients Name: gtk-vnc Version: 0.4.2 -Release: 2%{?dist}%{?extra_release} +Release: 3%{?dist}%{?extra_release} License: LGPLv2+ Group: Development/Libraries Source: http://ftp.gnome.org/pub/GNOME/sources/%{name}/0.4/%{name}-%{version}.tar.bz2 Patch1: %{name}-%{version}-motion-event-crash.patch Patch2: %{name}-%{version}-tls-shutdown-crash.patch Patch3: %{name}-%{version}-framebuffer-update-bounds-check.patch +Patch4: %{name}-%{version}-pixmap-cache.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) URL: http://live.gnome.org/gtk-vnc BuildRequires: gtk2-devel >= 2.14 @@ -152,6 +153,7 @@ cd %{name}-%{version} %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 cd .. %if %{with_gtk3} cp -a gtk-vnc-%{version} gtk-vnc2-%{version} @@ -297,6 +299,9 @@ rm -fr %{buildroot} %changelog +* Mon Nov 29 2010 Daniel P. Berrange - 0.4.2-3 +- Re-introduce a server side pixmap via cairo to cache framebuffer (rhbz #657542) + * Mon Nov 29 2010 Daniel P. Berrange - 0.4.2-2 - Fix crash in TLS shutdown code (rhbz #650601) - Fix crash in motion event handler (rhbz #650104)