[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