summaryrefslogtreecommitdiff
path: root/src/cairo-surface-wrapper.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-07-23 12:19:17 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-07-23 15:33:14 +0100
commita30a7402f73485dabdb6a016178247f9844017a1 (patch)
tree54a047cbed002b2ff4c83a305019b503314da882 /src/cairo-surface-wrapper.c
parentbff8e22eb6b7faeac04ca585cb739e7880a3335c (diff)
downloadcairo-a30a7402f73485dabdb6a016178247f9844017a1.tar.gz
image: replay the recording surface directly onto the target
백현기 reported a use-case where he was recording an entire web-page onto the recording surface, in order to facilitate panning. In this scenario, where there may be lots of similar surfaces within the recording we generate thousands of unused snapshot-images bloating memory usage and impairing performance. Under the right conditions we can replay directly onto the destination which not only bypasses the snapshots but also skips the following resampling. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-surface-wrapper.c')
-rw-r--r--src/cairo-surface-wrapper.c190
1 files changed, 111 insertions, 79 deletions
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 9e746f9c6..8dc40f842 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -54,18 +54,6 @@ _copy_transformed_pattern (cairo_pattern_t *pattern,
_cairo_pattern_transform (pattern, ctm_inverse);
}
-static inline cairo_bool_t
-_cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper)
-{
- return ! _cairo_matrix_is_identity (&wrapper->target->device_transform);
-}
-
-static cairo_bool_t
-_cairo_surface_wrapper_needs_extents_transform (cairo_surface_wrapper_t *wrapper)
-{
- return wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y);
-}
-
cairo_status_t
_cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper,
cairo_image_surface_t **image_out,
@@ -86,6 +74,24 @@ _cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper,
_cairo_surface_release_source_image (wrapper->target, image, image_extra);
}
+static void
+_cairo_surface_wrapper_get_transform (cairo_surface_wrapper_t *wrapper,
+ cairo_matrix_t *m)
+{
+ cairo_matrix_init_identity (m);
+
+ if (wrapper->has_extents && (wrapper->extents.x || wrapper->extents.y))
+ cairo_matrix_translate (m, -wrapper->extents.x, -wrapper->extents.y);
+
+ if (! _cairo_matrix_is_identity (&wrapper->transform))
+ cairo_matrix_multiply (m, &wrapper->transform, m);
+
+
+ if (! _cairo_matrix_is_identity (&wrapper->target->device_transform))
+ cairo_matrix_multiply (m, &wrapper->target->device_transform, m);
+}
+
+
cairo_status_t
_cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
@@ -108,21 +114,15 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
goto FINISH;
}
- if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
- _cairo_surface_wrapper_needs_extents_transform (wrapper))
- {
+ if (wrapper->needs_transform) {
cairo_matrix_t m;
- cairo_matrix_init_identity (&m);
-
- if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
- cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
-
- if (_cairo_surface_wrapper_needs_device_transform (wrapper))
- cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
+ _cairo_surface_wrapper_get_transform (wrapper, &m);
/* XXX */
- dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
+ dev_clip = _cairo_clip_copy_with_translation (dev_clip,
+ wrapper->extents.x,
+ wrapper->extents.y);
status = cairo_matrix_invert (&m);
assert (status == CAIRO_STATUS_SUCCESS);
@@ -131,6 +131,9 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
source = &source_copy.base;
}
+ if (wrapper->clip)
+ dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip);
+
status = _cairo_surface_paint (wrapper->target, op, source, dev_clip);
FINISH:
@@ -164,21 +167,14 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
goto FINISH;
}
- if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
- _cairo_surface_wrapper_needs_extents_transform (wrapper))
- {
+ if (wrapper->needs_transform) {
cairo_matrix_t m;
- cairo_matrix_init_identity (&m);
-
- if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
- cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
+ _cairo_surface_wrapper_get_transform (wrapper, &m);
- if (_cairo_surface_wrapper_needs_device_transform (wrapper))
- cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
-
- /* XXX */
- dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
+ dev_clip = _cairo_clip_copy_with_translation (dev_clip,
+ wrapper->extents.x,
+ wrapper->extents.y);
status = cairo_matrix_invert (&m);
assert (status == CAIRO_STATUS_SUCCESS);
@@ -190,6 +186,9 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
mask = &mask_copy.base;
}
+ if (wrapper->clip)
+ dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip);
+
status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);
FINISH:
@@ -230,18 +229,10 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
goto FINISH;
}
- if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
- _cairo_surface_wrapper_needs_extents_transform (wrapper))
- {
+ if (wrapper->needs_transform) {
cairo_matrix_t m;
- cairo_matrix_init_identity (&m);
-
- if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
- cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
-
- if (_cairo_surface_wrapper_needs_device_transform (wrapper))
- cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
+ _cairo_surface_wrapper_get_transform (wrapper, &m);
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (unlikely (status))
@@ -251,7 +242,9 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
dev_path = &path_copy;
/* XXX */
- dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
+ dev_clip = _cairo_clip_copy_with_translation (dev_clip,
+ wrapper->extents.x,
+ wrapper->extents.y);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
@@ -264,6 +257,9 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
source = &source_copy.base;
}
+ if (wrapper->clip)
+ dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip);
+
status = _cairo_surface_stroke (wrapper->target, op, source,
dev_path, stroke_style,
&dev_ctm, &dev_ctm_inverse,
@@ -316,18 +312,10 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
goto FINISH;
}
- if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
- _cairo_surface_wrapper_needs_extents_transform (wrapper))
- {
+ if (wrapper->needs_transform) {
cairo_matrix_t m;
- cairo_matrix_init_identity (&m);
-
- if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
- cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
-
- if (_cairo_surface_wrapper_needs_device_transform (wrapper))
- cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
+ _cairo_surface_wrapper_get_transform (wrapper, &m);
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (unlikely (status))
@@ -337,7 +325,9 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
dev_path = &path_copy;
/* XXX */
- dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
+ dev_clip = _cairo_clip_copy_with_translation (dev_clip,
+ wrapper->extents.x,
+ wrapper->extents.y);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
@@ -353,6 +343,9 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
fill_source = &fill_source_copy.base;
}
+ if (wrapper->clip)
+ dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip);
+
status = _cairo_surface_fill_stroke (wrapper->target,
fill_op, fill_source, fill_rule,
fill_tolerance, fill_antialias,
@@ -399,18 +392,10 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
goto FINISH;
}
- if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
- _cairo_surface_wrapper_needs_extents_transform (wrapper))
- {
+ if (wrapper->needs_transform) {
cairo_matrix_t m;
- cairo_matrix_init_identity (&m);
-
- if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
- cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
-
- if (_cairo_surface_wrapper_needs_device_transform (wrapper))
- cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
+ _cairo_surface_wrapper_get_transform (wrapper, &m);
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (unlikely (status))
@@ -420,7 +405,9 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
dev_path = &path_copy;
/* XXX */
- dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
+ dev_clip = _cairo_clip_copy_with_translation (dev_clip,
+ wrapper->extents.x,
+ wrapper->extents.y);
status = cairo_matrix_invert (&m);
assert (status == CAIRO_STATUS_SUCCESS);
@@ -429,6 +416,9 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
source = &source_copy.base;
}
+ if (wrapper->clip)
+ dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip);
+
status = _cairo_surface_fill (wrapper->target, op, source,
dev_path, fill_rule,
tolerance, antialias,
@@ -477,22 +467,16 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
goto FINISH;
}
- if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
- _cairo_surface_wrapper_needs_extents_transform (wrapper))
- {
+ if (wrapper->needs_transform) {
cairo_matrix_t m;
int i;
- cairo_matrix_init_identity (&m);
-
- if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
- cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
-
- if (_cairo_surface_wrapper_needs_device_transform (wrapper))
- cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
+ _cairo_surface_wrapper_get_transform (wrapper, &m);
/* XXX */
- dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
+ dev_clip = _cairo_clip_copy_with_translation (dev_clip,
+ wrapper->extents.x,
+ wrapper->extents.y);
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (dev_glyphs == NULL) {
@@ -512,6 +496,9 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
source = &source_copy.base;
}
+ if (wrapper->clip)
+ dev_clip = _cairo_clip_copy_intersect_clip (dev_clip, wrapper->clip);
+
status = _cairo_surface_show_text_glyphs (wrapper->target, op, source,
utf8, utf8_len,
dev_glyphs, num_glyphs,
@@ -555,6 +542,15 @@ _cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper,
}
}
+static cairo_bool_t
+_cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper)
+{
+ return
+ (wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y)) ||
+ ! _cairo_matrix_is_identity (&wrapper->transform) ||
+ ! _cairo_matrix_is_identity (&wrapper->target->device_transform);
+}
+
void
_cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper,
const cairo_rectangle_int_t *extents)
@@ -565,6 +561,38 @@ _cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper,
} else {
wrapper->has_extents = FALSE;
}
+
+ wrapper->needs_transform =
+ _cairo_surface_wrapper_needs_device_transform (wrapper);
+}
+
+void
+_cairo_surface_wrapper_set_inverse_transform (cairo_surface_wrapper_t *wrapper,
+ const cairo_matrix_t *transform)
+{
+ cairo_status_t status;
+
+ if (transform == NULL || _cairo_matrix_is_identity (transform)) {
+ cairo_matrix_init_identity (&wrapper->transform);
+
+ wrapper->needs_transform =
+ _cairo_surface_wrapper_needs_device_transform (wrapper);
+ } else {
+ wrapper->transform = *transform;
+ status = cairo_matrix_invert (&wrapper->transform);
+ /* should always be invertible unless given pathological input */
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ wrapper->needs_transform = TRUE;
+ }
+
+}
+
+void
+_cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper,
+ const cairo_clip_t *clip)
+{
+ wrapper->clip = clip;
}
void
@@ -590,8 +618,12 @@ void
_cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
cairo_surface_t *target)
{
+ _cairo_surface_wrapper_set_inverse_transform (wrapper, NULL);
+
wrapper->target = cairo_surface_reference (target);
wrapper->has_extents = FALSE;
+ wrapper->needs_transform =
+ ! _cairo_matrix_is_identity (&wrapper->target->device_transform);
}
void