[gtk+] gdk: Always clear backing store with Cairo



commit b478081b7dcda24496b03aaf21b282657d842d50
Author: Benjamin Otte <otte redhat com>
Date:   Sun Jul 25 18:13:19 2010 +0200

    gdk: Always clear backing store with Cairo
    
    The code to use Cairo existed but wasn't used on Unix due to a bug in
    XAA (that was fixed). Fwiw, we use EXA these days...

 gdk/gdkwindow.c |  159 +++++++++----------------------------------------------
 1 files changed, 25 insertions(+), 134 deletions(-)
---
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 46841be..c899cbc 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -4503,15 +4503,11 @@ gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
   END_DRAW;
 }
 
-typedef struct {
-  cairo_t *cr; /* if non-null, it means use this cairo context */
-  GdkGC *gc;   /* if non-null, it means use this GC instead */
-} BackingRectMethod;
-
-static void
-setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+static cairo_t *
+setup_backing_rect (GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  cairo_t *cr;
 
   if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
     {
@@ -4524,28 +4520,12 @@ setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWind
       x_offset_cairo += private->x;
       y_offset_cairo += private->y;
 
-      setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
+      cr = setup_backing_rect (GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
     }
   else if (private->bg_pixmap &&
 	   private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
 	   private->bg_pixmap != GDK_NO_BG)
     {
-/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
- * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
- * pixmap destination surface, can be very slow (on the order of seconds for a
- * whole-screen copy).  The workaround is to use pretty much the same code that
- * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
- * a tiled GC XFillRectangle().
- */
-
-/* Actually computing this flag is left as an exercise for the reader */
-#if defined (G_OS_UNIX)
-#  define GDK_CAIRO_REPEAT_IS_FAST 0
-#else
-#  define GDK_CAIRO_REPEAT_IS_FAST 1
-#endif
-
-#if GDK_CAIRO_REPEAT_IS_FAST
       cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
       cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
       cairo_surface_destroy (surface);
@@ -4559,31 +4539,19 @@ setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWind
 
       cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
 
-      method->cr = cairo_create (paint->surface);
-      method->gc = NULL;
+      cr = cairo_create (paint->surface);
 
-      cairo_set_source (method->cr, pattern);
+      cairo_set_source (cr, pattern);
       cairo_pattern_destroy (pattern);
-#else
-      guint gc_mask;
-      GdkGCValues gc_values;
-
-      gc_values.fill = GDK_TILED;
-      gc_values.tile = private->bg_pixmap;
-      gc_values.ts_x_origin = -x_offset_cairo;
-      gc_values.ts_y_origin = -y_offset_cairo;
-
-      gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
-
-      method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
-#endif
     }
   else
     {
-      method->cr = cairo_create (paint->surface);
+      cr = cairo_create (paint->surface);
 
-      gdk_cairo_set_source_color (method->cr, &private->bg_color);
+      gdk_cairo_set_source_color (cr, &private->bg_color);
     }
+
+  return cr;
 }
 
 static void
@@ -4592,64 +4560,25 @@ gdk_window_clear_backing_region (GdkWindow *window,
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowPaint *paint = private->paint_stack->data;
-  BackingRectMethod method;
   cairo_region_t *clip;
   GdkRectangle clipbox;
-#if 0
-  GTimer *timer;
-  double elapsed;
-#endif
+  cairo_t *cr;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-#if 0
-  timer = g_timer_new ();
-#endif
-
-  method.cr = NULL;
-  method.gc = NULL;
-  setup_backing_rect_method (&method, window, paint, 0, 0);
+  cr = setup_backing_rect (window, paint, 0, 0);
 
   clip = cairo_region_copy (paint->region);
   cairo_region_intersect (clip, region);
   cairo_region_get_extents (clip, &clipbox);
 
+  gdk_cairo_region (cr, clip);
+  cairo_fill (cr);
 
-  if (method.cr)
-    {
-      g_assert (method.gc == NULL);
-
-      gdk_cairo_region (method.cr, clip);
-      cairo_fill (method.cr);
-
-      cairo_destroy (method.cr);
-#if 0
-      elapsed = g_timer_elapsed (timer, NULL);
-      g_print ("Draw the background with Cairo: %fs\n", elapsed);
-#endif
-    }
-  else
-    {
-      g_assert (method.gc != NULL);
-
-      gdk_gc_set_clip_region (method.gc, clip);
-      gdk_draw_rectangle (window, method.gc, TRUE,
-			  clipbox.x, clipbox.y,
-			  clipbox.width, clipbox.height);
-      g_object_unref (method.gc);
-
-#if 0
-      elapsed = g_timer_elapsed (timer, NULL);
-      g_print ("Draw the background with GDK: %fs\n", elapsed);
-#endif
-    }
+  cairo_destroy (cr);
 
   cairo_region_destroy (clip);
-
-#if 0
-  g_timer_destroy (timer);
-#endif
 }
 
 static void
@@ -4661,8 +4590,8 @@ gdk_window_clear_backing_region_redirect (GdkWindow *window,
   cairo_region_t *clip_region;
   GdkRectangle clipbox;
   gint x_offset, y_offset;
-  BackingRectMethod method;
   GdkWindowPaint paint;
+  cairo_t *cr;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4686,32 +4615,12 @@ gdk_window_clear_backing_region_redirect (GdkWindow *window,
   paint.pixmap = redirect->pixmap;
   paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
 
-  method.cr = NULL;
-  method.gc = NULL;
-  setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
-
-  if (method.cr)
-    {
-      g_assert (method.gc == NULL);
-
-      gdk_cairo_region (method.cr, clip_region);
-      cairo_fill (method.cr);
-
-      cairo_destroy (method.cr);
-    }
-  else
-    {
-      g_assert (method.gc != NULL);
-
-      cairo_region_get_extents (clip_region, &clipbox);
-      gdk_gc_set_clip_region (method.gc, clip_region);
-      gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
-			  clipbox.x, clipbox.y,
-			  clipbox.width, clipbox.height);
-      g_object_unref (method.gc);
+  cr = setup_backing_rect (window, &paint, -x_offset, -y_offset);
 
-    }
+  gdk_cairo_region (cr, clip_region);
+  cairo_fill (cr);
 
+  cairo_destroy (cr);
   cairo_region_destroy (clip_region);
   cairo_surface_destroy (paint.surface);
 }
@@ -4721,10 +4630,10 @@ gdk_window_clear_backing_region_direct (GdkWindow *window,
 					cairo_region_t *region)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
-  BackingRectMethod method;
   GdkWindowPaint paint;
   cairo_region_t *clip;
   GdkRectangle clipbox;
+  cairo_t *cr;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4734,34 +4643,16 @@ gdk_window_clear_backing_region_direct (GdkWindow *window,
   paint.pixmap = window;
   paint.surface = _gdk_drawable_ref_cairo_surface (window);
 
-  method.cr = NULL;
-  method.gc = NULL;
-  setup_backing_rect_method (&method, window, &paint, 0, 0);
+  cr = setup_backing_rect (window, &paint, 0, 0);
 
   clip = cairo_region_copy (private->clip_region_with_children);
   cairo_region_intersect (clip, region);
   cairo_region_get_extents (clip, &clipbox);
 
-  if (method.cr)
-    {
-      g_assert (method.gc == NULL);
-
-      gdk_cairo_region (method.cr, clip);
-      cairo_fill (method.cr);
+  gdk_cairo_region (cr, clip);
+  cairo_fill (cr);
 
-      cairo_destroy (method.cr);
-    }
-  else
-    {
-      g_assert (method.gc != NULL);
-
-      gdk_gc_set_clip_region (method.gc, clip);
-      gdk_draw_rectangle (window, method.gc, TRUE,
-			  clipbox.x, clipbox.y,
-			  clipbox.width, clipbox.height);
-      g_object_unref (method.gc);
-
-    }
+  cairo_destroy (cr);
 
   cairo_region_destroy (clip);
   cairo_surface_destroy (paint.surface);



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