From cc9c14c70873c126ed5346533842401a4a82d9cb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 22:35:04 -0800 Subject: glamor: Rework the Render shader setup to be easily modified, like cairo-gl. --- glamor/glamor_priv.h | 16 ++++- glamor/glamor_render.c | 183 +++++++++++++++++++++++++------------------------ 2 files changed, 109 insertions(+), 90 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index dc1a5ca87..95aad7da1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -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; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e4a9441a4..f432b5f29 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -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) } } -void -glamor_init_composite_shaders(ScreenPtr screen) +static glamor_composite_shader * +glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) { - struct shader_key key; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_composite_shader *shader; - 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); + shader = &glamor_priv->composite_shader[key->source][key->mask]; + if (shader->prog == 0) + glamor_create_composite_shader(screen, key, shader); - 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); + return shader; +} + +void +glamor_init_composite_shaders(ScreenPtr screen) +{ } 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; } - } - if (mask && !mask->pDrawable) { - if (mask->pSourcePict->type == SourcePictTypeSolidFill) { - key.solid_mask = TRUE; + } else { + key.source = SHADER_SOURCE_TEXTURE_ALPHA; + } + 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; -- cgit v1.2.3