mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-31 09:00:16 +01:00
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@chris-wilson.co.uk>
This commit is contained in:
parent
36a1423045
commit
fd613cb9f9
6 changed files with 310 additions and 168 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue