[cairo-commit] 3 commits - src/cairo-gl-composite.c src/cairo-gl-gradient.c src/cairo-gl-operand.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-spans-compositor.c src/cairo-gl-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Oct 9 11:55:25 PDT 2011


 src/cairo-gl-composite.c        |    6 -
 src/cairo-gl-gradient.c         |    8 -
 src/cairo-gl-operand.c          |  175 +++++++++++++++++++++++++++++++---------
 src/cairo-gl-private.h          |   10 ++
 src/cairo-gl-shaders.c          |    6 -
 src/cairo-gl-spans-compositor.c |    2 
 src/cairo-gl-surface.c          |    9 --
 7 files changed, 163 insertions(+), 53 deletions(-)

New commits:
commit 34f507a919b0709caa2c0be30e43719356293dd1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Oct 8 13:54:28 2011 +0100

    gl: Need to increment reference count when copying operands
    
    Or else watch everything die with use-after-free of the cached
    gradients.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c59501e..6413255 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -69,7 +69,7 @@ _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
 					const cairo_gl_operand_t *source)
 {
     _cairo_gl_operand_destroy (&setup->src);
-    setup->src = *source;
+    _cairo_gl_operand_copy (&setup->src, source);
 }
 
 void
@@ -104,7 +104,7 @@ _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
 {
     _cairo_gl_operand_destroy (&setup->mask);
     if (mask)
-	setup->mask = *mask;
+	_cairo_gl_operand_copy (&setup->mask, mask);
 }
 
 void
@@ -242,7 +242,6 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
-        _cairo_gl_gradient_reference (operand->gradient.gradient);
         glActiveTexture (GL_TEXTURE0 + tex_unit);
         glBindTexture (ctx->tex_target, operand->gradient.gradient->tex);
         _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend);
@@ -292,7 +291,6 @@ _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
-        _cairo_gl_gradient_destroy (ctx->operands[tex_unit].gradient.gradient);
         dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
         break;
     }
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index a429257..aad2773 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -226,7 +226,7 @@ _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
 
     tex_width = _cairo_gl_gradient_sample_width (n_stops, stops);
 
-    CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1);
+    CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 2);
     gradient->cache_entry.hash = hash;
     gradient->cache_entry.size = tex_width;
     gradient->device = &ctx->base;
@@ -272,8 +272,8 @@ _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
     }
 
     /* we ignore errors here and just return an uncached gradient */
-    if (likely (! _cairo_cache_insert (&ctx->gradients, &gradient->cache_entry)))
-        _cairo_gl_gradient_reference (gradient);
+    if (unlikely (_cairo_cache_insert (&ctx->gradients, &gradient->cache_entry)))
+	CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1);
 
     *gradient_out = gradient;
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 86a96df..f0f7656 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -313,6 +313,30 @@ _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
 }
 
 void
