]> Pileus Git - ~andy/gtk/commitdiff
Redo Xft support to go directly to Picture objects instead of using
authorOwen Taylor <otaylor@redhat.com>
Mon, 5 Nov 2001 17:48:58 +0000 (17:48 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Mon, 5 Nov 2001 17:48:58 +0000 (17:48 +0000)
Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>

* gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
gdk/x11/gdkwindow-x11.c: Redo Xft support to go
directly to Picture objects instead of using XftDraw.
This fixes the problem where we weren't able to
properly destroy XftDraw objects before destroying
the accompanying windows, and probably improves
efficiency a bit too. (#50214)

13 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkdrawable-x11.h
gdk/x11/gdkgc-x11.c
gdk/x11/gdkpixmap-x11.c
gdk/x11/gdkprivate-x11.h
gdk/x11/gdkwindow-x11.c

index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index e8912c4145f9e017c1f1ca611cad07fc67102e97..2f34bfae108d91ac403cdbdec8453a594e579ba3 100644 (file)
@@ -1,3 +1,14 @@
+Mon Nov  5 12:46:44 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkgc-x11.c
+       gdk/x11/gdkpixmap-x11.c gdk/x11/gdkprivate-x11.h
+       gdk/x11/gdkwindow-x11.c: Redo Xft support to go
+       directly to Picture objects instead of using XftDraw.
+       This fixes the problem where we weren't able to 
+       properly destroy XftDraw objects before destroying
+       the accompanying windows, and probably improves
+       efficiency a bit too. (#50214)
+
 Mon Nov  5 10:01:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): 
index f5589dcb0a9365b76fa526344015793eb8abe4c2..0ca8d12201225ccb0ea45ffc2a027f4c06820034 100644 (file)
@@ -203,6 +203,70 @@ gdk_drawable_impl_x11_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+#ifdef HAVE_XFT
+static Picture
+gdk_x11_drawable_get_picture (GdkDrawable *drawable)
+{
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+
+  if (impl->picture == None)
+    {
+      GdkVisual *visual = gdk_drawable_get_visual (drawable);
+      XRenderPictFormat *format;
+
+      if (!visual)
+       {
+         g_warning ("Using Xft rendering requires the drawable argument to\n"
+                    "have a specified colormap. All windows have a colormap,\n"
+                    "however, pixmaps only have colormap by default if they\n"
+                    "were created with a non-NULL window argument. Otherwise\n"
+                    "a colormap must be set on them with gdk_drawable_set_colormap");
+         return None;
+       }
+
+      format = XRenderFindVisualFormat (impl->xdisplay, GDK_VISUAL_XVISUAL (visual));
+      impl->picture = XRenderCreatePicture (impl->xdisplay, impl->xid, format, 0, NULL);
+    }
+
+  return impl->picture;
+}
+
+static void
+gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
+                                     GdkGC       *gc)
+{
+  GdkGCX11 *gc_private = GDK_GC_X11 (gc);  
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  Picture picture = gdk_x11_drawable_get_picture (drawable);
+
+  if (gc_private->clip_region)
+    {
+      GdkRegionBox *boxes = gc_private->clip_region->rects;
+      gint n_boxes = gc_private->clip_region->numRects;
+      XRectangle *rects = g_new (XRectangle, n_boxes);
+      int i;
+
+      for (i=0; i < n_boxes; i++)
+       {
+         rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
+         rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
+         rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
+         rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
+       }
+
+      XRenderSetPictureClipRectangles (impl->xdisplay, picture, 0, 0, rects, n_boxes);
+
+      g_free (rects);
+    }
+  else
+    {
+      XRenderPictureAttributes pa;
+      pa.clip_mask = None;
+      XRenderChangePicture (impl->xdisplay, picture, CPClipMask, &pa);
+    }
+}
+#endif  
+
 /*****************************************************
  * X11 specific implementations of generic functions *
  *****************************************************/
@@ -581,40 +645,6 @@ gdk_x11_draw_lines (GdkDrawable *drawable,
   g_free (tmp_points);
 }
 
-#if HAVE_XFT
-static void
-update_xft_draw_clip (GdkGC *gc)
-{
-  GdkGCX11 *private = GDK_GC_X11 (gc);
-  int i;
-  
-  if (private->xft_draw)
-    {
-      if (private->clip_region)
-       {
-         GdkRegionBox *boxes = private->clip_region->rects;
-         Region region = XCreateRegion ();
-         
-         for (i=0; i<private->clip_region->numRects; i++)
-           {
-             XRectangle rect;
-             
-             rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
-             rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
-             rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
-             rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
-             XUnionRectWithRegion (&rect, region, region);
-           }
-         
-         XftDrawSetClip (private->xft_draw, region);
-         XDestroyRegion (region);
-       }
-      else
-       XftDrawSetClip (private->xft_draw, NULL);
-    }
-}
-#endif  
-
 static void
 gdk_x11_draw_glyphs (GdkDrawable      *drawable,
                     GdkGC            *gc,
@@ -630,39 +660,15 @@ gdk_x11_draw_glyphs (GdkDrawable      *drawable,
 #if HAVE_XFT
   if (PANGO_XFT_IS_FONT (font))
     {
-      GdkGCX11 *gc_x11 = GDK_GC_X11 (gc);
-      XftColor xft_color;
-      GdkColormap *cmap;
-      GdkColor color;
-      
-      cmap = gdk_gc_get_colormap (gc);
+      Picture src_picture;
+      Picture dest_picture;
 
-      _gdk_x11_gc_flush (gc);
-      
-      if (!gc_x11->xft_draw)
-       {
-         gc_x11->xft_draw = XftDrawCreate (impl->xdisplay,
-                                           impl->xid,
-                                           GDK_VISUAL_XVISUAL (gdk_colormap_get_visual (cmap)),
-                                           GDK_COLORMAP_XCOLORMAP (cmap));
-         update_xft_draw_clip (gc);
-       }
-      
-      else
-       {
-         XftDrawChange (gc_x11->xft_draw, impl->xid);
-         update_xft_draw_clip (gc);
-       }
-      
-      gdk_colormap_query_color (cmap, gc_x11->fg_pixel, &color);
-      
-      xft_color.color.red = color.red;
-      xft_color.color.green = color.green;
-      xft_color.color.blue = color.blue;
-      xft_color.color.alpha = 0xffff;
+      src_picture = _gdk_x11_gc_get_fg_picture (gc);
+
+      gdk_x11_drawable_update_picture_clip (drawable, gc);
+      dest_picture = gdk_x11_drawable_get_picture (drawable);
       
-      pango_xft_render (gc_x11->xft_draw, &xft_color,
-                       font, glyphs, x, y);
+      pango_xft_picture_render (impl->xdisplay, src_picture, dest_picture, font, glyphs, x, y);
     }
   else
 #endif  /* !HAVE_XFT */
index 7d20d50d52d61f5e00050aa99578ddee2747d5ed..aa681585d45785f3b8f264d2b3cb40e74070b2a8 100644 (file)
 #ifndef __GDK_DRAWABLE_X11_H__
 #define __GDK_DRAWABLE_X11_H__
 
+#include <config.h>
+
 #include <gdk/gdkdrawable.h>
 #include <gdk/x11/gdkx.h>
 
+#ifdef HAVE_XFT
+#include <X11/extensions/Xrender.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -57,6 +63,10 @@ struct _GdkDrawableImplX11
   
   Window xid;
   Display *xdisplay;
+
+#ifdef HAVE_XFT
+  Picture picture;
+#endif  
 };
  
 struct _GdkDrawableImplX11Class 
index ce3c60490e9c39192d9821af08602c7f84b640ff..f6c4da625c3956cc04e4a3ff27eccbd460ff5cb5 100644 (file)
 
 #include <config.h>
 
-#if HAVE_XFT
-#include <pango/pangoxft.h>
-#endif
-
 #include "gdkgc.h"
 #include "gdkprivate-x11.h"
 #include "gdkregion-generic.h"
@@ -112,13 +108,13 @@ gdk_gc_x11_finalize (GObject *object)
   if (x11_gc->clip_region)
     gdk_region_destroy (x11_gc->clip_region);
   
-  XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
-
 #if HAVE_XFT
-  if (x11_gc->xft_draw)
-    XftDrawDestroy (x11_gc->xft_draw);
+  if (x11_gc->fg_picture != None)
+    XRenderFreePicture (x11_gc->xdisplay, x11_gc->fg_picture);
 #endif  
   
+  XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -757,3 +753,93 @@ gdk_x11_gc_get_xgc (GdkGC *gc)
 
   return gc_x11->xgc;
 }
+
+/* Various bits of the below are roughly cribbed from XFree86
+ * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard
+ */
+
+static XRenderPictFormat *
+foreground_format (GdkGC *gc)
+{
+  XRenderPictFormat pf;
+
+  pf.type = PictTypeDirect;
+  pf.depth = 32;
+  pf.direct.redMask = 0xff;
+  pf.direct.greenMask = 0xff;
+  pf.direct.blueMask = 0xff;
+  pf.direct.alphaMask = 0xff;
+
+  return XRenderFindFormat (GDK_GC_XDISPLAY (gc),
+                           (PictFormatType |
+                            PictFormatDepth |
+                            PictFormatRedMask |
+                            PictFormatGreenMask |
+                            PictFormatBlueMask |
+                            PictFormatAlphaMask),
+                           &pf,
+                           0);
+}
+
+#ifdef HAVE_XFT
+/**
+ * _gdk_x11_gc_get_fg_picture:
+ * @gc: a #GdkGC
+ * 
+ * Gets a Xrender Picture object suitable for being the source
+ * drawable for drawing with the foreground the graphics context.
+ * (Currently, only foreground color is handled, but in the
+ * future we should handle tiles/stipples as well.)
+ * 
+ * Return value: a Picture, owned by the GC; this cannot be
+ *   used over subsequent modification of the GC.
+ **/
+Picture
+_gdk_x11_gc_get_fg_picture (GdkGC *gc)
+{
+  GdkGCX11 *x11_gc;
+  GdkColormap *cmap = gdk_gc_get_colormap (gc);
+  gboolean new = FALSE;
+  GdkColor color;
+  
+  g_return_val_if_fail (GDK_IS_GC_X11 (gc), None);
+
+  x11_gc = GDK_GC_X11 (gc);
+
+  if (x11_gc->fg_picture == None)
+    {
+      XRenderPictureAttributes pa;
+      XRenderPictFormat *pix_format = foreground_format (gc);
+
+      Pixmap pix = XCreatePixmap (x11_gc->xdisplay, _gdk_root_window,
+                                 1, 1, pix_format->depth);
+      pa.repeat = True;
+      x11_gc->fg_picture = XRenderCreatePicture (x11_gc->xdisplay, 
+                                                pix,
+                                                pix_format,
+                                                CPRepeat, &pa);
+      XFreePixmap (x11_gc->xdisplay, pix);
+      
+      new = TRUE;
+    }
+
+  gdk_colormap_query_color (cmap, x11_gc->fg_pixel, &color);
+
+  if (new ||
+      x11_gc->fg_picture_color.red != color.red ||
+      x11_gc->fg_picture_color.green != color.green ||
+      x11_gc->fg_picture_color.blue != color.blue)
+    {
+      x11_gc->fg_picture_color.red = color.red;
+      x11_gc->fg_picture_color.green = color.green;
+      x11_gc->fg_picture_color.blue = color.blue;
+      x11_gc->fg_picture_color.alpha = 0xffff;
+
+      XRenderFillRectangle (x11_gc->xdisplay, PictOpSrc, 
+                           x11_gc->fg_picture, &x11_gc->fg_picture_color,
+                           0, 0, 1, 1); 
+    }
+
+  return x11_gc->fg_picture;
+}
+#endif /* HAVE_XFT */
index 15804ce8a4764769567a4d5deec69dd82d3d2908..ae50cc3375874f6a723b253c66024cbf66b87087 100644 (file)
@@ -122,6 +122,15 @@ gdk_pixmap_impl_x11_finalize (GObject *object)
   GdkPixmapImplX11 *impl = GDK_PIXMAP_IMPL_X11 (object);
   GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_X11 (impl)->wrapper);
 
