[PATCH 6/7] glamor: Adapt glamor_program API to handle render acceleration
Keith Packard
keithp at keithp.com
Mon May 11 21:23:57 PDT 2015
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 <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"
+};
+
+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
More information about the xorg-devel
mailing list