Mesa (master): st/xorg: lots of render fixes

Zack Rusin zack at kemper.freedesktop.org
Thu Oct 22 15:47:30 UTC 2009


Module: Mesa
Branch: master
Commit: c4af8ce69e1a7105b0178da8a085b73ab984e432
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c4af8ce69e1a7105b0178da8a085b73ab984e432

Author: Zack Rusin <zackr at vmware.com>
Date:   Thu Oct 22 11:49:19 2009 -0400

st/xorg: lots of render fixes

fixes all the blend modes, fixes flushing/finishing semantics, adds
acceleration for the component alpha modes that we can support, fixes
src in mask shader and general cleanups

---

 src/gallium/state_trackers/xorg/xorg_composite.c |  168 ++++++++++++----------
 src/gallium/state_trackers/xorg/xorg_exa.c       |   19 ++-
 src/gallium/state_trackers/xorg/xorg_exa_tgsi.c  |   37 ++----
 src/gallium/state_trackers/xorg/xorg_exa_tgsi.h  |    3 +-
 4 files changed, 114 insertions(+), 113 deletions(-)

diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
index 7379e3b..297b6c5 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.c
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -13,68 +13,43 @@
 #define XFixedToDouble(f)    (((double) (f)) / 65536.)
 
 struct xorg_composite_blend {
-   int op:8;
+   int op : 8;
 
-   unsigned rgb_src_factor:5;    /**< PIPE_BLENDFACTOR_x */
-   unsigned alpha_src_factor:5;  /**< PIPE_BLENDFACTOR_x */
+   unsigned alpha_dst : 4;
+   unsigned alpha_src : 4;
 
-   unsigned rgb_dst_factor:5;    /**< PIPE_BLENDFACTOR_x */
-   unsigned alpha_dst_factor:5;  /**< PIPE_BLENDFACTOR_x */
+   unsigned rgb_src : 8;    /**< PIPE_BLENDFACTOR_x */
+   unsigned rgb_dst : 8;    /**< PIPE_BLENDFACTOR_x */
 };
 
 #define BLEND_OP_OVER 3
 static const struct xorg_composite_blend xorg_blends[] = {
    { PictOpClear,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
-
+     0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO},
    { PictOpSrc,
-     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
-
+     0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO},
    { PictOpDst,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
-     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
-
+     0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE},
    { PictOpOver,
-     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
    { PictOpOverReverse,
-     PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE},
    { PictOpIn,
-     PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
    { PictOpInReverse,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE },
-
+     0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA},
    { PictOpOut,
-     PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
    { PictOpOutReverse,
-     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
    { PictOpAtop,
-     PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
    { PictOpAtopReverse,
-     PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+     1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA},
    { PictOpXor,
-     PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_ONE },
-
+     1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
    { PictOpAdd,
-     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
-     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
+     0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE},
 };
 
 
@@ -95,38 +70,62 @@ pixel_to_float4(Pixel pixel, float *color)
 
 struct acceleration_info {
    int op : 16;
-   int with_mask : 1;
-   int component_alpha : 1;
 };
 static const struct acceleration_info accelerated_ops[] = {
-   {PictOpClear,       1, 0},
-   {PictOpSrc,         1, 0},
-   {PictOpDst,         1, 0},
-   {PictOpOver,        1, 0},
-   {PictOpOverReverse, 1, 0},
-   {PictOpIn,          1, 0},
-   {PictOpInReverse,   1, 0},
-   {PictOpOut,         1, 0},
-   {PictOpOutReverse,  1, 0},
-   {PictOpAtop,        1, 0},
-   {PictOpAtopReverse, 1, 0},
-   {PictOpXor,         1, 0},
-   {PictOpAdd,         1, 0},
-   {PictOpSaturate,    1, 0},
+   {PictOpClear,        },
+   {PictOpSrc,          },
+   {PictOpDst,          },
+   {PictOpOver,         },
+   {PictOpOverReverse,  },
+   {PictOpIn,           },
+   {PictOpInReverse,    },
+   {PictOpOut,          },
+   {PictOpOutReverse,   },
+   {PictOpAtop,         },
+   {PictOpAtopReverse,  },
+   {PictOpXor,          },
+   {PictOpAdd,          },
+   {PictOpSaturate,     },
 };
 
 static struct xorg_composite_blend
-blend_for_op(int op)
+blend_for_op(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+             PicturePtr pDstPicture)
 {
    const int num_blends =
       sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
    int i;
+   struct xorg_composite_blend blend = xorg_blends[BLEND_OP_OVER];
 
    for (i = 0; i < num_blends; ++i) {
       if (xorg_blends[i].op == op)
-         return xorg_blends[i];
+         blend = xorg_blends[i];
    }
-   return xorg_blends[BLEND_OP_OVER];
+
+   /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+    * it as always 1.
+    */
+   if (pDstPicture &&
+       PICT_FORMAT_A(pDstPicture->format) == 0 && blend.alpha_dst) {
+      if (blend.rgb_src == PIPE_BLENDFACTOR_DST_ALPHA)
+         blend.rgb_src = PIPE_BLENDFACTOR_ONE;
+      else if (blend.rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA)
+         blend.rgb_src = PIPE_BLENDFACTOR_ZERO;
+   }
+
+   /* If the source alpha is being used, then we should only be in a case where
+    * the source blend factor is 0, and the source blend value is the mask
+    * channels multiplied by the source picture's alpha.
+    */
+   if (pMaskPicture && pMaskPicture->componentAlpha &&
+       PICT_FORMAT_RGB(pMaskPicture->format) && blend.alpha_src) {
+      if (blend.rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) {
+         blend.rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR;
+      } else if (blend.rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) {
+         blend.rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR;
+      }
+   }
+   return blend;
 }
 
 static INLINE int
@@ -203,41 +202,50 @@ boolean xorg_composite_accelerated(int op,
 
    if (pSrcPicture->pSourcePict) {
       if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
-         XORG_FALLBACK("gradients not enabled (haven't been well tested)");
+         XORG_FALLBACK("Gradients not enabled (haven't been well tested)");
    }
 
    for (i = 0; i < accel_ops_count; ++i) {
       if (op == accelerated_ops[i].op) {
+         struct xorg_composite_blend blend = blend_for_op(op,
+                                                          pSrcPicture,
+                                                          pMaskPicture,
+                                                          pDstPicture);
          /* Check for component alpha */
-         if (pMaskPicture &&
-             (pMaskPicture->componentAlpha ||
-              (!accelerated_ops[i].with_mask)))
-            XORG_FALLBACK("component alpha unsupported (PictOpOver=%s(%d)",
-                          (accelerated_ops[i].op == PictOpOver) ? "yes" : "no",
-                          accelerated_ops[i].op);
+         if (pMaskPicture && pMaskPicture->componentAlpha &&
+             PICT_FORMAT_RGB(pMaskPicture->format)) {
+            if (blend.alpha_src &&
+                blend.rgb_src != PIPE_BLENDFACTOR_ZERO) {
+               XORG_FALLBACK("Component alpha not supported with source "
+                             "alpha and source value blending. (op=%d)",
+                             op);
+            }
+         }
          return TRUE;
       }
    }
-   XORG_FALLBACK("unsupported operation");
+   XORG_FALLBACK("Unsupported composition operation = %d", op);
 }
 
 static void
 bind_blend_state(struct exa_context *exa, int op,
-                 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+                 PicturePtr pSrcPicture,
+                 PicturePtr pMaskPicture,
+                 PicturePtr pDstPicture)
 {
    struct xorg_composite_blend blend_opt;
    struct pipe_blend_state blend;
 
-   blend_opt = blend_for_op(op);
+   blend_opt = blend_for_op(op, pSrcPicture, pMaskPicture, pDstPicture);
 
-   memset(&blend, 0, sizeof(struct pipe_blend_state)); 
+   memset(&blend, 0, sizeof(struct pipe_blend_state));
    blend.blend_enable = 1;
    blend.colormask |= PIPE_MASK_RGBA;
 
-   blend.rgb_src_factor   = blend_opt.rgb_src_factor;
-   blend.alpha_src_factor = blend_opt.alpha_src_factor;
-   blend.rgb_dst_factor   = blend_opt.rgb_dst_factor;
-   blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
+   blend.rgb_src_factor   = blend_opt.rgb_src;
+   blend.alpha_src_factor = blend_opt.rgb_src;
+   blend.rgb_dst_factor   = blend_opt.rgb_dst;
+   blend.alpha_dst_factor = blend_opt.rgb_dst;
 
    cso_set_blend(exa->renderer->cso, &blend);
 }
@@ -273,6 +281,8 @@ bind_shaders(struct exa_context *exa, int op,
    if (pMaskPicture) {
       vs_traits |= VS_MASK;
       fs_traits |= FS_MASK;
+      if (pMaskPicture->componentAlpha)
+         fs_traits |= FS_COMPONENT_ALPHA;
    }
 
    shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
@@ -428,7 +438,7 @@ boolean xorg_composite_bind_state(struct exa_context *exa,
 {
    renderer_bind_framebuffer(exa->renderer, pDst);
    renderer_bind_viewport(exa->renderer, pDst);
-   bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
+   bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture);
    renderer_bind_rasterizer(exa->renderer);
    bind_shaders(exa, op, pSrcPicture, pMaskPicture);
    bind_samplers(exa, op, pSrcPicture, pMaskPicture,
@@ -491,7 +501,7 @@ boolean xorg_solid_bind_state(struct exa_context *exa,
    renderer_bind_framebuffer(exa->renderer, pixmap);
    renderer_bind_viewport(exa->renderer, pixmap);
    renderer_bind_rasterizer(exa->renderer);
-   bind_blend_state(exa, PictOpSrc, NULL, NULL);
+   bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL);
    setup_constant_buffers(exa, pixmap);
 
    shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index 39c4d26..b83d97b 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -105,12 +105,21 @@ xorg_exa_common_done(struct exa_context *exa)
 static void
 ExaWaitMarker(ScreenPtr pScreen, int marker)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   modesettingPtr ms = modesettingPTR(pScrn);
+   struct exa_context *exa = ms->exa;
+
+#if 0
+   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
+#else
+   xorg_exa_finish(exa);
+#endif
 }
 
 static int
 ExaMarkSync(ScreenPtr pScreen)
 {
-    return 1;
+   return 1;
 }
 
 static Bool
@@ -258,11 +267,6 @@ ExaDone(PixmapPtr pPixmap)
     if (!priv)
 	return;
 
-#if 1
-    xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
-#else
-    xorg_exa_finish(exa);
-#endif
     xorg_exa_common_done(exa);
 }
 
@@ -442,7 +446,8 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
    struct exa_pixmap_priv *priv;
 
 #if DEBUG_PRINT
-   debug_printf("ExaPrepareComposite\n");
+   debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
+                op, pSrcPicture, pMaskPicture, pDstPicture);
 #endif
    if (!exa->pipe)
       XORG_FALLBACK("accle not enabled");
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
index 8c9b674..041f4f9 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
@@ -50,36 +50,20 @@ struct xorg_shaders {
    struct cso_hash *fs_hash;
 };
 
-static const char over_op[] =
-   "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
-   "MAD TEMP[3], TEMP[0], TEMP[3], TEMP[0]\n";
-
-
-static INLINE void
-create_preamble(struct ureg_program *ureg)
-{
-}
-
-
 static INLINE void
 src_in_mask(struct ureg_program *ureg,
             struct ureg_dst dst,
             struct ureg_src src,
-            struct ureg_src mask)
+            struct ureg_src mask,
+            boolean component_alpha)
 {
-#if 0
-   /* MUL dst, src, mask.a */
-   ureg_MUL(ureg, dst, src,
-            ureg_scalar(mask, TGSI_SWIZZLE_W));
-#else
-   /* MOV dst, src */
-   /* MUL dst.a, src.a, mask.a */
-   ureg_MOV(ureg, dst, src);
-   ureg_MUL(ureg,
-            ureg_writemask(dst, TGSI_WRITEMASK_W),
-            ureg_scalar(src, TGSI_SWIZZLE_W),
-            ureg_scalar(mask, TGSI_SWIZZLE_W));
-#endif
+   if (component_alpha) {
+      ureg_MUL(ureg, dst, src, mask);
+   }
+   else {
+      ureg_MUL(ureg, dst, src,
+               ureg_scalar(mask, TGSI_SWIZZLE_W));
+   }
 }
 
 static struct ureg_src
@@ -305,6 +289,7 @@ create_fs(struct pipe_context *pipe,
    boolean is_solid   = fs_traits & FS_SOLID_FILL;
    boolean is_lingrad = fs_traits & FS_LINGRAD_FILL;
    boolean is_radgrad = fs_traits & FS_RADGRAD_FILL;
+   boolean is_comp_alpha = fs_traits & FS_COMPONENT_ALPHA;
 
    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    if (ureg == NULL)
@@ -401,7 +386,7 @@ create_fs(struct pipe_context *pipe,
       ureg_TEX(ureg, mask,
                TGSI_TEXTURE_2D, mask_pos, mask_sampler);
       /* src IN mask */
-      src_in_mask(ureg, out, ureg_src(src), ureg_src(mask));
+      src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), is_comp_alpha);
       ureg_release_temporary(ureg, mask);
    }
 
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
index 33c2720..c290d44 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
@@ -23,7 +23,8 @@ enum xorg_fs_traits {
    FS_RADGRAD_FILL     = 1 << 4,
    FS_FILL             = (FS_SOLID_FILL |
                           FS_LINGRAD_FILL |
-                          FS_RADGRAD_FILL)
+                          FS_RADGRAD_FILL),
+   FS_COMPONENT_ALPHA  = 1 << 5
 };
 
 struct xorg_shader {




More information about the mesa-commit mailing list