glamor: Rework the Render shader setup to be easily modified, like cairo-gl.

This commit is contained in:
Eric Anholt 2010-02-09 22:35:04 -08:00 committed by Zhigang Gong
parent f4a3194837
commit 126fc09cb5
2 changed files with 108 additions and 89 deletions

View File

@ -98,6 +98,19 @@ typedef struct {
#define GLAMOR_NUM_GLYPH_CACHES 4
enum shader_source {
SHADER_SOURCE_SOLID,
SHADER_SOURCE_TEXTURE_ALPHA,
SHADER_SOURCE_COUNT,
};
enum shader_mask {
SHADER_MASK_NONE,
SHADER_MASK_SOLID,
SHADER_MASK_TEXTURE_ALPHA,
SHADER_MASK_COUNT,
};
typedef struct glamor_screen_private {
CreateGCProcPtr saved_create_gc;
CreatePixmapProcPtr saved_create_pixmap;
@ -130,7 +143,8 @@ typedef struct glamor_screen_private {
GLint put_image_xybitmap_bg_uniform_location;
/* glamor_composite */
glamor_composite_shader composite_shader[8];
glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT]
[SHADER_MASK_COUNT];
glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES];
} glamor_screen_private;

View File

@ -39,9 +39,8 @@
#include "glu3/glu3.h"
struct shader_key {
Bool solid_source;
Bool has_mask;
Bool solid_mask;
enum shader_source source;
enum shader_mask mask;
};
struct blendinfo {
@ -67,29 +66,6 @@ static struct blendinfo composite_op_info[] = {
[PictOpAdd] = {0, 0, GL_ONE, GL_ONE},
};
#define SOLID_SOURCE_INDEX 1
#define HAS_MASK_INDEX 2
#define SOLID_MASK_INDEX 3
static glamor_composite_shader *
glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key)
{
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int index = 0;
if (key->solid_source)
index += SOLID_SOURCE_INDEX;
if (key->has_mask) {
index += HAS_MASK_INDEX;
if (key->solid_mask)
index += SOLID_MASK_INDEX;
}
assert(index < ARRAY_SIZE(glamor_priv->composite_shader));
return &glamor_priv->composite_shader[index];
}
static GLuint
glamor_create_composite_fs(struct shader_key *key)
{
@ -104,12 +80,12 @@ glamor_create_composite_fs(struct shader_key *key)
const char *main_opening =
"void main()\n"
"{\n";
const char *source_pixmap_fetch =
const char *source_alpha_pixmap_fetch =
" vec4 source = texture2D(source_sampler, gl_TexCoord[0].xy);\n";
const char *mask_pixmap_fetch =
const char *mask_alpha_pixmap_fetch =
" vec4 mask = texture2D(mask_sampler, gl_TexCoord[1].xy);\n";
const char *source_in_mask =
" gl_FragColor = source * mask.w;\n";
" gl_FragColor = source * mask.a;\n";
const char *source_only =
" gl_FragColor = source;\n";
const char *main_closing =
@ -119,29 +95,49 @@ glamor_create_composite_fs(struct shader_key *key)
const char *source_fetch = "";
const char *mask_setup = "";
const char *mask_fetch = "";
const char *in;
GLuint prog;
if (key->solid_source) {
switch (key->source) {
case SHADER_SOURCE_SOLID:
source_setup = source_solid_header;
} else {
break;
case SHADER_SOURCE_TEXTURE_ALPHA:
source_setup = source_pixmap_header;
source_fetch = source_pixmap_fetch;
source_fetch = source_alpha_pixmap_fetch;
break;
FatalError("Bad composite shader source");
default:
FatalError("Bad composite source mask");
}
if (key->has_mask) {
if (key->solid_mask) {
mask_setup = mask_solid_header;
} else {
mask_setup = mask_pixmap_header;
mask_fetch = mask_pixmap_fetch;
}
switch (key->mask) {
case SHADER_MASK_NONE:
break;
case SHADER_MASK_SOLID:
mask_setup = mask_solid_header;
break;
case SHADER_MASK_TEXTURE_ALPHA:
mask_setup = mask_pixmap_header;
mask_fetch = mask_alpha_pixmap_fetch;
break;
default:
FatalError("Bad composite shader mask");
}
if (key->mask == SHADER_MASK_NONE) {
in = source_only;
} else {
in = source_in_mask;
}
source = XNFprintf("%s%s%s%s%s%s%s",
source_setup,
mask_setup,
main_opening,
source_fetch,
mask_fetch,
key->has_mask ? source_in_mask : source_only,
in,
main_closing);
prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source);
@ -156,19 +152,28 @@ glamor_create_composite_vs(struct shader_key *key)
const char *main_opening =
"void main()\n"
"{\n"
" gl_Position = gl_Vertex;\n"
" gl_Position = gl_Vertex;\n";
const char *source_coords =
" gl_TexCoord[0] = gl_MultiTexCoord0;\n";
const char *mask_coords =
" gl_TexCoord[1] = gl_MultiTexCoord1;\n";
const char *main_closing =
"}\n";
const char *source_coords_setup = "";
const char *mask_coords_setup = "";
char *source;
GLuint prog;
Bool compute_mask_coords = key->has_mask && !key->solid_mask;
source = XNFprintf("%s%s%s",
if (key->source != SHADER_SOURCE_SOLID)
source_coords_setup = source_coords;
if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID)
mask_coords_setup = mask_coords;
source = XNFprintf("%s%s%s%s",
main_opening,
compute_mask_coords ? mask_coords : "",
source_coords_setup,
mask_coords_setup,
main_closing);
prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source);
@ -178,13 +183,11 @@ glamor_create_composite_vs(struct shader_key *key)
}
static void
glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key)
glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
glamor_composite_shader *shader)
{
GLuint vs, fs, prog;
GLint source_sampler_uniform_location, mask_sampler_uniform_location;
glamor_composite_shader *shader;
shader = glamor_lookup_composite_shader(screen, key);
vs = glamor_create_composite_vs(key);
if (vs == 0)
@ -202,7 +205,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key)
glUseProgramObjectARB(prog);
if (key->solid_source) {
if (key->source == SHADER_SOURCE_SOLID) {
shader->source_uniform_location = glGetUniformLocationARB(prog,
"source");
} else {
@ -211,8 +214,8 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key)
glUniform1i(source_sampler_uniform_location, 0);
}
if (key->has_mask) {
if (key->solid_mask) {
if (key->mask != SHADER_MASK_NONE) {
if (key->mask == SHADER_MASK_SOLID) {
shader->mask_uniform_location = glGetUniformLocationARB(prog,
"mask");
} else {
@ -223,27 +226,22 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key)
}
}
static glamor_composite_shader *
glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key)
{
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_composite_shader *shader;
shader = &glamor_priv->composite_shader[key->source][key->mask];
if (shader->prog == 0)
glamor_create_composite_shader(screen, key, shader);
return shader;
}
void
glamor_init_composite_shaders(ScreenPtr screen)
{
struct shader_key key;
memset(&key, 0, sizeof(key));
key.has_mask = FALSE;
glamor_create_composite_shader(screen, &key);
key.has_mask = TRUE;
glamor_create_composite_shader(screen, &key);
key.solid_mask = TRUE;
glamor_create_composite_shader(screen, &key);
memset(&key, 0, sizeof(key));
key.solid_source = TRUE;
key.has_mask = FALSE;
glamor_create_composite_shader(screen, &key);
key.has_mask = TRUE;
glamor_create_composite_shader(screen, &key);
key.solid_mask = TRUE;
glamor_create_composite_shader(screen, &key);
}
static Bool
@ -505,33 +503,40 @@ glamor_composite_with_shader(CARD8 op,
BoxPtr box;
memset(&key, 0, sizeof(key));
key.has_mask = (mask != NULL);
if (!source->pDrawable) {
if (source->pSourcePict->type == SourcePictTypeSolidFill) {
key.solid_source = TRUE;
key.source = SHADER_SOURCE_SOLID;
} else {
ErrorF("gradient source\n");
glamor_fallback("gradient source\n");
goto fail;
}
} else {
key.source = SHADER_SOURCE_TEXTURE_ALPHA;
}
if (mask && !mask->pDrawable) {
if (mask->pSourcePict->type == SourcePictTypeSolidFill) {
key.solid_mask = TRUE;
if (mask) {
if (!mask->pDrawable) {
if (mask->pSourcePict->type == SourcePictTypeSolidFill) {
key.mask = SHADER_MASK_SOLID;
} else {
glamor_fallback("gradient mask\n");
goto fail;
}
} else {
ErrorF("gradient mask\n");
goto fail;
key.mask = SHADER_MASK_TEXTURE_ALPHA;
}
} else {
key.mask = SHADER_MASK_NONE;
}
if (source->alphaMap) {
ErrorF("source alphaMap\n");
glamor_fallback("source alphaMap\n");
goto fail;
}
if (mask && mask->alphaMap) {
ErrorF("mask alphaMap\n");
glamor_fallback("mask alphaMap\n");
goto fail;
}
if (!key.solid_source) {
if (key.source == SHADER_SOURCE_TEXTURE_ALPHA) {
source_pixmap = glamor_get_drawable_pixmap(source->pDrawable);
source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
if (source_pixmap == dest_pixmap) {
@ -545,7 +550,7 @@ glamor_composite_with_shader(CARD8 op,
if (!good_source_format(source))
goto fail;
}
if (mask && !key.solid_mask) {
if (key.mask == SHADER_MASK_TEXTURE_ALPHA) {
mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
if (mask_pixmap == dest_pixmap) {
@ -589,13 +594,13 @@ glamor_composite_with_shader(CARD8 op,
y_mask += mask->pDrawable->y;
}
if (key.solid_source) {
if (key.source == SHADER_SOURCE_SOLID) {
glamor_set_composite_solid(source, shader->source_uniform_location);
} else {
glamor_set_composite_texture(screen, 0, source, source_pixmap_priv);
}
if (key.has_mask) {
if (key.solid_mask) {
if (key.mask != SHADER_MASK_NONE) {
if (key.mask == SHADER_MASK_SOLID) {
glamor_set_composite_solid(mask, shader->mask_uniform_location);
} else {
glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv);
@ -614,13 +619,13 @@ glamor_composite_with_shader(CARD8 op,
glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
if (!key.solid_source) {
if (key.source != SHADER_SOURCE_SOLID) {
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (key.has_mask && !key.solid_mask) {
if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) {
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, mask_texcoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -637,7 +642,7 @@ glamor_composite_with_shader(CARD8 op,
vertices[3][0] = v_from_x_coord_x(dest_pixmap, box[i].x1);
vertices[3][1] = v_from_x_coord_y(dest_pixmap, box[i].y2);
if (!key.solid_source) {
if (key.source != SHADER_SOURCE_SOLID) {
int tx1 = box[i].x1 + x_source - x_dest;
int ty1 = box[i].y1 + y_source - y_dest;
int tx2 = box[i].x2 + x_source - x_dest;
@ -652,7 +657,7 @@ glamor_composite_with_shader(CARD8 op,
source_texcoords[3][1] = t_from_x_coord_y(source_pixmap, ty2);
}
if (key.has_mask && !key.solid_mask) {
if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) {
int tx1 = box[i].x1 + x_mask - x_dest;
int ty1 = box[i].y1 + y_mask - y_dest;
int tx2 = box[i].x2 + x_mask - x_dest;