[cairo-commit] 3 commits - src/cairo-gl-device.c src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-surface.c

Benjamin Otte company at kemper.freedesktop.org
Sat May 8 09:08:36 PDT 2010


 src/cairo-gl-device.c  |    9 ---
 src/cairo-gl-glyphs.c  |    4 -
 src/cairo-gl-private.h |   59 ++++++++++++++++++------
 src/cairo-gl-shaders.c |  105 +++++++++++++++++++++++---------------------
 src/cairo-gl-surface.c |  116 +++++++++++++++++++++----------------------------
 5 files changed, 153 insertions(+), 140 deletions(-)

New commits:
commit d2a250ad33dcd1a3960b07d2f0270266a3f3f106
Author: Benjamin Otte <otte at redhat.com>
Date:   Fri May 7 20:36:33 2010 +0200

    gl: Make the shader implementation per-context, not global

diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 0a8a74f..ab1010d 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -141,13 +141,7 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
 
     ctx->has_span_renderer = GLEW_ARB_vertex_buffer_object;
 
-    if (GLEW_VERSION_2_0 ||
-	(GLEW_ARB_fragment_shader &&
-	 GLEW_ARB_vertex_shader &&
-	 GLEW_ARB_shader_objects))
-    {
-	ctx->using_glsl = TRUE;
-    }
+    _cairo_gl_context_init_shaders (ctx);
 
     init_shader_program (&ctx->fill_rectangles_shader);
 
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 604d060..fe8fc87 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -326,7 +326,7 @@ _cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
 					&setup->composite->shader);
 	if (!_cairo_status_is_error (status)) {
 	    setup->in = in;
-	    _cairo_gl_use_program (setup->composite->shader);
+	    _cairo_gl_use_program (ctx, setup->composite->shader);
 	    _cairo_gl_set_src_operand (ctx, setup->composite);
 	    return;
 	}
