[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