+_cairo_gl_operand_copy (cairo_gl_operand_t *dst,
+			const cairo_gl_operand_t *src)
+{
+    *dst = *src;
+    switch (dst->type) {
+    case CAIRO_GL_OPERAND_CONSTANT:
+	break;
+    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
+    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
+    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
+	_cairo_gl_gradient_reference (dst->gradient.gradient);
+	break;
+    case CAIRO_GL_OPERAND_TEXTURE:
+	break;
+    default:
+    case CAIRO_GL_OPERAND_COUNT:
+        ASSERT_NOT_REACHED;
+    case CAIRO_GL_OPERAND_NONE:
+        break;
+    }
+}
+
+void
 _cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
 {
     switch (operand->type) {
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 7002392..6d8aab8 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -640,6 +640,10 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand,
                         uint8_t alpha);
 
 cairo_private void
+_cairo_gl_operand_copy (cairo_gl_operand_t *dst,
+			const cairo_gl_operand_t *src);
+
+cairo_private void
 _cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
 
 cairo_private const cairo_compositor_t *
commit a6c27b500ba8f910ff2a731eb6989c96e8977339
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Oct 8 11:08:43 2011 +0100

    gl: Basic fixes to get cairo-gl running again
    
    Let there be textures!
    
    Unbreak the setup of surface operands after my lazy convertion to the
    new compositor interface. This is still only the first step, but it gets
    the essentials up and running again, enough to keep me happy whilst
    sitting in the airport.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index 862430e..a429257 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -213,7 +213,7 @@ _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
         return CAIRO_INT_STATUS_UNSUPPORTED;
 
     hash = _cairo_gl_gradient_hash (n_stops, stops);
-    
+
     gradient = _cairo_gl_gradient_lookup (ctx, hash, n_stops, stops);
     if (gradient) {
         *gradient_out = _cairo_gl_gradient_reference (gradient);
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 8b345bb..86a96df 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -49,6 +49,8 @@
 #include "cairo-error-private.h"
 #include "cairo-image-surface-private.h"
 #include "cairo-surface-backend-private.h"
+#include "cairo-surface-offset-private.h"
+#include "cairo-surface-subsurface-private.h"
 
 static cairo_int_status_t
 _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
@@ -67,60 +69,124 @@ _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
     return _cairo_gl_context_release (ctx, status);
 }
 
-/*
- * Like cairo_pattern_acquire_surface(), but returns a matrix that transforms
- * from dest to src coords.
- */
+static cairo_status_t
+_cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
+				const cairo_pattern_t *_src,
+				cairo_gl_surface_t *dst,
+				int src_x, int src_y,
+				int dst_x, int dst_y,
+				int width, int height)
+{
+    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
+    cairo_gl_surface_t *surface;
+    cairo_surface_attributes_t *attributes;
+    cairo_matrix_t m;
+
+    surface = (cairo_gl_surface_t *) src->surface;
+    if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) {
+	if (_cairo_surface_is_subsurface (&surface->base)) {
+	    surface = (cairo_gl_surface_t *)
+		_cairo_surface_subsurface_get_target_with_offset (&surface->base, &src_x, &src_y);
+	}
+    }
+
+    attributes = &operand->texture.attributes;
+
+    operand->type = CAIRO_GL_OPERAND_TEXTURE;
+    operand->texture.surface =
+	(cairo_gl_surface_t *) cairo_surface_reference (&surface->base);
+    operand->texture.tex = surface->tex;
+
+    /* Translate the matrix from
+     * (unnormalized src -> unnormalized src) to
+     * (unnormalized dst -> unnormalized src)
+     */
+    cairo_matrix_init_translate (&m, src_x - dst_x, src_y - dst_y);
+    cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix);
+
+    /* Translate the matrix from
+     * (unnormalized dst -> unnormalized src) to
+     * (unnormalized dst -> normalized src)
+     */
+    if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
+	cairo_matrix_init_scale (&m,
+				 1.0,
+				 1.0);
+    } else {
+	cairo_matrix_init_scale (&m,
+				 1.0 / surface->width,
+				 1.0 / surface->height);
+    }
+    cairo_matrix_multiply (&attributes->matrix,
+			   &attributes->matrix,
+			   &m);
+
+    attributes->extend = src->base.extend;
+    attributes->filter = src->base.filter;
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_status_t
 _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
-				 const cairo_pattern_t *src,
+				 const cairo_pattern_t *_src,
 				 cairo_gl_surface_t *dst,
 				 int src_x, int src_y,
 				 int dst_x, int dst_y,
 				 int width, int height)
 {
+    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
     cairo_status_t status;
     cairo_matrix_t m;
     cairo_gl_surface_t *surface;
+    cairo_gl_context_t *ctx;
     cairo_surface_attributes_t *attributes;
 
     attributes = &operand->texture.attributes;
 
-#if 0
-    status = _cairo_pattern_acquire_surface (src, &dst->base,
-					     src_x, src_y,
-					     width, height,
-					     CAIRO_PATTERN_ACQUIRE_NONE,
-					     (cairo_surface_t **)
-					     &surface,
-					     attributes);
+    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
     if (unlikely (status))
 	return status;
-#endif
 
-    if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device) &&
-	(attributes->extend == CAIRO_EXTEND_REPEAT ||
-	 attributes->extend == CAIRO_EXTEND_REFLECT))
-    {
-	return UNSUPPORTED ("EXT_texture_rectangle with repeat/reflect");
+    surface = (cairo_gl_surface_t *)
+	_cairo_gl_surface_create_scratch (ctx,
+					  src->surface->content,
+					  width, height);
+    if (src->surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE) {
+	status = _cairo_gl_surface_draw_image (surface,
+				      (cairo_image_surface_t *)src->surface,
+				      src_x, src_y,
+				      width, height,
+				      0, 0);
+
+	attributes->extend = src->base.extend;
+	attributes->filter = src->base.filter;
+    } else {
+	cairo_surface_t *image;
+
+	image = cairo_surface_map_to_image (&surface->base, NULL);
+	status = _cairo_surface_offset_paint (image, src_x, src_y,
+					      CAIRO_OPERATOR_SOURCE, _src,
+					      NULL);
+	cairo_surface_unmap_image (&surface->base, image);
+
+	attributes->extend = CAIRO_EXTEND_NONE;
+	attributes->filter = CAIRO_FILTER_NEAREST;
     }
 
-    assert (_cairo_gl_surface_is_texture (surface));
+    status = _cairo_gl_context_release (ctx, status);
 
     operand->type = CAIRO_GL_OPERAND_TEXTURE;
     operand->texture.surface = surface;
     operand->texture.tex = surface->tex;
+
     /* Translate the matrix from
      * (unnormalized src -> unnormalized src) to
      * (unnormalized dst -> unnormalized src)
      */
-    cairo_matrix_init_translate (&m,
-				 src_x - dst_x + attributes->x_offset,
-				 src_y - dst_y + attributes->y_offset);
-    cairo_matrix_multiply (&attributes->matrix,
-			   &m,
-			   &attributes->matrix);
-
+    cairo_matrix_init_translate (&m, -dst_x, -dst_y);
+    cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix);
 
     /* Translate the matrix from
      * (unnormalized dst -> unnormalized src) to
@@ -138,7 +204,6 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
     cairo_matrix_multiply (&attributes->matrix,
 			   &attributes->matrix,
 			   &m);
-
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -286,26 +351,38 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 	_cairo_gl_solid_operand_init (operand,
 				      &((cairo_solid_pattern_t *) pattern)->color);
 	return CAIRO_STATUS_SUCCESS;
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	status = _cairo_gl_surface_operand_init (operand,
+						 pattern, dst,
+						 src_x, src_y,
+						 dst_x, dst_y,
+						 width, height);
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	    break;
+
+	return status;
+
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
 	status = _cairo_gl_gradient_operand_init (operand,
 						  pattern, dst,
 						  src_x, src_y,
 						  dst_x, dst_y);
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
+	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	    break;
 
-	/* fall through */
+	return status;
 
     default:
     case CAIRO_PATTERN_TYPE_MESH:
