mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-03-16 09:40:45 +01:00
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:
parent
2325d755b0
commit
1c18ab02c8
5 changed files with 437 additions and 396 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue