[PATCH 6/7] glamor: Adapt glamor_program API to handle render acceleration
Eric Anholt
eric at anholt.net
Tue May 12 13:48:34 PDT 2015
Summary: Tiny nitpicks, one functional concern.
Keith Packard <keithp at keithp.com> writes:
> This extends the existing API to support options needed for render
> accleratoin, including an additional fragment, 'combine', (which
acceleration
> provides a place to perform the source IN mask operation before the
> final OP dest state) and an addtional 'defines' parameter which
additional
> provides a way to add target-dependent values without using a uniform.
>
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
> 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"
> +};
This would be nice as:
[glamor_program_alpha_normal] = " gl_FragColor = source * mask.a;\n",
[glamor_program_alpha_ca_first] = " gl_FragColor = source.a * mask;\n",
[glamor_program_alpha_ca_second] = " 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;
missing space
> +
> + 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]))
if (op > ARRAY_SIZE(composite_op_info))
> + 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;
> + }
> + }
I don't think the glamor_program_source_picture path is complete -- what
about src->transform and src->alphaMap?
I'd be just fine with the text path only doing solids, and glyph-masking
a texture being something we fall back to the slow path for. If so, and
we need to do 1x1 repeating src (I think that's how a lot of text is
drawn still, right?), we might want to drop fill_pos in the facet and
just texture2D(sampler, vec2(0.5)).
> +
> + 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++;
> + }
This was hard to read, and I think explicit might be nicer:
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) {
/* Make sure we can also build the second program before deciding
* to use this path.
*/
if (!glamor_setup_one_program_render(screen,
&program_render->progs[source_type][glamor_program_alpha_ca_second],
source_type, glamor_program_alpha_ca_second, prim,
defines)) {
return NULL;
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg-devel/attachments/20150512/8d98f922/attachment.sig>
More information about the xorg-devel
mailing list