SOURCES: gtk+2-cairo-repeat-pattern-workaround.diff (NEW) - https:...
freetz
freetz at pld-linux.org
Tue Feb 7 18:07:48 CET 2006
Author: freetz Date: Tue Feb 7 17:07:48 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- https://bugs.freedesktop.org/show_bug.cgi?id=4320,
https://bugs.freedesktop.org/show_bug.cgi?id=4456,
http://bugzilla.gnome.org/show_bug.cgi?id=314616
---- Files affected:
SOURCES:
gtk+2-cairo-repeat-pattern-workaround.diff (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/gtk+2-cairo-repeat-pattern-workaround.diff
diff -u /dev/null SOURCES/gtk+2-cairo-repeat-pattern-workaround.diff:1.1
--- /dev/null Tue Feb 7 18:07:48 2006
+++ SOURCES/gtk+2-cairo-repeat-pattern-workaround.diff Tue Feb 7 18:07:43 2006
@@ -0,0 +1,195 @@
+2006-02-03 Federico Mena Quintero <federico at ximian.com>
+
+ Work around https://bugs.freedesktop.org/show_bug.cgi?id=4320,
+ which used to be our own
+ http://bugzilla.gnome.org/show_bug.cgi?id=314616. If one uses a
+ pixmap for a pattern in Cairo, and sets the pattern to
+ CAIRO_EXTEND_REPEAT; and if the destination surface is also a
+ pixmap, Cairo does a slow copy instead of using XCopyArea(). So,
+ we use the same code that we used in GTK+ 2.6 (pre-cairo), by
+ filling the double-buffer pixmap with a tiled GC and
+ XFillRectangle().
+
+ * gdk/gdkwindow.c (BackingRectMethod): New structure with a
+ cairo_t and a GdkGC field. Depending on which of these fields
+ gets filled in, we'll use Cairo or GDK to clear the double-buffer
+ pixmap when painting a window.
+ (setup_backing_rect_method): Fill a BackingRectMethod as
+ appropriate, depending on the window's configuration and our
+ knowledge of whether Cairo is fast or slow when doing repeating
+ patterns.
+ (gdk_window_clear_backing_rect): Call
+ setup_backing_rect_method(). Depending on what it returns, use
+ Cairo to clear the double-buffer pixmap, or plain GDK.
+
+Novell bug: https://bugzilla.novell.com/show_bug.cgi?id=117163
+
+--- gtk+/gdk/gdkwindow.c~ 2006-01-17 15:32:30.000000000 -0600
++++ gtk+/gdk/gdkwindow.c 2006-02-02 13:21:51.000000000 -0600
+@@ -1730,43 +1730,86 @@
+ RESTORE_GC (gc);
+ }
+
++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
+-gdk_window_set_bg_pattern (GdkWindow *window,
+- cairo_t *cr,
+- int x_offset,
+- int y_offset)
++setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+ {
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+ {
+- x_offset += private->x;
+- y_offset += private->y;
+- gdk_window_set_bg_pattern (GDK_WINDOW (private->parent), cr,
+- x_offset, y_offset);
++ GdkWindowPaint tmp_paint;
++
++ tmp_paint = *paint;
++ tmp_paint.x_offset += private->x;
++ tmp_paint.y_offset += private->y;
++
++ 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);
+ }
+- else if (private->bg_pixmap &&
+- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+- private->bg_pixmap != GDK_NO_BG)
++ 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);
+
+- if (x_offset != 0 || y_offset != 0)
++ if (x_offset_cairo != 0 || y_offset_cairo != 0)
+ {
+ cairo_matrix_t matrix;
+- cairo_matrix_init_translate (&matrix, x_offset, y_offset);
++ cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
+ cairo_pattern_set_matrix (pattern, &matrix);
+ }
+
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+- cairo_set_source (cr, pattern);
++
++ method->cr = cairo_create (paint->surface);
++ method->gc = NULL;
++
++ cairo_set_source (method->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
+ {
+- gdk_cairo_set_source_color (cr, &private->bg_color);
++ method->cr = cairo_create (paint->surface);
++
++ gdk_cairo_set_source_color (method->cr, &private->bg_color);
+ }
+ }
+
+@@ -1779,22 +1822,56 @@
+ {
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowPaint *paint = private->paint_stack->data;
+- cairo_t *cr;
++ BackingRectMethod method;
++#if 0
++ GTimer *timer;
++ double elapsed;
++#endif
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+- cr = cairo_create (paint->surface);
++#if 0
++ timer = g_timer_new ();
++#endif
++
++ method.cr = NULL;
++ method.gc = NULL;
++ setup_backing_rect_method (&method, window, paint, 0, 0);
++
++ if (method.cr)
++ {
++ g_assert (method.gc == NULL);
++
++ cairo_rectangle (method.cr, x, y, width, height);
++ cairo_clip (method.cr);
+
+- gdk_window_set_bg_pattern (window, cr, 0, 0);
++ gdk_cairo_region (method.cr, paint->region);
++ cairo_fill (method.cr);
+
+- cairo_rectangle (cr, x, y, width, height);
+- cairo_clip (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_cairo_region (cr, paint->region);
+- cairo_fill (cr);
++ gdk_gc_set_clip_region (method.gc, paint->region);
++ gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, 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);
++#if 0
++ g_timer_destroy (timer);
++#endif
+ }
+
+ /**
================================================================
More information about the pld-cvs-commit
mailing list