@@ -638,7 +638,7 @@ _render_glyphs (cairo_gl_surface_t	*dst,
     glDisableClientState (GL_TEXTURE_COORD_ARRAY);
     glActiveTexture (GL_TEXTURE1);
     glDisable (ctx->tex_target);
-    _cairo_gl_use_program (NULL);
+    _cairo_gl_use_program (ctx, NULL);
 
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
 
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c9b99c0..15e5466 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -80,6 +80,8 @@ typedef struct cairo_gl_glyph_cache {
     unsigned int width, height;
 } cairo_gl_glyph_cache_t;
 
+typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
+
 typedef struct cairo_gl_shader_program {
     GLuint vertex_shader;
     GLuint fragment_shader;
@@ -123,9 +125,10 @@ typedef struct _cairo_gl_context {
     GLint max_framebuffer_size;
     GLint max_texture_size;
     GLenum tex_target;
-    cairo_bool_t using_glsl;
     cairo_bool_t has_span_renderer;
 
+    const cairo_gl_shader_impl_t *shader_impl;
+
     cairo_gl_shader_program_t fill_rectangles_shader;
     cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
 					[CAIRO_GL_SHADER_MASK_COUNT]
@@ -234,7 +237,7 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
 static cairo_always_inline cairo_bool_t
 _cairo_gl_device_has_glsl (cairo_device_t *device)
 {
-    return ((cairo_gl_context_t *) device)->using_glsl;
+    return ((cairo_gl_context_t *) device)->shader_impl != NULL;
 }
 
 static cairo_always_inline cairo_bool_t
@@ -325,42 +328,54 @@ _cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
 }
 
 cairo_private void
+_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx);
+
+cairo_private void
 init_shader_program (cairo_gl_shader_program_t *program);
 
 cairo_private void
-destroy_shader_program (cairo_gl_shader_program_t *program);
+destroy_shader_program (cairo_gl_context_t *ctx,
+                        cairo_gl_shader_program_t *program);
 
 cairo_private cairo_status_t
-create_shader_program (cairo_gl_shader_program_t *program,
+create_shader_program (cairo_gl_context_t *ctx,
+                       cairo_gl_shader_program_t *program,
                        const char *vertex_text,
                        const char *fragment_text);
 
 cairo_private cairo_status_t
-bind_float_to_shader (GLuint program, const char *name,
+bind_float_to_shader (cairo_gl_context_t *ctx,
+                      GLuint program, const char *name,
                       float value);
 
 cairo_private cairo_status_t
-bind_vec2_to_shader (GLuint program, const char *name,
+bind_vec2_to_shader (cairo_gl_context_t *ctx,
+                     GLuint program, const char *name,
                      float value0, float value1);
 
 cairo_private cairo_status_t
-bind_vec3_to_shader (GLuint program, const char *name,
+bind_vec3_to_shader (cairo_gl_context_t *ctx,
+                     GLuint program, const char *name,
                      float value0, float value1,
                      float value2);
 
 cairo_private cairo_status_t
-bind_vec4_to_shader (GLuint program, const char *name,
+bind_vec4_to_shader (cairo_gl_context_t *ctx,
+                     GLuint program, const char *name,
                      float value0, float value1,
                      float value2, float value3);
 
 cairo_private cairo_status_t
-bind_matrix_to_shader (GLuint program, const char *name, cairo_matrix_t* m);
+bind_matrix_to_shader (cairo_gl_context_t *ctx,
+                       GLuint program, const char *name, cairo_matrix_t* m);
 
 cairo_private cairo_status_t
-bind_texture_to_shader (GLuint program, const char *name, GLuint tex_unit);
+bind_texture_to_shader (cairo_gl_context_t *ctx,
+                        GLuint program, const char *name, GLuint tex_unit);
 
 cairo_private void
-_cairo_gl_use_program (cairo_gl_shader_program_t *shader);
+_cairo_gl_use_program (cairo_gl_context_t *ctx,
+                       cairo_gl_shader_program_t *shader);
 
 cairo_private cairo_status_t
 _cairo_gl_get_program (cairo_gl_context_t *ctx,
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 3ad3383..8aa464e 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -35,7 +35,7 @@
 #include "cairo-gl-private.h"
 #include "cairo-error-private.h"
 
-typedef struct _shader_impl {
+typedef struct cairo_gl_shader_impl {
     cairo_status_t
     (*compile_shader) (GLuint *shader, GLenum type, const char *text);
 
@@ -393,7 +393,7 @@ use_program_core_2_0 (cairo_gl_shader_program_t *program)
 	glUseProgram (0);
 }
 
-static const shader_impl_t shader_impl_core_2_0 = {
+static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
     compile_shader_core_2_0,
     link_shader_core_2_0,
     destroy_shader_program_core_2_0,
@@ -406,7 +406,7 @@ static const shader_impl_t shader_impl_core_2_0 = {
     use_program_core_2_0,
 };
 
-static const shader_impl_t shader_impl_arb = {
+static const cairo_gl_shader_impl_t shader_impl_arb = {
     compile_shader_arb,
     link_shader_arb,
     destroy_shader_program_arb,
@@ -419,19 +419,19 @@ static const shader_impl_t shader_impl_arb = {
     use_program_arb,
 };
 
-static const shader_impl_t*
-get_impl (void)
+void
+_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
 {
     /* XXX multiple device support? */
     if (GLEW_VERSION_2_0) {
-        return &shader_impl_core_2_0;
+        ctx->shader_impl = &shader_impl_core_2_0;
     } else if (GLEW_ARB_shader_objects &&
                GLEW_ARB_fragment_shader &&
                GLEW_ARB_vertex_program) {
-        return &shader_impl_arb;
+        ctx->shader_impl = &shader_impl_arb;
+    } else {
+        ctx->shader_impl = NULL;
     }
-
-    return NULL;
 }
 
 void
@@ -444,18 +444,19 @@ init_shader_program (cairo_gl_shader_program_t *program)
 }
 
 void
-destroy_shader_program (cairo_gl_shader_program_t *program)
+destroy_shader_program (cairo_gl_context_t *ctx,
+                        cairo_gl_shader_program_t *program)
 {
-    return get_impl()->destroy_shader_program(program);
+    return ctx->shader_impl->destroy_shader_program (program);
 }
 
 cairo_status_t
-create_shader_program (cairo_gl_shader_program_t *program,
+create_shader_program (cairo_gl_context_t *ctx,
+                       cairo_gl_shader_program_t *program,
                        const char *vertex_text,
                        const char *fragment_text)
 {
     cairo_status_t status;
-    const shader_impl_t *impl;
 
     if (program->program != 0)
         return CAIRO_STATUS_SUCCESS;
@@ -463,32 +464,31 @@ create_shader_program (cairo_gl_shader_program_t *program,
     if (program->build_failure)
         return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    impl = get_impl ();
-    if (impl == NULL)
+    if (ctx->shader_impl == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = impl->compile_shader (&program->vertex_shader,
-				   GL_VERTEX_SHADER,
-				   vertex_text);
+    status = ctx->shader_impl->compile_shader (&program->vertex_shader,
+                                               GL_VERTEX_SHADER,
+                                               vertex_text);
     if (unlikely (status))
         goto FAILURE;
 
-    status = impl->compile_shader (&program->fragment_shader,
-				   GL_FRAGMENT_SHADER,
-				   fragment_text);
+    status = ctx->shader_impl->compile_shader (&program->fragment_shader,
+                                               GL_FRAGMENT_SHADER,
+                                               fragment_text);
     if (unlikely (status))
         goto FAILURE;
 
-    status = impl->link_shader (&program->program,
-				program->vertex_shader,
-				program->fragment_shader);
+    status = ctx->shader_impl->link_shader (&program->program,
+                                            program->vertex_shader,
+                                            program->fragment_shader);
     if (unlikely (status))
         goto FAILURE;
 
     return CAIRO_STATUS_SUCCESS;
 
  FAILURE:
-    destroy_shader_program (program);
+    destroy_shader_program (ctx, program);
     program->vertex_shader = 0;
     program->fragment_shader = 0;
     program->program = 0;
@@ -498,57 +498,61 @@ create_shader_program (cairo_gl_shader_program_t *program,
 }
 
 cairo_status_t
-bind_float_to_shader (GLuint program, const char *name,
+bind_float_to_shader (cairo_gl_context_t *ctx,
+                      GLuint program, const char *name,
                       float value)
 {
-    return get_impl()->bind_float_to_shader(program, name, value);
+    return ctx->shader_impl->bind_float_to_shader(program, name, value);
 }
 
 cairo_status_t
-bind_vec2_to_shader (GLuint program, const char *name,
+bind_vec2_to_shader (cairo_gl_context_t *ctx,
+                     GLuint program, const char *name,
                      float value0, float value1)
 {
-    return get_impl()->bind_vec2_to_shader(program, name, value0, value1);
+    return ctx->shader_impl->bind_vec2_to_shader(program, name, value0, value1);
 }
 
 cairo_status_t
-bind_vec3_to_shader (GLuint program, const char *name,
+bind_vec3_to_shader (cairo_gl_context_t *ctx,
+                     GLuint program, const char *name,
                      float value0, float value1,
                      float value2)
 {
-    return get_impl()->bind_vec3_to_shader(program, name, value0, value1, value2);
+    return ctx->shader_impl->bind_vec3_to_shader(program, name, value0, value1, value2);
 }
 
 cairo_status_t
-bind_vec4_to_shader (GLuint program, const char *name,
+bind_vec4_to_shader (cairo_gl_context_t *ctx,
+                     GLuint program, const char *name,
                      float value0, float value1,
                      float value2, float value3)
 {
-    return get_impl()->bind_vec4_to_shader(program, name, value0, value1, value2, value3);
+    return ctx->shader_impl->bind_vec4_to_shader(program, name, value0, value1, value2, value3);
 }
 
 cairo_status_t
-bind_matrix_to_shader (GLuint program, const char *name, cairo_matrix_t* m)
+bind_matrix_to_shader (cairo_gl_context_t *ctx,
+                       GLuint program, const char *name, cairo_matrix_t* m)
 {
-    return get_impl()->bind_matrix_to_shader(program, name, m);
+    return ctx->shader_impl->bind_matrix_to_shader(program, name, m);
 }
 
 cairo_status_t
-bind_texture_to_shader (GLuint program, const char *name, GLuint tex_unit)
+bind_texture_to_shader (cairo_gl_context_t *ctx,
+                        GLuint program, const char *name, GLuint tex_unit)
 {
-    return get_impl()->bind_texture_to_shader(program, name, tex_unit);
+    return ctx->shader_impl->bind_texture_to_shader(program, name, tex_unit);
 }
 
 void
-_cairo_gl_use_program (cairo_gl_shader_program_t *program)
+_cairo_gl_use_program (cairo_gl_context_t *ctx,
+                       cairo_gl_shader_program_t *program)
 {
-    const shader_impl_t *impl;
-
-    impl = get_impl ();
-    if (impl == NULL)
-	return;
+    if (!ctx->shader_impl)
+        return;
 
-    impl->use_program (program);
+    ctx->shader_impl->use_program (program);
 }
 
 static const char *vs_no_coords =
@@ -833,7 +837,7 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
     if (program->build_failure)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (get_impl () == NULL)
+    if (ctx->shader_impl == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     source_source = source_sources[source];
@@ -887,7 +891,8 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
     sprintf(fs_source, "%s%s%s", source_source, mask_source, in_source);
 
     init_shader_program (program);
-    status = create_shader_program (program,
+    status = create_shader_program (ctx,
+                                    program,
 				    vs_source,
 				    fs_source);
     free (fs_source);
@@ -895,19 +900,19 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
     if (_cairo_status_is_error (status))
 	return status;
 
-    _cairo_gl_use_program (program);
+    _cairo_gl_use_program (ctx, program);
     if (source != CAIRO_GL_SHADER_SOURCE_CONSTANT) {
-	status = bind_texture_to_shader (program->program, "source_sampler", 0);
+	status = bind_texture_to_shader (ctx, program->program, "source_sampler", 0);
 	assert (!_cairo_status_is_error (status));
     }
     if (mask != CAIRO_GL_SHADER_MASK_CONSTANT &&
 	mask != CAIRO_GL_SHADER_MASK_SPANS &&
 	mask != CAIRO_GL_SHADER_MASK_NONE) {
-	status = bind_texture_to_shader (program->program, "mask_sampler", 1);
+	status = bind_texture_to_shader (ctx, program->program, "mask_sampler", 1);
 	assert (!_cairo_status_is_error (status));
     }
 
-    _cairo_gl_use_program (NULL);
+    _cairo_gl_use_program (ctx, NULL);
 
     *out_program = program;
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index a2d09e5..82a3981 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -649,7 +649,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 		goto fail;
 	    }
 
-	    _cairo_gl_use_program (program);
+	    _cairo_gl_use_program (ctx, program);
 	} else {
 	    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 	}
@@ -712,7 +712,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 
 	if (_cairo_gl_device_has_glsl (&ctx->base))
-	    _cairo_gl_use_program (NULL);
+	    _cairo_gl_use_program (ctx, NULL);
 	glDeleteTextures (1, &tex);
 	glDisable (ctx->tex_target);
     }
@@ -1421,12 +1421,13 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
 	else
 	    uniform_name = "constant_mask";
 
-	status = bind_vec4_to_shader(setup->shader->program,
-                                     uniform_name,
-                                     color[0],
-                                     color[1],
-                                     color[2],
-                                     color[3]);
+	status = bind_vec4_to_shader (ctx,
+                                      setup->shader->program,
+                                      uniform_name,
+                                      color[0],
+                                      color[1],
+                                      color[2],
+                                      color[3]);
         assert (! _cairo_status_is_error (status));
 
 	return;
@@ -1509,12 +1510,12 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 	glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
 	glEnable (GL_TEXTURE_1D);
 
-	status = bind_matrix_to_shader (setup->shader->program,
+	status = bind_matrix_to_shader (ctx, setup->shader->program,
 					"source_matrix",
 					&setup->src.operand.linear.m);
 	assert (!_cairo_status_is_error (status));
 
-	status = bind_vec2_to_shader (setup->shader->program,
+	status = bind_vec2_to_shader (ctx, setup->shader->program,
 				      "source_segment",
 				      setup->src.operand.linear.segment_x,
 				      setup->src.operand.linear.segment_y);
@@ -1526,23 +1527,23 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 	glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
 	glEnable (GL_TEXTURE_1D);
 
-        status = bind_matrix_to_shader (setup->shader->program,
+        status = bind_matrix_to_shader (ctx, setup->shader->program,
 					"source_matrix",
 					&setup->src.operand.radial.m);
 	assert (!_cairo_status_is_error (status));
 
-        status = bind_vec2_to_shader (setup->shader->program,
+        status = bind_vec2_to_shader (ctx, setup->shader->program,
 				      "source_circle_1",
 				      setup->src.operand.radial.circle_1_x,
 				      setup->src.operand.radial.circle_1_y);
 	assert (!_cairo_status_is_error (status));
 
-        status = bind_float_to_shader (setup->shader->program,
+        status = bind_float_to_shader (ctx, setup->shader->program,
 				       "source_radius_0",
 				       setup->src.operand.radial.radius_0);
 	assert (!_cairo_status_is_error (status));
 
-        status = bind_float_to_shader (setup->shader->program,
+        status = bind_float_to_shader (ctx, setup->shader->program,
 				       "source_radius_1",
 				       setup->src.operand.radial.radius_1);
 	assert (!_cairo_status_is_error (status));
@@ -1594,7 +1595,8 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
 }
 
 static void
-_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_composite_setup_t *setup)
+_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
+                                            cairo_gl_composite_setup_t *setup)
 {
     cairo_status_t status;
 
@@ -1604,11 +1606,11 @@ _cairo_gl_set_linear_gradient_mask_operand (cairo_gl_composite_setup_t *setup)
     glBindTexture (GL_TEXTURE_1D, setup->mask.operand.linear.tex);
     glEnable (GL_TEXTURE_1D);
 
-    status = bind_matrix_to_shader (setup->shader->program,
+    status = bind_matrix_to_shader (ctx, setup->shader->program,
 			   "mask_matrix", &setup->mask.operand.linear.m);
     assert (!_cairo_status_is_error (status));
 
-    status = bind_vec2_to_shader (setup->shader->program,
+    status = bind_vec2_to_shader (ctx, setup->shader->program,
 			 "mask_segment",
 			 setup->mask.operand.linear.segment_x,
 			 setup->mask.operand.linear.segment_y);
@@ -1616,7 +1618,8 @@ _cairo_gl_set_linear_gradient_mask_operand (cairo_gl_composite_setup_t *setup)
 }
 
 static void
-_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_composite_setup_t *setup)
+_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
+                                            cairo_gl_composite_setup_t *setup)
 {
     cairo_status_t status;
 
@@ -1626,23 +1629,23 @@ _cairo_gl_set_radial_gradient_mask_operand (cairo_gl_composite_setup_t *setup)
     glBindTexture (GL_TEXTURE_1D, setup->mask.operand.radial.tex);
     glEnable (GL_TEXTURE_1D);
 
-    status = bind_matrix_to_shader (setup->shader->program,
+    status = bind_matrix_to_shader (ctx, setup->shader->program,
 				    "mask_matrix",
 				    &setup->mask.operand.radial.m);
     assert (!_cairo_status_is_error (status));
 
-    status = bind_vec2_to_shader (setup->shader->program,
+    status = bind_vec2_to_shader (ctx, setup->shader->program,
 				  "mask_circle_1",
 				  setup->mask.operand.radial.circle_1_x,
 				  setup->mask.operand.radial.circle_1_y);
     assert (!_cairo_status_is_error (status));
 
-    status = bind_float_to_shader (setup->shader->program,
+    status = bind_float_to_shader (ctx, setup->shader->program,
 				   "mask_radius_0",
 				   setup->mask.operand.radial.radius_0);
     assert (!_cairo_status_is_error (status));
 
-    status = bind_float_to_shader (setup->shader->program,
+    status = bind_float_to_shader (ctx, setup->shader->program,
 				   "mask_radius_1",
 				   setup->mask.operand.radial.radius_1);
     assert (!_cairo_status_is_error (status));
@@ -1676,12 +1679,12 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	/* Have to have a dummy texture bound in order to use the combiner unit. */
 	if (setup->shader) {
             cairo_status_t status;
-	    status = bind_vec4_to_shader(setup->shader->program,
-                                         "constant_mask",
-                                         setup->src.operand.constant.color[0],
-                                         setup->src.operand.constant.color[1],
-                                         setup->src.operand.constant.color[2],
-                                         setup->src.operand.constant.color[3]);
+	    status = bind_vec4_to_shader (ctx, setup->shader->program,
+                                          "constant_mask",
+                                          setup->src.operand.constant.color[0],
+                                          setup->src.operand.constant.color[1],
+                                          setup->src.operand.constant.color[2],
+                                          setup->src.operand.constant.color[3]);
             assert (! _cairo_status_is_error (status));
 	} else {
 	    glBindTexture (ctx->tex_target, ctx->dummy_tex);
@@ -1720,11 +1723,11 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	break;
 
     case OPERAND_LINEAR_GRADIENT:
-	_cairo_gl_set_linear_gradient_mask_operand (setup);
+	_cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
 	break;
 
     case OPERAND_RADIAL_GRADIENT:
-	_cairo_gl_set_radial_gradient_mask_operand (setup);
+	_cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
 	break;
     }
 }
@@ -1944,7 +1947,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
 
     if (op == CAIRO_OPERATOR_OVER) {
 	setup.shader = ca_source_alpha_program;
-	_cairo_gl_use_program (setup.shader);
+	_cairo_gl_use_program (ctx, setup.shader);
 	_cairo_gl_set_operator (dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
 	_cairo_gl_set_src_alpha_operand (ctx, &setup);
 	_cairo_gl_set_component_alpha_mask_operand (ctx, &setup);
@@ -1952,14 +1955,14 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
     }
 
     setup.shader = ca_source_program;
-    _cairo_gl_use_program (setup.shader);
+    _cairo_gl_use_program (ctx, setup.shader);
     _cairo_gl_set_operator (dst, CAIRO_OPERATOR_ADD, TRUE);
     _cairo_gl_set_src_operand (ctx, &setup);
     _cairo_gl_set_component_alpha_mask_operand (ctx, &setup);
     glDrawArrays (GL_QUADS, 0, num_vertices);
 
     glDisable (GL_BLEND);
-    _cairo_gl_use_program (NULL);
+    _cairo_gl_use_program (ctx, NULL);
 
     glDisableClientState (GL_VERTEX_ARRAY);
 
@@ -2082,7 +2085,7 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
     _cairo_gl_set_destination (ctx, dst);
     _cairo_gl_set_operator (dst, op, FALSE);
 
-    _cairo_gl_use_program (setup.shader);
+    _cairo_gl_use_program (ctx, setup.shader);
     _cairo_gl_set_src_operand (ctx, &setup);
 
     if (mask != NULL) {
@@ -2114,10 +2117,10 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
 	    }
 	    break;
 	case OPERAND_LINEAR_GRADIENT:
-	    _cairo_gl_set_linear_gradient_mask_operand (&setup);
+	    _cairo_gl_set_linear_gradient_mask_operand (ctx, &setup);
 	    break;
 	case OPERAND_RADIAL_GRADIENT:
-	    _cairo_gl_set_radial_gradient_mask_operand (&setup);
+	    _cairo_gl_set_radial_gradient_mask_operand (ctx, &setup);
 	    break;
 	}
     }
@@ -2205,7 +2208,7 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
 
     glDrawArrays (GL_QUADS, 0, num_vertices);
 
-    _cairo_gl_use_program (NULL);
+    _cairo_gl_use_program (ctx, NULL);
     glDisable (GL_BLEND);
 
     glDisableClientState (GL_VERTEX_ARRAY);
@@ -2411,7 +2414,8 @@ _cairo_gl_surface_fill_rectangles_glsl (void                  *abstract_surface,
     if (unlikely (status))
 	return status;
 
-    status = create_shader_program (&ctx->fill_rectangles_shader,
+    status = create_shader_program (ctx,
+                                    &ctx->fill_rectangles_shader,
 				    fill_vs_source,
 				    fill_fs_source);
     if (unlikely (status)) {
@@ -2430,12 +2434,13 @@ _cairo_gl_surface_fill_rectangles_glsl (void                  *abstract_surface,
 	vertices = vertices_stack;
     }
 
-    _cairo_gl_use_program (&ctx->fill_rectangles_shader);
+    _cairo_gl_use_program (ctx, &ctx->fill_rectangles_shader);
 
     _cairo_gl_set_destination (ctx, surface);
     _cairo_gl_set_operator (surface, op, FALSE);
 
-    status = bind_vec4_to_shader (ctx->fill_rectangles_shader.program,
+    status = bind_vec4_to_shader (ctx,
+                                  ctx->fill_rectangles_shader.program,
                                   "color",
                                   color->red * color->alpha,
                                   color->green * color->alpha,
@@ -2743,7 +2748,7 @@ _cairo_gl_surface_span_renderer_finish (void *abstract_renderer)
     }
 
     glDisable (GL_BLEND);
-    _cairo_gl_use_program (NULL);
+    _cairo_gl_use_program (renderer->ctx, NULL);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -2835,7 +2840,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
 
     src_attributes = &renderer->setup.src.operand.texture.attributes;
 
-    _cairo_gl_use_program (renderer->setup.shader);
+    _cairo_gl_use_program (renderer->ctx, renderer->setup.shader);
     _cairo_gl_set_operator (dst, op, FALSE);
     _cairo_gl_set_src_operand (renderer->ctx, &renderer->setup);
 
commit 4571055c46e82cbb6d3ab47860d63e400b338238
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 19:36:46 2010 +0200

    gl: Print GL errors when releasing the device
    
    Don't scatter calls to error printing around everywhere, instead do it
    in the one place where it matters.
    
    Also, convert the functions to macros, so we can use __FILE__ and
    __LINE__ when printing a warning

diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index b308598..c9b99c0 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -194,6 +194,12 @@ typedef struct _cairo_gl_composite_setup {
 
 cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
 
+#define _cairo_gl_check_error() do { \
+    GLenum err; \
+    while ((err = glGetError ())) \
+	fprintf (stderr, "%s:%d: GL error 0x%08x\n", __FILE__,__LINE__, (int) err); \
+} while (0)
+
 static inline cairo_device_t *
 _cairo_gl_context_create_in_error (cairo_status_t status)
 {
@@ -251,11 +257,10 @@ _cairo_gl_context_acquire (cairo_device_t *device,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_always_inline void
-_cairo_gl_context_release (cairo_gl_context_t *ctx)
-{
-    cairo_device_release (&ctx->base);
-}
+#define _cairo_gl_context_release(ctx) do {\
+    _cairo_gl_check_error (); \
+    cairo_device_release (&(ctx)->base); \
+} while (0)
 
 cairo_private void
 _cairo_gl_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 5e71b2f..a2d09e5 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -319,7 +319,7 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
 				  int			height)
 {
     cairo_gl_surface_t *surface;
-    GLenum err, format;
+    GLenum format;
     cairo_status_t status;
 
     assert (width <= ctx->max_framebuffer_size && height <= ctx->max_framebuffer_size);
@@ -379,10 +379,6 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
 			       0);
     ctx->current_target = NULL;
 
-    while ((err = glGetError ())) {
-	fprintf (stderr, "GL error in surface create: 0x%08x\n", err);
-    }
-
     status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
     if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
 	fprintf (stderr, "destination is framebuffer incomplete\n");
@@ -740,7 +736,6 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t      *surface,
 {
     cairo_image_surface_t *image;
     cairo_gl_context_t *ctx;
-    GLenum err;
     GLenum format, type;
     cairo_format_t cairo_format;
     unsigned int cpp;
@@ -792,9 +787,6 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t      *surface,
     if (surface->fb == 0 && GLEW_MESA_pack_invert)
 	glPixelStorei (GL_PACK_INVERT_MESA, 0);
 
-    while ((err = glGetError ()))
-	fprintf (stderr, "GL error 0x%08x\n", (int) err);
-
     _cairo_gl_context_release (ctx);
 
     *image_out = image;
@@ -1813,7 +1805,6 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
     struct gl_point *texcoord_mask = texcoord_mask_stack;
     cairo_status_t status;
     int num_vertices, i;
-    GLenum err;
     cairo_gl_composite_setup_t setup;
     cairo_gl_shader_program_t *ca_source_program = NULL;
     cairo_gl_shader_program_t *ca_source_alpha_program = NULL;
@@ -1984,9 +1975,6 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
     glDisable (GL_TEXTURE_1D);
     glDisable (ctx->tex_target);
 
-    while ((err = glGetError ()))
-	fprintf (stderr, "GL error 0x%08x\n", (int) err);
-
   CLEANUP:
     _cairo_gl_operand_destroy (&setup.src);
     if (mask != NULL)
@@ -2026,7 +2014,6 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
     struct gl_point *texcoord_mask = texcoord_mask_stack;
     cairo_status_t status;
     int num_vertices, i;
-    GLenum err;
     cairo_gl_composite_setup_t setup;
 
     if (! _cairo_gl_operator_is_supported (op))
@@ -2235,9 +2222,6 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
     glDisable (GL_TEXTURE_1D);
     glDisable (ctx->tex_target);
 
-    while ((err = glGetError ()))
-	fprintf (stderr, "GL error 0x%08x\n", (int) err);
-
     if (vertices != vertices_stack)
 	free (vertices);
 
@@ -2797,7 +2781,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
     cairo_status_t status;
     cairo_surface_attributes_t *src_attributes;
     const cairo_rectangle_int_t *extents;
-    GLenum err;
 
     renderer = calloc (1, sizeof (*renderer));
     if (unlikely (renderer == NULL))
@@ -2877,9 +2860,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
 	glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
     }
 
-    while ((err = glGetError ()))
-	fprintf (stderr, "GL error 0x%08x\n", (int) err);
-
     return &renderer->base;
 }
 
commit 59b31aeed9b3ec2a1ac6da188ef5e86d20626662
Author: Benjamin Otte <otte at redhat.com>
Date:   Sat May 8 15:09:39 2010 +0200

    gl: Make check_span_renderer() call not require a device lock
    
    Note that we didn't lock the device previously, so the function was
    broken.

diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 3d121e9..0a8a74f 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -139,6 +139,7 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
     else
 	ctx->tex_target = GL_TEXTURE_2D;
 
+    ctx->has_span_renderer = GLEW_ARB_vertex_buffer_object;
 
     if (GLEW_VERSION_2_0 ||
 	(GLEW_ARB_fragment_shader &&
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c0d9c62..b308598 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -124,6 +124,7 @@ typedef struct _cairo_gl_context {
     GLint max_texture_size;
     GLenum tex_target;
     cairo_bool_t using_glsl;
+    cairo_bool_t has_span_renderer;
 
     cairo_gl_shader_program_t fill_rectangles_shader;
     cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
@@ -230,6 +231,12 @@ _cairo_gl_device_has_glsl (cairo_device_t *device)
     return ((cairo_gl_context_t *) device)->using_glsl;
 }
 
+static cairo_always_inline cairo_bool_t
+cairo_gl_device_check_span_renderer (cairo_device_t *device)
+{
+  return ((cairo_gl_context_t *) device)->has_span_renderer;
+}
+
 static cairo_always_inline cairo_status_t cairo_warn
 _cairo_gl_context_acquire (cairo_device_t *device,
 			   cairo_gl_context_t **ctx)
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index f4bae56..5e71b2f 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2770,16 +2770,17 @@ _cairo_gl_surface_check_span_renderer (cairo_operator_t	  op,
 				       void			 *abstract_dst,
 				       cairo_antialias_t	  antialias)
 {
+    cairo_surface_t *surface = abstract_dst;
+
     if (! _cairo_gl_operator_is_supported (op))
 	return FALSE;
 
-    if (! GLEW_ARB_vertex_buffer_object)
+    if (! cairo_gl_device_check_span_renderer (surface->device))
 	return FALSE;
 
     return TRUE;
 
     (void) pattern;
-    (void) abstract_dst;
     (void) antialias;
 }
 


More information about the cairo-commit mailing list