This extends the existing API to support options needed for render accleratoin, including an additional fragment, 'combine', (which provides a place to perform the source IN mask operation before the final OP dest state) and an addtional 'defines' parameter which provides a way to add target-dependent values without using a uniform.
Signed-off-by: Keith Packard <[email protected]> --- glamor/glamor_copy.c | 2 +- glamor/glamor_dash.c | 2 +- glamor/glamor_points.c | 3 +- glamor/glamor_program.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++-- glamor/glamor_program.h | 51 ++++++++++- glamor/glamor_text.c | 2 +- 6 files changed, 279 insertions(+), 11 deletions(-) diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c index 921e80e..2ffe645 100644 --- a/glamor/glamor_copy.c +++ b/glamor/glamor_copy.c @@ -338,7 +338,7 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, if (!prog->prog) { if (!glamor_build_program(screen, prog, - copy_facet, NULL)) + copy_facet, NULL, NULL, NULL)) goto bail_ctx; } diff --git a/glamor/glamor_dash.c b/glamor/glamor_dash.c index 4281ff0..101228e 100644 --- a/glamor/glamor_dash.c +++ b/glamor/glamor_dash.c @@ -170,7 +170,7 @@ glamor_dash_setup(DrawablePtr drawable, GCPtr gc) if (!prog->prog) { if (!glamor_build_program(screen, prog, &glamor_facet_double_dash_lines, - NULL)) + NULL, NULL, NULL)) goto bail; } diff --git a/glamor/glamor_points.c b/glamor/glamor_points.c index df7e5a2..3ba4a69 100644 --- a/glamor/glamor_points.c +++ b/glamor/glamor_points.c @@ -60,7 +60,8 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint if (!prog->prog) { if (!glamor_build_program(screen, prog, &glamor_facet_point, - &glamor_fill_solid)) + &glamor_fill_solid, + NULL, NULL)) goto bail; } diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c index 8aab53f..857256d 100644 --- a/glamor/glamor_program.c +++ b/glamor/glamor_program.c @@ -183,6 +183,7 @@ fs_location_vars(glamor_program_location locations) static const char vs_template[] = "%s" /* version */ + "%s" /* defines */ "%s" /* prim vs_vars */ "%s" /* fill vs_vars */ "%s" /* location vs_vars */ @@ -195,12 +196,14 @@ static const char vs_template[] = static const char fs_template[] = "%s" /* version */ GLAMOR_DEFAULT_PRECISION + "%s" /* defines */ "%s" /* prim fs_vars */ "%s" /* fill fs_vars */ "%s" /* location fs_vars */ "void main() {\n" "%s" /* prim fs_exec */ "%s" /* fill fs_exec */ + "%s" /* combine */ "}\n"; static const char * @@ -236,7 +239,9 @@ Bool glamor_build_program(ScreenPtr screen, glamor_program *prog, const glamor_facet *prim, - const glamor_facet *fill) + const glamor_facet *fill, + const char *combine, + const char *defines) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -282,6 +287,7 @@ glamor_build_program(ScreenPtr screen, if (asprintf(&vs_prog_string, vs_template, str(version_string), + str(defines), str(prim->vs_vars), str(fill->vs_vars), vs_vars, @@ -292,26 +298,30 @@ glamor_build_program(ScreenPtr screen, if (asprintf(&fs_prog_string, fs_template, str(version_string), + str(defines), str(prim->fs_vars), str(fill->fs_vars), fs_vars, str(prim->fs_exec), - str(fill->fs_exec)) < 0) + str(fill->fs_exec), + str(combine)) < 0) fs_prog_string = NULL; if (!vs_prog_string || !fs_prog_string) goto fail; + prog->prog = glCreateProgram(); #if DBG - ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s", - prim->name, fill->name, vs_prog_string, fs_prog_string); + ErrorF("\n\tProgram %d for %s %s\n\tVertex shader:\n\n\t================\n%s\n\n\tFragment Shader:\n\n%s\t================\n", + prog->prog, prim->name, fill->name, vs_prog_string, fs_prog_string); #endif - prog->prog = glCreateProgram(); prog->flags = flags; prog->locations = locations; prog->prim_use = prim->use; + prog->prim_use_render = prim->use_render; prog->fill_use = fill->use; + prog->fill_use_render = fill->use_render; vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string); fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string); @@ -396,7 +406,7 @@ glamor_use_program_fill(PixmapPtr pixmap, if (!fill) return NULL; - if (!glamor_build_program(screen, prog, prim, fill)) + if (!glamor_build_program(screen, prog, prim, fill, NULL, NULL)) return NULL; } @@ -405,3 +415,211 @@ glamor_use_program_fill(PixmapPtr pixmap, return prog; } + +static struct blendinfo composite_op_info[] = { + [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, + [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, + [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, + [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, + [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, + [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, + [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, + [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, + [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, +}; + +static void +glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst) +{ + GLenum src_blend, dst_blend; + struct blendinfo *op_info; + + switch (alpha) { + case glamor_program_alpha_ca_first: + op = PictOpOutReverse; + break; + case glamor_program_alpha_ca_second: + op = PictOpAdd; + break; + default: + break; + } + + if (op == PictOpSrc) + return; + op_info = &composite_op_info[op]; + + src_blend = op_info->source_blend; + dst_blend = op_info->dest_blend; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dst->format) == 0 && op_info->dest_alpha) { + if (src_blend == GL_DST_ALPHA) + src_blend = GL_ONE; + else if (src_blend == GL_ONE_MINUS_DST_ALPHA) + src_blend = GL_ZERO; + } + + /* Set up the source alpha value for blending in component alpha mode. */ + if (alpha != glamor_program_alpha_normal && op_info->source_alpha) { + if (dst_blend == GL_SRC_ALPHA) + dst_blend = GL_SRC_COLOR; + else if (dst_blend == GL_ONE_MINUS_SRC_ALPHA) + dst_blend = GL_ONE_MINUS_SRC_COLOR; + } + + glEnable(GL_BLEND); + glBlendFunc(src_blend, dst_blend); +} + +static Bool +use_source_solid(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) +{ + + glamor_set_blend(op, prog->alpha, dst); + + glamor_set_color(glamor_get_drawable_pixmap(dst->pDrawable), + src->pSourcePict->solidFill.color, + prog->fg_uniform); + return TRUE; +} + +const glamor_facet glamor_source_solid = { + .name = "render_solid", + .fs_exec = " vec4 source = fg;\n", + .locations = glamor_program_location_fg, + .use_render = use_source_solid, +}; + +static Bool +use_source_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) +{ + glamor_set_blend(op, prog->alpha, dst); + + return glamor_set_texture((PixmapPtr) src->pDrawable, + 0, 0, + prog->fill_offset_uniform, + prog->fill_size_inv_uniform); + + return TRUE; +} + +const glamor_facet glamor_source_picture = { + .name = "render_picture", + .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n", + .fs_exec = " vec4 source = texture2D(sampler, fill_pos);\n", + .locations = glamor_program_location_fill, + .use_render = use_source_picture, +}; + +const glamor_facet *glamor_facet_source[glamor_program_source_count] = { + [glamor_program_source_solid] = &glamor_source_solid, + [glamor_program_source_picture] = &glamor_source_picture, +}; + +static const char *glamor_combine[] = { + " gl_FragColor = source * mask.a;\n", + " gl_FragColor = source.a * mask;\n", + " gl_FragColor = source * mask;\n" +}; + +static Bool +glamor_setup_one_program_render(ScreenPtr screen, + glamor_program *prog, + glamor_program_source source_type, + glamor_program_alpha alpha, + const glamor_facet *prim, + const char *defines) +{ + if(prog->failed) + return FALSE; + + if (!prog->prog) { + const glamor_facet *fill = glamor_facet_source[source_type]; + + if (!fill) + return FALSE; + + if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines)) + return FALSE; + prog->alpha = alpha; + } + + return TRUE; +} + +glamor_program * +glamor_setup_program_render(CARD8 op, + PicturePtr src, + PicturePtr mask, + PicturePtr dst, + glamor_program_render *program_render, + const glamor_facet *prim, + const char *defines) +{ + ScreenPtr screen = dst->pDrawable->pScreen; + glamor_program_alpha alpha; + glamor_program_source source_type; + glamor_program *prog, *ret; + + if (op > sizeof (composite_op_info)/sizeof (composite_op_info[0])) + return NULL; + + if (glamor_is_component_alpha(mask)) { + /* This only works for PictOpOver */ + if (op != PictOpOver) + return NULL; + alpha = glamor_program_alpha_ca_first; + } else + alpha = glamor_program_alpha_normal; + + if (src->pDrawable) + source_type = glamor_program_source_picture; + else { + SourcePictPtr sp = src->pSourcePict; + if (!sp) + return NULL; + switch (sp->type) { + case SourcePictTypeSolidFill: + source_type = glamor_program_source_solid; + break; + default: + return NULL; + } + } + + ret = &program_render->progs[source_type][alpha]; + for (;;) { + prog = &program_render->progs[source_type][alpha]; + + if (!glamor_setup_one_program_render(screen, prog, source_type, alpha, prim, defines)) + return NULL; + + if (alpha != glamor_program_alpha_ca_first) + break; + alpha++; + } + return ret; +} + +Bool +glamor_use_program_render(glamor_program *prog, + CARD8 op, + PicturePtr src, + PicturePtr dst) +{ + glUseProgram(prog->prog); + + if (prog->prim_use_render && !prog->prim_use_render(op, src, dst, prog)) + return FALSE; + + if (prog->fill_use_render && !prog->fill_use_render(op, src, dst, prog)) + return FALSE; + return TRUE; +} diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h index fa3877c..0ff12f6 100644 --- a/glamor/glamor_program.h +++ b/glamor/glamor_program.h @@ -37,13 +37,24 @@ typedef enum { glamor_program_flag_none = 0, } glamor_program_flag; +typedef enum { + glamor_program_alpha_normal, + glamor_program_alpha_ca_first, + glamor_program_alpha_ca_second, + glamor_program_alpha_count +} glamor_program_alpha; + typedef struct _glamor_program glamor_program; typedef Bool (*glamor_use) (PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg); +typedef Bool (*glamor_use_render) (CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog); + typedef struct { const char *name; const int version; + char *vs_defines; + char *fs_defines; const char *vs_vars; const char *vs_exec; const char *fs_vars; @@ -52,6 +63,7 @@ typedef struct { const glamor_program_flag flags; const char *source_name; glamor_use use; + glamor_use_render use_render; } glamor_facet; struct _glamor_program { @@ -71,6 +83,9 @@ struct _glamor_program { glamor_program_flag flags; glamor_use prim_use; glamor_use fill_use; + glamor_program_alpha alpha; + glamor_use_render prim_use_render; + glamor_use_render fill_use_render; }; typedef struct { @@ -83,7 +98,9 @@ Bool glamor_build_program(ScreenPtr screen, glamor_program *prog, const glamor_facet *prim, - const glamor_facet *fill); + const glamor_facet *fill, + const char *combine, + const char *defines); Bool glamor_use_program(PixmapPtr pixmap, @@ -97,4 +114,36 @@ glamor_use_program_fill(PixmapPtr pixmap, glamor_program_fill *program_fill, const glamor_facet *prim); +typedef enum { + glamor_program_source_solid, + glamor_program_source_picture, + glamor_program_source_count, +} glamor_program_source; + +typedef struct { + glamor_program progs[glamor_program_source_count][glamor_program_alpha_count]; +} glamor_program_render; + +static inline Bool +glamor_is_component_alpha(PicturePtr mask) { + if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) + return TRUE; + return FALSE; +} + +glamor_program * +glamor_setup_program_render(CARD8 op, + PicturePtr src, + PicturePtr mask, + PicturePtr dst, + glamor_program_render *program_render, + const glamor_facet *prim, + const char *defines); + +Bool +glamor_use_program_render(glamor_program *prog, + CARD8 op, + PicturePtr src, + PicturePtr dst); + #endif /* _GLAMOR_PROGRAM_H_ */ diff --git a/glamor/glamor_text.c b/glamor/glamor_text.c index 8d8c970..81a22a5 100644 --- a/glamor/glamor_text.c +++ b/glamor/glamor_text.c @@ -417,7 +417,7 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc, fill_facet = &glamor_facet_image_fill; } - if (!glamor_build_program(screen, prog, prim_facet, fill_facet)) + if (!glamor_build_program(screen, prog, prim_facet, fill_facet, NULL, NULL)) goto bail; } -- 2.1.4 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
