[cairo-commit] src/cairo-win32-surface.c
Jeff Muizelaar
jrmuizel at kemper.freedesktop.org
Thu Jun 18 14:23:27 PDT 2009
src/cairo-win32-surface.c | 146 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 144 insertions(+), 2 deletions(-)
New commits:
commit 7f238f542441cc5912d14e5c6f9c49ffd0b83fad
Author: Jeff Muizelaar <jmuizelaar at mozilla.com>
Date: Thu Jun 18 17:13:13 2009 -0400
Use the scanline rasterizer in the win32 backend.
Brings http://people.mozilla.com/~jmuizelaar/world-map.html from 8fps to 13fps
in Vista on a Mac Mini
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 389515b..6b48dba 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1969,6 +1969,148 @@ _cairo_win32_surface_reset (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
+typedef struct _cairo_win32_surface_span_renderer {
+ cairo_span_renderer_t base;
+
+ cairo_operator_t op;
+ const cairo_pattern_t *pattern;
+ cairo_antialias_t antialias;
+
+ cairo_image_surface_t *mask;
+ cairo_win32_surface_t *dst;
+
+ cairo_composite_rectangles_t composite_rectangles;
+} cairo_win32_surface_span_renderer_t;
+
+static cairo_status_t
+_cairo_win32_surface_span_renderer_render_row (
+ void *abstract_renderer,
+ int y,
+ const cairo_half_open_span_t *spans,
+ unsigned num_spans)
+{
+ cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
+ _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_win32_surface_span_renderer_destroy (void *abstract_renderer)
+{
+ cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
+ if (!renderer) return;
+
+ if (renderer->mask != NULL)
+ cairo_surface_destroy (&renderer->mask->base);
+
+ free (renderer);
+}
+
+static cairo_status_t
+_cairo_win32_surface_span_renderer_finish (void *abstract_renderer)
+{
+ cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ if (renderer->pattern == NULL || renderer->mask == NULL)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = cairo_surface_status (&renderer->mask->base);
+ if (status == CAIRO_STATUS_SUCCESS) {
+ cairo_composite_rectangles_t *rects = &renderer->composite_rectangles;
+ cairo_win32_surface_t *dst = renderer->dst;
+ cairo_pattern_t *mask_pattern = cairo_pattern_create_for_surface (&renderer->mask->base);
+ /* composite onto the image surface directly if we can */
+ if (dst->image) {
+ GdiFlush(); /* XXX: I'm not sure if this needed or not */
+
+ status = dst->image->backend->composite (renderer->op,
+ renderer->pattern, mask_pattern, dst->image,
+ rects->src.x,
+ rects->src.y,
+ 0, 0, /* mask.x, mask.y */
+ rects->dst.x, rects->dst.y,
+ rects->width, rects->height);
+ } else {
+ /* otherwise go through the fallback_composite path which
+ * will do the appropriate surface acquisition */
+ status = _cairo_surface_fallback_composite (
+ renderer->op,
+ renderer->pattern, mask_pattern, dst,
+ rects->src.x,
+ rects->src.y,
+ 0, 0, /* mask.x, mask.y */
+ rects->dst.x, rects->dst.y,
+ rects->width, rects->height);
+ }
+ cairo_pattern_destroy (mask_pattern);
+
+ }
+ if (status != CAIRO_STATUS_SUCCESS)
+ return _cairo_span_renderer_set_error (abstract_renderer,
+ status);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_bool_t
+_cairo_win32_surface_check_span_renderer (cairo_operator_t op,
+ const cairo_pattern_t *pattern,
+ void *abstract_dst,
+ cairo_antialias_t antialias,
+ const cairo_composite_rectangles_t *rects)
+{
+ (void) op;
+ (void) pattern;
+ (void) abstract_dst;
+ (void) antialias;
+ (void) rects;
+ return TRUE;
+}
+
+static cairo_span_renderer_t *
+_cairo_win32_surface_create_span_renderer (cairo_operator_t op,
+ const cairo_pattern_t *pattern,
+ void *abstract_dst,
+ cairo_antialias_t antialias,
+ const cairo_composite_rectangles_t *rects)
+{
+ cairo_win32_surface_t *dst = abstract_dst;
+ cairo_win32_surface_span_renderer_t *renderer
+ = calloc(1, sizeof(*renderer));
+ cairo_status_t status;
+ int width = rects->width;
+ int height = rects->height;
+
+ if (renderer == NULL)
+ return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
+
+ renderer->base.destroy = _cairo_win32_surface_span_renderer_destroy;
+ renderer->base.finish = _cairo_win32_surface_span_renderer_finish;
+ renderer->base.render_row =
+ _cairo_win32_surface_span_renderer_render_row;
+ renderer->op = op;
+ renderer->pattern = pattern;
+ renderer->antialias = antialias;
+ renderer->dst = dst;
+
+ renderer->composite_rectangles = *rects;
+
+ /* TODO: support rendering to A1 surfaces (or: go add span
+ * compositing to pixman.) */
+ renderer->mask = (cairo_image_surface_t *)
+ cairo_image_surface_create (CAIRO_FORMAT_A8,
+ width, height);
+
+ status = cairo_surface_status (&renderer->mask->base);
+
+ if (status != CAIRO_STATUS_SUCCESS) {
+ _cairo_win32_surface_span_renderer_destroy (renderer);
+ return _cairo_span_renderer_create_in_error (status);
+ }
+ return &renderer->base;
+}
+
+
static const cairo_surface_backend_t cairo_win32_surface_backend = {
CAIRO_SURFACE_TYPE_WIN32,
_cairo_win32_surface_create_similar,
@@ -1981,8 +2123,8 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
_cairo_win32_surface_composite,
_cairo_win32_surface_fill_rectangles,
NULL, /* composite_trapezoids */
- NULL, /* create_span_renderer */
- NULL, /* check_span_renderer */
+ _cairo_win32_surface_create_span_renderer,
+ _cairo_win32_surface_check_span_renderer,
NULL, /* copy_page */
NULL, /* show_page */
_cairo_win32_surface_set_clip_region,
More information about the cairo-commit
mailing list