diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index 1dcc6a134..68c9b80ca 100644 --- a/src/cairo-gl-composite.c +++ b/src/cairo-gl-composite.c @@ -134,7 +134,7 @@ static void _cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx, cairo_gl_composite_t *setup) { - _cairo_gl_shader_bind_matrix4f(ctx, "ModelViewProjectionMatrix", + _cairo_gl_shader_bind_matrix4f(ctx, ctx->current_shader->mvp_location, ctx->modelviewprojection_matrix); _cairo_gl_operand_bind_to_shader (ctx, &setup->src, CAIRO_GL_TEX_SOURCE); _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK); diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c index 7b5b404de..401574717 100644 --- a/src/cairo-gl-operand.c +++ b/src/cairo-gl-operand.c @@ -613,14 +613,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, cairo_gl_operand_t *operand, cairo_gl_tex_t tex_unit) { - char uniform_name[50]; - char *custom_part; - static const char *names[] = { "source", "mask" }; const cairo_matrix_t *texgen = NULL; - strcpy (uniform_name, names[tex_unit]); - custom_part = uniform_name + strlen (names[tex_unit]); - switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: @@ -629,9 +623,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, return; case CAIRO_GL_OPERAND_CONSTANT: - strcpy (custom_part, "_constant"); _cairo_gl_shader_bind_vec4 (ctx, - uniform_name, + ctx->current_shader->constant_location[tex_unit], operand->constant.color[0], operand->constant.color[1], operand->constant.color[2], @@ -640,21 +633,18 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - strcpy (custom_part, "_a"); _cairo_gl_shader_bind_float (ctx, - uniform_name, + ctx->current_shader->a_location[tex_unit], operand->gradient.a); /* fall through */ case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - strcpy (custom_part, "_circle_d"); _cairo_gl_shader_bind_vec3 (ctx, - uniform_name, + ctx->current_shader->circle_d_location[tex_unit], operand->gradient.circle_d.center.x, operand->gradient.circle_d.center.y, operand->gradient.circle_d.radius); - strcpy (custom_part, "_radius_0"); _cairo_gl_shader_bind_float (ctx, - uniform_name, + ctx->current_shader->radius_0_location[tex_unit], operand->gradient.radius_0); /* fall through */ case CAIRO_GL_OPERAND_LINEAR_GRADIENT: @@ -677,8 +667,9 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, width = operand->gradient.gradient->cache_entry.size, height = 1; } - strcpy (custom_part, "_texdims"); - _cairo_gl_shader_bind_vec2 (ctx, uniform_name, width, height); + _cairo_gl_shader_bind_vec2 (ctx, + ctx->current_shader->texdims_location[tex_unit], + width, height); } break; } @@ -691,10 +682,9 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, texgen = &operand->gradient.m; } if (texgen) { - char name[20]; - - sprintf (name, "%s_texgen", names[tex_unit]); - _cairo_gl_shader_bind_matrix(ctx, name, texgen); + _cairo_gl_shader_bind_matrix(ctx, + ctx->current_shader->texgen_location[tex_unit], + texgen); } } diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index d49e3d93f..8379abc95 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -201,6 +201,13 @@ typedef enum cairo_gl_tex { typedef struct cairo_gl_shader { GLuint fragment_shader; GLuint program; + GLint mvp_location; + GLint constant_location[2]; + GLint a_location[2]; + GLint circle_d_location[2]; + GLint radius_0_location[2]; + GLint texdims_location[2]; + GLint texgen_location[2]; } cairo_gl_shader_t; typedef enum cairo_gl_shader_in { @@ -651,35 +658,35 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, cairo_private void _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value); cairo_private void _cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value0, float value1); cairo_private void _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value0, float value1, float value2); cairo_private void _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value0, float value1, float value2, float value3); cairo_private void _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, - const char *name, + GLint location, const cairo_matrix_t* m); cairo_private void _cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx, - const char *name, + GLint location, GLfloat* gl_m); cairo_private void diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c index d8de71252..cc22cea41 100644 --- a/src/cairo-gl-shaders.c +++ b/src/cairo-gl-shaders.c @@ -805,6 +805,22 @@ link_shader_program (cairo_gl_context_t *ctx, ASSERT_NOT_REACHED; } +static GLint +_cairo_gl_get_op_uniform_location(cairo_gl_context_t *ctx, + cairo_gl_shader_t *shader, + cairo_gl_tex_t tex_unit, + const char *suffix) +{ + cairo_gl_dispatch_t *dispatch = &ctx->dispatch; + char uniform_name[100]; + const char *unit_name[2] = { "source", "mask" }; + + snprintf (uniform_name, sizeof (uniform_name), "%s_%s", + unit_name[tex_unit], suffix); + + return dispatch->GetUniformLocation (shader->program, uniform_name); +} + static cairo_status_t _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader, @@ -813,8 +829,10 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, cairo_bool_t use_coverage, const char *fragment_text) { + cairo_gl_dispatch_t *dispatch = &ctx->dispatch; unsigned int vertex_shader; cairo_status_t status; + int i; assert (shader->program == 0); @@ -828,12 +846,12 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, use_coverage, CAIRO_GL_VAR_NONE, &source); - if (unlikely (status)) - goto FAILURE; + if (unlikely (status)) + goto FAILURE; compile_shader (ctx, &ctx->vertex_shaders[vertex_shader], GL_VERTEX_SHADER, source); - free (source); + free (source); } compile_shader (ctx, &shader->fragment_shader, @@ -843,6 +861,25 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, ctx->vertex_shaders[vertex_shader], shader->fragment_shader); + shader->mvp_location = + dispatch->GetUniformLocation (shader->program, + "ModelViewProjectionMatrix"); + + for (i = 0; i < 2; i++) { + shader->constant_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "constant"); + shader->a_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "a"); + shader->circle_d_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "circle_d"); + shader->radius_0_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "radius_0"); + shader->texdims_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "texdims"); + shader->texgen_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "texgen"); + } + return CAIRO_STATUS_SUCCESS; FAILURE: @@ -887,64 +924,54 @@ _cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx, void _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location = dispatch->GetUniformLocation (ctx->current_shader->program, - name); assert (location != -1); dispatch->Uniform1f (location, value); } void _cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value0, float value1) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location = dispatch->GetUniformLocation (ctx->current_shader->program, - name); assert (location != -1); dispatch->Uniform2f (location, value0, value1); } void _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value0, float value1, float value2) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location = dispatch->GetUniformLocation (ctx->current_shader->program, - name); assert (location != -1); dispatch->Uniform3f (location, value0, value1, value2); } void _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, - const char *name, + GLint location, float value0, float value1, float value2, float value3) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location = dispatch->GetUniformLocation (ctx->current_shader->program, - name); assert (location != -1); dispatch->Uniform4f (location, value0, value1, value2, value3); } void _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, - const char *name, + GLint location, const cairo_matrix_t* m) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location = dispatch->GetUniformLocation (ctx->current_shader->program, - name); float gl_m[9] = { m->xx, m->xy, m->x0, m->yx, m->yy, m->y0, @@ -956,11 +983,9 @@ _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, void _cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx, - const char *name, GLfloat* gl_m) + GLint location, GLfloat* gl_m) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location = dispatch->GetUniformLocation (ctx->current_shader->program, - name); assert (location != -1); dispatch->UniformMatrix4fv (location, 1, GL_FALSE, gl_m); }