-    case CAIRO_PATTERN_TYPE_SURFACE:
-	return _cairo_gl_pattern_texture_setup (operand,
-						pattern, dst,
-						src_x, src_y,
-						dst_x, dst_y,
-						width, height);
+	break;
     }
+
+    return _cairo_gl_pattern_texture_setup (operand,
+					    pattern, dst,
+					    src_x, src_y,
+					    dst_x, dst_y,
+					    width, height);
 }
 
 cairo_filter_t
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index e1005ba..7002392 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -664,6 +664,12 @@ _cairo_gl_composite_glyphs (void			*_dst,
 			    int				 dst_y,
 			    cairo_composite_glyphs_info_t *info);
 
+cairo_private cairo_surface_t *
+_cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
+				  cairo_content_t	content,
+				  int			width,
+				  int			height);
+
 slim_hidden_proto (cairo_gl_surface_create);
 slim_hidden_proto (cairo_gl_surface_create_for_texture);
 
diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c
index 57cccc9..3e52f28 100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -337,7 +337,7 @@ static inline cairo_gl_operand_t *
 source_to_operand (cairo_surface_t *surface)
 {
     cairo_gl_source_t *source = (cairo_gl_source_t *)surface;
-    return &source->operand;
+    return source ? &source->operand : NULL;
 }
 
 static cairo_int_status_t
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index dec4b82..9fcbc3e 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -392,7 +392,7 @@ _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t   *ctx,
     return &surface->base;
 }
 
-static cairo_surface_t *
+cairo_surface_t *
 _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
 				  cairo_content_t	content,
 				  int			width,
@@ -715,13 +715,12 @@ _cairo_gl_surface_create_similar (void		 *abstract_surface,
 }
 
 static cairo_int_status_t
-_cairo_gl_surface_fill_alpha_channel (void *abstract_dst,
+_cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
+				      cairo_gl_context_t *ctx,
 				      int x, int y,
 				      int width, int height)
 {
-    cairo_gl_surface_t *dst = abstract_dst;
     cairo_gl_composite_t setup;
-    cairo_gl_context_t *ctx;
     cairo_status_t status;
 
     _cairo_gl_composite_flush (ctx);
@@ -849,7 +848,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	 * texture data.
 	 */
 	if (!has_alpha) {
-	    _cairo_gl_surface_fill_alpha_channel (dst,
+	    _cairo_gl_surface_fill_alpha_channel (dst, ctx,
 						  dst_x, dst_y,
 						  width, height);
 	}
commit 22c485017df7979c47e9c4ba708279c8c35e5149
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Oct 8 05:57:49 2011 +0100

    gl: Declare coverage input for fragment shaders.
    
    The most minor of oversights which prevented compilation of any spans
    based compositors.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 69609df..446b6af 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -866,8 +866,10 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
     cairo_gl_shader_emit_color (stream, ctx, mask, CAIRO_GL_TEX_MASK);
 
     coverage_str = "";
-    if (use_coverage)
-	coverage_str = " * coverage.a";
+    if (use_coverage) {
+	_cairo_output_stream_printf (stream, "varying float coverage;\n");
+	coverage_str = " * coverage";
+    }
 
     _cairo_output_stream_printf (stream,
         "void main()\n"


More information about the cairo-commit mailing list