mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-08 04:28:02 +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;
|
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 *
|
static cairo_gl_glyph_private_t *
|
||||||
_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache,
|
_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache,
|
||||||
cairo_scaled_glyph_t *scaled_glyph)
|
cairo_scaled_glyph_t *scaled_glyph)
|
||||||
|
|
@ -364,22 +242,23 @@ typedef struct _cairo_gl_glyphs_setup
|
||||||
cairo_gl_composite_setup_t *composite;
|
cairo_gl_composite_setup_t *composite;
|
||||||
cairo_region_t *clip;
|
cairo_region_t *clip;
|
||||||
cairo_gl_surface_t *dst;
|
cairo_gl_surface_t *dst;
|
||||||
cairo_gl_glyphs_shader_t shader;
|
|
||||||
cairo_operator_t op;
|
cairo_operator_t op;
|
||||||
cairo_bool_t component_alpha;
|
cairo_bool_t component_alpha;
|
||||||
|
cairo_gl_shader_source_t source;
|
||||||
|
cairo_gl_shader_in_t in;
|
||||||
} cairo_gl_glyphs_setup_t;
|
} cairo_gl_glyphs_setup_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
|
_cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
|
||||||
cairo_gl_glyphs_setup_t *setup,
|
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;
|
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);
|
_cairo_gl_set_src_operand (ctx, setup->composite);
|
||||||
else
|
else
|
||||||
_cairo_gl_set_src_alpha_operand (ctx, setup->composite);
|
_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_RGB, GL_TEXTURE1);
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, 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);
|
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
|
||||||
else
|
else
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
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
|
static void
|
||||||
_cairo_gl_glyphs_set_shader_glsl (cairo_gl_context_t *ctx,
|
_cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
|
||||||
cairo_gl_glyphs_setup_t *setup,
|
cairo_gl_glyphs_setup_t *setup,
|
||||||
cairo_gl_glyphs_shader_t shader)
|
cairo_gl_shader_in_t in)
|
||||||
{
|
{
|
||||||
enum cairo_gl_glyphs_shader_source glyphs_source;
|
if (setup->in == in)
|
||||||
|
|
||||||
if (setup->shader == shader)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (setup->composite->src.type == OPERAND_CONSTANT) {
|
if (ctx->using_glsl) {
|
||||||
glyphs_source = CAIRO_GL_GLYPHS_SOURCE_CONSTANT;
|
cairo_status_t status;
|
||||||
} else {
|
|
||||||
if (setup->composite->src.operand.texture.surface->base.content !=
|
status = _cairo_gl_get_program (ctx,
|
||||||
CAIRO_CONTENT_ALPHA)
|
setup->source,
|
||||||
{
|
CAIRO_GL_SHADER_MASK_TEXTURE,
|
||||||
glyphs_source = CAIRO_GL_GLYPHS_SOURCE_TEXTURE;
|
in,
|
||||||
} else {
|
&setup->composite->shader);
|
||||||
glyphs_source = CAIRO_GL_GLYPHS_SOURCE_TEXTURE_ALPHA;
|
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_glyphs_set_shader_fixed (ctx, setup, in);
|
||||||
_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -461,12 +327,12 @@ _cairo_gl_glyphs_draw (cairo_gl_context_t *ctx,
|
||||||
} else {
|
} else {
|
||||||
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
|
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
|
||||||
_cairo_gl_glyphs_set_shader(ctx, setup,
|
_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);
|
glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
|
||||||
|
|
||||||
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_ADD, TRUE);
|
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_ADD, TRUE);
|
||||||
_cairo_gl_glyphs_set_shader(ctx, setup,
|
_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);
|
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) {
|
if (!setup->component_alpha) {
|
||||||
_cairo_gl_set_operator (setup->dst, setup->op, FALSE);
|
_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) {
|
} else if (setup->op == CAIRO_OPERATOR_ADD) {
|
||||||
_cairo_gl_set_operator (setup->dst, setup->op, FALSE);
|
_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) {
|
if (setup->clip) {
|
||||||
|
|
@ -610,13 +476,6 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
||||||
if (unlikely (status))
|
if (unlikely (status))
|
||||||
return 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_gl_set_destination (dst);
|
||||||
|
|
||||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
|
|
@ -645,7 +504,19 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
||||||
if (setup.vbo_size > 4096)
|
if (setup.vbo_size > 4096)
|
||||||
setup.vbo_size = 4096;
|
setup.vbo_size = 4096;
|
||||||
setup.op = op;
|
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);
|
glGenBuffersARB (1, &vbo);
|
||||||
glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
|
glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
|
||||||
|
|
|
||||||
|
|
@ -87,19 +87,27 @@ typedef struct cairo_gl_shader_program {
|
||||||
cairo_bool_t build_failure;
|
cairo_bool_t build_failure;
|
||||||
} cairo_gl_shader_program_t;
|
} cairo_gl_shader_program_t;
|
||||||
|
|
||||||
enum cairo_gl_glyphs_shader_source {
|
typedef enum cairo_gl_shader_source {
|
||||||
CAIRO_GL_GLYPHS_SOURCE_CONSTANT,
|
CAIRO_GL_SHADER_SOURCE_CONSTANT,
|
||||||
CAIRO_GL_GLYPHS_SOURCE_TEXTURE,
|
CAIRO_GL_SHADER_SOURCE_TEXTURE,
|
||||||
CAIRO_GL_GLYPHS_SOURCE_TEXTURE_ALPHA,
|
CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA,
|
||||||
CAIRO_GL_GLYPHS_SOURCE_COUNT,
|
CAIRO_GL_SHADER_SOURCE_COUNT,
|
||||||
};
|
} cairo_gl_shader_source_t;
|
||||||
|
|
||||||
typedef enum cairo_gl_glyphs_shader {
|
typedef enum cairo_gl_shader_mask {
|
||||||
CAIRO_GL_GLYPHS_SHADER_NORMAL,
|
CAIRO_GL_SHADER_MASK_CONSTANT,
|
||||||
CAIRO_GL_GLYPHS_SHADER_CA_SOURCE,
|
CAIRO_GL_SHADER_MASK_TEXTURE,
|
||||||
CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA,
|
CAIRO_GL_SHADER_MASK_TEXTURE_ALPHA,
|
||||||
CAIRO_GL_GLYPHS_SHADER_COUNT,
|
CAIRO_GL_SHADER_MASK_NONE,
|
||||||
} cairo_gl_glyphs_shader_t;
|
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 {
|
typedef struct _cairo_gl_context {
|
||||||
cairo_device_t base;
|
cairo_device_t base;
|
||||||
|
|
@ -108,13 +116,12 @@ typedef struct _cairo_gl_context {
|
||||||
GLint max_framebuffer_size;
|
GLint max_framebuffer_size;
|
||||||
GLint max_texture_size;
|
GLint max_texture_size;
|
||||||
cairo_bool_t using_glsl;
|
cairo_bool_t using_glsl;
|
||||||
cairo_bool_t glsl_glyphs_inited;
|
|
||||||
cairo_bool_t using_glsl_glyphs;
|
|
||||||
|
|
||||||
cairo_bool_t using_shaders;
|
cairo_bool_t using_shaders;
|
||||||
cairo_gl_shader_program_t fill_rectangles_shader;
|
cairo_gl_shader_program_t fill_rectangles_shader;
|
||||||
cairo_gl_shader_program_t glyphs_shaders[CAIRO_GL_GLYPHS_SOURCE_COUNT]
|
cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
|
||||||
[CAIRO_GL_GLYPHS_SHADER_COUNT];
|
[CAIRO_GL_SHADER_MASK_COUNT]
|
||||||
|
[CAIRO_GL_SHADER_IN_COUNT];
|
||||||
|
|
||||||
cairo_gl_surface_t *current_target;
|
cairo_gl_surface_t *current_target;
|
||||||
cairo_gl_surface_t *glyphs_temporary_mask;
|
cairo_gl_surface_t *glyphs_temporary_mask;
|
||||||
|
|
@ -309,6 +316,13 @@ bind_texture_to_shader (GLuint program, const char *name, GLuint tex_unit);
|
||||||
void
|
void
|
||||||
_cairo_gl_use_program (cairo_gl_shader_program_t *shader);
|
_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);
|
slim_hidden_proto (cairo_gl_surface_create);
|
||||||
|
|
||||||
#endif /* CAIRO_GL_PRIVATE_H */
|
#endif /* CAIRO_GL_PRIVATE_H */
|
||||||
|
|
|
||||||
|
|
@ -659,3 +659,203 @@ _cairo_gl_use_program (cairo_gl_shader_program_t *program)
|
||||||
{
|
{
|
||||||
get_impl()->use_program (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