summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-gl-surface.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index a36d7b7a..9e796902 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -40,6 +40,7 @@
#include "cairoint.h"
+#include "cairo-boxes-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-error-private.h"
#include "cairo-gl-private.h"
@@ -1316,6 +1317,69 @@ _cairo_gl_surface_paint (void *abstract_surface,
}
static cairo_int_status_t
+_cairo_gl_surface_boxes (cairo_gl_surface_t *dst,
+ cairo_operator_t op,
+ const cairo_pattern_t *src,
+ cairo_boxes_t *boxes,
+ cairo_antialias_t antialias,
+ const cairo_composite_rectangles_t *extents,
+ cairo_clip_t *clip)
+{
+ cairo_status_t status;
+ cairo_region_t *clip_region = NULL;
+ cairo_span_renderer_t *renderer;
+ cairo_rectangular_scan_converter_t converter;
+ struct _cairo_boxes_chunk *chunk;
+ int i;
+
+ if (clip != NULL) {
+ status = _cairo_clip_get_region (clip, &clip_region);
+ if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
+ return CAIRO_STATUS_SUCCESS;
+ if (unlikely (_cairo_status_is_error (status)))
+ return status;
+
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ return UNSUPPORTED ("a clip surface would be required");
+ }
+
+ if (op == CAIRO_OPERATOR_SOURCE)
+ return UNSUPPORTED ("SOURCE compositing doesn't work in GL");
+ if (op == CAIRO_OPERATOR_CLEAR) {
+ op = CAIRO_OPERATOR_DEST_OUT;
+ src = &_cairo_pattern_white.base;
+ }
+
+ _cairo_rectangular_scan_converter_init (&converter, &extents->bounded);
+
+ for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+ const cairo_box_t *box = chunk->base;
+
+ for (i = 0; i < chunk->count; i++) {
+ status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
+ if (unlikely (status))
+ goto CLEANUP_CONVERTER;
+ }
+ }
+
+ renderer = _cairo_surface_create_span_renderer (op, src, &dst->base,
+ antialias, extents,
+ clip_region);
+
+ status = converter.base.generate (&converter.base, renderer);
+ if (unlikely (status))
+ goto CLEANUP_RENDERER;
+
+ status = renderer->finish (renderer);
+
+ CLEANUP_RENDERER:
+ renderer->destroy (renderer);
+ CLEANUP_CONVERTER:
+ converter.base.destroy (&converter.base);
+ return status;
+}
+
+static cairo_int_status_t
_cairo_gl_surface_polygon (cairo_gl_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *src,
@@ -1406,6 +1470,28 @@ _cairo_gl_surface_stroke (void *abstract_surface,
return status;
}
+ if (path->is_rectilinear) {
+ cairo_boxes_t boxes;
+
+ _cairo_boxes_init (&boxes);
+ _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
+
+ status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
+ style,
+ ctm,
+ &boxes);
+ if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ status = _cairo_gl_surface_boxes (surface, op, source,
+ &boxes, antialias,
+ &extents, clip);
+ }
+
+ _cairo_boxes_fini (&boxes);
+
+ if (likely (status != CAIRO_INT_STATUS_UNSUPPORTED))
+ goto OUT;
+ }
+
_cairo_polygon_init (&polygon);
_cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
@@ -1422,6 +1508,7 @@ _cairo_gl_surface_stroke (void *abstract_surface,
_cairo_polygon_fini (&polygon);
+ OUT:
if (have_clip)
_cairo_clip_fini (&local_clip);
@@ -1483,6 +1570,28 @@ _cairo_gl_surface_fill (void *abstract_surface,
return status;
}
+ if (_cairo_path_fixed_is_rectilinear_fill (path)) {
+ cairo_boxes_t boxes;
+
+ _cairo_boxes_init (&boxes);
+ _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
+
+ status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
+ fill_rule,
+ &boxes);
+ if (unlikely (status))
+ goto OUT;
+
+ status = _cairo_gl_surface_boxes (surface, op, source,
+ &boxes, antialias,
+ &extents, clip);
+
+ _cairo_boxes_fini (&boxes);
+
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto OUT;
+ }
+
_cairo_polygon_init (&polygon);
_cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
@@ -1495,6 +1604,7 @@ _cairo_gl_surface_fill (void *abstract_surface,
_cairo_polygon_fini (&polygon);
+ OUT:
if (clip_boxes != boxes_stack)
free (clip_boxes);