diff options
Diffstat (limited to 'gfx/cairo/quartz-cache-CGImageRef.patch')
-rw-r--r-- | gfx/cairo/quartz-cache-CGImageRef.patch | 173 |
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 + |