From 1c51c48606930b3a784c0bbc99a5a8eb2188ca5f Mon Sep 17 00:00:00 2001 From: Soeren Sandmann Date: Wed, 18 Feb 2004 00:59:14 +0000 Subject: [PATCH] GC caching, bug #125645 (based on patch by Brian Cameron) Wed Feb 18 01:44:59 2004 Soeren Sandmann GC caching, bug #125645 (based on patch by Brian Cameron) * gdk/gdkscreen.h (struct _GdkScreen): Add GC cache * gdk/gdkscreen.c (gdk_screen_dispose): New function. Unref the cached GC's here. * gdk/gdkdraw.c (_gdk_drawable_get_scratch_gc): New function to get a scratch gc. * gdk/gdkinternals.h: Declare the function here * gdk/gdkdraw.c (gdk_drawable_real_draw_pixbuf): Use _gdk_drawable_get_scratch_gc() instead of creating a new GC. * gdk/x11/gdkgeometry-x11.c (gdk_window_copy_area_scroll): same * gdk/x11/gdkdrawable-x11.c (draw_with_images): same * gdk/gdkwindow.c (gdk_window_get_composite_drawable): same * gdk/gdkwindow.c (gdk_window_end_paint): same * gdk/gdkpixmap.c (gdk_pixmap_colormap_new_from_pixbuf): same * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_threshold_alpha): same * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_pixmap_and_mask_for_colormap): same --- ChangeLog | 21 ++++++++++++ ChangeLog.pre-2-10 | 21 ++++++++++++ ChangeLog.pre-2-4 | 21 ++++++++++++ ChangeLog.pre-2-6 | 21 ++++++++++++ ChangeLog.pre-2-8 | 21 ++++++++++++ gdk/gdkdraw.c | 69 +++++++++++++++++++++++++++++++++------ gdk/gdkinternals.h | 4 +++ gdk/gdkpixbuf-render.c | 7 ++-- gdk/gdkpixmap.c | 3 +- gdk/gdkscreen.c | 30 +++++++++++++++-- gdk/gdkscreen.h | 3 ++ gdk/gdkwindow.c | 7 ++-- gdk/x11/gdkdrawable-x11.c | 3 +- gdk/x11/gdkgeometry-x11.c | 14 +++----- 14 files changed, 210 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 46e1aadfd6..aeb654b37f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +Wed Feb 18 01:44:59 2004 Soeren Sandmann + + GC caching, bug #125645 (based on patch by Brian Cameron) + + * gdk/gdkscreen.h (struct _GdkScreen): Add GC cache + * gdk/gdkscreen.c (gdk_screen_dispose): New function. Unref the + cached GC's here. + * gdk/gdkdraw.c (_gdk_drawable_get_scratch_gc): New function to + get a scratch gc. + * gdk/gdkinternals.h: Declare the function here + + * gdk/gdkdraw.c (gdk_drawable_real_draw_pixbuf): Use + _gdk_drawable_get_scratch_gc() instead of creating a new GC. + * gdk/x11/gdkgeometry-x11.c (gdk_window_copy_area_scroll): same + * gdk/x11/gdkdrawable-x11.c (draw_with_images): same + * gdk/gdkwindow.c (gdk_window_get_composite_drawable): same + * gdk/gdkwindow.c (gdk_window_end_paint): same + * gdk/gdkpixmap.c (gdk_pixmap_colormap_new_from_pixbuf): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_threshold_alpha): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_pixmap_and_mask_for_colormap): same + Tue Feb 17 23:28:33 2004 Matthias Clasen * gtk/gtkmenu.c (gtk_menu_init): ...and don't forget to initalize diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 46e1aadfd6..aeb654b37f 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,24 @@ +Wed Feb 18 01:44:59 2004 Soeren Sandmann + + GC caching, bug #125645 (based on patch by Brian Cameron) + + * gdk/gdkscreen.h (struct _GdkScreen): Add GC cache + * gdk/gdkscreen.c (gdk_screen_dispose): New function. Unref the + cached GC's here. + * gdk/gdkdraw.c (_gdk_drawable_get_scratch_gc): New function to + get a scratch gc. + * gdk/gdkinternals.h: Declare the function here + + * gdk/gdkdraw.c (gdk_drawable_real_draw_pixbuf): Use + _gdk_drawable_get_scratch_gc() instead of creating a new GC. + * gdk/x11/gdkgeometry-x11.c (gdk_window_copy_area_scroll): same + * gdk/x11/gdkdrawable-x11.c (draw_with_images): same + * gdk/gdkwindow.c (gdk_window_get_composite_drawable): same + * gdk/gdkwindow.c (gdk_window_end_paint): same + * gdk/gdkpixmap.c (gdk_pixmap_colormap_new_from_pixbuf): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_threshold_alpha): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_pixmap_and_mask_for_colormap): same + Tue Feb 17 23:28:33 2004 Matthias Clasen * gtk/gtkmenu.c (gtk_menu_init): ...and don't forget to initalize diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 46e1aadfd6..aeb654b37f 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,24 @@ +Wed Feb 18 01:44:59 2004 Soeren Sandmann + + GC caching, bug #125645 (based on patch by Brian Cameron) + + * gdk/gdkscreen.h (struct _GdkScreen): Add GC cache + * gdk/gdkscreen.c (gdk_screen_dispose): New function. Unref the + cached GC's here. + * gdk/gdkdraw.c (_gdk_drawable_get_scratch_gc): New function to + get a scratch gc. + * gdk/gdkinternals.h: Declare the function here + + * gdk/gdkdraw.c (gdk_drawable_real_draw_pixbuf): Use + _gdk_drawable_get_scratch_gc() instead of creating a new GC. + * gdk/x11/gdkgeometry-x11.c (gdk_window_copy_area_scroll): same + * gdk/x11/gdkdrawable-x11.c (draw_with_images): same + * gdk/gdkwindow.c (gdk_window_get_composite_drawable): same + * gdk/gdkwindow.c (gdk_window_end_paint): same + * gdk/gdkpixmap.c (gdk_pixmap_colormap_new_from_pixbuf): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_threshold_alpha): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_pixmap_and_mask_for_colormap): same + Tue Feb 17 23:28:33 2004 Matthias Clasen * gtk/gtkmenu.c (gtk_menu_init): ...and don't forget to initalize diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 46e1aadfd6..aeb654b37f 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,24 @@ +Wed Feb 18 01:44:59 2004 Soeren Sandmann + + GC caching, bug #125645 (based on patch by Brian Cameron) + + * gdk/gdkscreen.h (struct _GdkScreen): Add GC cache + * gdk/gdkscreen.c (gdk_screen_dispose): New function. Unref the + cached GC's here. + * gdk/gdkdraw.c (_gdk_drawable_get_scratch_gc): New function to + get a scratch gc. + * gdk/gdkinternals.h: Declare the function here + + * gdk/gdkdraw.c (gdk_drawable_real_draw_pixbuf): Use + _gdk_drawable_get_scratch_gc() instead of creating a new GC. + * gdk/x11/gdkgeometry-x11.c (gdk_window_copy_area_scroll): same + * gdk/x11/gdkdrawable-x11.c (draw_with_images): same + * gdk/gdkwindow.c (gdk_window_get_composite_drawable): same + * gdk/gdkwindow.c (gdk_window_end_paint): same + * gdk/gdkpixmap.c (gdk_pixmap_colormap_new_from_pixbuf): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_threshold_alpha): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_pixmap_and_mask_for_colormap): same + Tue Feb 17 23:28:33 2004 Matthias Clasen * gtk/gtkmenu.c (gtk_menu_init): ...and don't forget to initalize diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 46e1aadfd6..aeb654b37f 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,24 @@ +Wed Feb 18 01:44:59 2004 Soeren Sandmann + + GC caching, bug #125645 (based on patch by Brian Cameron) + + * gdk/gdkscreen.h (struct _GdkScreen): Add GC cache + * gdk/gdkscreen.c (gdk_screen_dispose): New function. Unref the + cached GC's here. + * gdk/gdkdraw.c (_gdk_drawable_get_scratch_gc): New function to + get a scratch gc. + * gdk/gdkinternals.h: Declare the function here + + * gdk/gdkdraw.c (gdk_drawable_real_draw_pixbuf): Use + _gdk_drawable_get_scratch_gc() instead of creating a new GC. + * gdk/x11/gdkgeometry-x11.c (gdk_window_copy_area_scroll): same + * gdk/x11/gdkdrawable-x11.c (draw_with_images): same + * gdk/gdkwindow.c (gdk_window_get_composite_drawable): same + * gdk/gdkwindow.c (gdk_window_end_paint): same + * gdk/gdkpixmap.c (gdk_pixmap_colormap_new_from_pixbuf): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_threshold_alpha): same + * gdk/gdkpixbuf-render.c (gdk_pixbuf_render_pixmap_and_mask_for_colormap): same + Tue Feb 17 23:28:33 2004 Matthias Clasen * gtk/gtkmenu.c (gtk_menu_init): ...and don't forget to initalize diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c index 97905bf566..79fa096658 100644 --- a/gdk/gdkdraw.c +++ b/gdk/gdkdraw.c @@ -1329,7 +1329,6 @@ gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable, gint x_dither, gint y_dither) { - gboolean free_gc = FALSE; GdkPixbuf *composited = NULL; gint dwidth, dheight; GdkRegion *clip; @@ -1405,12 +1404,7 @@ gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable, return; /* Actually draw */ - - if (!gc) - { - gc = gdk_gc_new (drawable); - free_gc = TRUE; - } + gc = _gdk_drawable_get_scratch_gc (drawable, FALSE); if (pixbuf->has_alpha) { @@ -1535,7 +1529,62 @@ gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable, out: if (composited) g_object_unref (composited); - - if (free_gc) - g_object_unref (gc); +} + +/** + * _gdk_drawable_get_scratch_gc: + * @drawable: A #GdkDrawable + * @graphics_exposures: Whether the reutrned #GdkGC should generate graphics exposures + * + * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has + * the standard values for @drawable, except for the graphics_exposures + * field which is determined by the @graphics_exposures parameter. + * + * The returned #GdkGC must not be altered in any way and must not + * be freed. + * + * Return value: A #GdkGC suitable for drawing on @drawable + * + * Since: 2.4 + **/ +GdkGC * +_gdk_drawable_get_scratch_gc (GdkDrawable *drawable, + gboolean graphics_exposures) +{ + GdkScreen *screen; + gint depth; + + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + screen = gdk_drawable_get_screen (drawable); + + g_return_val_if_fail (!screen->closed, NULL); + + depth = gdk_drawable_get_depth (drawable); + + if (graphics_exposures) + { + if (!screen->exposure_gcs[depth]) + { + GdkGCValues values; + GdkGCValuesMask mask; + + values.graphics_exposures = TRUE; + mask = GDK_GC_EXPOSURES; + screen->exposure_gcs[depth] = + gdk_gc_new_with_values (drawable, &values, mask); + } + + return screen->exposure_gcs[depth]; + } + else + { + if (!screen->normal_gcs[depth]) + { + screen->normal_gcs[depth] = + gdk_gc_new (drawable); + } + + return screen->normal_gcs[depth]; + } } diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 45c6e1c327..6f4c539424 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -210,6 +210,10 @@ GdkImage *_gdk_drawable_copy_to_image (GdkDrawable *drawable, gint width, gint height); +/* GC caching */ +GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable, + gboolean graphics_exposures); + /************************************* * Interfaces used by windowing code * *************************************/ diff --git a/gdk/gdkpixbuf-render.c b/gdk/gdkpixbuf-render.c index 8095188d95..b93fac33cc 100644 --- a/gdk/gdkpixbuf-render.c +++ b/gdk/gdkpixbuf-render.c @@ -25,6 +25,7 @@ #include "gdk-pixbuf-private.h" #include "gdkpixbuf.h" #include "gdkscreen.h" +#include "gdkinternals.h" @@ -82,6 +83,7 @@ gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, return; gc = gdk_gc_new (bitmap); + gc = _gdk_drawable_get_scratch_gc (GDK_DRAWABLE (bitmap), FALSE); if (!pixbuf->has_alpha) { @@ -130,8 +132,6 @@ gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, start + dest_x, y + dest_y, x - 1 + dest_x, y + dest_y); } - - g_object_unref (gc); } @@ -305,13 +305,12 @@ gdk_pixbuf_render_pixmap_and_mask_for_colormap (GdkPixbuf *pixbuf, gdk_colormap_get_visual (colormap)->depth); gdk_drawable_set_colormap (GDK_DRAWABLE (*pixmap_return), colormap); - gc = gdk_gc_new (*pixmap_return); + gc = _gdk_drawable_get_scratch_gc (*pixmap_return, FALSE); gdk_draw_pixbuf (*pixmap_return, gc, pixbuf, 0, 0, 0, 0, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), GDK_RGB_DITHER_NORMAL, 0, 0); - g_object_unref (gc); } if (mask_return) diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c index efc9763086..2392776350 100644 --- a/gdk/gdkpixmap.c +++ b/gdk/gdkpixmap.c @@ -529,12 +529,11 @@ gdk_pixmap_colormap_new_from_pixbuf (GdkColormap *colormap, else render_pixbuf = pixbuf; - tmp_gc = gdk_gc_new (pixmap); + tmp_gc = _gdk_drawable_get_scratch_gc (pixmap, FALSE); gdk_draw_pixbuf (pixmap, tmp_gc, render_pixbuf, 0, 0, 0, 0, gdk_pixbuf_get_width (render_pixbuf), gdk_pixbuf_get_height (render_pixbuf), GDK_RGB_DITHER_NORMAL, 0, 0); - g_object_unref (tmp_gc); if (render_pixbuf != pixbuf) g_object_unref (render_pixbuf); diff --git a/gdk/gdkscreen.c b/gdk/gdkscreen.c index 0492ab2095..329eab9540 100644 --- a/gdk/gdkscreen.c +++ b/gdk/gdkscreen.c @@ -23,11 +23,11 @@ #include "gdk.h" /* For gdk_rectangle_intersect() */ #include "gdkcolor.h" -#include "gdkinternals.h" #include "gdkwindow.h" #include "gdkscreen.h" -static void gdk_screen_class_init (GdkScreenClass *klass); +static void gdk_screen_class_init (GdkScreenClass *klass); +static void gdk_screen_dispose (GObject *object); enum { @@ -37,6 +37,8 @@ enum static guint signals[LAST_SIGNAL] = { 0 }; +static gpointer parent_class = NULL; + GType gdk_screen_get_type (void) { @@ -67,6 +69,12 @@ gdk_screen_get_type (void) static void gdk_screen_class_init (GdkScreenClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->dispose = gdk_screen_dispose; + /** * GdkScreen::size-changed: * @screen: the object on which the signal is emitted @@ -87,6 +95,24 @@ gdk_screen_class_init (GdkScreenClass *klass) 0); } +static void +gdk_screen_dispose (GObject *object) +{ + GdkScreen *screen = GDK_SCREEN (object); + gint i; + + for (i = 0; i < 32; ++i) + { + if (screen->exposure_gcs[i]) + g_object_unref (screen->exposure_gcs[i]); + + if (screen->normal_gcs[i]) + g_object_unref (screen->normal_gcs[i]); + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + void _gdk_screen_close (GdkScreen *screen) { diff --git a/gdk/gdkscreen.h b/gdk/gdkscreen.h index 6e2241aa5b..87a7ae0974 100644 --- a/gdk/gdkscreen.h +++ b/gdk/gdkscreen.h @@ -43,6 +43,9 @@ struct _GdkScreen GObject parent_instance; guint closed : 1; + + GdkGC *normal_gcs[32]; + GdkGC *exposure_gcs[32]; }; struct _GdkScreenClass diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index e06881e5cf..4d278dcc24 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1020,7 +1020,7 @@ gdk_window_end_paint (GdkWindow *window) gdk_region_get_clipbox (paint->region, &clip_box); - tmp_gc = gdk_gc_new (window); + tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE); _gdk_windowing_window_get_offsets (window, &x_offset, &y_offset); @@ -1033,7 +1033,6 @@ gdk_window_end_paint (GdkWindow *window) clip_box.x - x_offset, clip_box.y - y_offset, clip_box.width, clip_box.height); - g_object_unref (tmp_gc); g_object_unref (paint->pixmap); gdk_region_destroy (paint->region); g_free (paint); @@ -1398,7 +1397,7 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable, return g_object_ref (drawable); tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1); - tmp_gc = gdk_gc_new (tmp_pixmap); + tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE); /* Copy the current window contents */ gdk_draw_drawable (tmp_pixmap, @@ -1427,8 +1426,6 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable, *composite_x_offset = x; *composite_y_offset = y; - g_object_unref (tmp_gc); - return tmp_pixmap; } diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c index e5d4b30e0d..d18e9502eb 100644 --- a/gdk/x11/gdkdrawable-x11.c +++ b/gdk/x11/gdkdrawable-x11.c @@ -1260,7 +1260,7 @@ draw_with_images (GdkDrawable *drawable, dest_pict = gdk_x11_drawable_get_picture (drawable); - pix_gc = gdk_gc_new (pix); + pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE); for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT) { @@ -1291,7 +1291,6 @@ draw_with_images (GdkDrawable *drawable, XRenderFreePicture (xdisplay, mask); g_object_unref (pix); - g_object_unref (pix_gc); } typedef struct _ShmPixmapInfo ShmPixmapInfo; diff --git a/gdk/x11/gdkgeometry-x11.c b/gdk/x11/gdkgeometry-x11.c index 0ad1b5d64a..976b1aa987 100644 --- a/gdk/x11/gdkgeometry-x11.c +++ b/gdk/x11/gdkgeometry-x11.c @@ -226,25 +226,19 @@ gdk_window_copy_area_scroll (GdkWindow *window, if (dest_rect->width > 0 && dest_rect->height > 0) { - GC gc; - XGCValues values; - - values.graphics_exposures = True; - gc = XCreateGC (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - GCGraphicsExposures, &values); + GdkGC *gc; + gc = _gdk_drawable_get_scratch_gc (window, TRUE); + gdk_window_queue_translation (window, dx, dy); XCopyArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window), GDK_WINDOW_XID (window), - gc, + gdk_x11_gc_get_xgc (gc), dest_rect->x - dx, dest_rect->y - dy, dest_rect->width, dest_rect->height, dest_rect->x, dest_rect->y); - - XFreeGC (GDK_WINDOW_XDISPLAY (window), gc); } tmp_list = obj->children;