From 8737bc8b17ff0c437bb57df018bb7c540a394a7c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 12 Jun 2010 16:49:46 +0100 Subject: [PATCH] gl: start returning the failure status aftern an invalid GL op. --- src/cairo-gl-composite.c | 1 + src/cairo-gl-device.c | 26 ++++++++++++++++------- src/cairo-gl-glyphs.c | 10 ++++++--- src/cairo-gl-private.h | 45 ++++++++++++++++++++++++++++++---------- src/cairo-gl-surface.c | 40 +++++++++++++++++++++-------------- 5 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index ddb06d6df..0614fa356 100644 --- a/src/cairo-gl-composite.c +++ b/src/cairo-gl-composite.c @@ -58,6 +58,7 @@ _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst, status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient); _cairo_gl_context_release (ctx); + return status; } diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c index 51b72e007..380d393be 100644 --- a/src/cairo-gl-device.c +++ b/src/cairo-gl-device.c @@ -92,9 +92,7 @@ _gl_flush (void *device) glDisable (GL_SCISSOR_TEST); glDisable (GL_BLEND); - _cairo_gl_context_release (ctx); - - return CAIRO_STATUS_SUCCESS; + return _cairo_gl_context_release (ctx); } static void @@ -194,7 +192,7 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) fprintf (stderr, " GL_ARB_texture_non_power_of_two, GL_ARB_texture_rectangle\n"); } - if (!GLEW_ARB_texture_non_power_of_two) + if (! GLEW_ARB_texture_non_power_of_two) ctx->tex_target = GL_TEXTURE_RECTANGLE_EXT; else ctx->tex_target = GL_TEXTURE_2D; @@ -272,8 +270,23 @@ _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, 0); status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT); - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) - fprintf (stderr, "destination is framebuffer incomplete\n"); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + const char *str; + switch (status) { + //case GL_FRAMEBUFFER_UNDEFINED_EXT: str= "undefined"; break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: str= "incomplete attachment"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: str= "incomplete/missing attachment"; break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: str= "incomplete draw buffer"; break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: str= "incomplete read buffer"; break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: str= "unsupported"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: str= "incomplete multiple"; break; + default: str = "unknown error"; break; + } + + fprintf (stderr, + "destination is framebuffer incomplete: %s [%#x]\n", + str, status); + } } void @@ -311,4 +324,3 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx, glMatrixMode (GL_MODELVIEW); glLoadIdentity (); } - diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c index a19174d31..b390f8219 100644 --- a/src/cairo-gl-glyphs.c +++ b/src/cairo-gl-glyphs.c @@ -229,7 +229,7 @@ _render_glyphs (cairo_gl_surface_t *dst, cairo_gl_glyph_cache_t *cache = NULL; cairo_gl_context_t *ctx; cairo_gl_composite_t setup; - cairo_status_t status; + cairo_status_t status, status_maybe_ignored; int i = 0; *has_component_alpha = FALSE; @@ -313,7 +313,9 @@ _render_glyphs (cairo_gl_surface_t *dst, /* XXX: _cairo_gl_composite_begin() acquires the context a * second time. Need to refactor this loop so this doesn't happen. */ - _cairo_gl_context_release (ctx); + status = _cairo_gl_context_release (ctx); + if (unlikely (status)) + goto FINISH; } if (scaled_glyph->surface_private == NULL) { @@ -349,7 +351,9 @@ _render_glyphs (cairo_gl_surface_t *dst, FINISH: _cairo_scaled_font_thaw_cache (scaled_font); - _cairo_gl_context_release (ctx); + status_maybe_ignored = _cairo_gl_context_release (ctx); + if (status == CAIRO_STATUS_SUCCESS) + status = status_maybe_ignored; _cairo_gl_composite_fini (&setup); diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index a02e279ff..132fcb86e 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -43,10 +43,15 @@ #define CAIRO_GL_PRIVATE_H #include "cairoint.h" + #include "cairo-gl-gradient-private.h" + #include "cairo-device-private.h" +#include "cairo-error-private.h" #include "cairo-rtree-private.h" +#include + #include #include "cairo-gl.h" @@ -82,6 +87,7 @@ typedef struct _cairo_gl_surface { GLuint tex; /* GL texture object containing our data. */ GLuint fb; /* GL framebuffer object wrapping our data. */ + GLuint depth; /* GL framebuffer object holding depth */ } cairo_gl_surface_t; typedef struct cairo_gl_glyph_cache { @@ -218,13 +224,22 @@ typedef struct _cairo_gl_composite { cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend; cairo_private const char *_cairo_gl_error_to_string (GLenum err); -#define _cairo_gl_check_error() do { \ - GLenum err; \ - while ((err = glGetError ())) { \ - fprintf (stderr, "%s:%d: GL error 0x%04x: %s\n", __FILE__,__LINE__, (int) err, _cairo_gl_error_to_string (err)); \ - _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR); \ - } \ -} while (0) +static cairo_always_inline cairo_status_t +_do_cairo_gl_check_error (const char *file, int line) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + GLenum err; + + while (unlikely ((err = glGetError ()))) { + fprintf (stderr, "%s:%d: GL error 0x%04x: %s\n", + file, line, (int) err, + _cairo_gl_error_to_string (err)); + status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); + } + + return status; +} +#define _cairo_gl_check_error() _do_cairo_gl_check_error(__FILE__, __LINE__) static inline cairo_device_t * _cairo_gl_context_create_in_error (cairo_status_t status) @@ -276,14 +291,22 @@ _cairo_gl_context_acquire (cairo_device_t *device, if (unlikely (status)) return status; + assert (_cairo_gl_check_error () == CAIRO_STATUS_SUCCESS); + *ctx = (cairo_gl_context_t *) device; return CAIRO_STATUS_SUCCESS; } -#define _cairo_gl_context_release(ctx) do {\ - _cairo_gl_check_error (); \ - cairo_device_release (&(ctx)->base); \ -} while (0) +static cairo_always_inline cairo_status_t +_cairo_gl_context_release (cairo_gl_context_t *ctx) +{ + cairo_status_t status; + + status = _cairo_gl_check_error (); + cairo_device_release (&(ctx)->base); + + return status; +} cairo_private void _cairo_gl_context_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface); diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index e79f46c9f..e6aa6550f 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -66,7 +66,8 @@ _cairo_gl_surface_composite (cairo_operator_t op, unsigned int height, cairo_region_t *clip_region); -#define BIAS .375 +static cairo_status_t +_cairo_gl_surface_flush (void *abstract_surface); static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface) { @@ -86,6 +87,7 @@ const char *_cairo_gl_error_to_string (GLenum err) case GL_STACK_OVERFLOW: return "stack overflow"; case GL_STACK_UNDERFLOW: return "stack underflow"; case GL_OUT_OF_MEMORY: return "out of memory"; + case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: return "invalid framebuffer operation"; default: return "unknown error"; @@ -321,9 +323,8 @@ _cairo_gl_surface_clear (cairo_gl_surface_t *surface, glDisable (GL_SCISSOR_TEST); glClearColor (r, g, b, a); glClear (GL_COLOR_BUFFER_BIT); - _cairo_gl_context_release (ctx); - return CAIRO_STATUS_SUCCESS; + return _cairo_gl_context_release (ctx); } cairo_surface_t * @@ -369,7 +370,11 @@ cairo_gl_surface_create (cairo_device_t *abstract_device, return _cairo_surface_create_in_error (status); } - _cairo_gl_context_release (ctx); + status = _cairo_gl_context_release (ctx); + if (unlikely (status)) { + _cairo_gl_context_release (ctx); + return _cairo_surface_create_in_error (status); + } return &surface->base; } @@ -436,7 +441,7 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface) if (! _cairo_gl_surface_is_texture (surface)) { cairo_gl_context_t *ctx; - + if (_cairo_gl_context_acquire (surface->base.device, &ctx)) return; @@ -523,7 +528,9 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, if (unlikely (status)) return status; - cairo_surface_flush (&dst->base); + status = _cairo_gl_surface_flush (&dst->base); + if (unlikely (status)) + goto FAIL; glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp); @@ -664,11 +671,16 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t *surface, if (! _cairo_gl_surface_is_texture (surface) && GLEW_MESA_pack_invert) glPixelStorei (GL_PACK_INVERT_MESA, 0); - _cairo_gl_context_release (ctx); + status = _cairo_gl_context_release (ctx); + if (unlikely (status)) { + cairo_surface_destroy (&image->base); + return status; + } *image_out = image; if (rect_out != NULL) *rect_out = *interest; + return CAIRO_STATUS_SUCCESS; } @@ -692,13 +704,13 @@ _cairo_gl_surface_finish (void *abstract_surface) if (ctx->current_target == surface) ctx->current_target = NULL; + if (surface->depth) + glDeleteFramebuffersEXT (1, &surface->depth); if (surface->fb) glDeleteFramebuffersEXT (1, &surface->fb); glDeleteTextures (1, &surface->tex); - _cairo_gl_context_release (ctx); - - return CAIRO_STATUS_SUCCESS; + return _cairo_gl_context_release (ctx); } static cairo_status_t @@ -953,7 +965,7 @@ _cairo_gl_surface_composite (cairo_operator_t op, 0); } - _cairo_gl_context_release (ctx); + status = _cairo_gl_context_release (ctx); CLEANUP: _cairo_gl_composite_fini (&setup); @@ -1050,7 +1062,7 @@ _cairo_gl_surface_fill_rectangles (void *abstract_dst, 0); } - _cairo_gl_context_release (ctx); + status = _cairo_gl_context_release (ctx); CLEANUP: _cairo_gl_composite_fini (&setup); @@ -1295,9 +1307,7 @@ _cairo_gl_surface_flush (void *abstract_surface) (ctx->current_target == surface)) _cairo_gl_composite_flush (ctx); - _cairo_gl_context_release (ctx); - - return CAIRO_STATUS_SUCCESS; + return _cairo_gl_context_release (ctx); } static cairo_int_status_t