xserver: Branch 'master' - 9 commits

Eric Anholt anholt at kemper.freedesktop.org
Tue Jan 26 13:30:39 PST 2016


 glamor/glamor.c                    |   14 +
 glamor/glamor.h                    |    4 
 glamor/glamor_composite_glyphs.c   |    4 
 glamor/glamor_copy.c               |    3 
 glamor/glamor_egl.c                |   26 ++-
 glamor/glamor_fbo.c                |    4 
 glamor/glamor_picture.c            |   22 +-
 glamor/glamor_priv.h               |   21 ++
 glamor/glamor_program.c            |   43 ++++-
 glamor/glamor_program.h            |    1 
 glamor/glamor_render.c             |  273 +++++++++++++++++++------------------
 glamor/glamor_transfer.c           |    2 
 glamor/glamor_transform.c          |    6 
 glamor/glamor_utils.h              |    4 
 hw/kdrive/ephyr/ephyr_glamor_glx.c |   18 ++
 hw/xwayland/xwayland-glamor.c      |   15 +-
 16 files changed, 301 insertions(+), 159 deletions(-)

New commits:
commit 6978c8ee666a9224213173e7680e2d71b1094bab
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jan 19 08:06:25 2016 +1000

    xwayland: add support for use core profile for glamor. (v2)
    
    This adds support to Xwayland to try and use OpenGL core
    profile for glamor first.
    
    v1.1: use version defines.
    v2: let glamor work out core profile itself.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index c357217..7f6fb9a 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -270,6 +270,15 @@ xwl_drm_init_egl(struct xwl_screen *xwl_screen)
 {
     EGLint major, minor;
     const char *version;
+    static const EGLint config_attribs_core[] = {
+        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
+        EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GLAMOR_GL_CORE_VER_MAJOR,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GLAMOR_GL_CORE_VER_MINOR,
+        EGL_NONE
+    };
 
     if (xwl_screen->egl_display)
         return;
@@ -298,7 +307,11 @@ xwl_drm_init_egl(struct xwl_screen *xwl_screen)
     ErrorF("glamor: EGL version %s:\n", version);
 
     xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
-                                               NULL, EGL_NO_CONTEXT, NULL);
+                                               NULL, EGL_NO_CONTEXT, config_attribs_core);
+    if (!xwl_screen->egl_context)
+        xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
+                                                   NULL, EGL_NO_CONTEXT, NULL);
+
     if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
         ErrorF("Failed to create EGL context\n");
         return;
commit 79c3925532bc0d098c9a4da6d5117bdada56e0af
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jan 19 07:59:59 2016 +1000

    glamor: add core profile support to EGL glamor. (v2)
    
    v1.1: use version defines.
    v2: let glamor work it out itself
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index ea0443d..4bcd3ce 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -738,6 +738,15 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
 #endif
         EGL_NONE
     };
+    static const EGLint config_attribs_core[] = {
+        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
+        EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GLAMOR_GL_CORE_VER_MAJOR,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GLAMOR_GL_CORE_VER_MINOR,
+        EGL_NONE
+    };
 
     glamor_identify(0);
     glamor_egl = calloc(sizeof(*glamor_egl), 1);
@@ -798,12 +807,21 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
                                 KHR_surfaceless_opengl);
 #endif
 
