[cairo-commit] src/cairo-composite-rectangles.c src/cairo-composite-rectangles-private.h src/cairo-xcb-connection.c src/cairo-xcb-private.h src/cairo-xcb-surface.c src/cairo-xcb-surface-render.c
Chris Wilson
ickle at kemper.freedesktop.org
Mon Sep 19 07:25:45 PDT 2011
src/cairo-composite-rectangles-private.h | 4
src/cairo-composite-rectangles.c | 18 +
src/cairo-xcb-connection.c | 6
src/cairo-xcb-private.h | 14 -
src/cairo-xcb-surface-render.c | 122 +++---------
src/cairo-xcb-surface.c | 314 ++++++++++++++++++++++++-------
6 files changed, 310 insertions(+), 168 deletions(-)
New commits:
commit fd613cb9f94daff0c8d4fdb27ff89894d41682a3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue Aug 2 13:51:30 2011 +0100
xcb: track fallback damage
And only upload the parts of the image that are modified during the
fallback. I have to keep reminding myself that the goal is always to
reduce the amount of fallbacks required...
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-composite-rectangles-private.h b/src/cairo-composite-rectangles-private.h
index 8603108..fd77289 100644
--- a/src/cairo-composite-rectangles-private.h
+++ b/src/cairo-composite-rectangles-private.h
@@ -147,6 +147,10 @@ cairo_private cairo_bool_t
_cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite,
cairo_clip_t *clip);
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_add_to_damage (cairo_composite_rectangles_t *composite,
+ cairo_boxes_t *damage);
+
cairo_private void
_cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents);
diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index c66d3d6..7fc0f5f 100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -436,3 +436,21 @@ _cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *compo
_cairo_box_from_rectangle (&box, &extents);
return _cairo_clip_contains_box (clip, &box);
}
+
+cairo_int_status_t
+_cairo_composite_rectangles_add_to_damage (cairo_composite_rectangles_t *composite,
+ cairo_boxes_t *damage)
+{
+ cairo_int_status_t status;
+ int n;
+
+ for (n = 0; n < composite->clip->num_boxes; n++) {
+ status = _cairo_boxes_add (damage,
+ CAIRO_ANTIALIAS_NONE,
+ &composite->clip->boxes[n]);
+ if (unlikely (status))
+ return status;
+ }
+
+ return CAIRO_INT_STATUS_SUCCESS;
+}
diff --git a/src/cairo-xcb-connection.c b/src/cairo-xcb-connection.c
index 2808395..2c63a93 100644
--- a/src/cairo-xcb-connection.c
+++ b/src/cairo-xcb-connection.c
@@ -806,10 +806,9 @@ cairo_xcb_device_debug_cap_xshm_version (cairo_device_t *device,
int minor_version)
{
cairo_xcb_connection_t *connection = (cairo_xcb_connection_t *) device;
- cairo_status_t status;
if (device->backend->type != CAIRO_DEVICE_TYPE_XCB) {
- status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
+ _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return;
}
@@ -843,10 +842,9 @@ cairo_xcb_device_debug_cap_xrender_version (cairo_device_t *device,
int minor_version)
{
cairo_xcb_connection_t *connection = (cairo_xcb_connection_t *) device;
- cairo_status_t status;
if (device->backend->type != CAIRO_DEVICE_TYPE_XCB) {
- status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
+ _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return;
}
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index c27843a..42a112c 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -87,7 +87,8 @@ struct _cairo_xcb_shm_info {
struct _cairo_xcb_surface {
cairo_surface_t base;
- cairo_surface_t *fallback;
+ cairo_image_surface_t *fallback;
+ cairo_boxes_t fallback_damage;
cairo_xcb_connection_t *connection;
cairo_xcb_screen_t *screen;
@@ -430,14 +431,14 @@ cairo_private cairo_int_status_t
_cairo_xcb_surface_render_paint (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- const cairo_clip_t *clip);
+ cairo_composite_rectangles_t *composite);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_mask (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- const cairo_clip_t *clip);
+ cairo_composite_rectangles_t *composite);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
@@ -449,7 +450,7 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- const cairo_clip_t *clip);
+ cairo_composite_rectangles_t *composite);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
@@ -459,7 +460,7 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- const cairo_clip_t *clip);
+ cairo_composite_rectangles_t *composite);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
@@ -468,7 +469,8 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- const cairo_clip_t *clip);
+ cairo_composite_rectangles_t *composite,
+ cairo_bool_t overlap);
cairo_private void
_cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 42178b2..0cb7e15 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -3415,9 +3415,8 @@ cairo_int_status_t
_cairo_xcb_surface_render_paint (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- const cairo_clip_t *clip)
+ cairo_composite_rectangles_t *composite)
{
- cairo_composite_rectangles_t extents;
cairo_boxes_t boxes;
cairo_status_t status;
@@ -3430,36 +3429,20 @@ _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;
- surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (clip == NULL &&
- source->type == CAIRO_PATTERN_TYPE_SOLID &&
+ if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
(op == CAIRO_OPERATOR_SOURCE ||
+ op == CAIRO_OPERATOR_CLEAR ||
(surface->base.is_clear &&
(op == CAIRO_OPERATOR_ADD || op == CAIRO_OPERATOR_OVER))))
{
- cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
surface->deferred_clear = TRUE;
- surface->deferred_clear_color = solid->color;
+ surface->deferred_clear_color = composite->source_pattern.solid.color;
return CAIRO_STATUS_SUCCESS;
}
- status = _cairo_composite_rectangles_init_for_paint (&extents,
- &surface->base,
- op, source,
- clip);
- if (unlikely (status))
- return status;
-
- _cairo_clip_steal_boxes(extents.clip, &boxes);
- status = _clip_and_composite_boxes (surface, op, source, &boxes, &extents);
- _cairo_clip_unsteal_boxes (extents.clip, &boxes);
-
- _cairo_composite_rectangles_fini (&extents);
+ _cairo_clip_steal_boxes(composite->clip, &boxes);
+ status = _clip_and_composite_boxes (surface, op, source, &boxes, composite);
+ _cairo_clip_unsteal_boxes (composite->clip, &boxes);
return status;
}
@@ -3469,9 +3452,8 @@ _cairo_xcb_surface_render_mask (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- const cairo_clip_t *clip)
+ cairo_composite_rectangles_t *composite)
{
- cairo_composite_rectangles_t extents;
cairo_status_t status;
if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
@@ -3480,31 +3462,24 @@ _cairo_xcb_surface_render_mask (cairo_xcb_surface_t *surface,
if ((surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
- status = _cairo_composite_rectangles_init_for_mask (&extents, &surface->base,
- op, source, mask, clip);
- if (unlikely (status))
- return status;
-
if (mask->type == CAIRO_PATTERN_TYPE_SOLID &&
- extents.clip->path == NULL &&
- ! _cairo_clip_is_region (extents.clip)) {
+ composite->clip->path == NULL &&
+ ! _cairo_clip_is_region (composite->clip)) {
status = _clip_and_composite (surface, op, source,
_composite_opacity_boxes,
_composite_opacity_boxes,
(void *) mask,
- &extents, need_unbounded_clip (&extents));
+ composite, need_unbounded_clip (composite));
} else {
xcb_draw_func_t mask_func = NULL;
if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS)
- mask_func = extents.clip->path ? _composite_mask_clip : _composite_mask_clip_boxes;
+ mask_func = composite->clip->path ? _composite_mask_clip : _composite_mask_clip_boxes;
status = _clip_and_composite (surface, op, source,
_composite_mask, mask_func,
(void *) mask,
- &extents, need_bounded_clip (&extents));
+ composite, need_bounded_clip (composite));
}
- _cairo_composite_rectangles_fini (&extents);
-
return status;
}
@@ -3613,9 +3588,8 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- const cairo_clip_t *clip)
+ cairo_composite_rectangles_t *composite)
{
- cairo_composite_rectangles_t extents;
cairo_int_status_t status;
if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
@@ -3627,19 +3601,11 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- status = _cairo_composite_rectangles_init_for_stroke (&extents,
- &surface->base,
- op, source,
- path, style, ctm,
- clip);
- if (unlikely (status))
- return status;
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
cairo_boxes_t boxes;
- _cairo_boxes_init_with_clip (&boxes, extents.clip);
+ _cairo_boxes_init_with_clip (&boxes, composite->clip);
status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
style,
ctm,
@@ -3647,7 +3613,7 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
&boxes);
if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, &extents);
+ &boxes, composite);
}
_cairo_boxes_fini (&boxes);
}
@@ -3658,20 +3624,18 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
path, style,
ctm, ctm_inverse,
tolerance, antialias,
- &extents);
+ composite);
} else if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
status = _cairo_xcb_surface_render_stroke_via_mask (surface, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias,
- &extents);
+ composite);
} else {
ASSERT_NOT_REACHED;
}
}
- _cairo_composite_rectangles_fini (&extents);
-
return status;
}
@@ -3763,9 +3727,8 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- const cairo_clip_t *clip)
+ cairo_composite_rectangles_t *composite)
{
- cairo_composite_rectangles_t extents;
cairo_int_status_t status;
if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
@@ -3777,24 +3740,18 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- status = _cairo_composite_rectangles_init_for_fill (&extents, &surface->base,
- op, source, path,
- clip);
- if (unlikely (status))
- return status;
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_path_fixed_fill_is_rectilinear (path)) {
cairo_boxes_t boxes;
- _cairo_boxes_init_with_clip (&boxes, extents.clip);
+ _cairo_boxes_init_with_clip (&boxes, composite->clip);
status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
fill_rule,
antialias,
&boxes);
if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, &extents);
+ &boxes, composite);
}
_cairo_boxes_fini (&boxes);
}
@@ -3803,18 +3760,16 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) {
status = _cairo_xcb_surface_render_fill_as_polygon (surface, op, source, path,
fill_rule, tolerance, antialias,
- &extents);
+ composite);
} else if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
status = _cairo_xcb_surface_render_fill_via_mask (surface, op, source, path,
fill_rule, tolerance, antialias,
- &extents);
+ composite);
} else {
ASSERT_NOT_REACHED;
}
}
- _cairo_composite_rectangles_fini (&extents);
-
return status;
}
@@ -4759,11 +4714,10 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- const cairo_clip_t *clip)
+ cairo_composite_rectangles_t *composite,
+ cairo_bool_t overlap)
{
- cairo_composite_rectangles_t extents;
cairo_int_status_t status;
- cairo_bool_t overlap;
if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -4771,19 +4725,11 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS | CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
- status = _cairo_composite_rectangles_init_for_glyphs (&extents, &surface->base,
- op, source,
- scaled_font,
- glyphs, num_glyphs,
- clip, &overlap);
- if (unlikely (status))
- return status;
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS && 0) {
_cairo_scaled_font_freeze_cache (scaled_font);
- status = _can_composite_glyphs (surface, &extents.bounded,
+ status = _can_composite_glyphs (surface, &composite->bounded,
scaled_font, glyphs, &num_glyphs);
if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
composite_glyphs_info_t info;
@@ -4794,11 +4740,11 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
info.num_glyphs = num_glyphs;
info.use_mask =
overlap ||
- ! extents.is_bounded ||
- ! _cairo_clip_is_region(extents.clip);
+ ! composite->is_bounded ||
+ ! _cairo_clip_is_region(composite->clip);
- if (extents.mask.width > extents.unbounded.width ||
- extents.mask.height > extents.unbounded.height)
+ if (composite->mask.width > composite->unbounded.width ||
+ composite->mask.height > composite->unbounded.height)
{
/* Glyphs are tricky since we do not directly control the
* geometry and their inked extents depend on the
@@ -4809,8 +4755,8 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
}
status = _clip_and_composite (surface, op, source,
_composite_glyphs, NULL,
- &info, &extents,
- need_bounded_clip (&extents) |
+ &info, composite,
+ need_bounded_clip (composite) |
flags);
}
@@ -4822,10 +4768,8 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
status =
_cairo_xcb_surface_render_glyphs_via_mask (surface, op, source,
scaled_font, glyphs, num_glyphs,
- &extents);
+ composite);
}
- _cairo_composite_rectangles_fini (&extents);
-
return status;
}
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 67568bd..b3ca319 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -43,6 +43,7 @@
#include "cairo-xcb.h"
#include "cairo-xcb-private.h"
+#include "cairo-composite-rectangles-private.h"
#include "cairo-default-context-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-surface-backend-private.h"
@@ -188,9 +189,10 @@ _cairo_xcb_surface_finish (void *abstract_surface)
cairo_status_t status;
if (surface->fallback != NULL) {
- cairo_surface_finish (surface->fallback);
- cairo_surface_destroy (surface->fallback);
+ cairo_surface_finish (&surface->fallback->base);
+ cairo_surface_destroy (&surface->fallback->base);
}
+ _cairo_boxes_fini (&surface->fallback_damage);
cairo_list_del (&surface->link);
@@ -455,7 +457,7 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
cairo_surface_t *image;
if (surface->fallback != NULL) {
- image = cairo_surface_reference (surface->fallback);
+ image = cairo_surface_reference (&surface->fallback->base);
goto DONE;
}
@@ -582,6 +584,108 @@ _put_image (cairo_xcb_surface_t *surface,
return status;
}
+static cairo_int_status_t
+_put_shm_image_boxes (cairo_xcb_surface_t *surface,
+ cairo_image_surface_t *image,
+ xcb_gcontext_t gc,
+ cairo_boxes_t *boxes)
+{
+#if CAIRO_HAS_XCB_SHM_FUNCTIONS
+ cairo_xcb_shm_info_t *shm_info;
+
+ shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
+ (const cairo_user_data_key_t *) surface->connection);
+ if (shm_info != NULL) {
+ struct _cairo_boxes_chunk *chunk;
+
+ for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
+ int i;
+
+ for (i = 0; i < chunk->count; i++) {
+ cairo_box_t *b = &chunk->base[i];
+ int x = _cairo_fixed_integer_part (b->p1.x);
+ int y = _cairo_fixed_integer_part (b->p1.y);
+ int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
+ int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
+
+ _cairo_xcb_connection_shm_put_image (surface->connection,
+ surface->drawable,
+ gc,
+ surface->width, surface->height,
+ x, y,
+ width, height,
+ x, y,
+ image->depth,
+ shm_info->shm,
+ shm_info->offset);
+ }
+ }
+ }
+
+ return CAIRO_INT_STATUS_SUCCESS;
+#endif
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_status_t
+_put_image_boxes (cairo_xcb_surface_t *surface,
+ cairo_image_surface_t *image,
+ cairo_boxes_t *boxes)
+{
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
+ xcb_gcontext_t gc;
+
+ if (boxes->num_boxes == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* XXX track damaged region? */
+
+ status = _cairo_xcb_connection_acquire (surface->connection);
+ if (unlikely (status))
+ return status;
+
+ assert (image->pixman_format == surface->pixman_format);
+ assert (image->depth == surface->depth);
+ assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
+
+ gc = _cairo_xcb_screen_get_gc (surface->screen,
+ surface->drawable,
+ surface->depth);
+
+ status = _put_shm_image_boxes (surface, image, gc, boxes);
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ struct _cairo_boxes_chunk *chunk;
+
+ for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
+ int i;
+
+ for (i = 0; i < chunk->count; i++) {
+ cairo_box_t *b = &chunk->base[i];
+ int x = _cairo_fixed_integer_part (b->p1.x);
+ int y = _cairo_fixed_integer_part (b->p1.y);
+ int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
+ int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
+ _cairo_xcb_connection_put_image (surface->connection,
+ surface->drawable, gc,
+ width, height,
+ x, y,
+ image->depth,
+ image->stride,
+ image->data +
+ x * PIXMAN_FORMAT_BPP (image->pixman_format) / 8 +
+ y * image->stride);
+
+ }
+ }
+ status = CAIRO_STATUS_SUCCESS;
+ }
+
+ _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
+ _cairo_xcb_connection_release (surface->connection);
+ return status;
+}
+
static cairo_status_t
_cairo_xcb_surface_flush (void *abstract_surface)
{
@@ -598,20 +702,27 @@ _cairo_xcb_surface_flush (void *abstract_surface)
status = surface->base.status;
if (status == CAIRO_STATUS_SUCCESS && ! surface->base.finished) {
- status = cairo_surface_status (surface->fallback);
+ status = cairo_surface_status (&surface->fallback->base);
- if (status == CAIRO_STATUS_SUCCESS) {
- status = _put_image (surface, (cairo_image_surface_t *)surface->fallback);
- }
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
+ CAIRO_FILL_RULE_WINDING,
+ &surface->fallback_damage);
+
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = _put_image_boxes (surface,
+ surface->fallback,
+ &surface->fallback_damage);
if (status == CAIRO_STATUS_SUCCESS) {
_cairo_surface_attach_snapshot (&surface->base,
- surface->fallback,
+ &surface->fallback->base,
cairo_surface_finish);
}
}
- cairo_surface_destroy (surface->fallback);
+ _cairo_boxes_clear (&surface->fallback_damage);
+ cairo_surface_destroy (&surface->fallback->base);
surface->fallback = NULL;
return status;
@@ -625,7 +736,7 @@ _cairo_xcb_surface_map_to_image (void *abstract_surface,
cairo_surface_t *image;
if (surface->fallback)
- return surface->fallback->backend->map_to_image (surface->fallback, extents);
+ return surface->fallback->base.backend->map_to_image (&surface->fallback->base, extents);
image = _get_image (surface, TRUE,
extents->x, extents->y,
@@ -638,10 +749,8 @@ _cairo_xcb_surface_map_to_image (void *abstract_surface,
* uploading the image will handle the problem for us.
*/
if (surface->deferred_clear &&
- ! (extents->x == 0 &&
- extents->y == 0 &&
- extents->width == surface->width &&
- extents->height == surface->height)) {
+ ! (extents->width == surface->width &&
+ extents->height == surface->height)) {
cairo_status_t status = _cairo_xcb_surface_clear (surface);
if (unlikely (status)) {
cairo_surface_destroy(image);
@@ -661,22 +770,32 @@ _cairo_xcb_surface_unmap (void *abstract_surface,
cairo_xcb_surface_t *surface = abstract_surface;
if (surface->fallback)
- return surface->fallback->backend->unmap_image (surface->fallback, image);
+ return surface->fallback->base.backend->unmap_image (&surface->fallback->base, image);
return _put_image (abstract_surface, image);
}
static cairo_surface_t *
-_cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface)
+_cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface,
+ cairo_composite_rectangles_t *composite)
{
- cairo_surface_t *image;
+ cairo_image_surface_t *image;
+ cairo_status_t status;
- image = _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
+ image = (cairo_image_surface_t *)
+ _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
/* If there was a deferred clear, _get_image applied it */
- if (image->status == CAIRO_STATUS_SUCCESS)
+ if (image->base.status == CAIRO_STATUS_SUCCESS) {
surface->deferred_clear = FALSE;
- return image;
+ surface->fallback = image;
+ }
+
+ status = _cairo_composite_rectangles_add_to_damage (composite,
+ &surface->fallback_damage);
+ if (unlikely (status))
+ return _cairo_surface_create_in_error (status);
+ return &surface->fallback->base;
}
static cairo_int_status_t
@@ -686,21 +805,34 @@ _cairo_xcb_surface_paint (void *abstract_surface,
const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t composite;
cairo_int_status_t status;
+ status = _cairo_composite_rectangles_init_for_paint (&composite,
+ &surface->base,
+ op, source,
+ clip);
+ if (unlikely (status))
+ return status;
+
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_paint (surface, op, source, clip);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto done;
- status = _cairo_xcb_surface_render_paint (surface, op, source, clip);
+ status = _cairo_xcb_surface_render_paint (surface, op, source,
+ &composite);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- surface->fallback = _cairo_xcb_surface_fallback (surface);
+ goto done;
}
- return _cairo_surface_paint (surface->fallback, op, source, clip);
+ status = _cairo_surface_paint (_cairo_xcb_surface_fallback (surface,
+ &composite),
+ op, source, clip);
+
+done:
+ _cairo_composite_rectangles_fini (&composite);
+ return status;
}
static cairo_int_status_t
@@ -711,25 +843,34 @@ _cairo_xcb_surface_mask (void *abstract_surface,
const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t composite;
cairo_int_status_t status;
+ status = _cairo_composite_rectangles_init_for_mask (&composite,
+ &surface->base,
+ op, source, mask, clip);
+ if (unlikely (status))
+ return status;
+
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_mask (surface,
op, source, mask, clip);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto done;
status = _cairo_xcb_surface_render_mask (surface,
- op, source, mask, clip);
+ op, source, mask, &composite);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- surface->fallback = _cairo_xcb_surface_fallback (surface);
+ goto done;
}
- return _cairo_surface_mask (surface->fallback,
- op, source, mask,
- clip);
+ status = _cairo_surface_mask (_cairo_xcb_surface_fallback (surface,
+ &composite),
+ op, source, mask,
+ clip);
+done:
+ _cairo_composite_rectangles_fini (&composite);
+ return status;
}
static cairo_int_status_t
@@ -745,8 +886,17 @@ _cairo_xcb_surface_stroke (void *abstract_surface,
const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t composite;
cairo_int_status_t status;
+ status = _cairo_composite_rectangles_init_for_stroke (&composite,
+ &surface->base,
+ op, source,
+ path, style, ctm,
+ clip);
+ if (unlikely (status))
+ return status;
+
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_stroke (surface, op, source,
path, style,
@@ -755,26 +905,28 @@ _cairo_xcb_surface_stroke (void *abstract_surface,
clip);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto done;
status = _cairo_xcb_surface_render_stroke (surface, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias,
- clip);
+ &composite);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- surface->fallback = _cairo_xcb_surface_fallback (surface);
+ goto done;
}
- return _cairo_surface_stroke (surface->fallback,
- op, source,
- path, style,
- ctm, ctm_inverse,
- tolerance, antialias,
- clip);
+ status = _cairo_surface_stroke (_cairo_xcb_surface_fallback (surface,
+ &composite),
+ op, source,
+ path, style,
+ ctm, ctm_inverse,
+ tolerance, antialias,
+ clip);
+done:
+ _cairo_composite_rectangles_fini (&composite);
+ return status;
}
static cairo_int_status_t
@@ -788,31 +940,41 @@ _cairo_xcb_surface_fill (void *abstract_surface,
const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t composite;
cairo_int_status_t status;
+ status = _cairo_composite_rectangles_init_for_fill (&composite,
+ &surface->base,
+ op, source, path,
+ clip);
+ if (unlikely (status))
+ return status;
+
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_fill (surface, op, source,
path, fill_rule,
tolerance, antialias,
clip);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto done;
status = _cairo_xcb_surface_render_fill (surface, op, source,
path, fill_rule,
tolerance, antialias,
- clip);
+ &composite);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- surface->fallback = _cairo_xcb_surface_fallback (surface);
+ goto done;
}
- return _cairo_surface_fill (surface->fallback,
- op, source,
- path, fill_rule,
- tolerance, antialias,
- clip);
+ status = _cairo_surface_fill (_cairo_xcb_surface_fallback (surface,
+ &composite),
+ op, source,
+ path, fill_rule,
+ tolerance, antialias,
+ clip);
+done:
+ _cairo_composite_rectangles_fini (&composite);
+ return status;
}
static cairo_int_status_t
@@ -825,7 +987,18 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t composite;
cairo_int_status_t status;
+ cairo_bool_t overlap;
+
+ status = _cairo_composite_rectangles_init_for_glyphs (&composite,
+ &surface->base,
+ op, source,
+ scaled_font,
+ glyphs, num_glyphs,
+ clip, &overlap);
+ if (unlikely (status))
+ return status;
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_glyphs (surface,
@@ -833,25 +1006,27 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
scaled_font, glyphs, num_glyphs,
clip);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto done;
status = _cairo_xcb_surface_render_glyphs (surface,
op, source,
scaled_font, glyphs, num_glyphs,
- clip);
+ &composite, overlap);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- surface->fallback = _cairo_xcb_surface_fallback (surface);
+ goto done;
}
- return _cairo_surface_show_text_glyphs (surface->fallback,
- op, source,
- NULL, 0,
- glyphs, num_glyphs,
- NULL, 0, 0,
- scaled_font,
- clip);
+ status = _cairo_surface_show_text_glyphs (_cairo_xcb_surface_fallback (surface,
+ &composite),
+ op, source,
+ NULL, 0,
+ glyphs, num_glyphs,
+ NULL, 0, 0,
+ scaled_font,
+ clip);
+done:
+ _cairo_composite_rectangles_fini (&composite);
+ return status;
}
const cairo_surface_backend_t _cairo_xcb_surface_backend = {
@@ -910,8 +1085,6 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen,
surface->screen = screen;
cairo_list_add (&surface->link, &screen->surfaces);
- surface->fallback = NULL;
-
surface->drawable = drawable;
surface->owns_pixmap = owns_pixmap;
@@ -931,6 +1104,9 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen,
surface->pixman_format = pixman_format;
surface->xrender_format = xrender_format;
+ surface->fallback = NULL;
+ _cairo_boxes_init (&surface->fallback_damage);
+
return &surface->base;
}
More information about the cairo-commit
mailing list