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.
This commit is contained in:
Chris Wilson 2010-05-17 11:42:26 +01:00
parent 2325d755b0
commit 1c18ab02c8
5 changed files with 437 additions and 396 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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_private void
destroy_shader_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *program);
_cairo_gl_shader_init (cairo_gl_shader_t *shader);
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_private void
bind_float_to_shader (cairo_gl_context_t *ctx,
GLuint program, 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_private void
bind_vec3_to_shader (cairo_gl_context_t *ctx,
GLuint program, 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_private void
bind_matrix_to_shader (cairo_gl_context_t *ctx,
GLuint program, 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_private void
_cairo_gl_use_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *shader);
_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
_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_program);
cairo_private void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader,
const char *name,
float value);
cairo_private void
_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
_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
_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
_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
_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_set_shader (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader);
cairo_private void
_cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader);
slim_hidden_proto (cairo_gl_surface_create);

View file

@ -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)
bind_vec4_arb (cairo_gl_shader_t *shader,
const char *name,
float value0,
float value1,
float value2,
float value3)
{
GLint location = glGetUniformLocationARB (program, name);
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)
bind_vec4_core_2_0 (cairo_gl_shader_t *shader,
const char *name,
float value0,
float value1,
float value2,
float value3)
{
GLint location = glGetUniformLocation (program, name);
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;
if (program->program != 0)
return CAIRO_STATUS_SUCCESS;
if (program->build_failure)
return CAIRO_INT_STATUS_UNSUPPORTED;
cairo_status_t status;
if (ctx->shader_impl == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
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;
}
_cairo_gl_use_program (ctx, &entry->program);
status = _cairo_cache_insert (&ctx->shaders, &entry->base);
if (unlikely (status)) {
_cairo_gl_shader_fini (ctx, &entry->shader);
free (entry);
return status;
}
_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_set_shader (ctx, NULL);
_cairo_gl_use_program (ctx, NULL);
*out_program = &entry->program;
return status;
*out = &entry->shader;
return CAIRO_STATUS_SUCCESS;
}

View file

@ -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;
cairo_gl_shader_t *shader;
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)) {
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;