[cairo-commit] 4 commits - src/cairo-gl-composite.c src/cairo-gl-device.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-surface.c
Chris Wilson
ickle at kemper.freedesktop.org
Mon May 17 04:50:56 PDT 2010
src/cairo-gl-composite.c | 138 ++++++------
src/cairo-gl-device.c | 14 -
src/cairo-gl-private.h | 100 +++++----
src/cairo-gl-shaders.c | 508 ++++++++++++++++++++++++++---------------------
src/cairo-gl-surface.c | 75 +++---
5 files changed, 450 insertions(+), 385 deletions(-)
New commits:
commit 145db7a427e594f1d68a6c0f4afe5e365e219cf0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon May 17 12:37:46 2010 +0100
gl: Check status after composite_begin
Skip the unnecessary work in _cairo_gl_surface_composite() if we fail
to setup the GL composite operation.
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 2fcc701..b5f33e3 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -994,6 +994,8 @@ _cairo_gl_surface_composite (cairo_operator_t op,
}
status = _cairo_gl_composite_begin (ctx, &setup);
+ if (unlikely (status))
+ goto CLEANUP;
if (clip_region != NULL) {
int i, num_rectangles;
commit 8695c41e80ce932fd5dd434307b92f323a937c7c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon May 17 12:36:54 2010 +0100
gl: Throw a _cairo_error when detecting a GLerror
This allows us to easily set an breakpoint and inspect cairo's state
when we do something illegal.
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index bb12c9b..1f03d41 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -206,8 +206,10 @@ 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 ())) \
+ 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 inline cairo_device_t *
commit 1c18ab02c8d41be8e5886cbb34aeda5099189fef
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon May 17 11:42:26 2010 +0100
gl: Rename cairo_gl_shader_program_t to cairo_gl_shader_t
And complete the move of the shaders into the cairo_gl_shader namespace.
Of particular note, the bind_*_to_shader become
_cairo_gl_shader_bind_*() and have proper types.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 91f94f9..98e52f9 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -565,13 +565,13 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
else
uniform_name = "mask_constant";
- bind_vec4_to_shader (ctx,
- setup->shader->program,
- uniform_name,
- color[0],
- color[1],
- color[2],
- color[3]);
+ _cairo_gl_shader_bind_vec4 (ctx,
+ setup->shader,
+ uniform_name,
+ color[0],
+ color[1],
+ color[2],
+ color[3]);
return;
}
@@ -652,14 +652,14 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
- bind_matrix_to_shader (ctx, setup->shader->program,
- "source_matrix",
- &setup->src.operand.linear.m);
+ _cairo_gl_shader_bind_matrix (ctx, setup->shader,
+ "source_matrix",
+ &setup->src.operand.linear.m);
- bind_vec2_to_shader (ctx, setup->shader->program,
- "source_segment",
- setup->src.operand.linear.segment_x,
- setup->src.operand.linear.segment_y);
+ _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
+ "source_segment",
+ setup->src.operand.linear.segment_x,
+ setup->src.operand.linear.segment_y);
break;
case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
@@ -667,22 +667,22 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
- bind_matrix_to_shader (ctx, setup->shader->program,
- "source_matrix",
- &setup->src.operand.radial.m);
+ _cairo_gl_shader_bind_matrix (ctx, setup->shader,
+ "source_matrix",
+ &setup->src.operand.radial.m);
- 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);
+ _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
+ "source_circle_1",
+ setup->src.operand.radial.circle_1_x,
+ setup->src.operand.radial.circle_1_y);
- bind_float_to_shader (ctx, setup->shader->program,
- "source_radius_0",
- setup->src.operand.radial.radius_0);
+ _cairo_gl_shader_bind_float (ctx, setup->shader,
+ "source_radius_0",
+ setup->src.operand.radial.radius_0);
- bind_float_to_shader (ctx, setup->shader->program,
- "source_radius_1",
- setup->src.operand.radial.radius_1);
+ _cairo_gl_shader_bind_float (ctx, setup->shader,
+ "source_radius_1",
+ setup->src.operand.radial.radius_1);
break;
default:
case CAIRO_GL_OPERAND_COUNT:
@@ -751,13 +751,13 @@ _cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
glBindTexture (GL_TEXTURE_1D, setup->mask.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
- bind_matrix_to_shader (ctx, setup->shader->program,
- "mask_matrix", &setup->mask.operand.linear.m);
+ _cairo_gl_shader_bind_matrix (ctx, setup->shader,
+ "mask_matrix", &setup->mask.operand.linear.m);
- bind_vec2_to_shader (ctx, setup->shader->program,
- "mask_segment",
- setup->mask.operand.linear.segment_x,
- setup->mask.operand.linear.segment_y);
+ _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
+ "mask_segment",
+ setup->mask.operand.linear.segment_x,
+ setup->mask.operand.linear.segment_y);
}
static void
@@ -770,22 +770,22 @@ _cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
glBindTexture (GL_TEXTURE_1D, setup->mask.operand.radial.tex);
glEnable (GL_TEXTURE_1D);
- bind_matrix_to_shader (ctx, setup->shader->program,
- "mask_matrix",
- &setup->mask.operand.radial.m);
+ _cairo_gl_shader_bind_matrix (ctx, setup->shader,
+ "mask_matrix",
+ &setup->mask.operand.radial.m);
- 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);
+ _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
+ "mask_circle_1",
+ setup->mask.operand.radial.circle_1_x,
+ setup->mask.operand.radial.circle_1_y);
- bind_float_to_shader (ctx, setup->shader->program,
- "mask_radius_0",
- setup->mask.operand.radial.radius_0);
+ _cairo_gl_shader_bind_float (ctx, setup->shader,
+ "mask_radius_0",
+ setup->mask.operand.radial.radius_0);
- bind_float_to_shader (ctx, setup->shader->program,
- "mask_radius_1",
- setup->mask.operand.radial.radius_1);
+ _cairo_gl_shader_bind_float (ctx, setup->shader,
+ "mask_radius_1",
+ setup->mask.operand.radial.radius_1);
}
/* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
@@ -815,12 +815,12 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
case CAIRO_GL_OPERAND_CONSTANT:
/* Have to have a dummy texture bound in order to use the combiner unit. */
if (setup->shader) {
- bind_vec4_to_shader (ctx, setup->shader->program,
- "mask_constant",
- setup->src.operand.constant.color[0],
- setup->src.operand.constant.color[1],
- setup->src.operand.constant.color[2],
- setup->src.operand.constant.color[3]);
+ _cairo_gl_shader_bind_vec4 (ctx, setup->shader,
+ "mask_constant",
+ setup->src.operand.constant.color[0],
+ setup->src.operand.constant.color[1],
+ setup->src.operand.constant.color[2],
+ setup->src.operand.constant.color[3]);
} else {
glBindTexture (ctx->tex_target, ctx->dummy_tex);
glActiveTexture (GL_TEXTURE1);
@@ -1044,12 +1044,12 @@ _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx,
*/
if (setup->op == CAIRO_OPERATOR_OVER) {
setup->op = CAIRO_OPERATOR_ADD;
- status = _cairo_gl_get_program (ctx,
- setup->src.type,
- setup->mask.type,
- CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
- &setup->pre_shader);
- if (unlikely (_cairo_status_is_error (status)))
+ status = _cairo_gl_get_shader (ctx,
+ setup->src.type,
+ setup->mask.type,
+ CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
+ &setup->pre_shader);
+ if (unlikely (status))
return status;
}
@@ -1070,13 +1070,13 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
return status;
}
- status = _cairo_gl_get_program (ctx,
- setup->src.type,
- setup->mask.type,
- setup->has_component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE
- : CAIRO_GL_SHADER_IN_NORMAL,
- &setup->shader);
- if (_cairo_status_is_error (status)) {
+ status = _cairo_gl_get_shader (ctx,
+ setup->src.type,
+ setup->mask.type,
+ setup->has_component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE
+ : CAIRO_GL_SHADER_IN_NORMAL,
+ &setup->shader);
+ if (unlikely (status)) {
setup->pre_shader = NULL;
return status;
}
@@ -1094,7 +1094,7 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
setup->op,
setup->has_component_alpha);
- _cairo_gl_use_program (ctx, setup->shader);
+ _cairo_gl_set_shader (ctx, setup->shader);
glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
@@ -1142,13 +1142,13 @@ _cairo_gl_composite_draw (cairo_gl_context_t *ctx,
if (! setup->pre_shader) {
glDrawArrays (GL_TRIANGLES, 0, count);
} else {
- _cairo_gl_use_program (ctx, setup->pre_shader);
+ _cairo_gl_set_shader (ctx, setup->pre_shader);
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
_cairo_gl_set_src_alpha_operand (ctx, setup);
_cairo_gl_set_component_alpha_mask_operand (ctx, setup);
glDrawArrays (GL_TRIANGLES, 0, count);
- _cairo_gl_use_program (ctx, setup->shader);
+ _cairo_gl_set_shader (ctx, setup->shader);
_cairo_gl_set_operator (setup->dst, setup->op, TRUE);
_cairo_gl_set_src_operand (ctx, setup);
_cairo_gl_set_component_alpha_mask_operand (ctx, setup);
@@ -1332,7 +1332,7 @@ _cairo_gl_composite_end (cairo_gl_context_t *ctx,
glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
- _cairo_gl_use_program (ctx, NULL);
+ _cairo_gl_set_shader (ctx, NULL);
glDisable (GL_BLEND);
glDisableClientState (GL_VERTEX_ARRAY);
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index e506ca7..e31fc05 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -64,15 +64,10 @@ static void
_gl_finish (void *device)
{
cairo_gl_context_t *ctx = device;
- int i;
_gl_lock (device);
- for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
- destroy_shader (ctx, ctx->vertex_shaders[i]);
- }
-
- _cairo_cache_fini (&ctx->shaders);
+ _cairo_gl_context_fini_shaders (ctx);
_gl_unlock (device);
}
@@ -117,6 +112,7 @@ static const cairo_device_backend_t _cairo_gl_device_backend = {
cairo_status_t
_cairo_gl_context_init (cairo_gl_context_t *ctx)
{
+ cairo_status_t status;
int n;
_cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
@@ -162,9 +158,9 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
else
ctx->tex_target = GL_TEXTURE_2D;
- _cairo_gl_context_init_shaders (ctx);
-
- init_shader_program (&ctx->fill_rectangles_shader);
+ status = _cairo_gl_context_init_shaders (ctx);
+ if (unlikely (status))
+ return status;
/* Set up the dummy texture for tex_env_combine with constant color. */
glGenTextures (1, &ctx->dummy_tex);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 3c157f5..bb12c9b 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -102,11 +102,10 @@ typedef enum cairo_gl_operand_type {
typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
-typedef struct cairo_gl_shader_program {
+typedef struct cairo_gl_shader {
GLuint fragment_shader;
GLuint program;
- cairo_bool_t build_failure;
-} cairo_gl_shader_program_t;
+} cairo_gl_shader_t;
typedef enum cairo_gl_shader_in {
CAIRO_GL_SHADER_IN_NORMAL,
@@ -138,7 +137,7 @@ typedef struct _cairo_gl_context {
const cairo_gl_shader_impl_t *shader_impl;
GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX + 1];
- cairo_gl_shader_program_t fill_rectangles_shader;
+ cairo_gl_shader_t fill_rectangles_shader;
cairo_cache_t shaders;
cairo_gl_surface_t *current_target;
@@ -194,8 +193,8 @@ typedef struct _cairo_gl_composite {
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
- cairo_gl_shader_program_t *shader;
- cairo_gl_shader_program_t *pre_shader; /* for component alpha */
+ cairo_gl_shader_t *shader;
+ cairo_gl_shader_t *pre_shader; /* for component alpha */
char *vb;
unsigned int vb_offset;
@@ -403,66 +402,74 @@ _cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
return (surface->height - 1) - y;
}
-cairo_private void
+cairo_private cairo_status_t
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx);
cairo_private void
-destroy_shader (cairo_gl_context_t *ctx, GLuint shader);
+_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx);
cairo_private void
-init_shader_program (cairo_gl_shader_program_t *program);
+_cairo_gl_shader_init (cairo_gl_shader_t *shader);
-cairo_private void
-destroy_shader_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_program_t *program);
+cairo_private cairo_status_t
+_cairo_gl_shader_compile (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *program,
+ cairo_gl_var_type_t src,
+ cairo_gl_var_type_t mask,
+ const char *fragment_text);
cairo_private cairo_status_t
-create_shader_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_program_t *program,
- cairo_gl_var_type_t src,
- cairo_gl_var_type_t mask,
- const char *fragment_text);
+_cairo_gl_get_shader (cairo_gl_context_t *ctx,
+ cairo_gl_operand_type_t source,
+ cairo_gl_operand_type_t mask,
+ cairo_gl_shader_in_t in,
+ cairo_gl_shader_t **out_program);
cairo_private void
-bind_float_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value);
+_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value);
cairo_private void
-bind_vec2_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value0, float value1);
+_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value0, float value1);
cairo_private void
-bind_vec3_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value0, float value1,
- float value2);
+_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2);
cairo_private void
-bind_vec4_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value0, float value1,
- float value2, float value3);
+_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value0, float value1,
+ float value2, float value3);
cairo_private void
-bind_matrix_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name, cairo_matrix_t* m);
+_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ cairo_matrix_t* m);
cairo_private void
-bind_texture_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name, GLuint tex_unit);
+_cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ GLuint tex_unit);
cairo_private void
-_cairo_gl_use_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_program_t *shader);
+_cairo_gl_set_shader (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader);
-cairo_private cairo_status_t
-_cairo_gl_get_program (cairo_gl_context_t *ctx,
- cairo_gl_operand_type_t source,
- cairo_gl_operand_type_t mask,
- cairo_gl_shader_in_t in,
- cairo_gl_shader_program_t **out_program);
+cairo_private void
+_cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader);
slim_hidden_proto (cairo_gl_surface_create);
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 403f76f..b364c71 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -43,10 +43,10 @@
#include "cairo-output-stream-private.h"
typedef struct cairo_gl_shader_impl {
- cairo_status_t
+ void
(*compile_shader) (GLuint *shader, GLenum type, const char *text);
- cairo_status_t
+ void
(*link_shader) (GLuint *program, GLuint vert, GLuint frag);
void
@@ -56,36 +56,46 @@ typedef struct cairo_gl_shader_impl {
(*destroy_program) (GLuint program);
void
- (*bind_float_to_shader) (GLuint program, const char *name,
- float value);
+ (*bind_float) (cairo_gl_shader_t *shader,
+ const char *name,
+ float value);
void
- (*bind_vec2_to_shader) (GLuint program, const char *name,
- float value0, float value1);
+ (*bind_vec2) (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1);
void
- (*bind_vec3_to_shader) (GLuint program, const char *name,
- float value0, float value1,
- float value2);
+ (*bind_vec3) (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2);
void
- (*bind_vec4_to_shader) (GLuint program, const char *name,
- float value0, float value1,
- float value2, float value3);
+ (*bind_vec4) (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0, float value1,
+ float value2, float value3);
void
- (*bind_matrix_to_shader) (GLuint program, const char *name, cairo_matrix_t* m);
+ (*bind_matrix) (cairo_gl_shader_t *shader,
+ const char *name,
+ cairo_matrix_t* m);
void
- (*bind_texture_to_shader) (GLuint program, const char *name, GLuint tex_unit);
+ (*bind_texture) (cairo_gl_shader_t *shader,
+ const char *name,
+ GLuint tex_unit);
void
- (*use_program) (cairo_gl_shader_program_t *program);
+ (*use) (cairo_gl_shader_t *shader);
} shader_impl_t;
/* ARB_shader_objects / ARB_vertex_shader / ARB_fragment_shader extensions
API. */
-static cairo_status_t
+static void
compile_shader_arb (GLuint *shader, GLenum type, const char *text)
{
const char* strings[1] = { text };
@@ -115,13 +125,11 @@ compile_shader_arb (GLuint *shader, GLenum type, const char *text)
printf ("OpenGL shader compilation failed.\n");
}
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ ASSERT_NOT_REACHED;
}
-
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
link_shader_arb (GLuint *program, GLuint vert, GLuint frag)
{
GLint gl_status;
@@ -147,10 +155,8 @@ link_shader_arb (GLuint *program, GLuint vert, GLuint frag)
printf ("OpenGL shader link failed.\n");
}
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ ASSERT_NOT_REACHED;
}
-
- return CAIRO_STATUS_SUCCESS;
}
static void
@@ -166,47 +172,57 @@ destroy_program_arb (GLuint shader)
}
static void
-bind_float_to_shader_arb (GLuint program, const char *name,
- float value)
+bind_float_arb (cairo_gl_shader_t *shader,
+ const char *name,
+ float value)
{
- GLint location = glGetUniformLocationARB (program, name);
+ GLint location = glGetUniformLocationARB (shader->program, name);
assert (location != -1);
glUniform1fARB (location, value);
}
static void
-bind_vec2_to_shader_arb (GLuint program, const char *name,
- float value0, float value1)
+bind_vec2_arb (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1)
{
- GLint location = glGetUniformLocationARB (program, name);
+ GLint location = glGetUniformLocationARB (shader->program, name);
assert (location != -1);
glUniform2fARB (location, value0, value1);
}
static void
-bind_vec3_to_shader_arb (GLuint program, const char *name,
- float value0, float value1,
- float value2)
+bind_vec3_arb (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2)
{
- GLint location = glGetUniformLocationARB (program, name);
+ GLint location = glGetUniformLocationARB (shader->program, name);
assert (location != -1);
glUniform3fARB (location, value0, value1, value2);
}
static void
-bind_vec4_to_shader_arb (GLuint program, const char *name,
- float value0, float value1,
- float value2, float value3)
-{
- GLint location = glGetUniformLocationARB (program, name);
+bind_vec4_arb (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2,
+ float value3)
+{
+ GLint location = glGetUniformLocationARB (shader->program, name);
assert (location != -1);
glUniform4fARB (location, value0, value1, value2, value3);
}
static void
-bind_matrix_to_shader_arb (GLuint program, const char *name, cairo_matrix_t* m)
+bind_matrix_arb (cairo_gl_shader_t *shader,
+ const char *name,
+ cairo_matrix_t* m)
{
- GLint location = glGetUniformLocationARB (program, name);
+ GLint location = glGetUniformLocationARB (shader->program, name);
float gl_m[16] = {
m->xx, m->xy, 0, m->x0,
m->yx, m->yy, 0, m->y0,
@@ -218,24 +234,26 @@ bind_matrix_to_shader_arb (GLuint program, const char *name, cairo_matrix_t* m)
}
static void
-bind_texture_to_shader_arb (GLuint program, const char *name, GLuint tex_unit)
+bind_texture_arb (cairo_gl_shader_t *shader,
+ const char *name,
+ GLuint tex_unit)
{
- GLint location = glGetUniformLocationARB (program, name);
+ GLint location = glGetUniformLocationARB (shader->program, name);
assert (location != -1);
glUniform1iARB (location, tex_unit);
}
static void
-use_program_arb (cairo_gl_shader_program_t *program)
+use_program_arb (cairo_gl_shader_t *shader)
{
- if (program)
- glUseProgramObjectARB (program->program);
+ if (shader)
+ glUseProgramObjectARB (shader->program);
else
glUseProgramObjectARB (0);
}
/* OpenGL Core 2.0 API. */
-static cairo_status_t
+static void
compile_shader_core_2_0 (GLuint *shader, GLenum type, const char *text)
{
const char* strings[1] = { text };
@@ -265,13 +283,11 @@ compile_shader_core_2_0 (GLuint *shader, GLenum type, const char *text)
printf ("OpenGL shader compilation failed.\n");
}
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ ASSERT_NOT_REACHED;
}
-
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
link_shader_core_2_0 (GLuint *program, GLuint vert, GLuint frag)
{
GLint gl_status;
@@ -297,10 +313,8 @@ link_shader_core_2_0 (GLuint *program, GLuint vert, GLuint frag)
printf ("OpenGL shader link failed.\n");
}
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ ASSERT_NOT_REACHED;
}
-
- return CAIRO_STATUS_SUCCESS;
}
static void
@@ -312,51 +326,59 @@ destroy_shader_core_2_0 (GLuint shader)
static void
destroy_program_core_2_0 (GLuint shader)
{
- glDeleteProgram (shader);
+ glDeleteProgram (shader);
}
static void
-bind_float_to_shader_core_2_0 (GLuint program, const char *name,
- float value)
+bind_float_core_2_0 (cairo_gl_shader_t *shader,
+ const char *name,
+ float value)
{
- GLint location = glGetUniformLocation (program, name);
+ GLint location = glGetUniformLocation (shader->program, name);
assert (location != -1);
glUniform1f (location, value);
}
static void
-bind_vec2_to_shader_core_2_0 (GLuint program, const char *name,
- float value0, float value1)
+bind_vec2_core_2_0 (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1)
{
- GLint location = glGetUniformLocation (program, name);
+ GLint location = glGetUniformLocation (shader->program, name);
assert (location != -1);
glUniform2f (location, value0, value1);
}
static void
-bind_vec3_to_shader_core_2_0 (GLuint program, const char *name,
- float value0, float value1,
- float value2)
+bind_vec3_core_2_0 (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2)
{
- GLint location = glGetUniformLocation (program, name);
+ GLint location = glGetUniformLocation (shader->program, name);
assert (location != -1);
glUniform3f (location, value0, value1, value2);
}
static void
-bind_vec4_to_shader_core_2_0 (GLuint program, const char *name,
- float value0, float value1,
- float value2, float value3)
-{
- GLint location = glGetUniformLocation (program, name);
+bind_vec4_core_2_0 (cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2,
+ float value3)
+{
+ GLint location = glGetUniformLocation (shader->program, name);
assert (location != -1);
glUniform4f (location, value0, value1, value2, value3);
}
static void
-bind_matrix_to_shader_core_2_0 (GLuint program, const char *name, cairo_matrix_t* m)
+bind_matrix_core_2_0 (cairo_gl_shader_t *shader, const char *name, cairo_matrix_t* m)
{
- GLint location = glGetUniformLocation (program, name);
+ GLint location = glGetUniformLocation (shader->program, name);
float gl_m[16] = {
m->xx, m->xy, 0, m->x0,
m->yx, m->yy, 0, m->y0,
@@ -368,18 +390,18 @@ bind_matrix_to_shader_core_2_0 (GLuint program, const char *name, cairo_matrix_t
}
static void
-bind_texture_to_shader_core_2_0 (GLuint program, const char *name, GLuint tex_unit)
+bind_texture_core_2_0 (cairo_gl_shader_t *shader, const char *name, GLuint tex_unit)
{
- GLint location = glGetUniformLocation (program, name);
+ GLint location = glGetUniformLocation (shader->program, name);
assert (location != -1);
glUniform1i (location, tex_unit);
}
static void
-use_program_core_2_0 (cairo_gl_shader_program_t *program)
+use_program_core_2_0 (cairo_gl_shader_t *shader)
{
- if (program)
- glUseProgram (program->program);
+ if (shader)
+ glUseProgram (shader->program);
else
glUseProgram (0);
}
@@ -389,12 +411,12 @@ static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
link_shader_core_2_0,
destroy_shader_core_2_0,
destroy_program_core_2_0,
- bind_float_to_shader_core_2_0,
- bind_vec2_to_shader_core_2_0,
- bind_vec3_to_shader_core_2_0,
- bind_vec4_to_shader_core_2_0,
- bind_matrix_to_shader_core_2_0,
- bind_texture_to_shader_core_2_0,
+ bind_float_core_2_0,
+ bind_vec2_core_2_0,
+ bind_vec3_core_2_0,
+ bind_vec4_core_2_0,
+ bind_matrix_core_2_0,
+ bind_texture_core_2_0,
use_program_core_2_0,
};
@@ -403,12 +425,12 @@ static const cairo_gl_shader_impl_t shader_impl_arb = {
link_shader_arb,
destroy_shader_arb,
destroy_program_arb,
- bind_float_to_shader_arb,
- bind_vec2_to_shader_arb,
- bind_vec3_to_shader_arb,
- bind_vec4_to_shader_arb,
- bind_matrix_to_shader_arb,
- bind_texture_to_shader_arb,
+ bind_float_arb,
+ bind_vec2_arb,
+ bind_vec3_arb,
+ bind_vec4_arb,
+ bind_matrix_arb,
+ bind_texture_arb,
use_program_arb,
};
@@ -421,7 +443,7 @@ typedef struct _cairo_shader_cache_entry {
cairo_gl_shader_in_t in;
cairo_gl_context_t *ctx; /* XXX: needed to destroy the program */
- cairo_gl_shader_program_t program;
+ cairo_gl_shader_t shader;
} cairo_shader_cache_entry_t;
static cairo_bool_t
@@ -447,13 +469,19 @@ _cairo_gl_shader_cache_destroy (void *data)
{
cairo_shader_cache_entry_t *entry = data;
- destroy_shader_program (entry->ctx, &entry->program);
+ _cairo_gl_shader_fini (entry->ctx, &entry->shader);
free (entry);
}
-void
+cairo_status_t
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
{
+ static const char *fill_fs_source =
+ "uniform vec4 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}\n";
cairo_status_t status;
/* XXX multiple device support? */
@@ -474,31 +502,50 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
NULL,
_cairo_gl_shader_cache_destroy,
CAIRO_GL_MAX_SHADERS_PER_CONTEXT);
+ if (unlikely (status))
+ return status;
+
+ _cairo_gl_shader_init (&ctx->fill_rectangles_shader);
+ status = _cairo_gl_shader_compile (ctx,
+ &ctx->fill_rectangles_shader,
+ CAIRO_GL_VAR_NONE,
+ CAIRO_GL_VAR_NONE,
+ fill_fs_source);
+ if (unlikely (status))
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
}
void
-init_shader_program (cairo_gl_shader_program_t *program)
+_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx)
{
- program->fragment_shader = 0;
- program->program = 0;
- program->build_failure = FALSE;
+ int i;
+
+ for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
+ if (ctx->vertex_shaders[i])
+ ctx->shader_impl->destroy_shader (ctx->vertex_shaders[i]);
+ }
+
+ _cairo_cache_fini (&ctx->shaders);
}
void
-destroy_shader (cairo_gl_context_t *ctx, GLuint shader)
+_cairo_gl_shader_init (cairo_gl_shader_t *shader)
{
- if (shader)
- ctx->shader_impl->destroy_shader (shader);
+ shader->fragment_shader = 0;
+ shader->program = 0;
}
void
-destroy_shader_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_program_t *program)
+_cairo_gl_shader_fini (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader)
{
- destroy_shader (ctx, program->fragment_shader);
+ if (shader->fragment_shader)
+ ctx->shader_impl->destroy_shader (shader->fragment_shader);
- if (program->program)
- ctx->shader_impl->destroy_program (program->program);
+ if (shader->program)
+ ctx->shader_impl->destroy_program (shader->program);
}
typedef enum cairo_gl_operand_target {
@@ -574,35 +621,39 @@ cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
}
}
-static char *
+static cairo_status_t
cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
cairo_gl_var_type_t mask,
- cairo_gl_var_type_t dest)
+ cairo_gl_var_type_t dest,
+ char **out)
{
cairo_output_stream_t *stream = _cairo_memory_stream_create ();
unsigned char *source;
unsigned int length;
+ cairo_status_t status;
cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_OPERAND_SOURCE);
cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_OPERAND_MASK);
cairo_gl_shader_emit_variable (stream, dest, CAIRO_GL_OPERAND_DEST);
-
- _cairo_output_stream_printf (stream,
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n");
+
+ _cairo_output_stream_printf (stream,
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n");
cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_OPERAND_SOURCE);
cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_OPERAND_MASK);
cairo_gl_shader_emit_vertex (stream, dest, CAIRO_GL_OPERAND_DEST);
-
- _cairo_output_stream_write (stream,
- "}\n\0", 3);
- if (_cairo_memory_stream_destroy (stream, &source, &length))
- return NULL;
+ _cairo_output_stream_write (stream,
+ "}\n\0", 3);
- return (char *) source;
+ status = _cairo_memory_stream_destroy (stream, &source, &length);
+ if (unlikely (status))
+ return status;
+
+ *out = (char *) source;
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -706,23 +757,25 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
}
}
-static char *
+static cairo_status_t
cairo_gl_shader_get_fragment_source (GLuint tex_target,
cairo_gl_shader_in_t in,
cairo_gl_operand_type_t src,
cairo_gl_operand_type_t mask,
- cairo_gl_operand_type_t dest)
+ cairo_gl_operand_type_t dest,
+ char **out)
{
cairo_output_stream_t *stream = _cairo_memory_stream_create ();
unsigned char *source;
unsigned int length;
+ cairo_status_t status;
cairo_gl_shader_emit_color (stream, tex_target, src, CAIRO_GL_OPERAND_SOURCE);
cairo_gl_shader_emit_color (stream, tex_target, mask, CAIRO_GL_OPERAND_MASK);
if (dest != CAIRO_GL_OPERAND_NONE)
cairo_gl_shader_emit_color (stream, tex_target, dest, CAIRO_GL_OPERAND_DEST);
- _cairo_output_stream_printf (stream,
+ _cairo_output_stream_printf (stream,
"void main()\n"
"{\n");
switch (in) {
@@ -730,155 +783,160 @@ cairo_gl_shader_get_fragment_source (GLuint tex_target,
default:
ASSERT_NOT_REACHED;
case CAIRO_GL_SHADER_IN_NORMAL:
- _cairo_output_stream_printf (stream,
+ _cairo_output_stream_printf (stream,
" gl_FragColor = get_source() * get_mask().a;\n");
break;
case CAIRO_GL_SHADER_IN_CA_SOURCE:
- _cairo_output_stream_printf (stream,
+ _cairo_output_stream_printf (stream,
" gl_FragColor = get_source() * get_mask();\n");
break;
case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA:
- _cairo_output_stream_printf (stream,
+ _cairo_output_stream_printf (stream,
" gl_FragColor = get_source().a * get_mask();\n");
break;
}
- _cairo_output_stream_write (stream,
+ _cairo_output_stream_write (stream,
"}\n\0", 3);
- if (_cairo_memory_stream_destroy (stream, &source, &length))
- return NULL;
+ status = _cairo_memory_stream_destroy (stream, &source, &length);
+ if (unlikely (status))
+ return status;
- return (char *) source;
+ *out = (char *) source;
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-create_shader_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_program_t *program,
- cairo_gl_var_type_t src,
- cairo_gl_var_type_t mask,
- const char *fragment_text)
+_cairo_gl_shader_compile (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ cairo_gl_var_type_t src,
+ cairo_gl_var_type_t mask,
+ const char *fragment_text)
{
- cairo_status_t status;
unsigned int vertex_shader;
+ cairo_status_t status;
- if (program->program != 0)
+ if (ctx->shader_impl == NULL)
return CAIRO_STATUS_SUCCESS;
- if (program->build_failure)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (ctx->shader_impl == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (shader->program == 0);
vertex_shader = cairo_gl_var_type_hash (src, mask, CAIRO_GL_VAR_NONE);
if (ctx->vertex_shaders[vertex_shader] == 0) {
- char *source = cairo_gl_shader_get_vertex_source (src, mask, CAIRO_GL_VAR_NONE);
- if (unlikely (source == NULL))
- goto FAILURE;
+ char *source;
- status = ctx->shader_impl->compile_shader (&ctx->vertex_shaders[vertex_shader],
- GL_VERTEX_SHADER,
- source);
- free (source);
+ status = cairo_gl_shader_get_vertex_source (src,
+ mask,
+ CAIRO_GL_VAR_NONE,
+ &source);
if (unlikely (status))
goto FAILURE;
+
+ ctx->shader_impl->compile_shader (&ctx->vertex_shaders[vertex_shader],
+ GL_VERTEX_SHADER,
+ source);
+ free (source);
}
- status = ctx->shader_impl->compile_shader (&program->fragment_shader,
- GL_FRAGMENT_SHADER,
- fragment_text);
- if (unlikely (status))
- goto FAILURE;
+ ctx->shader_impl->compile_shader (&shader->fragment_shader,
+ GL_FRAGMENT_SHADER,
+ fragment_text);
- status = ctx->shader_impl->link_shader (&program->program,
- ctx->vertex_shaders[vertex_shader],
- program->fragment_shader);
- if (unlikely (status))
- goto FAILURE;
+ ctx->shader_impl->link_shader (&shader->program,
+ ctx->vertex_shaders[vertex_shader],
+ shader->fragment_shader);
return CAIRO_STATUS_SUCCESS;
FAILURE:
- destroy_shader_program (ctx, program);
- program->fragment_shader = 0;
- program->program = 0;
- program->build_failure = TRUE;
+ _cairo_gl_shader_fini (ctx, shader);
+ shader->fragment_shader = 0;
+ shader->program = 0;
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ return status;
}
void
-bind_float_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value)
+_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value)
{
- ctx->shader_impl->bind_float_to_shader(program, name, value);
+ ctx->shader_impl->bind_float (shader, name, value);
}
void
-bind_vec2_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value0, float value1)
+_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1)
{
- ctx->shader_impl->bind_vec2_to_shader(program, name, value0, value1);
+ ctx->shader_impl->bind_vec2 (shader, name, value0, value1);
}
void
-bind_vec3_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value0, float value1,
- float value2)
+_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value0,
+ float value1,
+ float value2)
{
- ctx->shader_impl->bind_vec3_to_shader(program, name, value0, value1, value2);
+ ctx->shader_impl->bind_vec3 (shader, name, value0, value1, value2);
}
void
-bind_vec4_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name,
- float value0, float value1,
- float value2, float value3)
+_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name,
+ float value0, float value1,
+ float value2, float value3)
{
- ctx->shader_impl->bind_vec4_to_shader(program, name, value0, value1, value2, value3);
+ ctx->shader_impl->bind_vec4 (shader, name, value0, value1, value2, value3);
}
void
-bind_matrix_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name, cairo_matrix_t* m)
+_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name, cairo_matrix_t* m)
{
- ctx->shader_impl->bind_matrix_to_shader(program, name, m);
+ ctx->shader_impl->bind_matrix (shader, name, m);
}
void
-bind_texture_to_shader (cairo_gl_context_t *ctx,
- GLuint program, const char *name, GLuint tex_unit)
+_cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ const char *name, GLuint tex_unit)
{
- ctx->shader_impl->bind_texture_to_shader(program, name, tex_unit);
+ ctx->shader_impl->bind_texture (shader, name, tex_unit);
}
void
-_cairo_gl_use_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_program_t *program)
+_cairo_gl_set_shader (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader)
{
- if (!ctx->shader_impl)
- return;
+ if (ctx->shader_impl == NULL)
+ return;
- ctx->shader_impl->use_program (program);
+ ctx->shader_impl->use (shader);
}
cairo_status_t
-_cairo_gl_get_program (cairo_gl_context_t *ctx,
- cairo_gl_operand_type_t source,
- cairo_gl_operand_type_t mask,
- cairo_gl_shader_in_t in,
- cairo_gl_shader_program_t **out_program)
+_cairo_gl_get_shader (cairo_gl_context_t *ctx,
+ cairo_gl_operand_type_t source,
+ cairo_gl_operand_type_t mask,
+ cairo_gl_shader_in_t in,
+ cairo_gl_shader_t **out)
{
cairo_shader_cache_entry_t lookup, *entry;
char *fs_source;
cairo_status_t status;
+ *out = NULL;
if (ctx->shader_impl == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ return CAIRO_STATUS_SUCCESS;
lookup.src = source;
lookup.mask = mask;
@@ -889,21 +947,19 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base);
if (entry) {
- if (entry->program.build_failure)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- assert (entry->program.program);
- *out_program = &entry->program;
+ assert (entry->shader.program);
+ *out = &entry->shader;
return CAIRO_STATUS_SUCCESS;
}
- fs_source = cairo_gl_shader_get_fragment_source (ctx->tex_target,
- in,
- source,
- mask,
- CAIRO_GL_OPERAND_NONE);
- if (unlikely (fs_source == NULL))
- return CAIRO_STATUS_NO_MEMORY;
+ status = cairo_gl_shader_get_fragment_source (ctx->tex_target,
+ in,
+ source,
+ mask,
+ CAIRO_GL_OPERAND_NONE,
+ &fs_source);
+ if (unlikely (status))
+ return status;
entry = malloc (sizeof (cairo_shader_cache_entry_t));
if (unlikely (entry == NULL)) {
@@ -914,38 +970,38 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t));
entry->ctx = ctx;
- init_shader_program (&entry->program);
- status = create_shader_program (ctx,
- &entry->program,
- cairo_gl_operand_get_var_type (source),
- cairo_gl_operand_get_var_type (mask),
- fs_source);
+ _cairo_gl_shader_init (&entry->shader);
+ status = _cairo_gl_shader_compile (ctx,
+ &entry->shader,
+ cairo_gl_operand_get_var_type (source),
+ cairo_gl_operand_get_var_type (mask),
+ fs_source);
free (fs_source);
if (unlikely (status)) {
- /* still add to cache, so we know we got a build failure */
- if (_cairo_status_is_error (status) ||
- _cairo_cache_insert (&ctx->shaders, &entry->base)) {
- free (entry);
- }
+ free (entry);
+ return status;
+ }
+ status = _cairo_cache_insert (&ctx->shaders, &entry->base);
+ if (unlikely (status)) {
+ _cairo_gl_shader_fini (ctx, &entry->shader);
+ free (entry);
return status;
}
- _cairo_gl_use_program (ctx, &entry->program);
+ _cairo_gl_set_shader (ctx, &entry->shader);
if (source != CAIRO_GL_OPERAND_CONSTANT) {
- bind_texture_to_shader (ctx, entry->program.program, "source_sampler", 0);
+ _cairo_gl_shader_bind_texture (ctx, &entry->shader, "source_sampler", 0);
}
if (mask != CAIRO_GL_OPERAND_CONSTANT &&
mask != CAIRO_GL_OPERAND_SPANS &&
mask != CAIRO_GL_OPERAND_NONE) {
- bind_texture_to_shader (ctx, entry->program.program, "mask_sampler", 1);
+ _cairo_gl_shader_bind_texture (ctx, &entry->shader, "mask_sampler", 1);
}
- status = _cairo_cache_insert (&ctx->shaders, &entry->base);
-
- _cairo_gl_use_program (ctx, NULL);
+ _cairo_gl_set_shader (ctx, NULL);
- *out_program = &entry->program;
- return status;
+ *out = &entry->shader;
+ return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 0432bd1..2fcc701 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -605,19 +605,19 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
GLfloat vertices[8], texcoords[8];
if (_cairo_gl_device_has_glsl (&ctx->base)) {
- cairo_gl_shader_program_t *program;
-
- status = _cairo_gl_get_program (ctx,
- CAIRO_GL_OPERAND_TEXTURE,
- CAIRO_GL_OPERAND_NONE,
- CAIRO_GL_SHADER_IN_NORMAL,
- &program);
- if (_cairo_status_is_error (status)) {
+ cairo_gl_shader_t *shader;
+
+ status = _cairo_gl_get_shader (ctx,
+ CAIRO_GL_OPERAND_TEXTURE,
+ CAIRO_GL_OPERAND_NONE,
+ CAIRO_GL_SHADER_IN_NORMAL,
+ &shader);
+ if (unlikely (status)) {
_cairo_gl_context_release (ctx);
goto fail;
}
- _cairo_gl_use_program (ctx, program);
+ _cairo_gl_set_shader (ctx, shader);
} else {
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
@@ -679,8 +679,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
glDisableClientState (GL_VERTEX_ARRAY);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- if (_cairo_gl_device_has_glsl (&ctx->base))
- _cairo_gl_use_program (ctx, NULL);
+ _cairo_gl_set_shader (ctx, NULL);
glDeleteTextures (1, &tex);
glDisable (ctx->tex_target);
}
@@ -1181,12 +1180,6 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
cairo_gl_context_t *ctx;
int i;
GLfloat *vertices;
- static const char *fill_fs_source =
- "uniform vec4 color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = color;\n"
- "}\n";
cairo_status_t status;
if (! _cairo_gl_operator_is_supported (op))
@@ -1196,16 +1189,6 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
if (unlikely (status))
return status;
- status = create_shader_program (ctx,
- &ctx->fill_rectangles_shader,
- CAIRO_GL_VAR_NONE,
- CAIRO_GL_VAR_NONE,
- fill_fs_source);
- if (unlikely (status)) {
- _cairo_gl_context_release (ctx);
- return status;
- }
-
if (num_rects > N_STACK_RECTS) {
vertices = _cairo_malloc_ab (num_rects, sizeof (GLfloat) * 4 * 2);
if (!vertices) {
@@ -1217,18 +1200,17 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
vertices = vertices_stack;
}
- _cairo_gl_use_program (ctx, &ctx->fill_rectangles_shader);
-
_cairo_gl_context_set_destination (ctx, surface);
_cairo_gl_set_operator (surface, op, FALSE);
- bind_vec4_to_shader (ctx,
- ctx->fill_rectangles_shader.program,
- "color",
- color->red * color->alpha,
- color->green * color->alpha,
- color->blue * color->alpha,
- color->alpha);
+ _cairo_gl_set_shader (ctx, &ctx->fill_rectangles_shader);
+ _cairo_gl_shader_bind_vec4 (ctx,
+ &ctx->fill_rectangles_shader,
+ "color",
+ color->red * color->alpha,
+ color->green * color->alpha,
+ color->blue * color->alpha,
+ color->alpha);
for (i = 0; i < num_rects; i++) {
vertices[i * 8 + 0] = rects[i].x;
commit 2325d755b03958d8ead9a995c0d1d03e4f93af0c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon May 17 10:33:46 2010 +0100
gl: Pretty print the error GLenum.
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 77d0ef7..3c157f5 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -204,10 +204,11 @@ 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%08x\n", __FILE__,__LINE__, (int) err); \
+ fprintf (stderr, "%s:%d: GL error 0x%04x: %s\n", __FILE__,__LINE__, (int) err, _cairo_gl_error_to_string (err)); \
} while (0)
static inline cairo_device_t *
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index f485682..0432bd1 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -58,6 +58,25 @@ static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
return surface->backend == &_cairo_gl_surface_backend;
}
+const char *_cairo_gl_error_to_string (GLenum err)
+{
+ switch ((int) err) {
+ case GL_NO_ERROR:
+ ASSERT_NOT_REACHED;
+ return "success";
+
+ case GL_INVALID_ENUM: return "invalid enum";
+ case GL_INVALID_VALUE: return "invalid value";
+ case GL_INVALID_OPERATION: return "invalid operation";
+ case GL_STACK_OVERFLOW: return "stack overflow";
+ case GL_STACK_UNDERFLOW: return "stack underflow";
+ case GL_OUT_OF_MEMORY: return "out of memory";
+
+ default:
+ return "unknown error";
+ }
+}
+
cairo_bool_t
_cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
GLenum *internal_format, GLenum *format,
More information about the cairo-commit
mailing list