diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-17 11:42:26 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-17 11:54:28 +0100 |
commit | 1c18ab02c8d41be8e5886cbb34aeda5099189fef (patch) | |
tree | e23a5bf07a564c4505f61cda7805811284a94b4c | |
parent | 2325d755b03958d8ead9a995c0d1d03e4f93af0c (diff) |
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.
-rw-r--r-- | src/cairo-gl-composite.c | 138 | ||||
-rw-r--r-- | src/cairo-gl-device.c | 14 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 93 | ||||
-rw-r--r-- | src/cairo-gl-shaders.c | 508 | ||||
-rw-r--r-- | src/cairo-gl-surface.c | 54 |
5 files changed, 424 insertions, 383 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index 91f94f97..98e52f9e 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 e506ca71..e31fc055 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 3c157f5a..bb12c9b2 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 403f76f5..b364c71c 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 0432bd10..2fcc701f 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; |