|
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 |
|
5 |
|
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 { |
|
10 |
|
11 CGContextRef cgContext; |
|
12 CGAffineTransform cgContextBaseCTM; |
|
13 |
|
14 void *imageData; |
|
15 cairo_surface_t *imageSurfaceEquiv; |
|
16 |
|
17 cairo_surface_clipper_t clipper; |
|
18 + |
|
19 + /** |
|
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. |
|
23 + */ |
|
24 + CGImageRef bitmapContextImage; |
|
25 + |
|
26 cairo_rectangle_int_t extents; |
|
27 } cairo_quartz_surface_t; |
|
28 |
|
29 typedef struct cairo_quartz_image_surface { |
|
30 cairo_surface_t base; |
|
31 |
|
32 cairo_rectangle_int_t extents; |
|
33 |
|
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)) { |
|
41 *image_out = NULL; |
|
42 return CAIRO_STATUS_SUCCESS; |
|
43 } |
|
44 |
|
45 if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) { |
|
46 - *image_out = CGBitmapContextCreateImage (surface->cgContext); |
|
47 - if (*image_out) |
|
48 - return CAIRO_STATUS_SUCCESS; |
|
49 + if (!surface->bitmapContextImage) { |
|
50 + surface->bitmapContextImage = |
|
51 + CGBitmapContextCreateImage (surface->cgContext); |
|
52 + } |
|
53 + if (surface->bitmapContextImage) { |
|
54 + *image_out = CGImageRetain (surface->bitmapContextImage); |
|
55 + return CAIRO_STATUS_SUCCESS; |
|
56 + } |
|
57 } |
|
58 } |
|
59 |
|
60 if (stype != CAIRO_SURFACE_TYPE_IMAGE) { |
|
61 status = _cairo_surface_acquire_source_image (source, |
|
62 &isurf, &image_extra); |
|
63 if (status) |
|
64 return status; |
|
65 @@ -1589,16 +1594,29 @@ _cairo_quartz_setup_radial_source (cairo |
|
66 |
|
67 CGColorSpaceRelease(rgb); |
|
68 CGFunctionRelease(gradFunc); |
|
69 |
|
70 state->action = DO_SHADING; |
|
71 } |
|
72 |
|
73 /** |
|
74 + * Call this before any operation that can modify the contents of a |
|
75 + * cairo_quartz_surface_t. |
|
76 + */ |
|
77 +static void |
|
78 +_cairo_quartz_surface_will_change (cairo_quartz_surface_t *surface) |
|
79 +{ |
|
80 + if (surface->bitmapContextImage) { |
|
81 + CGImageRelease (surface->bitmapContextImage); |
|
82 + surface->bitmapContextImage = NULL; |
|
83 + } |
|
84 +} |
|
85 + |
|
86 +/** |
|
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 |
|
89 * surface->cgContext. |
|
90 */ |
|
91 static cairo_quartz_drawing_state_t |
|
92 _cairo_quartz_setup_state (cairo_quartz_surface_t *surface, |
|
93 const cairo_pattern_t *source, |
|
94 cairo_operator_t op, |
|
95 @@ -1609,16 +1627,18 @@ _cairo_quartz_setup_state (cairo_quartz_ |
|
96 cairo_status_t status; |
|
97 |
|
98 state.context = context; |
|
99 state.image = NULL; |
|
100 state.imageSurface = NULL; |
|
101 state.shading = NULL; |
|
102 state.pattern = NULL; |
|
103 |
|
104 + _cairo_quartz_surface_will_change (surface); |
|
105 + |
|
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); |
|
110 |
|
111 CGContextSetInterpolationQuality (context, _cairo_quartz_filter_to_quartz (source->filter)); |
|
112 |
|
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); |
|
118 |
|
119 CGContextRelease (surface->cgContext); |
|
120 |
|
121 surface->cgContext = NULL; |
|
122 |
|
123 + if (surface->bitmapContextImage) { |
|
124 + CGImageRelease (surface->bitmapContextImage); |
|
125 + surface->bitmapContextImage = NULL; |
|
126 + } |
|
127 + |
|
128 if (surface->imageSurfaceEquiv) { |
|
129 cairo_surface_destroy (surface->imageSurfaceEquiv); |
|
130 surface->imageSurfaceEquiv = NULL; |
|
131 } |
|
132 |
|
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, |
|
138 void **image_extra) |
|
139 { |
|
140 cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; |
|
141 cairo_int_status_t status; |
|
142 |
|
143 ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface)); |
|
144 |
|
145 + _cairo_quartz_surface_will_change (surface); |
|
146 + |
|
147 status = _cairo_quartz_get_image (surface, image_out); |
|
148 if (status) |
|
149 return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
150 |
|
151 *image_rect = surface->extents; |
|
152 *image_extra = NULL; |
|
153 |
|
154 return CAIRO_STATUS_SUCCESS; |
|
155 @@ -2939,16 +2966,17 @@ _cairo_quartz_surface_create_internal (C |
|
156 */ |
|
157 CGContextSaveGState (cgContext); |
|
158 |
|
159 surface->cgContext = cgContext; |
|
160 surface->cgContextBaseCTM = CGContextGetCTM (cgContext); |
|
161 |
|
162 surface->imageData = NULL; |
|
163 surface->imageSurfaceEquiv = NULL; |
|
164 + surface->bitmapContextImage = NULL; |
|
165 |
|
166 return surface; |
|
167 } |
|
168 |
|
169 /** |
|
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 |
|
173 |