+#ifndef GLAMOR_GLES2
     glamor_egl->context = eglCreateContext(glamor_egl->display,
                                            NULL, EGL_NO_CONTEXT,
-                                           config_attribs);
-    if (glamor_egl->context == EGL_NO_CONTEXT) {
-        xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n");
-        goto error;
+                                           config_attribs_core);
+#else
+    glamor_egl->context = NULL;
+#endif
+    if (!glamor_egl->context) {
+        glamor_egl->context = eglCreateContext(glamor_egl->display,
+                                               NULL, EGL_NO_CONTEXT,
+                                               config_attribs);
+        if (glamor_egl->context == EGL_NO_CONTEXT) {
+            xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n");
+            goto error;
+        }
     }
 
     if (!eglMakeCurrent(glamor_egl->display,
commit 98c3504dcfcec227b9c7798a0bd287941cec0691
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Sep 10 19:05:08 2014 -0700

    ephyr: Create 3.1 core profile context if possible (v3)
    
    On desktop GL, ask for a 3.1 core profile context if that's available,
    otherwise create a generic context.
    
    v2: tell glamor the profile is a core one.
    v2.1: add/use GL version defines
    v3: let glamor work out core itself
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index 30c5245..b9fe8d1 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -41,6 +41,10 @@
 #include "os.h"
 #include <X11/Xproto.h>
 
+/* until we need geometry shaders GL3.1 should suffice. */
+/* Xephyr has it's own copy of this for build reasons */
+#define GLAMOR_GL_CORE_VER_MAJOR 3
+#define GLAMOR_GL_CORE_VER_MINOR 1
 /** @{
  *
  * global state for Xephyr with glamor.
@@ -319,7 +323,19 @@ ephyr_glamor_glx_screen_init(xcb_window_t win)
                        "GLX_EXT_create_context_es2_profile\n");
         }
     } else {
-        ctx = glXCreateContext(dpy, visual_info, NULL, True);
+        static const int context_attribs[] = {
+            GLX_CONTEXT_PROFILE_MASK_ARB,
+            GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+            GLX_CONTEXT_MAJOR_VERSION_ARB,
+            GLAMOR_GL_CORE_VER_MAJOR,
+            GLX_CONTEXT_MINOR_VERSION_ARB,
+            GLAMOR_GL_CORE_VER_MINOR,
+            0,
+        };
+        ctx = glXCreateContextAttribsARB(dpy, fb_config, NULL, True,
+                                         context_attribs);
+        if (!ctx)
+            ctx = glXCreateContext(dpy, visual_info, NULL, True);
     }
     if (ctx == NULL)
         FatalError("glXCreateContext failed\n");
commit 564d9f0f8c17bb3c13aa3ca36da7825454dc5de3
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jan 11 14:00:35 2016 +1000

    glamor: add core profile support. (v2)
    
    Glamor works out from the profile if it is
    core.
    
    This flag is used to disable quads for rendering.
    
    v1.1: split long line + make whitespace conform (Michel)
    v1.2: add GL 3.1 version defines
    v2: move to having glamor work out the profile.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 25967b6..e9c1d9e 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -579,9 +579,15 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_priv->has_dual_blend =
         epoxy_has_gl_extension("GL_ARB_blend_func_extended");
 
+    /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */
+    glamor_priv->is_core_profile =
+        gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility");
+
     glamor_setup_debug_output(screen);
 
-    glamor_priv->use_quads = (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
+    glamor_priv->use_quads = (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) &&
+                             !glamor_priv->is_core_profile;
+
     /* Driver-specific hack: Avoid using GL_QUADS on VC4, where
      * they'll be emulated more expensively than we can with our
      * cached IB.
diff --git a/glamor/glamor.h b/glamor/glamor.h
index a4e0655..a73e9ef 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -66,6 +66,10 @@ typedef enum glamor_pixmap_type {
 #define GLAMOR_VALID_FLAGS      (GLAMOR_USE_EGL_SCREEN                \
                                  | GLAMOR_NO_DRI3)
 
+/* until we need geometry shaders GL3.1 should suffice. */
+#define GLAMOR_GL_CORE_VER_MAJOR 3
+#define GLAMOR_GL_CORE_VER_MINOR 1
+
 /* @glamor_init: Initialize glamor internal data structure.
  *
  * @screen: Current screen pointer.
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index d2ef266..f1eed5b 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -217,6 +217,7 @@ typedef struct glamor_screen_private {
     Bool use_quads;
     Bool has_vertex_array_object;
     Bool has_dual_blend;
+    Bool is_core_profile;
     int max_fbo_size;
 
     GLuint one_channel_format;
commit e6754dcb59ee21abb42421a28f4e467295584f67
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Sep 10 19:02:55 2014 -0700

    glamor: Use GL_RED instead of GL_ALPHA if we have texture_swizzle (v3)
    
    GL_RED is supported by core profiles while GL_ALPHA is not; use GL_RED
    for one channel objects (depth 1 to 8), and then swizzle them into the
    alpha channel when used as a mask.
    
    [airlied: updated to master, add swizzle to composited glyphs and xv paths]
    
    v2: consolidate setting swizzle into the texture creation code, it
        should work fine there. Handle swizzle when setting color as well.
    v3: Fix drawing to a8 with Render (changes by anholt, reviewed by airlied).
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index d4f3be2..25967b6 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -599,6 +599,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
 #endif
 
+    glamor_priv->one_channel_format = GL_ALPHA;
+    if (epoxy_has_gl_extension("GL_ARB_texture_rg") && epoxy_has_gl_extension("GL_ARB_texture_swizzle"))
+        glamor_priv->one_channel_format = GL_RED;
+
     glamor_set_debug_level(&glamor_debug_level);
 
     glamor_priv->saved_procs.create_screen_resources =
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index b1b584d..5bfffe5 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -75,6 +75,8 @@ cache_format(GLenum format)
 {
     switch (format) {
     case GL_ALPHA:
+    case GL_LUMINANCE:
+    case GL_RED:
         return 2;
     case GL_RGB:
         return 1;
@@ -338,6 +340,8 @@ _glamor_create_tex(glamor_screen_private *glamor_priv,
     glBindTexture(GL_TEXTURE_2D, tex);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    if (format == glamor_priv->one_channel_format && format == GL_RED)
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
     glamor_priv->suppress_gl_out_of_memory_logging = true;
     glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
                  format, GL_UNSIGNED_BYTE, NULL);
diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c
index 352858f..b069ce5 100644
--- a/glamor/glamor_picture.c
+++ b/glamor/glamor_picture.c
@@ -41,19 +41,21 @@
  * Return 0 if find a matched texture type. Otherwise return -1.
  **/
 static int
-glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
+glamor_get_tex_format_type_from_pictformat_gl(ScreenPtr pScreen,
+                                              PictFormatShort format,
                                               GLenum *tex_format,
                                               GLenum *tex_type,
                                               int *no_alpha,
                                               int *revert,
                                               int *swap_rb, int is_upload)
 {
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
     *no_alpha = 0;
     *revert = REVERT_NONE;
     *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
     switch (format) {
     case PICT_a1:
-        *tex_format = GL_ALPHA;
+        *tex_format = glamor_priv->one_channel_format;
         *tex_type = GL_UNSIGNED_BYTE;
         *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
         break;
@@ -111,7 +113,7 @@ glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
         *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
         break;
     case PICT_a8:
-        *tex_format = GL_ALPHA;
+        *tex_format = glamor_priv->one_channel_format;
         *tex_type = GL_UNSIGNED_BYTE;
         break;
     case PICT_x4r4g4b4:
@@ -137,13 +139,15 @@ glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
 #define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
 
 static int
-glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format,
+glamor_get_tex_format_type_from_pictformat_gles2(ScreenPtr pScreen,
+                                                 PictFormatShort format,
                                                  GLenum *tex_format,
                                                  GLenum *tex_type,
                                                  int *no_alpha,
                                                  int *revert,
                                                  int *swap_rb, int is_upload)
 {
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
     int need_swap_rb = 0;
 
     *no_alpha = 0;
@@ -264,13 +268,13 @@ glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format,
         break;
 
     case PICT_a1:
-        *tex_format = GL_ALPHA;
+        *tex_format = glamor_priv->one_channel_format;
         *tex_type = GL_UNSIGNED_BYTE;
         *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
         break;
 
     case PICT_a8:
-        *tex_format = GL_ALPHA;
+        *tex_format = glamor_priv->one_channel_format;
         *tex_type = GL_UNSIGNED_BYTE;
         *revert = REVERT_NONE;
         break;
@@ -317,14 +321,16 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
         glamor_get_screen_private(pixmap->drawable.pScreen);
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        return glamor_get_tex_format_type_from_pictformat_gl(pict_format,
+        return glamor_get_tex_format_type_from_pictformat_gl(pixmap->drawable.pScreen,
+                                                             pict_format,
                                                              format, type,
                                                              no_alpha,
                                                              revert,
                                                              swap_rb,
                                                              is_upload);
     } else {
-        return glamor_get_tex_format_type_from_pictformat_gles2(pict_format,
+        return glamor_get_tex_format_type_from_pictformat_gles2(pixmap->drawable.pScreen,
+                                                                pict_format,
                                                                 format, type,
                                                                 no_alpha,
                                                                 revert,
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index e49aee5..d2ef266 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -116,10 +116,17 @@ enum shader_in {
     SHADER_IN_COUNT,
 };
 
+enum shader_dest_swizzle {
+    SHADER_DEST_SWIZZLE_DEFAULT,
+    SHADER_DEST_SWIZZLE_ALPHA_TO_RED,
+    SHADER_DEST_SWIZZLE_COUNT,
+};
+
 struct shader_key {
     enum shader_source source;
     enum shader_mask mask;
     enum shader_in in;
+    enum shader_dest_swizzle dest_swizzle;
 };
 
 struct blendinfo {
@@ -212,6 +219,8 @@ typedef struct glamor_screen_private {
     Bool has_dual_blend;
     int max_fbo_size;
 
+    GLuint one_channel_format;
+
     struct xorg_list
         fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT];
     unsigned long fbo_cache_watermark;
@@ -282,7 +291,8 @@ typedef struct glamor_screen_private {
     int render_nr_quads;
     glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT]
         [SHADER_MASK_COUNT]
-        [SHADER_IN_COUNT];
+        [SHADER_IN_COUNT]
+        [SHADER_DEST_SWIZZLE_COUNT];
 
     /* shaders to restore a texture to another texture. */
     GLint finish_access_prog[2];
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 4e66f6d..5712cf8 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -177,33 +177,46 @@ glamor_create_composite_fs(struct shader_key *key)
         "		return rel_sampler(mask_sampler, mask_texture,\n"
         "				   mask_wh, mask_repeat_mode, 1);\n"
         "}\n";
+
+    const char *dest_swizzle_default =
+        "vec4 dest_swizzle(vec4 color)\n"
+        "{"
+        "	return color;"
+        "}";
+    const char *dest_swizzle_alpha_to_red =
+        "vec4 dest_swizzle(vec4 color)\n"
+        "{"
+        "	float undef;\n"
+        "	return vec4(color.a, undef, undef, undef);"
+        "}";
+
     const char *in_source_only =
         "void main()\n"
         "{\n"
-        "	gl_FragColor = get_source();\n"
+        "	gl_FragColor = dest_swizzle(get_source());\n"
         "}\n";
     const char *in_normal =
         "void main()\n"
         "{\n"
-        "	gl_FragColor = get_source() * get_mask().a;\n"
+        "	gl_FragColor = dest_swizzle(get_source() * get_mask().a);\n"
         "}\n";
     const char *in_ca_source =
         "void main()\n"
         "{\n"
-        "	gl_FragColor = get_source() * get_mask();\n"
+        "	gl_FragColor = dest_swizzle(get_source() * get_mask());\n"
         "}\n";
     const char *in_ca_alpha =
         "void main()\n"
         "{\n"
-        "	gl_FragColor = get_source().a * get_mask();\n"
+        "	gl_FragColor = dest_swizzle(get_source().a * get_mask());\n"
         "}\n";
     const char *in_ca_dual_blend =
         "out vec4 color0;\n"
         "out vec4 color1;\n"
         "void main()\n"
         "{\n"
-        "	color0 = get_source() * get_mask();\n"
-        "	color1 = get_source().a * get_mask();\n"
+        "	color0 = dest_swizzle(get_source() * get_mask());\n"
+        "	color1 = dest_swizzle(get_source().a * get_mask());\n"
         "}\n";
     const char *header_ca_dual_blend =
         "#version 130\n";
@@ -214,6 +227,7 @@ glamor_create_composite_fs(struct shader_key *key)
     const char *in;
     const char *header;
     const char *header_norm = "";
+    const char *dest_swizzle;
     GLuint prog;
 
     switch (key->source) {
@@ -246,6 +260,21 @@ glamor_create_composite_fs(struct shader_key *key)
         FatalError("Bad composite shader mask");
     }
 
+    /* If we're storing to an a8 texture but our texture format is
+     * GL_RED because of a core context, then we need to make sure to
+     * put the alpha into the red channel.
+     */
+    switch (key->dest_swizzle) {
+    case SHADER_DEST_SWIZZLE_DEFAULT:
+        dest_swizzle = dest_swizzle_default;
+        break;
+    case SHADER_DEST_SWIZZLE_ALPHA_TO_RED:
+        dest_swizzle = dest_swizzle_alpha_to_red;
+        break;
+    default:
+        FatalError("Bad composite shader dest swizzle");
+    }
+
     header = header_norm;
     switch (key->in) {
     case SHADER_IN_SOURCE_ONLY:
@@ -271,8 +300,8 @@ glamor_create_composite_fs(struct shader_key *key)
     XNFasprintf(&source,
                 "%s"
                 GLAMOR_DEFAULT_PRECISION
-                "%s%s%s%s%s%s", header, repeat_define, relocate_texture,
-                rel_sampler, source_fetch, mask_fetch, in);
+                "%s%s%s%s%s%s%s", header, repeat_define, relocate_texture,
+                rel_sampler, source_fetch, mask_fetch, dest_swizzle, in);
 
     prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source);
     free(source);
@@ -386,18 +415,36 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_composite_shader *shader;
 
-    shader = &glamor_priv->composite_shader[key->source][key->mask][key->in];
+    shader = &glamor_priv->composite_shader[key->source][key->mask][key->in][key->dest_swizzle];
     if (shader->prog == 0)
         glamor_create_composite_shader(screen, key, shader);
 
     return shader;
 }
 
+static GLenum
+glamor_translate_blend_alpha_to_red(GLenum blend)
+{
+    switch (blend) {
+    case GL_SRC_ALPHA:
+        return GL_SRC_COLOR;
+    case GL_DST_ALPHA:
+        return GL_DST_COLOR;
+    case GL_ONE_MINUS_SRC_ALPHA:
+        return GL_ONE_MINUS_SRC_COLOR;
+    case GL_ONE_MINUS_DST_ALPHA:
+        return GL_ONE_MINUS_DST_COLOR;
+    default:
+        return blend;
+    }
+}
+
 static Bool
 glamor_set_composite_op(ScreenPtr screen,
                         CARD8 op, struct blendinfo *op_info_result,
                         PicturePtr dest, PicturePtr mask,
-                        enum ca_state ca_state)
+                        enum ca_state ca_state,
+                        struct shader_key *key)
 {
     GLenum source_blend, dest_blend;
     struct blendinfo *op_info;
@@ -444,6 +491,14 @@ glamor_set_composite_op(ScreenPtr screen,
         }
     }
 
+    /* If we're outputting our alpha to the red channel, then any
+     * reads of alpha for blending need to come from the red channel.
+     */
+    if (key->dest_swizzle == SHADER_DEST_SWIZZLE_ALPHA_TO_RED) {
+        source_blend = glamor_translate_blend_alpha_to_red(source_blend);
+        dest_blend = glamor_translate_blend_alpha_to_red(dest_blend);
+    }
+
     op_info_result->source_blend = source_blend;
     op_info_result->dest_blend = dest_blend;
     op_info_result->source_alpha = op_info->source_alpha;
@@ -841,6 +896,13 @@ glamor_composite_choose_shader(CARD8 op,
         key.in = SHADER_IN_SOURCE_ONLY;
     }
 
+    if (dest_pixmap->drawable.bitsPerPixel <= 8 &&
+        glamor_priv->one_channel_format == GL_RED) {
+        key.dest_swizzle = SHADER_DEST_SWIZZLE_ALPHA_TO_RED;
+    } else {
+        key.dest_swizzle = SHADER_DEST_SWIZZLE_DEFAULT;
+    }
+
     if (source && source->alphaMap) {
         glamor_fallback("source alphaMap\n");
         goto fail;
@@ -970,8 +1032,10 @@ glamor_composite_choose_shader(CARD8 op,
         goto fail;
     }
 
-    if (!glamor_set_composite_op(screen, op, op_info, dest, mask, ca_state))
+    if (!glamor_set_composite_op(screen, op, op_info, dest, mask, ca_state,
+                                 &key)) {
         goto fail;
+    }
 
     *shader = glamor_lookup_composite_shader(screen, &key);
     if ((*shader)->prog == 0) {
diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
index 155d7e0..91e1747 100644
--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -42,7 +42,7 @@ glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type)
         *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
         break;
     case 8:
-        *format = GL_ALPHA;
+        *format = glamor_get_screen_private(pixmap->drawable.pScreen)->one_channel_format;
         *type = GL_UNSIGNED_BYTE;
         break;
     default:
diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
index f476a99..ad06943 100644
--- a/glamor/glamor_transform.c
+++ b/glamor/glamor_transform.c
@@ -111,12 +111,18 @@ glamor_set_color(PixmapPtr      pixmap,
                  CARD32         pixel,
                  GLint          uniform)
 {
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private((pixmap)->drawable.pScreen);
     float       color[4];
 
     glamor_get_rgba_from_pixel(pixel,
                                &color[0], &color[1], &color[2], &color[3],
                                format_for_pixmap(pixmap));
 
+    if ((pixmap->drawable.depth == 1 || pixmap->drawable.depth == 8) &&
+	glamor_priv->one_channel_format == GL_RED)
+      color[0] = color[3];
+
     glUniform4fv(uniform, 1, color);
 }
 
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index e648af2..d4366c1 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -757,7 +757,7 @@ gl_iformat_for_pixmap(PixmapPtr pixmap)
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
         ((pixmap)->drawable.depth == 1 || (pixmap)->drawable.depth == 8)) {
-        return GL_ALPHA;
+        return glamor_priv->one_channel_format;
     } else {
         return GL_RGBA;
     }
@@ -867,6 +867,8 @@ glamor_pict_format_is_compatible(PicturePtr picture)
         return (picture->format == PICT_a8r8g8b8 ||
                 picture->format == PICT_x8r8g8b8);
     case GL_ALPHA:
+    case GL_RED:
+    case GL_LUMINANCE:
         return (picture->format == PICT_a8);
     default:
         return FALSE;
commit 5042b0652b9fe5fed57a233880c3429ba390d86d
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 20 12:33:25 2016 -0800

    glamor: Drop duplicated GLAMOR_DEFAULT_PRECISIONs in render accel.
    
    We only need it once at the top of the shader, so just put it
    there.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index e563e40..4e66f6d 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -72,7 +72,6 @@ glamor_create_composite_fs(struct shader_key *key)
         "uniform int 			source_repeat_mode;\n"
         "uniform int 			mask_repeat_mode;\n";
     const char *relocate_texture =
-        GLAMOR_DEFAULT_PRECISION
         "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n"
         "{\n"
         "   vec2 rel_tex; \n"
@@ -119,14 +118,12 @@ glamor_create_composite_fs(struct shader_key *key)
         "}\n";
 
     const char *source_solid_fetch =
-        GLAMOR_DEFAULT_PRECISION
         "uniform vec4 source;\n"
         "vec4 get_source()\n"
         "{\n"
         "	return source;\n"
         "}\n";
     const char *source_alpha_pixmap_fetch =
-        GLAMOR_DEFAULT_PRECISION
         "varying vec2 source_texture;\n"
         "uniform sampler2D source_sampler;\n"
         "uniform vec4 source_wh;"
@@ -139,7 +136,6 @@ glamor_create_composite_fs(struct shader_key *key)
         "				   source_wh, source_repeat_mode, 0);\n"
         "}\n";
     const char *source_pixmap_fetch =
-        GLAMOR_DEFAULT_PRECISION
         "varying vec2 source_texture;\n"
         "uniform sampler2D source_sampler;\n"
         "uniform vec4 source_wh;\n"
@@ -152,14 +148,12 @@ glamor_create_composite_fs(struct shader_key *key)
         "				   source_wh, source_repeat_mode, 1);\n"
         "}\n";
     const char *mask_solid_fetch =
-        GLAMOR_DEFAULT_PRECISION
         "uniform vec4 mask;\n"
         "vec4 get_mask()\n"
         "{\n"
         "	return mask;\n"
         "}\n";
     const char *mask_alpha_pixmap_fetch =
-        GLAMOR_DEFAULT_PRECISION
         "varying vec2 mask_texture;\n"
         "uniform sampler2D mask_sampler;\n"
         "uniform vec4 mask_wh;\n"
@@ -172,7 +166,6 @@ glamor_create_composite_fs(struct shader_key *key)
         "				   mask_wh, mask_repeat_mode, 0);\n"
         "}\n";
     const char *mask_pixmap_fetch =
-        GLAMOR_DEFAULT_PRECISION
         "varying vec2 mask_texture;\n"
         "uniform sampler2D mask_sampler;\n"
         "uniform vec4 mask_wh;\n"
@@ -185,31 +178,26 @@ glamor_create_composite_fs(struct shader_key *key)
         "				   mask_wh, mask_repeat_mode, 1);\n"
         "}\n";
     const char *in_source_only =
-        GLAMOR_DEFAULT_PRECISION
         "void main()\n"
         "{\n"
         "	gl_FragColor = get_source();\n"
         "}\n";
     const char *in_normal =
-        GLAMOR_DEFAULT_PRECISION
         "void main()\n"
         "{\n"
         "	gl_FragColor = get_source() * get_mask().a;\n"
         "}\n";
     const char *in_ca_source =
-        GLAMOR_DEFAULT_PRECISION
         "void main()\n"
         "{\n"
         "	gl_FragColor = get_source() * get_mask();\n"
         "}\n";
     const char *in_ca_alpha =
-        GLAMOR_DEFAULT_PRECISION
         "void main()\n"
         "{\n"
         "	gl_FragColor = get_source().a * get_mask();\n"
         "}\n";
     const char *in_ca_dual_blend =
-        GLAMOR_DEFAULT_PRECISION
         "out vec4 color0;\n"
         "out vec4 color1;\n"
         "void main()\n"
@@ -280,7 +268,10 @@ glamor_create_composite_fs(struct shader_key *key)
         FatalError("Bad composite IN type");
     }
 
-    XNFasprintf(&source, "%s%s%s%s%s%s%s", header, repeat_define, relocate_texture,
+    XNFasprintf(&source,
+                "%s"
+                GLAMOR_DEFAULT_PRECISION
+                "%s%s%s%s%s%s", header, repeat_define, relocate_texture,
                 rel_sampler, source_fetch, mask_fetch, in);
 
     prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source);
commit 1fd82c764d5b24107e60f2173e30e5d24a2f2667
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jan 19 02:01:09 2016 +0000

    glamor: don't do copy if we have 0 boxes to copy.
    
    This happens if you run twm + mplayer + xclock and drag
    the clock over the mplayer. If we don't catch it, we cause
    an illegal draw elements command to be passed to GL.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c
index 028acf2..1adfba0 100644
--- a/glamor/glamor_copy.c
+++ b/glamor/glamor_copy.c
@@ -640,6 +640,9 @@ glamor_copy(DrawablePtr src,
             Pixel bitplane,
             void *closure)
 {
+    if (nbox == 0)
+	return;
+
     if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
         return;
     glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
commit e7308b6c77561df44c04f81509f8ada678705d94
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jan 12 18:13:46 2016 +1000

    glamor: Add support for CA rendering in a single pass.
    
    It's been on the list to add dual source blending support to avoid the
    two pass componentAlpha code.  Radeon has done this for a while in
    EXA, so let's add support to bring glamor up to using it.
    
    This adds dual blend to both render and composite glyphs paths.
    
    Initial results show close to doubling of speed of x11perf -rgb10text.
    
    v2: Fix breakage of all of CA acceleration for systems without
        GL_ARB_blend_func_extended.  Add CA support for all the ops we
        support in non-CA mode when blend_func_extended is present.  Clean
        up some comments and formatting.  (changes by anholt)
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 0b5ebef..d4f3be2 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -576,6 +576,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         epoxy_has_gl_extension("GL_NV_pack_subimage");
     glamor_priv->has_vertex_array_object =
         epoxy_has_gl_extension("GL_ARB_vertex_array_object");
+    glamor_priv->has_dual_blend =
+        epoxy_has_gl_extension("GL_ARB_blend_func_extended");
 
     glamor_setup_debug_output(screen);
 
diff --git a/glamor/glamor_composite_glyphs.c b/glamor/glamor_composite_glyphs.c
index 8692904..2e4dfe2 100644
--- a/glamor/glamor_composite_glyphs.c
+++ b/glamor/glamor_composite_glyphs.c
@@ -186,7 +186,9 @@ static const glamor_facet glamor_facet_composite_glyphs_130 = {
     .vs_exec = ("       vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
                 GLAMOR_POS(gl_Position, (primitive.xy + pos))
                 "       glyph_pos = (source + pos) * ATLAS_DIM_INV;\n"),
-    .fs_vars = ("varying vec2 glyph_pos;\n"),
+    .fs_vars = ("varying vec2 glyph_pos;\n"
+                "out vec4 color0;\n"
+                "out vec4 color1;\n"),
     .fs_exec = ("       vec4 mask = texture2D(atlas, glyph_pos);\n"),
     .source_name = "source",
     .locations = glamor_program_location_atlas,
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 8ed53e7..e49aee5 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -86,6 +86,12 @@ typedef struct glamor_composite_shader {
     };
 } glamor_composite_shader;
 
+enum ca_state {
+    CA_NONE,
+    CA_TWO_PASS,
+    CA_DUAL_BLEND,
+};
+
 enum shader_source {
     SHADER_SOURCE_SOLID,
     SHADER_SOURCE_TEXTURE,
@@ -106,6 +112,7 @@ enum shader_in {
     SHADER_IN_NORMAL,
     SHADER_IN_CA_SOURCE,
     SHADER_IN_CA_ALPHA,
+    SHADER_IN_CA_DUAL_BLEND,
     SHADER_IN_COUNT,
 };
 
@@ -202,6 +209,7 @@ typedef struct glamor_screen_private {
     Bool has_rw_pbo;
     Bool use_quads;
     Bool has_vertex_array_object;
+    Bool has_dual_blend;
     int max_fbo_size;
 
     struct xorg_list
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index 416c54a..ddab16f 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -344,6 +344,10 @@ glamor_build_program(ScreenPtr          screen,
 #endif
         glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name);
     }
+    if (prog->alpha == glamor_program_alpha_dual_blend) {
+        glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0");
+        glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1");
+    }
 
     glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name);
 
@@ -474,11 +478,24 @@ glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst)
     }
 
     /* 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)
+    if (alpha == glamor_program_alpha_dual_blend) {
+        switch (dst_blend) {
+        case GL_SRC_ALPHA:
+            dst_blend = GL_SRC1_COLOR;
+            break;
+        case GL_ONE_MINUS_SRC_ALPHA:
+            dst_blend = GL_ONE_MINUS_SRC1_COLOR;
+            break;
+        }
+    } else if (alpha != glamor_program_alpha_normal) {
+        switch (dst_blend) {
+        case GL_SRC_ALPHA:
             dst_blend = GL_SRC_COLOR;
-        else if (dst_blend == GL_ONE_MINUS_SRC_ALPHA)
+            break;
+        case GL_ONE_MINUS_SRC_ALPHA:
             dst_blend = GL_ONE_MINUS_SRC_COLOR;
+            break;
+        }
     }
 
     glEnable(GL_BLEND);
@@ -547,7 +564,9 @@ static const glamor_facet *glamor_facet_source[glamor_program_source_count] = {
 static const char *glamor_combine[] = {
     [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"
+    [glamor_program_alpha_ca_second] = "       gl_FragColor = source * mask;\n",
+    [glamor_program_alpha_dual_blend] = "      color0 = source * mask;\n"
+                                        "      color1 = source.a * mask;\n"
 };
 
 static Bool
@@ -567,9 +586,9 @@ glamor_setup_one_program_render(ScreenPtr               screen,
         if (!fill)
             return FALSE;
 
+        prog->alpha = alpha;
         if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines))
             return FALSE;
-        prog->alpha = alpha;
     }
 
     return TRUE;
@@ -585,6 +604,7 @@ glamor_setup_program_render(CARD8                 op,
                             const char            *defines)
 {
     ScreenPtr                   screen = dst->pDrawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_program_alpha        alpha;
     glamor_program_source       source_type;
     glamor_program              *prog;
@@ -593,10 +613,15 @@ glamor_setup_program_render(CARD8                 op,
         return NULL;
 
     if (glamor_is_component_alpha(mask)) {
-        /* This only works for PictOpOver */
-        if (op != PictOpOver)
-            return NULL;
-        alpha = glamor_program_alpha_ca_first;
+        if (glamor_priv->has_dual_blend) {
+            alpha = glamor_program_alpha_dual_blend;
+        } else {
+            /* This only works for PictOpOver */
+            if (op != PictOpOver)
+                return NULL;
+
+            alpha = glamor_program_alpha_ca_first;
+        }
     } else
         alpha = glamor_program_alpha_normal;
 
diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
index 9e561cd..ab6e46f 100644
--- a/glamor/glamor_program.h
+++ b/glamor/glamor_program.h
@@ -43,6 +43,7 @@ typedef enum {
     glamor_program_alpha_normal,
     glamor_program_alpha_ca_first,
     glamor_program_alpha_ca_second,
+    glamor_program_alpha_dual_blend,
     glamor_program_alpha_count
 } glamor_program_alpha;
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 1b226aa..e563e40 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -208,10 +208,24 @@ glamor_create_composite_fs(struct shader_key *key)
         "{\n"
         "	gl_FragColor = get_source().a * get_mask();\n"
         "}\n";
+    const char *in_ca_dual_blend =
+        GLAMOR_DEFAULT_PRECISION
+        "out vec4 color0;\n"
+        "out vec4 color1;\n"
+        "void main()\n"
+        "{\n"
+        "	color0 = get_source() * get_mask();\n"
+        "	color1 = get_source().a * get_mask();\n"
+        "}\n";
+    const char *header_ca_dual_blend =
+        "#version 130\n";
+
     char *source;
     const char *source_fetch;
     const char *mask_fetch = "";
     const char *in;
+    const char *header;
+    const char *header_norm = "";
     GLuint prog;
 
     switch (key->source) {
@@ -244,6 +258,7 @@ glamor_create_composite_fs(struct shader_key *key)
         FatalError("Bad composite shader mask");
     }
 
+    header = header_norm;
     switch (key->in) {
     case SHADER_IN_SOURCE_ONLY:
         in = in_source_only;
@@ -257,11 +272,15 @@ glamor_create_composite_fs(struct shader_key *key)
     case SHADER_IN_CA_ALPHA:
         in = in_ca_alpha;
         break;
+    case SHADER_IN_CA_DUAL_BLEND:
+        in = in_ca_dual_blend;
+        header = header_ca_dual_blend;
+        break;
     default:
         FatalError("Bad composite IN type");
     }
 
-    XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture,
+    XNFasprintf(&source, "%s%s%s%s%s%s%s", header, repeat_define, relocate_texture,
                 rel_sampler, source_fetch, mask_fetch, in);
 
     prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source);
@@ -331,6 +350,10 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
     glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0");
     glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1");
 
+    if (key->in == SHADER_IN_CA_DUAL_BLEND) {
+        glBindFragDataLocationIndexed(prog, 0, 0, "color0");
+        glBindFragDataLocationIndexed(prog, 0, 1, "color1");
+    }
     glamor_link_glsl_prog(screen, prog, "composite");
 
     shader->prog = prog;
@@ -382,7 +405,8 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct
 static Bool
 glamor_set_composite_op(ScreenPtr screen,
                         CARD8 op, struct blendinfo *op_info_result,
-                        PicturePtr dest, PicturePtr mask)
+                        PicturePtr dest, PicturePtr mask,
+                        enum ca_state ca_state)
 {
     GLenum source_blend, dest_blend;
     struct blendinfo *op_info;
@@ -391,6 +415,7 @@ glamor_set_composite_op(ScreenPtr screen,
         glamor_fallback("unsupported render op %d \n", op);
         return GL_FALSE;
     }
+
     op_info = &composite_op_info[op];
 
     source_blend = op_info->source_blend;
@@ -407,12 +432,25 @@ glamor_set_composite_op(ScreenPtr screen,
     }
 
     /* Set up the source alpha value for blending in component alpha mode. */
-    if (mask && mask->componentAlpha
-        && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) {
-        if (dest_blend == GL_SRC_ALPHA)
+    if (ca_state == CA_DUAL_BLEND) {
+        switch (dest_blend) {
+        case GL_SRC_ALPHA:
+            dest_blend = GL_SRC1_COLOR;
+            break;
+        case GL_ONE_MINUS_SRC_ALPHA:
+            dest_blend = GL_ONE_MINUS_SRC1_COLOR;
+            break;
+        }
+    } else if (mask && mask->componentAlpha
+               && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) {
+        switch (dest_blend) {
+        case GL_SRC_ALPHA:
             dest_blend = GL_SRC_COLOR;
-        else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA)
+            break;
+        case GL_ONE_MINUS_SRC_ALPHA:
             dest_blend = GL_ONE_MINUS_SRC_COLOR;
+            break;
+        }
     }
 
     op_info_result->source_blend = source_blend;
@@ -623,6 +661,10 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src,
         src_type = PICT_TYPE_A;
         mask_type = PICT_FORMAT_TYPE(mask);
         break;
+    case SHADER_IN_CA_DUAL_BLEND:
+        src_type = PICT_FORMAT_TYPE(src);
+        mask_type = PICT_FORMAT_TYPE(mask);
+        break;
     default:
         return FALSE;
     }
@@ -715,9 +757,11 @@ glamor_composite_choose_shader(CARD8 op,
                                struct shader_key *s_key,
                                glamor_composite_shader ** shader,
                                struct blendinfo *op_info,
-                               PictFormatShort *psaved_source_format)
+                               PictFormatShort *psaved_source_format,
+                               enum ca_state ca_state)
 {
     ScreenPtr screen = dest->pDrawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     enum glamor_pixmap_status source_status = GLAMOR_NONE;
     enum glamor_pixmap_status mask_status = GLAMOR_NONE;
     PictFormatShort saved_source_format = 0;
@@ -786,6 +830,8 @@ glamor_composite_choose_shader(CARD8 op,
         else {
             if (op == PictOpClear)
                 key.mask = SHADER_MASK_NONE;
+            else if (glamor_priv->has_dual_blend)
+                key.in = SHADER_IN_CA_DUAL_BLEND;
             else if (op == PictOpSrc || op == PictOpAdd
                      || op == PictOpIn || op == PictOpOut
                      || op == PictOpOverReverse)
@@ -933,7 +979,7 @@ glamor_composite_choose_shader(CARD8 op,
         goto fail;
     }
 
-    if (!glamor_set_composite_op(screen, op, op_info, dest, mask))
+    if (!glamor_set_composite_op(screen, op, op_info, dest, mask, ca_state))
         goto fail;
 
     *shader = glamor_lookup_composite_shader(screen, &key);
@@ -1025,7 +1071,7 @@ glamor_composite_with_shader(CARD8 op,
                              glamor_pixmap_private *mask_pixmap_priv,
                              glamor_pixmap_private *dest_pixmap_priv,
                              int nrect, glamor_composite_rect_t *rects,
-                             Bool two_pass_ca)
+                             enum ca_state ca_state)
 {
     ScreenPtr screen = dest->pDrawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -1048,17 +1094,17 @@ glamor_composite_with_shader(CARD8 op,
                                         source_pixmap_priv, mask_pixmap_priv,
                                         dest_pixmap_priv,
                                         &key, &shader, &op_info,
-                                        &saved_source_format)) {
+                                        &saved_source_format, ca_state)) {
         glamor_fallback("glamor_composite_choose_shader failed\n");
         return ret;
     }
-    if (two_pass_ca) {
+    if (ca_state == CA_TWO_PASS) {
         if (!glamor_composite_choose_shader(PictOpAdd, source, mask, dest,
                                             source_pixmap, mask_pixmap, dest_pixmap,
                                             source_pixmap_priv,
                                             mask_pixmap_priv, dest_pixmap_priv,
                                             &key_ca, &shader_ca, &op_info_ca,
-                                            &saved_source_format)) {
+                                            &saved_source_format, ca_state)) {
             glamor_fallback("glamor_composite_choose_shader failed\n");
             return ret;
         }
@@ -1173,7 +1219,7 @@ glamor_composite_with_shader(CARD8 op,
         glamor_put_vbo_space(screen);
         glamor_flush_composite_rects(screen);
         nrect -= rect_processed;
-        if (two_pass_ca) {
+        if (ca_state == CA_TWO_PASS) {
             glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv,
                                               &key_ca, shader_ca, &op_info_ca);
             glamor_flush_composite_rects(screen);
@@ -1278,6 +1324,7 @@ glamor_composite_clipped_region(CARD8 op,
     glamor_pixmap_private *source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
     glamor_pixmap_private *mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
     glamor_pixmap_private *dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(dest_pixmap->drawable.pScreen);
     ScreenPtr screen = dest->pDrawable->pScreen;
     PicturePtr temp_src = source, temp_mask = mask;
     PixmapPtr temp_src_pixmap = source_pixmap;
@@ -1295,7 +1342,7 @@ glamor_composite_clipped_region(CARD8 op,
     int height;
     BoxPtr box;
     int nbox;
-    Bool two_pass_ca = FALSE;
+    enum ca_state ca_state = CA_NONE;
 
     extent = RegionExtents(region);
     box = RegionRects(region);
@@ -1357,14 +1404,15 @@ glamor_composite_clipped_region(CARD8 op,
         x_temp_mask = -extent->x1 + x_dest + dest->pDrawable->x;
         y_temp_mask = -extent->y1 + y_dest + dest->pDrawable->y;
     }
-    /* Do two-pass PictOpOver componentAlpha, until we enable
-     * dual source color blending.
-     */
 
     if (mask && mask->componentAlpha) {
-        if (op == PictOpOver) {
-            two_pass_ca = TRUE;
-            op = PictOpOutReverse;
+        if (glamor_priv->has_dual_blend) {
+            ca_state = CA_DUAL_BLEND;
+        } else {
+            if (op == PictOpOver) {
+                ca_state = CA_TWO_PASS;
+                op = PictOpOutReverse;
+            }
         }
     }
 
@@ -1416,7 +1464,7 @@ glamor_composite_clipped_region(CARD8 op,
                                           temp_src_pixmap, temp_mask_pixmap, dest_pixmap,
                                           temp_src_priv, temp_mask_priv,
                                           dest_pixmap_priv,
-                                          box_cnt, prect, two_pass_ca);
+                                          box_cnt, prect, ca_state);
         if (!ok)
             break;
         nbox -= box_cnt;
@@ -1477,7 +1525,7 @@ glamor_composite(CARD8 op,
     if (op >= ARRAY_SIZE(composite_op_info))
         goto fail;
 
-    if (mask && mask->componentAlpha) {
+    if (mask && mask->componentAlpha && !glamor_priv->has_dual_blend) {
         if (op == PictOpAtop
             || op == PictOpAtopReverse
             || op == PictOpXor || op >= PictOpSaturate) {
commit cab14a9a08ff06bc4cbef79c7be8f1d07c07ebf9
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 21 12:01:02 2016 -0800

    glamor: Drop the composite_with_copy path entirely.
    
    I originally inherited this from the EXA code, without determining
    whether it was really needed.  Regular composite should end up doing
    the same thing, since it's all just shaders anyway.  To the extent
    that it doesn't, we should fix composite.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 92b6b0c..1b226aa 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -508,41 +508,6 @@ glamor_set_composite_solid(float *color, GLint uniform_location)
     glUniform4fv(uniform_location, 1, color);
 }
 
-static int
-compatible_formats(CARD8 op, PicturePtr dst, PicturePtr src)
-{
-    if (op == PictOpSrc) {
-        /* We can't do direct copies between different depths at 16bpp
-         * because r,g,b are allocated to different bits.
-         */
-        if (dst->pDrawable->bitsPerPixel == 16 &&
-            dst->pDrawable->depth != src->pDrawable->depth) {
-            return 0;
-        }
-
-        if (src->format == dst->format)
-            return 1;
-
-        if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8)
-            return 1;
-
-        if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8)
-            return 1;
-    }
-    else if (op == PictOpOver) {
-        if (src->alphaMap || dst->alphaMap)
-            return 0;
-
-        if (src->format != dst->format)
-            return 0;
-
-        if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8)
-            return 1;
-    }
-
-    return 0;
-}
-
 static char
 glamor_get_picture_location(PicturePtr picture)
 {
@@ -564,54 +529,6 @@ glamor_get_picture_location(PicturePtr picture)
     return glamor_get_drawable_location(picture->pDrawable);
 }
 
-static Bool
-glamor_composite_with_copy(CARD8 op,
-                           PicturePtr source,
-                           PicturePtr dest,
-                           INT16 x_source,
-                           INT16 y_source,
-                           INT16 x_dest, INT16 y_dest, RegionPtr region)
-{
-    int ret = FALSE;
-
-    if (!source->pDrawable)
-        return FALSE;
-
-    if (!compatible_formats(op, dest, source))
-        return FALSE;
-
-    if (source->repeat || source->transform) {
-        return FALSE;
-    }
-
-    x_dest += dest->pDrawable->x;
-    y_dest += dest->pDrawable->y;
-    x_source += source->pDrawable->x;
-    y_source += source->pDrawable->y;
-    if (PICT_FORMAT_A(source->format) == 0) {
-        /* Fallback if we sample outside the source so that we
-         * swizzle the correct clear color for out-of-bounds texels.
-         */
-        if (region->extents.x1 + x_source - x_dest < 0)
-            goto cleanup_region;
-        if (region->extents.x2 + x_source - x_dest > source->pDrawable->width)
-            goto cleanup_region;
-
-        if (region->extents.y1 + y_source - y_dest < 0)
-            goto cleanup_region;
-        if (region->extents.y2 + y_source - y_dest > source->pDrawable->height)
-            goto cleanup_region;
-    }
-    glamor_copy(source->pDrawable,
-                dest->pDrawable, NULL,
-                RegionRects(region), RegionNumRects(region),
-                x_source - x_dest, y_source - y_dest,
-                FALSE, FALSE, 0, NULL);
-    ret = TRUE;
- cleanup_region:
-    return ret;
-}
-
 static void *
 glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 {
@@ -1451,15 +1368,6 @@ glamor_composite_clipped_region(CARD8 op,
         }
     }
 
-    if (!mask && temp_src) {
-        if (glamor_composite_with_copy(op, temp_src, dest,
-                                       x_temp_src, y_temp_src,
-                                       x_dest, y_dest, region)) {
-            ok = TRUE;
-            goto out;
-        }
-    }
-
     if (temp_src_pixmap == dest_pixmap) {
         glamor_fallback("source and dest pixmaps are the same\n");
         goto out;


More information about the xorg-commit mailing list