summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/quartz-cache-CGImageRef.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/quartz-cache-CGImageRef.patch')
-rw-r--r--gfx/cairo/quartz-cache-CGImageRef.patch173
1 files changed, 173 insertions, 0 deletions
diff --git a/gfx/cairo/quartz-cache-CGImageRef.patch b/gfx/cairo/quartz-cache-CGImageRef.patch
new file mode 100644
index 000000000..f27f03081
--- /dev/null
+++ b/gfx/cairo/quartz-cache-CGImageRef.patch
@@ -0,0 +1,173 @@
+changeset: 42954:7881873b2b5d
+user: Robert O'Callahan <robert@ocallahan.org>
+date: Tue Jun 01 11:19:45 2010 +1200
+summary: Bug 552537. Cache the CGImageRef that we create for a CGBitmapContext so that we can take advantage of Quartz caching optimizations. r=jrmuizel
+
+diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
+--- a/gfx/cairo/cairo/src/cairo-quartz-private.h
++++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
+@@ -49,16 +49,24 @@ typedef struct cairo_quartz_surface {
+
+ CGContextRef cgContext;
+ CGAffineTransform cgContextBaseCTM;
+
+ void *imageData;
+ cairo_surface_t *imageSurfaceEquiv;
+
+ cairo_surface_clipper_t clipper;
++
++ /**
++ * If non-null, this is a CGImage representing the contents of the surface.
++ * We clear this out before any painting into the surface, so that we
++ * don't force a copy to be created.
++ */
++ CGImageRef bitmapContextImage;
++
+ cairo_rectangle_int_t extents;
+ } cairo_quartz_surface_t;
+
+ typedef struct cairo_quartz_image_surface {
+ cairo_surface_t base;
+
+ cairo_rectangle_int_t extents;
+
+diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
+--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
+@@ -1134,19 +1134,24 @@ _cairo_surface_to_cgimage (cairo_surface
+ if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) source;
+ if (IS_EMPTY(surface)) {
+ *image_out = NULL;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) {
+- *image_out = CGBitmapContextCreateImage (surface->cgContext);
+- if (*image_out)
+- return CAIRO_STATUS_SUCCESS;
++ if (!surface->bitmapContextImage) {
++ surface->bitmapContextImage =
++ CGBitmapContextCreateImage (surface->cgContext);
++ }
++ if (surface->bitmapContextImage) {
++ *image_out = CGImageRetain (surface->bitmapContextImage);
++ return CAIRO_STATUS_SUCCESS;
++ }
+ }
+ }
+
+ if (stype != CAIRO_SURFACE_TYPE_IMAGE) {
+ status = _cairo_surface_acquire_source_image (source,
+ &isurf, &image_extra);
+ if (status)
+ return status;
+@@ -1589,16 +1594,29 @@ _cairo_quartz_setup_radial_source (cairo
+
+ CGColorSpaceRelease(rgb);
+ CGFunctionRelease(gradFunc);
+
+ state->action = DO_SHADING;
+ }
+
+ /**
++ * Call this before any operation that can modify the contents of a
++ * cairo_quartz_surface_t.
++ */
++static void
++_cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
++{
++ if (surface->bitmapContextImage) {
++ CGImageRelease (surface->bitmapContextImage);
++ surface->bitmapContextImage = NULL;
++ }
++}
++
++/**
+ * Sets up internal state to be used to draw the source mask, stored in
+ * cairo_quartz_state_t. Guarantees to call CGContextSaveGState on
+ * surface->cgContext.
+ */
+ static cairo_quartz_drawing_state_t
+ _cairo_quartz_setup_state (cairo_quartz_surface_t *surface,
+ const cairo_pattern_t *source,
+ cairo_operator_t op,
+@@ -1609,16 +1627,18 @@ _cairo_quartz_setup_state (cairo_quartz_
+ cairo_status_t status;
+
+ state.context = context;
+ state.image = NULL;
+ state.imageSurface = NULL;
+ state.shading = NULL;
+ state.pattern = NULL;
+
++ _cairo_quartz_surface_will_change (surface);
++
+ // Save before we change the pattern, colorspace, etc. so that
+ // we can restore and make sure that quartz releases our
+ // pattern (which may be stack allocated)
+ CGContextSaveGState(context);
+
+ CGContextSetInterpolationQuality (context, _cairo_quartz_filter_to_quartz (source->filter));
+
+ status = _cairo_quartz_surface_set_cairo_operator (surface, op);
+@@ -1936,16 +1956,21 @@ _cairo_quartz_surface_finish (void *abst
+ /* Restore our saved gstate that we use to reset clipping */
+ CGContextRestoreGState (surface->cgContext);
+ _cairo_surface_clipper_reset (&surface->clipper);
+
+ CGContextRelease (surface->cgContext);
+
+ surface->cgContext = NULL;
+
++ if (surface->bitmapContextImage) {
++ CGImageRelease (surface->bitmapContextImage);
++ surface->bitmapContextImage = NULL;
++ }
++
+ if (surface->imageSurfaceEquiv) {
+ cairo_surface_destroy (surface->imageSurfaceEquiv);
+ surface->imageSurfaceEquiv = NULL;
+ }
+
+ if (surface->imageData) {
+ free (surface->imageData);
+ surface->imageData = NULL;
+@@ -2006,16 +2031,18 @@ _cairo_quartz_surface_acquire_dest_image
+ cairo_rectangle_int_t *image_rect,
+ void **image_extra)
+ {
+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
+ cairo_int_status_t status;
+
+ ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface));
+
++ _cairo_quartz_surface_will_change (surface);
++
+ status = _cairo_quartz_get_image (surface, image_out);
+ if (status)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ *image_rect = surface->extents;
+ *image_extra = NULL;
+
+ return CAIRO_STATUS_SUCCESS;
+@@ -2939,16 +2966,17 @@ _cairo_quartz_surface_create_internal (C
+ */
+ CGContextSaveGState (cgContext);
+
+ surface->cgContext = cgContext;
+ surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
+
+ surface->imageData = NULL;
+ surface->imageSurfaceEquiv = NULL;
++ surface->bitmapContextImage = NULL;
+
+ return surface;
+ }
+
+ /**
+ * cairo_quartz_surface_create_for_cg_context
+ * @cgContext: the existing CGContext for which to create the surface
+ * @width: width of the surface, in pixels
+