summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-06-05 15:22:44 +0200
committerBenjamin Otte <otte@redhat.com>2010-06-07 13:37:49 +0200
commit1d11af083f5368c88032a33ff40d0e21c139db18 (patch)
treec37fe1701800170a824c760555098899689ccc59
parent550335efeddf813c1bec493513254fdbd34a9ace (diff)
gl: Add a simple spans renderer for stroke/fill
It's very simple as clipped polygons or ANTIALIAS_NONE still return UNSUPPORTED. Also, no optimizations are done, so even pixel-aligned rectangles use the full span rendering. Still, there are no performance regressions in the benchmark traces and firefox-talos-svg and swfdec-giant-steps both got ~15% faster.
-rw-r--r--src/cairo-gl-surface.c178
1 files changed, 175 insertions, 3 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 9aa88528..cb1f9c49 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1211,7 +1211,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
goto FAIL;
status = _cairo_gl_composite_set_source (&renderer->setup, src,
- rects->source.x, rects->source.y,
+ extents->x, extents->y,
extents->x, extents->y,
extents->width, extents->height);
if (unlikely (status))
@@ -1299,6 +1299,178 @@ _cairo_gl_surface_paint (void *abstract_surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
+static cairo_int_status_t
+_cairo_gl_surface_polygon (cairo_gl_surface_t *dst,
+ cairo_operator_t op,
+ const cairo_pattern_t *src,
+ cairo_polygon_t *polygon,
+ cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias,
+ const cairo_composite_rectangles_t *extents,
+ cairo_clip_t *clip)
+{
+ cairo_status_t status;
+
+ if (clip)
+ return UNSUPPORTED ("a clip!");
+ if (! _cairo_surface_check_span_renderer (op, src, &dst->base, antialias))
+ return UNSUPPORTED ("no span renderer");
+
+ status = _cairo_surface_composite_polygon (&dst->base,
+ op,
+ src,
+ fill_rule,
+ antialias,
+ extents,
+ polygon,
+ NULL);
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_gl_surface_stroke (void *abstract_surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ const cairo_stroke_style_t *style,
+ const cairo_matrix_t *ctm,
+ const cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_clip_t *clip)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t extents;
+ cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
+ int num_boxes = ARRAY_LENGTH (boxes_stack);
+ cairo_clip_t local_clip;
+ cairo_bool_t have_clip = FALSE;
+ cairo_polygon_t polygon;
+ cairo_status_t status;
+
+ status = _cairo_composite_rectangles_init_for_stroke (&extents,
+ surface->width,
+ surface->height,
+ op, source,
+ path, style, ctm,
+ clip);
+ if (unlikely (status))
+ return status;
+
+ if (_cairo_clip_contains_rectangle (clip, &extents))
+ clip = NULL;
+
+ if (clip != NULL) {
+ clip = _cairo_clip_init_copy (&local_clip, clip);
+ have_clip = TRUE;
+ }
+
+ status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+ if (unlikely (status)) {
+ if (have_clip)
+ _cairo_clip_fini (&local_clip);
+
+ return status;
+ }
+
+ _cairo_polygon_init (&polygon);
+ _cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
+
+ status = _cairo_path_fixed_stroke_to_polygon (path,
+ style,
+ ctm, ctm_inverse,
+ tolerance,
+ &polygon);
+ if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ status = _cairo_gl_surface_polygon (surface, op, source, &polygon,
+ CAIRO_FILL_RULE_WINDING, antialias,
+ &extents, clip);
+ }
+
+ _cairo_polygon_fini (&polygon);
+
+ if (have_clip)
+ _cairo_clip_fini (&local_clip);
+
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_gl_surface_fill (void *abstract_surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_clip_t *clip)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+ cairo_composite_rectangles_t extents;
+ cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
+ cairo_clip_t local_clip;
+ cairo_bool_t have_clip = FALSE;
+ int num_boxes = ARRAY_LENGTH (boxes_stack);
+ cairo_polygon_t polygon;
+ cairo_status_t status;
+
+ status = _cairo_composite_rectangles_init_for_fill (&extents,
+ surface->width,
+ surface->height,
+ op, source, path,
+ clip);
+ if (unlikely (status))
+ return status;
+
+ if (_cairo_clip_contains_rectangle (clip, &extents))
+ clip = NULL;
+
+#if 0
+ if (extents.is_bounded && clip != NULL) {
+ cairo_clip_path_t *clip_path;
+
+ if (((clip_path = _clip_get_single_path (clip)) != NULL) &&
+ _cairo_path_fixed_equal (&clip_path->path, path))
+ {
+ clip = NULL;
+ }
+ }
+#endif
+
+ if (clip != NULL) {
+ clip = _cairo_clip_init_copy (&local_clip, clip);
+ have_clip = TRUE;
+ }
+
+ status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+ if (unlikely (status)) {
+ if (have_clip)
+ _cairo_clip_fini (&local_clip);
+
+ return status;
+ }
+
+ _cairo_polygon_init (&polygon);
+ _cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
+
+ status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
+ if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ status = _cairo_gl_surface_polygon (surface, op, source, &polygon,
+ fill_rule, antialias,
+ &extents, clip);
+ }
+
+ _cairo_polygon_fini (&polygon);
+
+ if (clip_boxes != boxes_stack)
+ free (clip_boxes);
+
+ if (have_clip)
+ _cairo_clip_fini (&local_clip);
+
+ return status;
+}
+
const cairo_surface_backend_t _cairo_gl_surface_backend = {
CAIRO_SURFACE_TYPE_GL,
_cairo_gl_surface_create_similar,
@@ -1327,8 +1499,8 @@ const cairo_surface_backend_t _cairo_gl_surface_backend = {
_cairo_gl_surface_scaled_glyph_fini,
_cairo_gl_surface_paint,
NULL, /* mask */
- NULL, /* stroke */
- NULL, /* fill */
+ _cairo_gl_surface_stroke,
+ _cairo_gl_surface_fill,
_cairo_gl_surface_show_glyphs, /* show_glyphs */
NULL /* snapshot */
};