[cairo-commit] 3 commits - src/cairoint.h src/cairo-meta-surface.c src/cairo-surface.c util/cairo-trace
Chris Wilson
ickle at kemper.freedesktop.org
Sat Jul 4 05:53:05 PDT 2009
src/cairo-meta-surface.c | 19 ++++++++-
src/cairo-surface.c | 92 +++++++++++++++++++++++++++++++++++------------
src/cairoint.h | 3 +
util/cairo-trace/trace.c | 42 +++++++++++++++------
4 files changed, 120 insertions(+), 36 deletions(-)
New commits:
commit 7903c80ee81777bab6eec408c10b2b59330b10f7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Jul 4 13:50:15 2009 +0100
[meta] Cache replays when used as a pattern source
Use the cow-snapshotting mechanism to store the meta surface replay (either
to an image inside acquire_source_image() or to a similar surface during
clone_similar()).
Fixes Bug 17971 -- Extreme slowdown for manual convolutions in most
vector backends.
https://bugs.freedesktop.org/show_bug.cgi?id=17971
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 71e6b59..4fb2722 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -244,6 +244,15 @@ _cairo_meta_surface_acquire_source_image (void *abstract_surface,
cairo_meta_surface_t *surface = abstract_surface;
cairo_surface_t *image;
+ image = _cairo_surface_has_snapshot (&surface->base,
+ &_cairo_image_surface_backend,
+ surface->content);
+ if (image != NULL) {
+ *image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
+ *image_extra = NULL;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
image = _cairo_image_surface_create_with_content (surface->content,
ceil (surface->width_pixels),
ceil (surface->height_pixels));
@@ -254,10 +263,15 @@ _cairo_meta_surface_acquire_source_image (void *abstract_surface,
return status;
}
+ status = _cairo_surface_attach_snapshot (&surface->base, image, NULL);
+ if (unlikely (status)) {
+ cairo_surface_destroy (image);
+ return status;
+ }
+
*image_out = (cairo_image_surface_t *) image;
*image_extra = NULL;
-
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static void
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 55aee0e..63e1810 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -267,15 +267,19 @@ _cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_surface_t *
_cairo_surface_has_snapshot (cairo_surface_t *surface,
- const cairo_surface_backend_t *backend)
+ const cairo_surface_backend_t *backend,
+ cairo_content_t content)
{
cairo_surface_t **snapshots;
unsigned int i;
snapshots = _cairo_array_index (&surface->snapshots, 0);
for (i = 0; i < surface->snapshots.num_elements; i++) {
- if (snapshots[i]->backend == backend)
+ if (snapshots[i]->backend == backend &&
+ snapshots[i]->content == content)
+ {
return snapshots[i];
+ }
}
return NULL;
@@ -1506,27 +1510,67 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* First check to see if we can replay to a similar surface */
if (_cairo_surface_is_meta (src)) {
+ cairo_meta_surface_t *meta = (cairo_meta_surface_t *) src;
cairo_surface_t *similar;
- similar = cairo_surface_create_similar (surface,
- src->content & content,
- width, height);
- status = similar->status;
- if (unlikely (status))
- return status;
-
- cairo_surface_set_device_offset (similar, -src_x, -src_y);
-
- status = cairo_meta_surface_replay (src, similar);
- if (unlikely (status)) {
- cairo_surface_destroy (similar);
- return status;
+ similar = _cairo_surface_has_snapshot (src,
+ surface->backend,
+ src->content & content);
+ if (similar != NULL) {
+ *clone_out = cairo_surface_reference (similar);
+ *clone_offset_x = 0;
+ *clone_offset_y = 0;
+ return CAIRO_STATUS_SUCCESS;
}
- *clone_out = similar;
- *clone_offset_x = src_x;
- *clone_offset_y = src_y;
- return CAIRO_STATUS_SUCCESS;
+ if (width*height*8 < meta->extents.width*meta->extents.height) {
+ similar = cairo_surface_create_similar (surface,
+ src->content & content,
+ width, height);
+ status = similar->status;
+ if (unlikely (status))
+ return status;
+
+ cairo_surface_set_device_offset (similar, -src_x, -src_y);
+
+ status = cairo_meta_surface_replay (src, similar);
+ if (unlikely (status)) {
+ cairo_surface_destroy (similar);
+ return status;
+ }
+
+ *clone_out = similar;
+ *clone_offset_x = src_x;
+ *clone_offset_y = src_y;
+ return CAIRO_STATUS_SUCCESS;
+ } else {
+ similar = cairo_surface_create_similar (surface,
+ src->content & content,
+ meta->extents.width,
+ meta->extents.height);
+ status = similar->status;
+ if (unlikely (status))
+ return status;
+
+ status = cairo_meta_surface_replay (src, similar);
+ if (unlikely (status)) {
+ cairo_surface_destroy (similar);
+ return status;
+ }
+
+ status = _cairo_surface_attach_snapshot (src,
+ similar,
+ NULL);
+ if (unlikely (status)) {
+ cairo_surface_destroy (similar);
+ return status;
+ }
+
+ *clone_out = similar;
+ *clone_offset_x = 0;
+ *clone_offset_y = 0;
+ return CAIRO_STATUS_SUCCESS;
+ }
}
/* If we failed, try again with an image surface */
@@ -1604,7 +1648,9 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
if (surface->snapshot_of != NULL)
return cairo_surface_reference (surface);
- snapshot = _cairo_surface_has_snapshot (surface, surface->backend);
+ snapshot = _cairo_surface_has_snapshot (surface,
+ surface->backend,
+ surface->content);
if (snapshot != NULL)
return cairo_surface_reference (snapshot);
@@ -1618,7 +1664,8 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
cairo_surface_t *previous;
previous = _cairo_surface_has_snapshot (surface,
- snapshot->backend);
+ snapshot->backend,
+ snapshot->content);
if (previous != NULL) {
cairo_surface_destroy (snapshot);
return cairo_surface_reference (previous);
@@ -1628,7 +1675,8 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
if (snapshot == NULL) {
snapshot = _cairo_surface_has_snapshot (surface,
- &_cairo_image_surface_backend);
+ &_cairo_image_surface_backend,
+ surface->content);
if (snapshot != NULL)
return cairo_surface_reference (snapshot);
diff --git a/src/cairoint.h b/src/cairoint.h
index 52f813f..fed81a5 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1997,7 +1997,8 @@ _cairo_surface_attach_snapshot (cairo_surface_t *surface,
cairo_private cairo_surface_t *
_cairo_surface_has_snapshot (cairo_surface_t *surface,
- const cairo_surface_backend_t *backend);
+ const cairo_surface_backend_t *backend,
+ cairo_content_t content);
cairo_private void
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
commit f353ba46a3b8c260f96588fd6bb8d07c2a09d01a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Jul 4 13:49:35 2009 +0100
[meta] Copy extents on snapshotting.
Need to copy across the extents as well when snapshotting.
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 3c2b74e..71e6b59 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -582,6 +582,7 @@ _cairo_meta_surface_snapshot (void *abstract_other)
meta->width_pixels = other->width_pixels;
meta->height_pixels = other->height_pixels;
+ meta->extents = other->extents;
meta->replay_start_idx = other->replay_start_idx;
meta->content = other->content;
commit f4019be7bdff5c67d679f4de1070c25aa99a993d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Jul 4 13:16:42 2009 +0100
[trace] Remove a few transient pattern def/undef
It is easier on the eye to use
'1 index set-source exch pop'
rather than
'dup /p0 exch def p0 set-source /p0 undef'
(as patterns are expected to be temporary so we strive to avoid naming
them).
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 92b4981..e910d9e 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -1985,20 +1985,29 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
{
_emit_line_info ();
if (cr != NULL && source != NULL && _write_lock ()) {
+ Object *obj = _get_object (PATTERN, source);
+ bool need_context_and_pattern = true;
+
if (_is_current (PATTERN, source, 0) &&
_is_current (CONTEXT, cr, 1))
{
- _consume_operand ();
+ if (obj->defined) {
+ _consume_operand ();
+ need_context_and_pattern = false;
+ }
}
else if (_is_current (PATTERN, source, 1) &&
_is_current (CONTEXT, cr, 0))
{
- _trace_printf ("exch ");
- _exch_operands ();
- _consume_operand ();
+ if (obj->defined) {
+ _trace_printf ("exch ");
+ _exch_operands ();
+ _consume_operand ();
+ need_context_and_pattern = false;
+ }
}
- else
- {
+
+ if (need_context_and_pattern) {
_emit_context (cr);
_emit_pattern_id (source);
}
@@ -2353,18 +2362,29 @@ cairo_mask (cairo_t *cr, cairo_pattern_t *pattern)
{
_emit_line_info ();
if (cr != NULL && pattern != NULL && _write_lock ()) {
+ Object *obj = _get_object (PATTERN, pattern);
+ bool need_context_and_pattern = true;
+
if (_is_current (PATTERN, pattern, 0) &&
_is_current (CONTEXT, cr, 1))
{
- _consume_operand ();
+ if (obj->defined) {
+ _consume_operand ();
+ need_context_and_pattern = false;
+ }
}
else if (_is_current (PATTERN, pattern, 1) &&
_is_current (CONTEXT, cr, 0))
{
- _trace_printf ("exch ");
- _exch_operands ();
- _consume_operand ();
- } else {
+ if (obj->defined) {
+ _trace_printf ("exch ");
+ _exch_operands ();
+ _consume_operand ();
+ need_context_and_pattern = false;
+ }
+ }
+
+ if (need_context_and_pattern) {
_emit_context (cr);
_emit_pattern_id (pattern);
}
More information about the cairo-commit
mailing list