+#ifdef HAVE_XFT  
+  {
+    GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
+
+    if (draw_impl->picture)
+      XRenderFreePicture (draw_impl->xdisplay, draw_impl->picture);
+  }
+#endif /* HAVE_XFT */  
+
   if (!impl->is_foreign)
     XFreePixmap (GDK_PIXMAP_XDISPLAY (wrapper), GDK_PIXMAP_XID (wrapper));
   
index 8b960974fb672deeafc2b67a2aabe06d0b83ec4b..6552ff5383c55a25c242228b9353010396b6a081 100644 (file)
 
 #include <config.h>
 
+#if HAVE_XFT
+#include <X11/extensions/Xrender.h>
+#endif
+
 #define GDK_TYPE_GC_X11              (_gdk_gc_x11_get_type ())
 #define GDK_GC_X11(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_X11, GdkGCX11))
 #define GDK_GC_X11_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GC_X11, GdkGCX11Class))
@@ -60,10 +64,10 @@ struct _GdkGCX11
   GdkRegion *clip_region;
   guint dirty_mask;
 
-  /* We can't conditionalize on HAVE_XFT here, so we simply always
-   * have this here as a gpointer.
-   */
-  gpointer xft_draw;
+#ifdef HAVE_XFT  
+  Picture fg_picture;
+  XRenderColor fg_picture_color; 
+#endif  
   gulong fg_pixel;
 };
 
@@ -95,6 +99,10 @@ gint          gdk_send_xevent          (Window           window,
 
 GType _gdk_gc_x11_get_type (void);
 
+#ifdef HAVE_XFT
+Picture _gdk_x11_gc_get_fg_picture     (GdkGC            *gc);
+#endif /* HAVE_XFT */
+
 GdkGC *_gdk_x11_gc_new                  (GdkDrawable     *drawable,
                                         GdkGCValues     *values,
                                         GdkGCValuesMask  values_mask);
index f6d6d89d901192e355480091f15eb0f588597f39..49a663694336f115b0ed8e10d829a8b98c674874 100644 (file)
@@ -738,6 +738,15 @@ _gdk_windowing_window_destroy (GdkWindow *window,
   if (private->extension_events != 0)
     gdk_input_window_destroy (window);
 
+#ifdef HAVE_XFT  
+  {
+    GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+
+    if (draw_impl->picture)
+      XRenderFreePicture (draw_impl->xdisplay, draw_impl->picture);
+  }
+#endif /* HAVE_XFT */  
+
   if (private->window_type == GDK_WINDOW_FOREIGN)
     {
       if (!foreign_destroy && (private->parent != NULL))