[cairo-commit] 3 commits - src/cairo-gl-operand.c src/cairo-surface-subsurface.c src/cairo-xlib-source.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Nov 25 04:28:33 PST 2011


 src/cairo-gl-operand.c         |   84 +++++++++++++++++++++++++++++++++++++++--
 src/cairo-surface-subsurface.c |    4 +
 src/cairo-xlib-source.c        |    2 
 3 files changed, 84 insertions(+), 6 deletions(-)

New commits:
commit f308ba7a444741b2cb26f7b09f86553723d7a22f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Nov 25 12:22:56 2011 +0000

    subsurface: Replace any existing snapshot
    
    Only allow one owner to keep their snapshot on the subsurface, and
    so automatically replace any previous snapshot.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index d115c33..b43dd40 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -86,7 +86,7 @@ _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
 
     sub = (cairo_surface_subsurface_t *) src->surface;
 
-    if (sub->snapshot) {
+    if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_GL) {
 	surface = (cairo_gl_surface_t *)
 	    cairo_surface_reference (sub->snapshot);
     } else {
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 2fb9562..09f49d0 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -529,7 +529,9 @@ _cairo_surface_subsurface_set_snapshot (cairo_surface_t *surface,
 {
     cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface;
 
-    assert (ss->snapshot == NULL);
+    if (ss->snapshot)
+	_cairo_surface_detach_snapshot (ss->snapshot);
+
     ss->snapshot = cairo_surface_reference (snapshot);
 
     _cairo_surface_attach_snapshot (ss->target, &ss->base,
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c
index 54d8757..a098cf2 100644
--- a/src/cairo-xlib-source.c
+++ b/src/cairo-xlib-source.c
@@ -666,7 +666,7 @@ subsurface_source (cairo_xlib_surface_t *dst,
 	}
     }
 
-    if (sub->snapshot) {
+    if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_XLIB) {
 	src = (cairo_xlib_surface_t *) cairo_surface_reference (sub->snapshot);
 	source = &src->embedded_source;
     } else {
commit 03be2019cd12936cf86d304a9391b5be2bf6e39e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Nov 25 12:21:18 2011 +0000

    gl: And enable subsurface caching of the clones
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 76cc710..d115c33 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -86,31 +86,38 @@ _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
 
     sub = (cairo_surface_subsurface_t *) src->surface;
 
-    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
-    if (unlikely (status))
-	return status;
-
-    surface = (cairo_gl_surface_t *)
-	_cairo_gl_surface_create_scratch (ctx,
-					  sub->target->content,
-					  extents->width, extents->height);
-    if (surface->base.status)
-	return _cairo_gl_context_release (ctx, surface->base.status);
-
-    _cairo_pattern_init_for_surface (&local_pattern, sub->target);
-    cairo_matrix_init_translate (&local_pattern.base.matrix,
-				 sub->extents.x, sub->extents.y);
-    local_pattern.base.filter = CAIRO_FILTER_NEAREST;
-    status = _cairo_surface_paint (&surface->base,
-				   CAIRO_OPERATOR_SOURCE,
-				   &local_pattern.base,
-				   NULL);
-    _cairo_pattern_fini (&local_pattern.base);
+    if (sub->snapshot) {
+	surface = (cairo_gl_surface_t *)
+	    cairo_surface_reference (sub->snapshot);
+    } else {
+	status = _cairo_gl_context_acquire (dst->base.device, &ctx);
+	if (unlikely (status))
+	    return status;
+
+	surface = (cairo_gl_surface_t *)
+	    _cairo_gl_surface_create_scratch (ctx,
+					      sub->target->content,
+					      extents->width, extents->height);
+	if (surface->base.status)
+	    return _cairo_gl_context_release (ctx, surface->base.status);
+
+	_cairo_pattern_init_for_surface (&local_pattern, sub->target);
+	cairo_matrix_init_translate (&local_pattern.base.matrix,
+				     sub->extents.x, sub->extents.y);
+	local_pattern.base.filter = CAIRO_FILTER_NEAREST;
+	status = _cairo_surface_paint (&surface->base,
+				       CAIRO_OPERATOR_SOURCE,
+				       &local_pattern.base,
+				       NULL);
+	_cairo_pattern_fini (&local_pattern.base);
+
+	status = _cairo_gl_context_release (ctx, status);
+	if (unlikely (status)) {
+	    cairo_surface_destroy (&surface->base);
+	    return status;
+	}
 
-    status = _cairo_gl_context_release (ctx, status);
-    if (unlikely (status)) {
-	cairo_surface_destroy (&surface->base);
-	return status;
+	_cairo_surface_subsurface_set_snapshot (&sub->base, &surface->base);
     }
 
     attributes = &operand->texture.attributes;
commit 5f6d3fe40b52785c80f210c6597328311c987eb3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Nov 25 12:15:31 2011 +0000

    gl: Temporarily clone a subsurface as required
    
    When the sample extents exceed the subsurface bounds we need to clone
    the subsurface into a regular surface in order to correctly handle the
    CAIRO_EXTEND_NONE extend mode (i.e prevent sampling out-of-bounds).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 8ff37c8..76cc710 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -70,6 +70,73 @@ _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
 }
 
 static cairo_status_t
+_cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
+					 const cairo_pattern_t *_src,
+					 cairo_gl_surface_t *dst,
+					 const cairo_rectangle_int_t *sample,
+					 const cairo_rectangle_int_t *extents)
+{
+    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
+    cairo_surface_pattern_t local_pattern;
+    cairo_surface_subsurface_t *sub;
+    cairo_gl_surface_t *surface;
+    cairo_gl_context_t *ctx;
+    cairo_surface_attributes_t *attributes;
+    cairo_status_t status;
+
+    sub = (cairo_surface_subsurface_t *) src->surface;
+
+    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
+    if (unlikely (status))
+	return status;
+
+    surface = (cairo_gl_surface_t *)
+	_cairo_gl_surface_create_scratch (ctx,
+					  sub->target->content,
+					  extents->width, extents->height);
+    if (surface->base.status)
+	return _cairo_gl_context_release (ctx, surface->base.status);
+
+    _cairo_pattern_init_for_surface (&local_pattern, sub->target);
+    cairo_matrix_init_translate (&local_pattern.base.matrix,
+				 sub->extents.x, sub->extents.y);
+    local_pattern.base.filter = CAIRO_FILTER_NEAREST;
+    status = _cairo_surface_paint (&surface->base,
+				   CAIRO_OPERATOR_SOURCE,
+				   &local_pattern.base,
+				   NULL);
+    _cairo_pattern_fini (&local_pattern.base);
+
+    status = _cairo_gl_context_release (ctx, status);
+    if (unlikely (status)) {
+	cairo_surface_destroy (&surface->base);
+	return status;
+    }
+
+    attributes = &operand->texture.attributes;
+
+    operand->type = CAIRO_GL_OPERAND_TEXTURE;
+    operand->texture.surface = surface;
+    operand->texture.tex = surface->tex;
+
+    if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
+	attributes->matrix = src->base.matrix;
+    } else {
+	cairo_matrix_t m;
+
+	cairo_matrix_init_scale (&m,
+				 1.0 / surface->width,
+				 1.0 / surface->height);
+	cairo_matrix_multiply (&attributes->matrix, &src->base.matrix, &m);
+    }
+
+    attributes->extend = src->base.extend;
+    attributes->filter = src->base.filter;
+    attributes->has_component_alpha = src->base.has_component_alpha;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
 				   const cairo_pattern_t *_src,
 				   cairo_gl_surface_t *dst,
@@ -84,11 +151,13 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
 
     sub = (cairo_surface_subsurface_t *) src->surface;
 
-    if (sample->x < 0 || sample->y < 0 ||
-	sample->x + sample->width  > sub->extents.width ||
-	sample->y + sample->height > sub->extents.height)
+    if (src->base.extend == CAIRO_EXTEND_NONE &&
+	(sample->x < 0 || sample->y < 0 ||
+	 sample->x + sample->width  > sub->extents.width ||
+	 sample->y + sample->height > sub->extents.height))
     {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _cairo_gl_subsurface_clone_operand_init (operand, _src,
+							dst, sample, extents);
     }
 
     surface = (cairo_gl_surface_t *) sub->target;


More information about the cairo-commit mailing list