summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-02 00:34:37 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-09-02 00:34:37 +0100
commit59c4fe93ee30c8182ae1a29267b9c08602e2f6c5 (patch)
treea7be9ea3690aa81a1ab255db0bb7963cd7068229
parent075fc5666abe006c434bf7ec28d2d4f0226a1d3a (diff)
[xlib] Eliminate GC clipping
Eradicate the use of clipping with GC. By never using clipping, we never have to worry about retrieving a dirty clip from the GC cache.
-rw-r--r--src/cairo-xlib-private.h12
-rw-r--r--src/cairo-xlib-screen.c50
-rw-r--r--src/cairo-xlib-surface-private.h2
-rw-r--r--src/cairo-xlib-surface.c197
4 files changed, 116 insertions, 145 deletions
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index e92bb942..33601e89 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -85,7 +85,7 @@ struct _cairo_xlib_screen {
cairo_font_options_t font_options;
GC gc[4];
- int gc_depths; /* 4 x uint8_t, high bit == needs reset */
+ int gc_depths; /* 4 x uint8_t */
cairo_array_t visuals;
};
@@ -171,15 +171,13 @@ _cairo_xlib_screen_close_display (cairo_xlib_screen_t *info);
cairo_private GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- Drawable drawable,
- unsigned int *need_reset);
+ int depth,
+ Drawable drawable);
cairo_private void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- GC gc,
- cairo_bool_t reset_clip);
+ int depth,
+ GC gc);
cairo_private cairo_font_options_t *
_cairo_xlib_screen_get_font_options (cairo_xlib_screen_t *info);
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 38e64af3..800c6d2e 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -380,9 +380,8 @@ _cairo_xlib_screen_get (Display *dpy,
#if HAS_ATOMIC_OPS
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- Drawable drawable,
- unsigned int *dirty)
+ int depth,
+ Drawable drawable)
{
XGCValues gcv;
int i, new, old;
@@ -394,13 +393,13 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
if (old == 0)
break;
- if (((old >> 0) & 0x7f) == depth)
+ if (((old >> 0) & 0xff) == depth)
i = 0;
- else if (((old >> 8) & 0x7f) == depth)
+ else if (((old >> 8) & 0xff) == depth)
i = 1;
- else if (((old >> 16) & 0x7f) == depth)
+ else if (((old >> 16) & 0xff) == depth)
i = 2;
- else if (((old >> 24) & 0x7f) == depth)
+ else if (((old >> 24) & 0xff) == depth)
i = 3;
else
break;
@@ -411,10 +410,6 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
if (likely (gc != NULL)) {
(void) _cairo_atomic_ptr_cmpxchg (&info->gc[i], gc, NULL);
-
- if (old & 0x80 << (8 * i))
- *dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
-
return gc;
}
@@ -426,25 +421,23 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- GC gc,
- cairo_bool_t reset_clip)
+ int depth,
+ GC gc)
{
int i, old, new;
- depth |= reset_clip ? 0x80 : 0;
do {
do {
i = -1;
old = info->gc_depths;
- if (((old >> 0) & 0x7f) == 0)
+ if (((old >> 0) & 0xff) == 0)
i = 0;
- else if (((old >> 8) & 0x7f) == 0)
+ else if (((old >> 8) & 0xff) == 0)
i = 1;
- else if (((old >> 16) & 0x7f) == 0)
+ else if (((old >> 16) & 0xff) == 0)
i = 2;
- else if (((old >> 24) & 0x7f) == 0)
+ else if (((old >> 24) & 0xff) == 0)
i = 3;
else
goto out;
@@ -468,19 +461,15 @@ out:
#else
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- Drawable drawable,
- unsigned int *dirty)
+ int depth,
+ Drawable drawable)
{
GC gc = NULL;
int i;
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
- if (((info->gc_depths >> (8*i)) & 0x7f) == depth) {
- if (info->gc_depths & 0x80 << (8*i))
- *dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
-
+ if (((info->gc_depths >> (8*i)) & 0xff) == depth) {
info->gc_depths &= ~(0xff << (8*i));
gc = info->gc[i];
break;
@@ -502,17 +491,14 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info,
void
_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info,
- unsigned int depth,
- GC gc,
- cairo_bool_t reset_clip)
+ int depth,
+ GC gc)
{
int i;
- depth |= reset_clip ? 0x80 : 0;
-
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
- if (((info->gc_depths >> (8*i)) & 0x7f) == 0)
+ if (((info->gc_depths >> (8*i)) & 0xff) == 0)
break;
}
diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h
index b3cbe045..f8215696 100644
--- a/src/cairo-xlib-surface-private.h
+++ b/src/cairo-xlib-surface-private.h
@@ -49,7 +49,6 @@ struct _cairo_xlib_surface {
cairo_xlib_screen_t *screen;
cairo_xlib_hook_t close_display_hook;
- GC gc;
Drawable drawable;
cairo_bool_t owns_pixmap;
Visual *visual;
@@ -88,7 +87,6 @@ struct _cairo_xlib_surface {
Picture dst_picture, src_picture;
unsigned int clip_dirty;
- cairo_bool_t gc_has_clip_rects;
XRectangle embedded_clip_rects[8];
XRectangle *clip_rects;
int num_clip_rects;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index b53f4dec..1de6a974 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -83,11 +83,10 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
int depth);
static cairo_status_t
-_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface,
- cairo_bool_t set_clip);
+_cairo_xlib_surface_get_gc (cairo_xlib_surface_t *surface, GC *gc);
static void
-_cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t *surface);
+_cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc);
static void
_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface);
@@ -380,14 +379,6 @@ _cairo_xlib_surface_finish (void *abstract_surface)
XRenderFreePicture (surface->dpy, surface->src_picture);
}
- if (surface->gc != NULL) {
- _cairo_xlib_screen_put_gc (surface->screen,
- surface->depth,
- surface->gc,
- surface->gc_has_clip_rects);
- surface->gc = NULL;
- }
-
if (surface->clip_rects != surface->embedded_clip_rects)
free (surface->clip_rects);
@@ -742,8 +733,9 @@ _get_image_surface (cairo_xlib_surface_t *surface,
* temporary pixmap
*/
Pixmap pixmap;
+ GC gc;
- status = _cairo_xlib_surface_ensure_gc (surface, FALSE);
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
if (unlikely (status))
return status;
@@ -752,7 +744,7 @@ _get_image_surface (cairo_xlib_surface_t *surface,
extents.width, extents.height,
surface->depth);
if (pixmap) {
- XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc,
+ XCopyArea (surface->dpy, surface->drawable, pixmap, gc,
extents.x, extents.y,
extents.width, extents.height,
0, 0);
@@ -766,10 +758,10 @@ _get_image_surface (cairo_xlib_surface_t *surface,
XFreePixmap (surface->dpy, pixmap);
}
+ _cairo_xlib_surface_put_gc (surface, gc);
+
if (ximage == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_xlib_surface_maybe_put_gc (surface);
}
_swap_ximage_to_native (ximage);
@@ -947,21 +939,6 @@ _cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface)
}
static void
-_cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t *surface)
-{
- surface->gc_has_clip_rects = surface->clip_region != NULL;
- if (surface->clip_region != NULL) {
- XSetClipRectangles(surface->dpy, surface->gc,
- 0, 0,
- surface->clip_rects,
- surface->num_clip_rects, YXSorted);
- } else
- XSetClipMask (surface->dpy, surface->gc, None);
-
- surface->clip_dirty &= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
-}
-
-static void
_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
{
if (!surface->dst_picture) {
@@ -976,49 +953,23 @@ _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
}
static cairo_status_t
-_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface,
- cairo_bool_t set_clip)
+_cairo_xlib_surface_get_gc (cairo_xlib_surface_t *surface, GC *gc)
{
-
- if (surface->gc == NULL) {
- surface->gc = _cairo_xlib_screen_get_gc (surface->screen,
- surface->depth,
- surface->drawable,
- &surface->clip_dirty);
- if (unlikely (surface->gc == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- surface->gc_has_clip_rects =
- surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
- }
-
- if (set_clip) {
- if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC)
- _cairo_xlib_surface_set_gc_clip_rects (surface);
- } else {
- if (surface->gc_has_clip_rects) {
- surface->gc_has_clip_rects = FALSE;
- XSetClipMask (surface->dpy, surface->gc, None);
-
- surface->clip_dirty |= CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC;
- }
- }
+ *gc = _cairo_xlib_screen_get_gc (surface->screen,
+ surface->depth,
+ surface->drawable);
+ if (unlikely (*gc == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
static void
-_cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t *surface)
+_cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc)
{
- /* return the GC back to the common pool if clean */
- if (surface->gc_has_clip_rects)
- return;
-
_cairo_xlib_screen_put_gc (surface->screen,
surface->depth,
- surface->gc,
- FALSE);
- surface->gc = NULL;
+ gc);
}
static cairo_status_t
@@ -1036,6 +987,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
cairo_status_t status;
cairo_bool_t own_data;
+ GC gc;
_pixman_format_to_masks (image->pixman_format, &image_masks);
@@ -1173,16 +1125,15 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
}
}
- /* XXX set clip? */
- status = _cairo_xlib_surface_ensure_gc (surface, FALSE);
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
if (unlikely (status))
goto BAIL;
- XPutImage (surface->dpy, surface->drawable, surface->gc,
+ XPutImage (surface->dpy, surface->drawable, gc,
&ximage, src_x, src_y, dst_x, dst_y,
width, height);
- _cairo_xlib_surface_maybe_put_gc (surface);
+ _cairo_xlib_surface_put_gc (surface, gc);
BAIL:
if (own_data)
@@ -2136,6 +2087,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
cairo_bool_t is_integer_translation;
cairo_bool_t needs_alpha_composite;
cairo_content_t src_content;
+ GC gc;
if (mask_pattern != NULL && ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return UNSUPPORTED ("no support for masks");
@@ -2183,10 +2135,6 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
goto BAIL;
}
- status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
- if (unlikely (status))
- goto BAIL;
-
switch (operation)
{
case DO_RENDER:
@@ -2196,6 +2144,10 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
if (unlikely (status))
goto BAIL;
+ status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
+ if (unlikely (status))
+ goto BAIL;
+
_cairo_xlib_surface_ensure_dst_picture (dst);
if (mask) {
status = _cairo_xlib_surface_set_attributes (mask, &mask_attr,
@@ -2231,7 +2183,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
break;
case DO_XCOPYAREA:
- status = _cairo_xlib_surface_ensure_gc (dst, TRUE);
+ status = _cairo_xlib_surface_get_gc (dst, &gc);
if (unlikely (status))
goto BAIL;
@@ -2240,16 +2192,38 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
/* This is a pre-condition for DO_XCOPYAREA. */
assert (is_integer_translation);
- XCopyArea (dst->dpy,
- src->drawable,
- dst->drawable,
- dst->gc,
- src_x + src_attr.x_offset + itx,
- src_y + src_attr.y_offset + ity,
- width, height,
- dst_x, dst_y);
+ if (clip_region == NULL) {
+ XCopyArea (dst->dpy,
+ src->drawable,
+ dst->drawable,
+ gc,
+ src_x + src_attr.x_offset + itx,
+ src_y + src_attr.y_offset + ity,
+ width, height,
+ dst_x, dst_y);
+ } else {
+ int n, num_rects;
+
+ src_x += src_attr.x_offset + itx - dst_x;
+ src_y += src_attr.y_offset + ity - dst_y;
+
+ num_rects = cairo_region_num_rectangles (clip_region);
+ for (n = 0; n < num_rects; n++) {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (clip_region, n, &rect);
+ XCopyArea (dst->dpy,
+ src->drawable,
+ dst->drawable,
+ gc,
+ rect.x + src_x,
+ rect.y + src_y,
+ rect.width, rect.height,
+ rect.x, rect.y);
+ }
+ }
- _cairo_xlib_surface_maybe_put_gc (dst);
+ _cairo_xlib_surface_put_gc (dst, gc);
break;
case DO_XTILE:
@@ -2261,23 +2235,42 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
* _recategorize_composite_operation.
*/
- status = _cairo_xlib_surface_ensure_gc (dst, TRUE);
+ status = _cairo_xlib_surface_get_gc (dst, &gc);
if (unlikely (status))
goto BAIL;
+
is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix,
&itx, &ity);
/* This is a pre-condition for DO_XTILE. */
assert (is_integer_translation);
- XSetTSOrigin (dst->dpy, dst->gc,
+ XSetTSOrigin (dst->dpy, gc,
- (itx + src_attr.x_offset), - (ity + src_attr.y_offset));
- XSetTile (dst->dpy, dst->gc, src->drawable);
- XSetFillStyle (dst->dpy, dst->gc, FillTiled);
+ XSetTile (dst->dpy, gc, src->drawable);
+ XSetFillStyle (dst->dpy, gc, FillTiled);
+
+ if (clip_region == NULL) {
+ XFillRectangle (dst->dpy, dst->drawable, gc,
+ dst_x, dst_y, width, height);
+ } else {
+ int n, num_rects;
- XFillRectangle (dst->dpy, dst->drawable, dst->gc,
- dst_x, dst_y, width, height);
+ src_x += src_attr.x_offset + itx;
+ src_y += src_attr.y_offset + ity;
- _cairo_xlib_surface_maybe_put_gc (dst);
+ num_rects = cairo_region_num_rectangles (clip_region);
+ for (n = 0; n < num_rects; n++) {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (clip_region, n, &rect);
+ rect.x -= dst_x;
+ rect.y -= dst_y;
+ XFillRectangle (dst->dpy, dst->drawable, gc,
+ rect.x, rect.y, rect.width, rect.height);
+ }
+ }
+
+ _cairo_xlib_surface_put_gc (dst, gc);
break;
case DO_UNSUPPORTED:
@@ -2316,11 +2309,12 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
cairo_solid_pattern_t solid;
cairo_surface_t *solid_surface = NULL;
cairo_surface_attributes_t attrs;
+ GC gc;
int i;
_cairo_pattern_init_solid (&solid, color, CAIRO_CONTENT_COLOR);
- status = _cairo_xlib_surface_ensure_gc (surface, FALSE);
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
if (unlikely (status))
return status;
@@ -2332,25 +2326,27 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
CAIRO_PATTERN_ACQUIRE_NONE,
&solid_surface,
&attrs);
- if (unlikely (status))
- return status;
+ if (unlikely (status)) {
+ _cairo_xlib_surface_put_gc (surface, gc);
+ return status;
+ }
assert (_cairo_surface_is_xlib (solid_surface));
- XSetTSOrigin (surface->dpy, surface->gc,
+ XSetTSOrigin (surface->dpy, gc,
- (surface->base.device_transform.x0 + attrs.x_offset),
- (surface->base.device_transform.y0 + attrs.y_offset));
- XSetTile (surface->dpy, surface->gc,
+ XSetTile (surface->dpy, gc,
((cairo_xlib_surface_t *) solid_surface)->drawable);
- XSetFillStyle (surface->dpy, surface->gc, FillTiled);
+ XSetFillStyle (surface->dpy, gc, FillTiled);
for (i = 0; i < num_rects; i++) {
- XFillRectangle (surface->dpy, surface->drawable, surface->gc,
+ XFillRectangle (surface->dpy, surface->drawable, gc,
rects[i].x, rects[i].y,
rects[i].width, rects[i].height);
}
- _cairo_xlib_surface_maybe_put_gc (surface);
+ _cairo_xlib_surface_put_gc (surface, gc);
_cairo_pattern_release_surface (&solid.base, solid_surface, &attrs);
@@ -2859,11 +2855,6 @@ _cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data)
surface->drawable = None;
surface->owns_pixmap = FALSE;
}
-
- if (surface->gc != NULL) {
- XFreeGC (dpy, surface->gc);
- surface->gc = NULL;
- }
}
static cairo_surface_t *
@@ -2947,7 +2938,6 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
surface->screen = _cairo_xlib_screen_reference (screen);
surface->display = screen->display;
- surface->gc = NULL;
surface->drawable = drawable;
surface->owns_pixmap = FALSE;
surface->use_pixmap = 0;
@@ -2979,7 +2969,6 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
surface->xtransform = identity;
surface->clip_region = NULL;
- surface->gc_has_clip_rects = FALSE;
surface->clip_rects = surface->embedded_clip_rects;
surface->num_clip_rects = 0;
surface->clip_dirty = 0;