[cairo] [PATCH 2/2] gl/msaa: Add support for unbounded operators

Henry (Yu) Song - SISA hsong at sisa.samsung.com
Mon Nov 7 09:36:30 PST 2011


Add support for unbounded operators by creating an intermediate
surface which will be drawn back to the destination with the
appropriate compositing operator.
---
src/cairo-gl-msaa-compositor.c |  101 ++++++++++++++++++++++++++++++++++++++-
src/cairo-gl-private.h         |    8 +++
src/cairo-gl-surface.c         |    6 ++-
3 files changed, 111 insertions(+), 4 deletions(-)

diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 2c8e4f5..4cc7361 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -231,6 +231,59 @@ _draw_clip_to_stencil_buffer (cairo_gl_context_t   *ctx,
}
 static cairo_int_status_t
+_ensure_intermediate_surface (cairo_gl_surface_t *surface)
+{
+    cairo_gl_surface_t *intermediate = (cairo_gl_surface_t *) surface->intermediate;
+    cairo_surface_t *new_surface = NULL;
+
+    if (intermediate != NULL &&
+     intermediate->width == surface->width &&
+     intermediate->height == surface->height) {
+     return _cairo_gl_surface_clear (intermediate, CAIRO_COLOR_TRANSPARENT);
+    }
+
+    if (intermediate != NULL) {
+     cairo_surface_destroy (surface->intermediate);
+     surface->intermediate = NULL;
+    }
+
+    new_surface = cairo_surface_create_similar (&surface->base,
+                                   CAIRO_CONTENT_COLOR_ALPHA,
+                                   surface->width,
+                                   surface->height);
+
+    if (new_surface == NULL)
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (unlikely (new_surface->status)) {
+        cairo_surface_destroy (new_surface);
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    assert (cairo_surface_get_type (new_surface) == CAIRO_SURFACE_TYPE_GL);
+    surface->intermediate = new_surface;
+    return _cairo_gl_surface_clear ((cairo_gl_surface_t *) new_surface, CAIRO_COLOR_TRANSPARENT);
+}
+
+static cairo_int_status_t
+_paint_back_intermediate_surface (cairo_gl_surface_t *surface,
+                         cairo_operator_t op,
+                         cairo_clip_t *clip)
+{
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_surface_pattern_t tmp_pattern;
+
+    surface->intermediate->is_clear = FALSE;
+    _cairo_pattern_init_for_surface (&tmp_pattern,
+                            (cairo_surface_t*) surface->intermediate);
+    tmp_pattern.base.has_component_alpha = FALSE;
+    status = _cairo_surface_paint (&surface->base, op, &(tmp_pattern.base), clip);
+
+    _cairo_pattern_fini (&tmp_pattern.base);
+    return status;
+}
+
+
+static cairo_int_status_t
_cairo_gl_msaa_compositor_paint (const cairo_compositor_t  *compositor,
                        cairo_composite_rectangles_t *composite)
{
@@ -369,16 +422,29 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t      *compositor,
                         cairo_antialias_t           antialias)
{
     cairo_int_status_t status;
-    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
     struct _tristrip_composite_info info;
+    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
+    cairo_gl_surface_t *original_dst = dst;
+    cairo_operator_t op = composite->op;
+    cairo_operator_t original_op = op;
+
+
     cairo_bool_t used_stencil_buffer_for_clip = FALSE;
     if (antialias != CAIRO_ANTIALIAS_NONE)
     return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (! _cairo_operator_bounded_by_mask (op)) {
+     if (unlikely ((status = _ensure_intermediate_surface (dst))))
+         return status;
+     dst = (cairo_gl_surface_t *) dst->intermediate;
+     op = CAIRO_OPERATOR_OVER;
+    }
+
+
     status = _cairo_gl_composite_init (&info.setup,
-                              composite->op,
+                              op,
                              dst,
                              FALSE, /* assume_component_alpha */
                              &composite->bounded);
@@ -428,6 +494,14 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t      *compositor,
     _cairo_gl_composite_flush (info.ctx);
+    if (! _cairo_operator_bounded_by_mask (original_op)) {
+     status = _paint_back_intermediate_surface (original_dst,
+                                      original_op,
+                                      composite->clip);
+     if (unlikely (status))
+         goto finish;
+    }
+
finish:
     _cairo_gl_composite_fini (&info.setup);
@@ -449,7 +523,12 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
                       cairo_antialias_t       antialias)
{
     cairo_gl_composite_t setup;
+
     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
+    cairo_gl_surface_t *original_dst = dst;
+    cairo_operator_t op = composite->op;
+    cairo_operator_t original_op = op;
+
     cairo_gl_context_t *ctx = NULL;
     cairo_int_status_t status;
     cairo_traps_t traps;
@@ -457,13 +536,20 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t      *compositor,
     if (antialias != CAIRO_ANTIALIAS_NONE)
     return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (! _cairo_operator_bounded_by_mask (op)) {
+     if (unlikely ((status = _ensure_intermediate_surface (dst))))
+         return status;
+     dst = (cairo_gl_surface_t *) dst->intermediate;
+     op = CAIRO_OPERATOR_OVER;
+    }
+
     _cairo_traps_init (&traps);
     status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
     if (unlikely (status))
     goto cleanup_traps;
     status = _cairo_gl_composite_init (&setup,
-                              composite->op,
+                              op,
                              dst,
                              FALSE, /* assume_component_alpha */
                              &composite->bounded);
@@ -499,6 +585,15 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
         goto cleanup_setup;
     _cairo_gl_composite_flush (ctx);
+
+    if (! _cairo_operator_bounded_by_mask (original_op)) {
+     status = _paint_back_intermediate_surface (original_dst,
+                                      original_op,
+                                      composite->clip);
+     if (unlikely (status))
+         goto cleanup_setup;
+    }
+
cleanup_setup:
     _cairo_gl_composite_fini (&setup);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 19c7c1f..17da7f0 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -119,6 +119,10 @@ typedef struct _cairo_gl_surface {
     GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */
     int owns_tex;
     cairo_bool_t needs_update;
+
+    /* The intermediate surface is used for
+       unbounded operators in the MSAA compositor. */
+    cairo_surface_t *intermediate;
} cairo_gl_surface_t;
 typedef struct cairo_gl_glyph_cache {
@@ -374,6 +378,10 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
                       int width, int height,
                       int dst_x, int dst_y);
+cairo_private cairo_status_t
+_cairo_gl_surface_clear (cairo_gl_surface_t  *surface,
+                 const cairo_color_t *color);
+
static cairo_always_inline cairo_bool_t
_cairo_gl_device_has_glsl (cairo_device_t *device)
{
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index c781ec4..5b7d930 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -363,6 +363,7 @@ _cairo_gl_surface_init (cairo_device_t *device,
     surface->width = width;
     surface->height = height;
     surface->needs_update = FALSE;
+    surface->intermediate = NULL;
}
 static cairo_surface_t *
@@ -446,7 +447,7 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
     return &surface->base;
}
-static cairo_status_t
+cairo_status_t
_cairo_gl_surface_clear (cairo_gl_surface_t  *surface,
                          const cairo_color_t *color)
{
@@ -906,6 +907,9 @@ _cairo_gl_surface_finish (void *abstract_surface)
     cairo_status_t status;
     cairo_gl_context_t *ctx;
+    if (surface->intermediate)
+     cairo_surface_destroy (surface->intermediate);
+
     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
     if (unlikely (status))
         return status;
--
1.7.5.4



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cairographics.org/archives/cairo/attachments/20111107/e98a8805/attachment.html>


More information about the cairo mailing list