diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-29 15:28:49 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-29 15:40:47 +0100 |
commit | 0660f62fe5ffdd86eedf8262f3ac50fb039491c1 (patch) | |
tree | 51dd66a1da49dea6b42bac221023eecc22b6e715 /src/cairo-gl-composite.c | |
parent | c2150b344123823098a57a0653b9857f7dc8c8d6 (diff) | |
download | cairo-0660f62fe5ffdd86eedf8262f3ac50fb039491c1.tar.gz |
gl: Rectilinear fast path
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-gl-composite.c')
-rw-r--r-- | src/cairo-gl-composite.c | 186 |
1 files changed, 185 insertions, 1 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index c259fe912..6ea8c85bf 100644 --- a/src/cairo-gl-composite.c +++ b/src/cairo-gl-composite.c @@ -282,7 +282,7 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand, int dst_x, int dst_y, int width, int height) { - cairo_status_t status; + cairo_int_status_t status; switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: @@ -1430,7 +1430,184 @@ _composite_boxes (cairo_gl_surface_t *dst, _cairo_pattern_fini (&mask.base); _cairo_gl_composite_fini (&setup); + return status; +} + +static cairo_bool_t converter_add_box (cairo_box_t *box, void *closure) +{ + return _cairo_rectangular_scan_converter_add_box (closure, box, 1) == CAIRO_STATUS_SUCCESS; +} + +typedef struct _cairo_gl_surface_span_renderer { + cairo_span_renderer_t base; + + cairo_gl_composite_t setup; + + int xmin, xmax; + int ymin, ymax; + + cairo_gl_context_t *ctx; +} cairo_gl_surface_span_renderer_t; + +static cairo_status_t +_cairo_gl_render_bounded_spans (void *abstract_renderer, + int y, int height, + const cairo_half_open_span_t *spans, + unsigned num_spans) +{ + cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; + + if (num_spans == 0) + return CAIRO_STATUS_SUCCESS; + + do { + if (spans[0].coverage) { + _cairo_gl_composite_emit_rect (renderer->ctx, + spans[0].x, y, + spans[1].x, y + height, + spans[0].coverage); + } + spans++; + } while (--num_spans > 1); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_gl_render_unbounded_spans (void *abstract_renderer, + int y, int height, + const cairo_half_open_span_t *spans, + unsigned num_spans) +{ + cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; + + if (y > renderer->ymin) { + _cairo_gl_composite_emit_rect (renderer->ctx, + renderer->xmin, renderer->ymin, + renderer->xmax, y, + 0); + } + + if (num_spans == 0) { + _cairo_gl_composite_emit_rect (renderer->ctx, + renderer->xmin, y, + renderer->xmax, y + height, + 0); + } else { + if (spans[0].x != renderer->xmin) { + _cairo_gl_composite_emit_rect (renderer->ctx, + renderer->xmin, y, + spans[0].x, y + height, + 0); + } + + do { + _cairo_gl_composite_emit_rect (renderer->ctx, + spans[0].x, y, + spans[1].x, y + height, + spans[0].coverage); + spans++; + } while (--num_spans > 1); + + if (spans[0].x != renderer->xmax) { + _cairo_gl_composite_emit_rect (renderer->ctx, + spans[0].x, y, + renderer->xmax, y + height, + 0); + } + } + + renderer->ymin = y + height; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_gl_finish_unbounded_spans (void *abstract_renderer) +{ + cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; + + if (renderer->ymax > renderer->ymin) { + _cairo_gl_composite_emit_rect (renderer->ctx, + renderer->xmin, renderer->ymin, + renderer->xmax, renderer->ymax, + 0); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_gl_finish_bounded_spans (void *abstract_renderer) +{ + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_composite_unaligned_boxes (cairo_gl_surface_t *dst, + cairo_operator_t op, + const cairo_pattern_t *pattern, + cairo_boxes_t *boxes, + const cairo_composite_rectangles_t *composite) +{ + cairo_rectangular_scan_converter_t converter; + cairo_gl_surface_span_renderer_t renderer; + const cairo_rectangle_int_t *extents; + cairo_status_t status; + + if (composite->clip->path) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* XXX for ADD or if we know the boxes are disjoint we can do a simpler + * pass, but for now... */ + + _cairo_rectangular_scan_converter_init (&converter, &composite->bounded); + cairo_boxes_for_each_box (boxes, converter_add_box, &converter); + + if (composite->is_bounded) { + renderer.base.render_rows = _cairo_gl_render_bounded_spans; + renderer.base.finish = _cairo_gl_finish_bounded_spans; + extents = &composite->bounded; + } else { + renderer.base.render_rows = _cairo_gl_render_unbounded_spans; + renderer.base.finish = _cairo_gl_finish_unbounded_spans; + extents = &composite->unbounded; + } + renderer.xmin = extents->x; + renderer.xmax = extents->x + extents->width; + renderer.ymin = extents->y; + renderer.ymax = extents->y + extents->height; + + status = _cairo_gl_composite_init (&renderer.setup, + op, dst, + FALSE, extents); + if (unlikely (status)) + goto FAIL; + + status = _cairo_gl_composite_set_source (&renderer.setup, pattern, + extents->x, extents->y, + extents->x, extents->y, + extents->width, extents->height); + if (unlikely (status)) + goto FAIL; + + _cairo_gl_composite_set_mask_spans (&renderer.setup); + if (! composite->is_bounded) + _cairo_gl_composite_set_clip_region (&renderer.setup, + _cairo_clip_get_region (composite->clip)); + + status = _cairo_gl_composite_begin (&renderer.setup, &renderer.ctx); + if (unlikely (status)) + goto FAIL; + + status = converter.base.generate (&converter.base, &renderer.base); + + converter.base.destroy (&converter.base); + renderer.base.finish (&renderer.base); + + status = _cairo_gl_context_release (renderer.ctx, status); +FAIL: + _cairo_gl_composite_fini (&renderer.setup); return status; } @@ -1481,6 +1658,9 @@ _cairo_gl_clip_and_composite_boxes (cairo_gl_surface_t *dst, if (boxes->num_boxes == 0 && extents->is_bounded) return CAIRO_STATUS_SUCCESS; + if (! _cairo_gl_operator_is_supported (op)) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (boxes->is_pixel_aligned && _cairo_clip_is_region (extents->clip) && (op == CAIRO_OPERATOR_SOURCE || (dst->base.is_clear && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)))) @@ -1554,6 +1734,10 @@ _cairo_gl_clip_and_composite_boxes (cairo_gl_surface_t *dst, if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; + status = _composite_unaligned_boxes (dst, op, src, boxes, extents); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + /* Otherwise XXX */ return CAIRO_INT_STATUS_UNSUPPORTED; } |