summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2013-01-04 16:31:01 -0800
committerMartin Robinson <mrobinson@igalia.com>2013-01-04 16:31:01 -0800
commit9194904fa838a115b4dc58e5bff7a235cc2a9a7a (patch)
treedd04e54cefd43651db511081071cd0a993e0d322
parent9bff4508443abe002fcb0ffdb9b1897272f1c588 (diff)
downloadcairo-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.c43
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.