mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-03 06:50:41 +02:00
[gl] Move the glyphs shader construction to a more general location.
This commit is contained in:
parent
f475351f75
commit
106bc158ba
3 changed files with 272 additions and 187 deletions
|
|
@ -136,128 +136,6 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_glyphs_setup_shaders (cairo_gl_context_t *ctx)
|
||||
{
|
||||
static const char *vs_source_constant =
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
" mask_texcoords = gl_MultiTexCoord1.xy;\n"
|
||||
"}\n";
|
||||
static const char *vs_source_texture =
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
" source_texcoords = gl_MultiTexCoord0.xy;\n"
|
||||
" mask_texcoords = gl_MultiTexCoord1.xy;\n"
|
||||
"}\n";
|
||||
static const char *glyphs_source_constant =
|
||||
"uniform vec4 constant_source;\n"
|
||||
"vec4 get_source()\n"
|
||||
"{\n"
|
||||
" return constant_source;\n"
|
||||
"}\n";
|
||||
static const char *glyphs_source_texture =
|
||||
"uniform sampler2D source_sampler;\n"
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"vec4 get_source()\n"
|
||||
"{\n"
|
||||
" return texture2D(source_sampler, source_texcoords);\n"
|
||||
"}\n";
|
||||
static const char *glyphs_source_texture_alpha =
|
||||
"uniform sampler2D source_sampler;\n"
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"vec4 get_source()\n"
|
||||
"{\n"
|
||||
" return vec4(0, 0, 0, texture2D(source_sampler, source_texcoords).a);\n"
|
||||
"}\n";
|
||||
static const char *glyphs_in_normal =
|
||||
"uniform sampler2D mask_sampler;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 mask = texture2D(mask_sampler, mask_texcoords);\n"
|
||||
" gl_FragColor = get_source() * mask.a;\n"
|
||||
"}\n";
|
||||
static const char *glyphs_in_component_alpha_source =
|
||||
"uniform sampler2D mask_sampler;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 mask = texture2D(mask_sampler, mask_texcoords);\n"
|
||||
" gl_FragColor = get_source() * mask;\n"
|
||||
"}\n";
|
||||
static const char *glyphs_in_component_alpha_alpha =
|
||||
"uniform sampler2D mask_sampler;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 mask = texture2D(mask_sampler, mask_texcoords);\n"
|
||||
" gl_FragColor = get_source().a * mask;\n"
|
||||
"}\n";
|
||||
const char *glyphs_source_sources[CAIRO_GL_GLYPHS_SOURCE_COUNT] = {
|
||||
glyphs_source_constant,
|
||||
glyphs_source_texture,
|
||||
glyphs_source_texture_alpha,
|
||||
};
|
||||
const char *glyphs_in_sources[CAIRO_GL_GLYPHS_SHADER_COUNT] = {
|
||||
glyphs_in_normal,
|
||||
glyphs_in_component_alpha_source,
|
||||
glyphs_in_component_alpha_alpha,
|
||||
};
|
||||
enum cairo_gl_glyphs_shader_source source;
|
||||
enum cairo_gl_glyphs_shader in;
|
||||
|
||||
for (source = 0; source < CAIRO_GL_GLYPHS_SOURCE_COUNT; source++) {
|
||||
for (in = 0; in < CAIRO_GL_GLYPHS_SHADER_COUNT; in++) {
|
||||
const char *source_source = glyphs_source_sources[source];
|
||||
const char *in_source = glyphs_in_sources[in];
|
||||
char *fs_source = _cairo_malloc (strlen(source_source) +
|
||||
strlen(in_source) +
|
||||
1);
|
||||
const char *vs_source;
|
||||
cairo_status_t status;
|
||||
cairo_gl_shader_program_t *program = &ctx->glyphs_shaders[source][in];
|
||||
|
||||
if (source == CAIRO_GL_GLYPHS_SOURCE_CONSTANT)
|
||||
vs_source = vs_source_constant;
|
||||
else
|
||||
vs_source = vs_source_texture;
|
||||
|
||||
if (!fs_source)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
sprintf(fs_source, "%s%s", source_source, in_source);
|
||||
|
||||
init_shader_program (program);
|
||||
status = create_shader_program (program,
|
||||
vs_source,
|
||||
fs_source);
|
||||
free (fs_source);
|
||||
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
_cairo_gl_use_program (program);
|
||||
bind_texture_to_shader (program->program, "mask_sampler", 1);
|
||||
if (source == CAIRO_GL_GLYPHS_SOURCE_CONSTANT) {
|
||||
vs_source = vs_source_constant;
|
||||
} else {
|
||||
bind_texture_to_shader (program->program, "source_sampler", 0);
|
||||
vs_source = vs_source_texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_gl_use_program (NULL);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_gl_glyph_private_t *
|
||||
_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
|
|
@ -364,22 +242,23 @@ typedef struct _cairo_gl_glyphs_setup
|
|||
cairo_gl_composite_setup_t *composite;
|
||||
cairo_region_t *clip;
|
||||
cairo_gl_surface_t *dst;
|
||||
cairo_gl_glyphs_shader_t shader;
|
||||
cairo_operator_t op;
|
||||
cairo_bool_t component_alpha;
|
||||
cairo_gl_shader_source_t source;
|
||||
cairo_gl_shader_in_t in;
|
||||
} cairo_gl_glyphs_setup_t;
|
||||
|
||||
static void
|
||||
_cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyphs_setup_t *setup,
|
||||
cairo_gl_glyphs_shader_t shader)
|
||||
cairo_gl_shader_in_t in)
|
||||
{
|
||||
if (setup->shader == shader)
|
||||
if (setup->in == in)
|
||||
return;
|
||||
|
||||
setup->shader = shader;
|
||||
setup->in = in;
|
||||
|
||||
if (shader != CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA)
|
||||
if (in != CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA)
|
||||
_cairo_gl_set_src_operand (ctx, setup->composite);
|
||||
else
|
||||
_cairo_gl_set_src_alpha_operand (ctx, setup->composite);
|
||||
|
|
@ -400,7 +279,7 @@ _cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
|
|||
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
|
||||
if (setup->shader == CAIRO_GL_GLYPHS_SHADER_NORMAL)
|
||||
if (in == CAIRO_GL_SHADER_IN_NORMAL)
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
|
||||
else
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
|
@ -413,43 +292,30 @@ _cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
|
|||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_glyphs_set_shader_glsl (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyphs_setup_t *setup,
|
||||
cairo_gl_glyphs_shader_t shader)
|
||||
_cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyphs_setup_t *setup,
|
||||
cairo_gl_shader_in_t in)
|
||||
{
|
||||
enum cairo_gl_glyphs_shader_source glyphs_source;
|
||||
|
||||
if (setup->shader == shader)
|
||||
if (setup->in == in)
|
||||
return;
|
||||
|
||||
if (setup->composite->src.type == OPERAND_CONSTANT) {
|
||||
glyphs_source = CAIRO_GL_GLYPHS_SOURCE_CONSTANT;
|
||||
} else {
|
||||
if (setup->composite->src.operand.texture.surface->base.content !=
|
||||
CAIRO_CONTENT_ALPHA)
|
||||
{
|
||||
glyphs_source = CAIRO_GL_GLYPHS_SOURCE_TEXTURE;
|
||||
} else {
|
||||
glyphs_source = CAIRO_GL_GLYPHS_SOURCE_TEXTURE_ALPHA;
|
||||
if (ctx->using_glsl) {
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gl_get_program (ctx,
|
||||
setup->source,
|
||||
CAIRO_GL_SHADER_MASK_TEXTURE,
|
||||
in,
|
||||
&setup->composite->shader);
|
||||
if (!_cairo_status_is_error (status)) {
|
||||
setup->in = in;
|
||||
_cairo_gl_use_program (setup->composite->shader);
|
||||
_cairo_gl_set_src_operand (ctx, setup->composite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setup->composite->shader = &ctx->glyphs_shaders[glyphs_source][shader];
|
||||
_cairo_gl_use_program (setup->composite->shader);
|
||||
_cairo_gl_set_src_operand (ctx, setup->composite);
|
||||
|
||||
setup->shader = shader;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyphs_setup_t *setup,
|
||||
cairo_gl_glyphs_shader_t shader)
|
||||
{
|
||||
if (ctx->using_glsl_glyphs)
|
||||
_cairo_gl_glyphs_set_shader_glsl (ctx, setup, shader);
|
||||
else
|
||||
_cairo_gl_glyphs_set_shader_fixed (ctx, setup, shader);
|
||||
_cairo_gl_glyphs_set_shader_fixed (ctx, setup, in);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -461,12 +327,12 @@ _cairo_gl_glyphs_draw (cairo_gl_context_t *ctx,
|
|||
} else {
|
||||
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
|
||||
_cairo_gl_glyphs_set_shader(ctx, setup,
|
||||
CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA);
|
||||
CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA);
|
||||
glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
|
||||
|
||||
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_ADD, TRUE);
|
||||
_cairo_gl_glyphs_set_shader(ctx, setup,
|
||||
CAIRO_GL_GLYPHS_SHADER_CA_SOURCE);
|
||||
CAIRO_GL_SHADER_IN_CA_SOURCE);
|
||||
glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
|
||||
}
|
||||
}
|
||||
|
|
@ -488,10 +354,10 @@ _cairo_gl_flush_glyphs (cairo_gl_context_t *ctx,
|
|||
|
||||
if (!setup->component_alpha) {
|
||||
_cairo_gl_set_operator (setup->dst, setup->op, FALSE);
|
||||
_cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_GLYPHS_SHADER_NORMAL);
|
||||
_cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_SHADER_IN_NORMAL);
|
||||
} else if (setup->op == CAIRO_OPERATOR_ADD) {
|
||||
_cairo_gl_set_operator (setup->dst, setup->op, FALSE);
|
||||
_cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_GLYPHS_SHADER_CA_SOURCE);
|
||||
_cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_SHADER_IN_CA_SOURCE);
|
||||
}
|
||||
|
||||
if (setup->clip) {
|
||||
|
|
@ -610,13 +476,6 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (ctx->using_glsl && !ctx->glsl_glyphs_inited) {
|
||||
cairo_status_t status = _cairo_gl_glyphs_setup_shaders (ctx);
|
||||
if (!_cairo_status_is_error (status))
|
||||
ctx->using_glsl_glyphs = TRUE;
|
||||
ctx->glsl_glyphs_inited = TRUE;
|
||||
}
|
||||
|
||||
_cairo_gl_set_destination (dst);
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
|
|
@ -645,7 +504,19 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
if (setup.vbo_size > 4096)
|
||||
setup.vbo_size = 4096;
|
||||
setup.op = op;
|
||||
setup.shader = CAIRO_GL_GLYPHS_SHADER_COUNT; /* unset */
|
||||
setup.in = CAIRO_GL_SHADER_IN_COUNT; /* unset */
|
||||
|
||||
if (setup.composite->src.type == OPERAND_CONSTANT) {
|
||||
setup.source = CAIRO_GL_SHADER_SOURCE_CONSTANT;
|
||||
} else {
|
||||
if (setup.composite->src.operand.texture.surface->base.content !=
|
||||
CAIRO_CONTENT_ALPHA)
|
||||
{
|
||||
setup.source = CAIRO_GL_SHADER_SOURCE_TEXTURE;
|
||||
} else {
|
||||
setup.source = CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
glGenBuffersARB (1, &vbo);
|
||||
glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
|
||||
|
|
|
|||
|
|
@ -87,19 +87,27 @@ typedef struct cairo_gl_shader_program {
|
|||
cairo_bool_t build_failure;
|
||||
} cairo_gl_shader_program_t;
|
||||
|
||||
enum cairo_gl_glyphs_shader_source {
|
||||
CAIRO_GL_GLYPHS_SOURCE_CONSTANT,
|
||||
CAIRO_GL_GLYPHS_SOURCE_TEXTURE,
|
||||
CAIRO_GL_GLYPHS_SOURCE_TEXTURE_ALPHA,
|
||||
CAIRO_GL_GLYPHS_SOURCE_COUNT,
|
||||
};
|
||||
typedef enum cairo_gl_shader_source {
|
||||
CAIRO_GL_SHADER_SOURCE_CONSTANT,
|
||||
CAIRO_GL_SHADER_SOURCE_TEXTURE,
|
||||
CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA,
|
||||
CAIRO_GL_SHADER_SOURCE_COUNT,
|
||||
} cairo_gl_shader_source_t;
|
||||
|
||||
typedef enum cairo_gl_glyphs_shader {
|
||||
CAIRO_GL_GLYPHS_SHADER_NORMAL,
|
||||
CAIRO_GL_GLYPHS_SHADER_CA_SOURCE,
|
||||
CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA,
|
||||
CAIRO_GL_GLYPHS_SHADER_COUNT,
|
||||
} cairo_gl_glyphs_shader_t;
|
||||
typedef enum cairo_gl_shader_mask {
|
||||
CAIRO_GL_SHADER_MASK_CONSTANT,
|
||||
CAIRO_GL_SHADER_MASK_TEXTURE,
|
||||
CAIRO_GL_SHADER_MASK_TEXTURE_ALPHA,
|
||||
CAIRO_GL_SHADER_MASK_NONE,
|
||||
CAIRO_GL_SHADER_MASK_COUNT,
|
||||
} cairo_gl_shader_mask_t;
|
||||
|
||||
typedef enum cairo_gl_shader_in {
|
||||
CAIRO_GL_SHADER_IN_NORMAL,
|
||||
CAIRO_GL_SHADER_IN_CA_SOURCE,
|
||||
CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
|
||||
CAIRO_GL_SHADER_IN_COUNT,
|
||||
} cairo_gl_shader_in_t;
|
||||
|
||||
typedef struct _cairo_gl_context {
|
||||
cairo_device_t base;
|
||||
|
|
@ -108,13 +116,12 @@ typedef struct _cairo_gl_context {
|
|||
GLint max_framebuffer_size;
|
||||
GLint max_texture_size;
|
||||
cairo_bool_t using_glsl;
|
||||
cairo_bool_t glsl_glyphs_inited;
|
||||
cairo_bool_t using_glsl_glyphs;
|
||||
|
||||
cairo_bool_t using_shaders;
|
||||
cairo_gl_shader_program_t fill_rectangles_shader;
|
||||
cairo_gl_shader_program_t glyphs_shaders[CAIRO_GL_GLYPHS_SOURCE_COUNT]
|
||||
[CAIRO_GL_GLYPHS_SHADER_COUNT];
|
||||
cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
|
||||
[CAIRO_GL_SHADER_MASK_COUNT]
|
||||
[CAIRO_GL_SHADER_IN_COUNT];
|
||||
|
||||
cairo_gl_surface_t *current_target;
|
||||
cairo_gl_surface_t *glyphs_temporary_mask;
|
||||
|
|
@ -309,6 +316,13 @@ bind_texture_to_shader (GLuint program, const char *name, GLuint tex_unit);
|
|||
void
|
||||
_cairo_gl_use_program (cairo_gl_shader_program_t *shader);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gl_get_program (cairo_gl_context_t *ctx,
|
||||
cairo_gl_shader_source_t source,
|
||||
cairo_gl_shader_mask_t mask,
|
||||
cairo_gl_shader_in_t in,
|
||||
cairo_gl_shader_program_t **out_program);
|
||||
|
||||
slim_hidden_proto (cairo_gl_surface_create);
|
||||
|
||||
#endif /* CAIRO_GL_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -659,3 +659,203 @@ _cairo_gl_use_program (cairo_gl_shader_program_t *program)
|
|||
{
|
||||
get_impl()->use_program (program);
|
||||
}
|
||||
|
||||
static const char *vs_no_coords =
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
"}\n";
|
||||
static const char *vs_source_coords =
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
" source_texcoords = gl_MultiTexCoord0.xy;\n"
|
||||
"}\n";
|
||||
static const char *vs_mask_coords =
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
" mask_texcoords = gl_MultiTexCoord1.xy;\n"
|
||||
"}\n";
|
||||
static const char *vs_source_mask_coords =
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
" source_texcoords = gl_MultiTexCoord0.xy;\n"
|
||||
" mask_texcoords = gl_MultiTexCoord1.xy;\n"
|
||||
"}\n";
|
||||
static const char *fs_source_constant =
|
||||
"uniform vec4 constant_source;\n"
|
||||
"vec4 get_source()\n"
|
||||
"{\n"
|
||||
" return constant_source;\n"
|
||||
"}\n";
|
||||
static const char *fs_source_texture =
|
||||
"uniform sampler2D source_sampler;\n"
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"vec4 get_source()\n"
|
||||
"{\n"
|
||||
" return texture2D(source_sampler, source_texcoords);\n"
|
||||
"}\n";
|
||||
static const char *fs_source_texture_alpha =
|
||||
"uniform sampler2D source_sampler;\n"
|
||||
"varying vec2 source_texcoords;\n"
|
||||
"vec4 get_source()\n"
|
||||
"{\n"
|
||||
" return vec4(0, 0, 0, texture2D(source_sampler, source_texcoords).a);\n"
|
||||
"}\n";
|
||||
static const char *fs_mask_constant =
|
||||
"uniform vec4 constant_mask;\n"
|
||||
"vec4 get_mask()\n"
|
||||
"{\n"
|
||||
" return constant_mask;\n"
|
||||
"}\n";
|
||||
static const char *fs_mask_texture =
|
||||
"uniform sampler2D mask_sampler;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"vec4 get_mask()\n"
|
||||
"{\n"
|
||||
" return texture2D(mask_sampler, mask_texcoords);\n"
|
||||
"}\n";
|
||||
static const char *fs_mask_texture_alpha =
|
||||
"uniform sampler2D mask_sampler;\n"
|
||||
"varying vec2 mask_texcoords;\n"
|
||||
"vec4 get_mask()\n"
|
||||
"{\n"
|
||||
" return vec4(0, 0, 0, texture2D(mask_sampler, mask_texcoords).a);\n"
|
||||
"}\n";
|
||||
static const char *fs_mask_none =
|
||||
"vec4 get_mask()\n"
|
||||
"{\n"
|
||||
" return vec4(0, 0, 0, 1);\n"
|
||||
"}\n";
|
||||
static const char *fs_in_normal =
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = get_source() * get_mask().a;\n"
|
||||
"}\n";
|
||||
static const char *fs_in_component_alpha_source =
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = get_source() * get_mask();\n"
|
||||
"}\n";
|
||||
static const char *fs_in_component_alpha_alpha =
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = get_source().a * get_mask();\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* This function reduces the GLSL program combinations we compile when
|
||||
* there are non-functional differences.
|
||||
*/
|
||||
static cairo_gl_shader_program_t *
|
||||
_cairo_gl_select_program (cairo_gl_context_t *ctx,
|
||||
cairo_gl_shader_source_t source,
|
||||
cairo_gl_shader_mask_t mask,
|
||||
cairo_gl_shader_in_t in)
|
||||
{
|
||||
if (in == CAIRO_GL_SHADER_IN_NORMAL &&
|
||||
mask == CAIRO_GL_SHADER_MASK_TEXTURE_ALPHA)
|
||||
{
|
||||
mask = CAIRO_GL_SHADER_MASK_TEXTURE;
|
||||
}
|
||||
if (in == CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA &&
|
||||
source == CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA)
|
||||
{
|
||||
source = CAIRO_GL_SHADER_SOURCE_TEXTURE;
|
||||
}
|
||||
|
||||
return &ctx->shaders[source][mask][in];
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gl_get_program (cairo_gl_context_t *ctx,
|
||||
cairo_gl_shader_source_t source,
|
||||
cairo_gl_shader_mask_t mask,
|
||||
cairo_gl_shader_in_t in,
|
||||
cairo_gl_shader_program_t **out_program)
|
||||
{
|
||||
const char *source_sources[CAIRO_GL_SHADER_SOURCE_COUNT] = {
|
||||
fs_source_constant,
|
||||
fs_source_texture,
|
||||
fs_source_texture_alpha,
|
||||
};
|
||||
const char *mask_sources[CAIRO_GL_SHADER_MASK_COUNT] = {
|
||||
fs_mask_constant,
|
||||
fs_mask_texture,
|
||||
fs_mask_texture_alpha,
|
||||
fs_mask_none,
|
||||
};
|
||||
const char *in_sources[CAIRO_GL_SHADER_IN_COUNT] = {
|
||||
fs_in_normal,
|
||||
fs_in_component_alpha_source,
|
||||
fs_in_component_alpha_alpha,
|
||||
};
|
||||
cairo_gl_shader_program_t *program;
|
||||
const char *source_source, *mask_source, *in_source;
|
||||
const char *vs_source;
|
||||
char *fs_source;
|
||||
cairo_status_t status;
|
||||
|
||||
program = _cairo_gl_select_program(ctx, source, mask, in);
|
||||
if (program->program) {
|
||||
*out_program = program;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (program->build_failure)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
source_source = source_sources[source];
|
||||
mask_source = mask_sources[mask];
|
||||
in_source = in_sources[in];
|
||||
fs_source = _cairo_malloc (strlen(source_source) +
|
||||
strlen(mask_source) +
|
||||
strlen(in_source) +
|
||||
1);
|
||||
|
||||
if (source == CAIRO_GL_SHADER_SOURCE_CONSTANT) {
|
||||
if (mask == CAIRO_GL_SHADER_MASK_CONSTANT)
|
||||
vs_source = vs_no_coords;
|
||||
else
|
||||
vs_source = vs_mask_coords;
|
||||
} else {
|
||||
if (mask == CAIRO_GL_SHADER_MASK_CONSTANT)
|
||||
vs_source = vs_source_coords;
|
||||
else
|
||||
vs_source = vs_source_mask_coords;
|
||||
}
|
||||
|
||||
if (!fs_source)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
sprintf(fs_source, "%s%s%s", source_source, mask_source, in_source);
|
||||
|
||||
init_shader_program (program);
|
||||
status = create_shader_program (program,
|
||||
vs_source,
|
||||
fs_source);
|
||||
free (fs_source);
|
||||
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
_cairo_gl_use_program (program);
|
||||
if (source != CAIRO_GL_SHADER_SOURCE_CONSTANT) {
|
||||
bind_texture_to_shader (program->program, "source_sampler", 0);
|
||||
}
|
||||
if (mask != CAIRO_GL_SHADER_MASK_CONSTANT) {
|
||||
bind_texture_to_shader (program->program, "mask_sampler", 1);
|
||||
}
|
||||
|
||||
_cairo_gl_use_program (NULL);
|
||||
|
||||
*out_program = program;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue