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.
This commit is contained in:
Martin Robinson 2013-01-04 16:31:01 -08:00
parent 9bff450844
commit 9194904fa8

View file

@ -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.