[cairo-commit] 5 commits - src/cairo-surface-subsurface.c src/cairo-xcb-private.h src/cairo-xcb-surface.c src/cairo-xcb-surface-render.c src/cairo-xlib-xcb-surface.c test/cairo-test-runner.c
Chris Wilson
ickle at kemper.freedesktop.org
Sat May 8 12:19:27 PDT 2010
src/cairo-surface-subsurface.c | 10 +-
src/cairo-xcb-private.h | 5 +
src/cairo-xcb-surface-render.c | 171 ++++++++++++++++++++++++++++++++++++++++-
src/cairo-xcb-surface.c | 31 ++++---
src/cairo-xlib-xcb-surface.c | 23 +++++
test/cairo-test-runner.c | 10 ++
6 files changed, 226 insertions(+), 24 deletions(-)
New commits:
commit 9d863cd3942c3086c24d67305f7a5892604d0eeb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat May 8 18:20:11 2010 +0100
xcb: Find the correct xcb_screen_t for faking Screen
When choosing the xcb_screen_t to use for the xlib-xcb backing surface,
it helps if it matches the screen used to generate similar surfaces and
snapshots - otherwise we end up pulling the image back from the XServer
every time we want to use the Picture.
diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index 4db129e..7e674bf 100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -342,6 +342,21 @@ cairo_xlib_surface_create_for_bitmap (Display *dpy,
}
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+static xcb_screen_t *
+_cairo_xcb_screen_from_root (xcb_connection_t *connection,
+ xcb_window_t id)
+{
+ xcb_depth_iterator_t d;
+ xcb_screen_iterator_t s;
+
+ s = xcb_setup_roots_iterator (xcb_get_setup (connection));
+ for (; s.rem; xcb_screen_next (&s)) {
+ if (s.data->root == id)
+ return s.data;
+ }
+
+ return NULL;
+}
cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
Drawable drawable,
@@ -351,6 +366,8 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
int height)
{
xcb_render_pictforminfo_t xcb_format;
+ xcb_connection_t *connection;
+ xcb_screen_t *screen;
xcb_format.id = format->id;
xcb_format.type = format->type;
@@ -365,9 +382,11 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
xcb_format.direct.alpha_mask = format->direct.alphaMask;
xcb_format.colormap = format->colormap;
+ connection = XGetXCBConnection (dpy);
+ screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
+
return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, format,
- cairo_xcb_surface_create_with_xrender_format (XGetXCBConnection (dpy),
- (xcb_screen_t *) scr,
+ cairo_xcb_surface_create_with_xrender_format (connection, screen,
drawable,
&xcb_format,
width, height));
commit 448d3571088463fc61641badcdfdc8c0002ae12a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat May 8 09:59:54 2010 +0100
xcb: Upload images in place.
A common operation is to store an image in a similar surface, so
construct a fast path to avoid the allocation and double-blit through a
temporary pixmap.
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index c03d8c2..1c8fc41 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -85,6 +85,8 @@ struct _cairo_xcb_surface {
cairo_bool_t owns_pixmap;
int use_pixmap;
+ cairo_bool_t deferred_clear;
+
int width;
int height;
int depth;
@@ -435,6 +437,9 @@ cairo_private void
_cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font);
+cairo_private void
+_cairo_xcb_surface_clear (cairo_xcb_surface_t *dst);
+
cairo_private cairo_status_t
_cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t *dst,
const cairo_pattern_t *src_pattern,
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index dba8750..c108bae 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -1131,7 +1131,7 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
const cairo_surface_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
- cairo_surface_t *const source = pattern->surface;
+ cairo_surface_t *source = pattern->surface;
cairo_xcb_picture_t *picture;
cairo_filter_t filter;
cairo_extend_t extend;
@@ -1144,6 +1144,17 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
return _cairo_xcb_black_picture (target);
}
+ {
+ cairo_xcb_surface_t *snapshot;
+
+ snapshot = (cairo_xcb_surface_t *)
+ _cairo_surface_has_snapshot (source, &_cairo_xcb_surface_backend);
+ if (snapshot != NULL) {
+ if (snapshot->screen == target->screen)
+ source = &snapshot->base;
+ }
+ }
+
picture = (cairo_xcb_picture_t *)
_cairo_surface_has_snapshot (source, &_cairo_xcb_picture_backend);
if (picture != NULL) {
@@ -1440,7 +1451,7 @@ COMPILE_TIME_ASSERT (sizeof (xcb_rectangle_t) <= sizeof (cairo_box_t));
static cairo_status_t
_render_fill_boxes (void *abstract_dst,
cairo_operator_t op,
- const cairo_color_t *color,
+ const cairo_color_t *color,
cairo_boxes_t *boxes)
{
cairo_xcb_surface_t *dst = abstract_dst;
@@ -2324,6 +2335,27 @@ _cairo_xcb_surface_fixup_unbounded_boxes (cairo_xcb_surface_t *dst,
return status;
}
+void
+_cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
+{
+ xcb_gcontext_t gc;
+ xcb_rectangle_t rect;
+
+ gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
+
+ rect.x = rect.y = 0;
+ rect.width = dst->width;
+ rect.height = dst->height;
+
+ _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
+ dst->drawable, gc,
+ 1, &rect);
+
+ _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
+
+ dst->deferred_clear = FALSE;
+}
+
static cairo_status_t
_clip_and_composite (cairo_xcb_surface_t *dst,
cairo_operator_t op,
@@ -2373,6 +2405,9 @@ _clip_and_composite (cairo_xcb_surface_t *dst,
return status;
}
+ if (dst->deferred_clear)
+ _cairo_xcb_surface_clear (dst);
+
_cairo_xcb_surface_ensure_picture (dst);
if (clip_region != NULL)
@@ -2526,7 +2561,7 @@ _composite_boxes (cairo_xcb_surface_t *dst,
else
color = &((cairo_solid_pattern_t *) src)->color;
- if (! (op == CAIRO_OPERATOR_IN && color->alpha >= 0xff00))
+ if (! (op == CAIRO_OPERATOR_IN && color->alpha_short >= 0xff00))
status = _render_fill_boxes (dst, op, color, boxes);
}
else
@@ -2573,6 +2608,112 @@ _composite_boxes (cairo_xcb_surface_t *dst,
}
static cairo_status_t
+_upload_image_inplace (cairo_xcb_surface_t *surface,
+ const cairo_pattern_t *source,
+ const cairo_rectangle_int_t *extents)
+{
+ const cairo_surface_pattern_t *pattern;
+ cairo_image_surface_t *image;
+ xcb_gcontext_t gc;
+ cairo_status_t status;
+ int len, tx, ty;
+
+ if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ pattern = (const cairo_surface_pattern_t *) source;
+ if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ {
+ cairo_xcb_surface_t *snapshot;
+
+ snapshot = (cairo_xcb_surface_t *)
+ _cairo_surface_has_snapshot (pattern->surface, &_cairo_xcb_surface_backend);
+ if (snapshot != NULL) {
+ if (snapshot->screen == surface->screen)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ }
+
+ {
+ cairo_xcb_picture_t *snapshot;
+
+ snapshot = (cairo_xcb_picture_t *)
+ _cairo_surface_has_snapshot (pattern->surface, &_cairo_xcb_picture_backend);
+ if (snapshot != NULL) {
+ if (snapshot->screen == surface->screen)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ }
+
+ image = (cairo_image_surface_t *) pattern->surface;
+ if (image->format == CAIRO_FORMAT_INVALID)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (image->depth != surface->depth)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ image = (cairo_image_surface_t *) pattern->surface;
+ if (source->extend != CAIRO_EXTEND_NONE &&
+ (extents->x + tx < 0 ||
+ extents->y + ty < 0 ||
+ extents->x + tx + extents->width > image->width ||
+ extents->y + ty + extents->height > image->height))
+ {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ status = _cairo_xcb_connection_acquire (surface->connection);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_xcb_connection_take_socket (surface->connection);
+ if (unlikely (status)) {
+ _cairo_xcb_connection_release (surface->connection);
+ return status;
+ }
+ gc = _cairo_xcb_screen_get_gc (surface->screen, surface->drawable, image->depth);
+
+ /* Do we need to trim the image? */
+ len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format));
+ if (len == image->stride) {
+ _cairo_xcb_connection_put_image (surface->connection,
+ surface->drawable, gc,
+ image->width, image->height,
+ extents->x, extents->y,
+ image->depth,
+ image->stride,
+ image->data);
+ } else {
+ _cairo_xcb_connection_put_subimage (surface->connection,
+ surface->drawable, gc,
+ extents->x + tx, extents->y + ty,
+ image->width, image->height,
+ PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
+ image->stride,
+ extents->x, extents->y,
+ image->depth,
+ image->data);
+
+ }
+
+ _cairo_xcb_screen_put_gc (surface->screen, image->depth, gc);
+ _cairo_xcb_connection_release (surface->connection);
+
+ if (surface->width == image->width && surface->height == image->height &&
+ extents->width == image->width && extents->height == image->height)
+ {
+ _cairo_surface_attach_snapshot (&image->base, &surface->base, NULL);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
_clip_and_composite_boxes (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *src,
@@ -2587,9 +2728,26 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
if (boxes->num_boxes == 0 && extents->is_bounded)
return CAIRO_STATUS_SUCCESS;
+ if (clip == NULL &&
+ (op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && dst->base.is_clear)) &&
+ boxes->num_boxes == 1 &&
+ extents->bounded.width == dst->width &&
+ extents->bounded.height == dst->height)
+ {
+ op = CAIRO_OPERATOR_SOURCE;
+ dst->deferred_clear = FALSE;
+
+ status = _upload_image_inplace (dst, src, &extents->bounded);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+ }
+
if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
return _core_boxes (dst, op, src, boxes, antialias, clip, extents);
+ if (dst->deferred_clear)
+ _cairo_xcb_surface_clear (dst);
+
/* Use a fast path if the boxes are pixel aligned */
status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@@ -2906,6 +3064,11 @@ _cairo_xcb_surface_render_paint (cairo_xcb_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
+ if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
+ surface->deferred_clear = TRUE;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
status = _cairo_composite_rectangles_init_for_paint (&extents,
surface->width,
surface->height,
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index f21d580..7b72832 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -398,6 +398,17 @@ _get_image (cairo_xcb_surface_t *surface,
xcb_get_image_reply_t *reply;
cairo_status_t status;
+ if (surface->base.is_clear || surface->deferred_clear) {
+ image = (cairo_image_surface_t *)
+ _cairo_image_surface_create_with_pixman_format (NULL,
+ surface->pixman_format,
+ surface->width,
+ surface->height,
+ 0);
+ *image_out = image;
+ return image->base.status;
+ }
+
connection = surface->connection;
status = _cairo_xcb_connection_acquire (connection);
@@ -414,18 +425,6 @@ _get_image (cairo_xcb_surface_t *surface,
goto FAIL;
}
- if (surface->base.is_clear) {
- image = (cairo_image_surface_t *)
- _cairo_image_surface_create_with_pixman_format (NULL,
- surface->pixman_format,
- surface->width,
- surface->height,
- 0);
- status = image->base.status;
- *image_out = image;
- goto FAIL;
- }
-
if (surface->use_pixmap == 0) {
status = _cairo_xcb_connection_get_image (connection,
surface->drawable,
@@ -687,8 +686,12 @@ _cairo_xcb_surface_flush (void *abstract_surface)
if (surface->drm != NULL && ! surface->marked_dirty)
return surface->drm->backend->flush (surface->drm);
- if (likely (surface->fallback == NULL))
+ if (likely (surface->fallback == NULL)) {
+ if (! surface->base.finished && surface->deferred_clear)
+ _cairo_xcb_surface_clear (surface);
+
return CAIRO_STATUS_SUCCESS;
+ }
status = surface->base.status;
if (status == CAIRO_STATUS_SUCCESS && ! surface->base.finished) {
@@ -1077,6 +1080,8 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen,
surface->owns_pixmap = owns_pixmap;
surface->use_pixmap = 0;
+ surface->deferred_clear = FALSE;
+
surface->width = width;
surface->height = height;
surface->depth = PIXMAN_FORMAT_DEPTH (pixman_format);
commit e48cbd3b47a6e4f7c1f66b3085df41546460e477
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat May 8 09:56:46 2010 +0100
xcb: Reset picture after failed snapshot.
Clear the local picture variable if we cannot use the snapshot so that
we are forced to create a new and valid picture.
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 5ea02e8..dba8750 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -1131,13 +1131,12 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
const cairo_surface_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
- cairo_surface_t *source;
+ cairo_surface_t *const source = pattern->surface;
cairo_xcb_picture_t *picture;
cairo_filter_t filter;
cairo_extend_t extend;
cairo_status_t status;
- source = pattern->surface;
if (source->is_clear) {
if (source->content & CAIRO_CONTENT_ALPHA)
return _cairo_xcb_transparent_picture (target);
@@ -1152,6 +1151,7 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
picture = (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
goto setup_picture;
}
+ picture = NULL;
}
if (source->type == CAIRO_SURFACE_TYPE_XCB)
commit 4e3c19833ef8631c1f1cd54870c0a86d88252886
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri May 7 21:30:13 2010 +0100
test: Force cairo-test-suite to return SUCCESS
Set the CAIRO_TEST_FORCE_PASS environment variable to run through the
test suite and ignore errors. Useful for forcing distcheck to continue
past a broken test suite.
diff --git a/test/cairo-test-runner.c b/test/cairo-test-runner.c
index 1e789ec..d130321 100644
--- a/test/cairo-test-runner.c
+++ b/test/cairo-test-runner.c
@@ -94,6 +94,7 @@ typedef struct _cairo_test_runner {
cairo_bool_t list_only;
cairo_bool_t full_test;
cairo_bool_t exact_test_names;
+ cairo_bool_t force_pass;
} cairo_test_runner_t;
typedef enum {
@@ -532,6 +533,9 @@ _runner_fini (cairo_test_runner_t *runner)
cairo_test_fini (&runner->base);
+ if (runner->force_pass)
+ return CAIRO_TEST_SUCCESS;
+
return runner->num_failed + runner->num_crashed ?
CAIRO_TEST_FAILURE :
runner->num_passed + runner->num_xfailed ?
@@ -672,6 +676,12 @@ main (int argc, char **argv)
}
}
+ if (getenv ("CAIRO_TEST_FORCE_PASS")) {
+ const char *env = getenv ("CAIRO_TEST_FORCE_PASS");
+
+ runner.force_pass = atoi (env);
+ }
+
_parse_cmdline (&runner, &argc, &argv);
append_argv (&argc, &argv, getenv ("CAIRO_TESTS"));
commit ad8abc01105f02a05497969b6b5ec2c8742daeb2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri May 7 21:28:58 2010 +0100
subsurface: Don't double apply device offset for deep subsurfaces.
If we have a subsurface of a subsurface then the device offset has
already been applied to the extents that we use to offset the new
subsurface.
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 90fb16d..59b56a4 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -522,13 +522,13 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
surface->extents.x += sub->extents.x;
surface->extents.y += sub->extents.y;
target = sub->target;
+ } else {
+ ret = _cairo_matrix_is_integer_translation (&target->device_transform, &tx, &ty);
+ assert (ret);
+ surface->extents.x += tx;
+ surface->extents.y += ty;
}
- ret = _cairo_matrix_is_integer_translation (&target->device_transform, &tx, &ty);
- assert (ret);
- surface->extents.x += tx;
- surface->extents.y += ty;
-
surface->target = cairo_surface_reference (target);
surface->owns_target = FALSE;
More information about the cairo-commit
mailing list