Redo Xft support to go directly to Picture objects instead of using

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)
This commit is contained in:
Owen Taylor 2001-11-05 17:48:58 +00:00 committed by Owen Taylor
parent 8a31888a04
commit 42634ee735
13 changed files with 282 additions and 77 deletions

View 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):

View 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):

View 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):

View 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):

View 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):

View 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):

View 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):

View 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);
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);
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;
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 */

View File

@ -27,9 +27,15 @@
#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

View File

@ -26,10 +26,6 @@
#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 */

View 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));

View File

@ -39,6 +39,10 @@
#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);

View 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))