forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			173 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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
 | |
| 
 | 
