1 changeset: 42954:7881873b2b5d
2 user: Robert O'Callahan <robert@ocallahan.org>
3 date: Tue Jun 01 11:19:45 2010 +1200
4 summary: Bug 552537. Cache the CGImageRef that we create for a CGBitmapContext so that we can take advantage of Quartz caching optimizations. r=jrmuizel
6 diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h
7 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h
8 +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h
9 @@ -49,16 +49,24 @@ typedef struct cairo_quartz_surface {
11 CGContextRef cgContext;
12 CGAffineTransform cgContextBaseCTM;
15 cairo_surface_t *imageSurfaceEquiv;
17 cairo_surface_clipper_t clipper;
20 + * If non-null, this is a CGImage representing the contents of the surface.
21 + * We clear this out before any painting into the surface, so that we
22 + * don't force a copy to be created.
24 + CGImageRef bitmapContextImage;
26 cairo_rectangle_int_t extents;
27 } cairo_quartz_surface_t;
29 typedef struct cairo_quartz_image_surface {
32 cairo_rectangle_int_t extents;
34 diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
35 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
36 +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
37 @@ -1134,19 +1134,24 @@ _cairo_surface_to_cgimage (cairo_surface
38 if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
39 cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) source;
40 if (IS_EMPTY(surface)) {
42 return CAIRO_STATUS_SUCCESS;
45 if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) {
46 - *image_out = CGBitmapContextCreateImage (surface->cgContext);
48 - return CAIRO_STATUS_SUCCESS;
49 + if (!surface->bitmapContextImage) {
50 + surface->bitmapContextImage =
51 + CGBitmapContextCreateImage (surface->cgContext);
53 + if (surface->bitmapContextImage) {
54 + *image_out = CGImageRetain (surface->bitmapContextImage);
55 + return CAIRO_STATUS_SUCCESS;
60 if (stype != CAIRO_SURFACE_TYPE_IMAGE) {
61 status = _cairo_surface_acquire_source_image (source,
62 &isurf, &image_extra);
65 @@ -1589,16 +1594,29 @@ _cairo_quartz_setup_radial_source (cairo
67 CGColorSpaceRelease(rgb);
68 CGFunctionRelease(gradFunc);
70 state->action = DO_SHADING;
74 + * Call this before any operation that can modify the contents of a
75 + * cairo_quartz_surface_t.
78 +_cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface)
80 + if (surface->bitmapContextImage) {
81 + CGImageRelease (surface->bitmapContextImage);
82 + surface->bitmapContextImage = NULL;
87 * Sets up internal state to be used to draw the source mask, stored in
88 * cairo_quartz_state_t. Guarantees to call CGContextSaveGState on
91 static cairo_quartz_drawing_state_t
92 _cairo_quartz_setup_state (cairo_quartz_surface_t *surface,
93 const cairo_pattern_t *source,
95 @@ -1609,16 +1627,18 @@ _cairo_quartz_setup_state (cairo_quartz_
96 cairo_status_t status;
98 state.context = context;
100 state.imageSurface = NULL;
101 state.shading = NULL;
102 state.pattern = NULL;
104 + _cairo_quartz_surface_will_change (surface);
106 // Save before we change the pattern, colorspace, etc. so that
107 // we can restore and make sure that quartz releases our
108 // pattern (which may be stack allocated)
109 CGContextSaveGState(context);
111 CGContextSetInterpolationQuality (context, _cairo_quartz_filter_to_quartz (source->filter));
113 status = _cairo_quartz_surface_set_cairo_operator (surface, op);
114 @@ -1936,16 +1956,21 @@ _cairo_quartz_surface_finish (void *abst
115 /* Restore our saved gstate that we use to reset clipping */
116 CGContextRestoreGState (surface->cgContext);
117 _cairo_surface_clipper_reset (&surface->clipper);
119 CGContextRelease (surface->cgContext);
121 surface->cgContext = NULL;
123 + if (surface->bitmapContextImage) {
124 + CGImageRelease (surface->bitmapContextImage);
125 + surface->bitmapContextImage = NULL;
128 if (surface->imageSurfaceEquiv) {
129 cairo_surface_destroy (surface->imageSurfaceEquiv);
130 surface->imageSurfaceEquiv = NULL;
133 if (surface->imageData) {
134 free (surface->imageData);
135 surface->imageData = NULL;
136 @@ -2006,16 +2031,18 @@ _cairo_quartz_surface_acquire_dest_image
137 cairo_rectangle_int_t *image_rect,
140 cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
141 cairo_int_status_t status;
143 ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface));
145 + _cairo_quartz_surface_will_change (surface);
147 status = _cairo_quartz_get_image (surface, image_out);
149 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
151 *image_rect = surface->extents;
154 return CAIRO_STATUS_SUCCESS;
155 @@ -2939,16 +2966,17 @@ _cairo_quartz_surface_create_internal (C
157 CGContextSaveGState (cgContext);
159 surface->cgContext = cgContext;
160 surface->cgContextBaseCTM = CGContextGetCTM (cgContext);
162 surface->imageData = NULL;
163 surface->imageSurfaceEquiv = NULL;
164 + surface->bitmapContextImage = NULL;
170 * cairo_quartz_surface_create_for_cg_context
171 * @cgContext: the existing CGContext for which to create the surface
172 * @width: width of the surface, in pixels