diff options
author | Martin Robinson <mrobinson@igalia.com> | 2013-01-04 16:31:01 -0800 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2013-01-04 16:31:01 -0800 |
commit | 9194904fa838a115b4dc58e5bff7a235cc2a9a7a (patch) | |
tree | dd04e54cefd43651db511081071cd0a993e0d322 | |
parent | 9bff4508443abe002fcb0ffdb9b1897272f1c588 (diff) | |
download | cairo-9194904fa838a115b4dc58e5bff7a235cc2a9a7a.tar.gz |
gl: Better handling of clear surfaces
When clearing a GL surface, set is_clear to true, and when mapping to an
image, handle is_clear like surfaces without modification. Additionally,
explicitly clear surfaces created via cairo_surface_create_similar.
-rw-r--r-- | src/cairo-gl-surface.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index 4b74cf0c0..4ca876cd7 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -508,9 +508,36 @@ _cairo_gl_surface_clear (cairo_gl_surface_t *surface, glClearColor (r, g, b, a); glClear (GL_COLOR_BUFFER_BIT); + if (a == 0) + surface->base.is_clear = TRUE; + return _cairo_gl_context_release (ctx, status); } +static cairo_surface_t * +_cairo_gl_surface_create_and_clear_scratch (cairo_gl_context_t *ctx, + cairo_content_t content, + int width, + int height) +{ + cairo_gl_surface_t *surface; + cairo_int_status_t status; + + surface = (cairo_gl_surface_t *) + _cairo_gl_surface_create_scratch (ctx, content, width, height); + if (unlikely (surface->base.status)) + return &surface->base; + + /* Cairo surfaces start out initialized to transparent (black) */ + status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); + if (unlikely (status)) { + cairo_surface_destroy (&surface->base); + return _cairo_surface_create_in_error (status); + } + + return &surface->base; +} + cairo_surface_t * cairo_gl_surface_create (cairo_device_t *abstract_device, cairo_content_t content, @@ -538,16 +565,13 @@ cairo_gl_surface_create (cairo_device_t *abstract_device, return _cairo_surface_create_in_error (status); surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, content, width, height); + _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height); if (unlikely (surface->base.status)) { status = _cairo_gl_context_release (ctx, surface->base.status); cairo_surface_destroy (&surface->base); return _cairo_surface_create_in_error (status); } - /* Cairo surfaces start out initialized to transparent (black) */ - status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); - status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) { cairo_surface_destroy (&surface->base); @@ -740,7 +764,7 @@ _cairo_gl_surface_create_similar (void *abstract_surface, if (unlikely (status)) return _cairo_surface_create_in_error (status); - surface = _cairo_gl_surface_create_scratch (ctx, content, width, height); + surface = _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height); status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) { @@ -1055,13 +1079,20 @@ _cairo_gl_surface_map_to_image (void *abstract_surface, extents->width, extents->height, -1); - if (unlikely (image->base.status) || surface->base.serial == 0) { + if (unlikely (image->base.status)) { status = _cairo_gl_context_release (ctx, status); return image; } cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y); + /* If the original surface has not been modified or + * is clear, we can avoid downloading data. */ + if (surface->base.is_clear || surface->base.serial == 0) { + status = _cairo_gl_context_release (ctx, status); + return image; + } + /* This is inefficient, as we'd rather just read the thing without making * it the destination. But then, this is the fallback path, so let's not * fall back instead. |