st/xorg: Incase of format missmatch swizzle channels and set alpha
authorJakob Bornecrantz <jakob@vmware.com>
Thu, 12 Nov 2009 10:16:30 +0000 (11:16 +0100)
committerJakob Bornecrantz <jakob@vmware.com>
Mon, 16 Nov 2009 22:33:44 +0000 (23:33 +0100)
This path is only hit for icons in gnome so far

src/gallium/state_trackers/xorg/xorg_composite.c
src/gallium/state_trackers/xorg/xorg_exa.c
src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
src/gallium/state_trackers/xorg/xorg_exa_tgsi.h

index 02dc949..1ff19a2 100644 (file)
@@ -228,10 +228,59 @@ bind_blend_state(struct exa_context *exa, int op,
    cso_set_blend(exa->renderer->cso, &blend);
 }
 
+static unsigned
+picture_format_fixups(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture, boolean mask)
+{
+   boolean set_alpha = FALSE;
+   boolean swizzle = FALSE;
+   unsigned ret = 0;
+
+   if (pSrc->picture_format == pSrcPicture->format)
+      return 0;
+
+   if (pSrc->picture_format != PICT_a8r8g8b8) {
+      assert(!"can not handle formats");
+      return 0;
+   }
+
+   /* pSrc->picture_format == PICT_a8r8g8b8 */
+   switch (pSrcPicture->format) {
+   case PICT_x8b8g8r8:
+   case PICT_b8g8r8:
+      set_alpha = TRUE; /* fall trough */
+   case PICT_a8b8g8r8:
+      swizzle = TRUE;
+      break;
+   case PICT_x8r8g8b8:
+   case PICT_r8g8b8:
+      set_alpha = TRUE; /* fall through */
+   case PICT_a8r8g8b8:
+      break;
+#ifdef PICT_TYPE_BGRA
+   case PICT_b8g8r8a8:
+   case PICT_b8g8r8x8:
+   case PICT_a2r10g10b10:
+   case PICT_x2r10g10b10:
+   case PICT_a2b10g10r10:
+   case PICT_x2b10g10r10:
+#endif
+   default:
+      assert(!"can not handle formats");
+      return 0;
+   }
+
+   if (set_alpha)
+      ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
+   if (swizzle)
+      ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB;
+
+   return ret;
+}
 
 static void
 bind_shaders(struct exa_context *exa, int op,
-             PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+             PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+             struct exa_pixmap_priv *pSrc, struct exa_pixmap_priv *pMask)
 {
    unsigned vs_traits = 0, fs_traits = 0;
    struct xorg_shader shader;
@@ -257,6 +306,8 @@ bind_shaders(struct exa_context *exa, int op,
          fs_traits |= FS_COMPOSITE;
          vs_traits |= VS_COMPOSITE;
       }
+
+      fs_traits |= picture_format_fixups(pSrc, pSrcPicture, FALSE);
    }
 
    if (pMaskPicture) {
@@ -273,6 +324,8 @@ bind_shaders(struct exa_context *exa, int op,
          } else
             fs_traits |= FS_CA_FULL;
       }
+
+      fs_traits |= picture_format_fixups(pMask, pMaskPicture, TRUE);
    }
 
    shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
@@ -438,7 +491,7 @@ boolean xorg_composite_bind_state(struct exa_context *exa,
    renderer_bind_viewport(exa->renderer, pDst);
    bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture);
    renderer_bind_rasterizer(exa->renderer);
-   bind_shaders(exa, op, pSrcPicture, pMaskPicture);
+   bind_shaders(exa, op, pSrcPicture, pMaskPicture, pSrc, pMask);
    bind_samplers(exa, op, pSrcPicture, pMaskPicture,
                  pDstPicture, pSrc, pMask, pDst);
    setup_constant_buffers(exa, pDst);
index 735cabf..25c9fce 100644 (file)
@@ -468,6 +468,41 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
 }
 
 static Bool
+picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
+{
+   if (pSrc->picture_format == pSrcPicture->format)
+      return TRUE;
+
+   if (pSrc->picture_format != PICT_a8r8g8b8)
+      return FALSE;
+
+   /* pSrc->picture_format == PICT_a8r8g8b8 */
+   switch (pSrcPicture->format) {
+   case PICT_a8r8g8b8:
+   case PICT_x8r8g8b8:
+   case PICT_a8b8g8r8:
+   case PICT_x8b8g8r8:
+   /* just treat these two as x8... */
+   case PICT_r8g8b8:
+   case PICT_b8g8r8:
+      return TRUE;
+#ifdef PICT_TYPE_BGRA
+   case PICT_b8g8r8a8:
+   case PICT_b8g8r8x8:
+      return FALSE; /* does not support swizzleing the alpha channel yet */
+   case PICT_a2r10g10b10:
+   case PICT_x2r10g10b10:
+   case PICT_a2b10g10r10:
+   case PICT_x2b10g10r10:
+      return FALSE;
+#endif
+   default:
+      return FALSE;
+   }
+   return FALSE;
+}
+
+static Bool
 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
                    PicturePtr pMaskPicture, PicturePtr pDstPicture,
                    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
@@ -512,7 +547,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
                                           PIPE_TEXTURE_USAGE_SAMPLER, 0))
          XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
 
-      if (priv->picture_format != pSrcPicture->format)
+      if (!picture_check_formats(priv, pSrcPicture))
          XORG_FALLBACK("pSrc pic_format: %s != %s",
                        render_format_name(priv->picture_format),
                        render_format_name(pSrcPicture->format));
@@ -528,7 +563,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
                                           PIPE_TEXTURE_USAGE_SAMPLER, 0))
          XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
 
-      if (priv->picture_format != pMaskPicture->format)
+      if (!picture_check_formats(priv, pMaskPicture))
          XORG_FALLBACK("pMask pic_format: %s != %s",
                        render_format_name(priv->picture_format),
                        render_format_name(pMaskPicture->format));
index f855775..cbb9ec1 100644 (file)
@@ -359,12 +359,18 @@ xrender_tex(struct ureg_program *ureg,
             struct ureg_dst dst,
             struct ureg_src coords,
             struct ureg_src sampler,
-            boolean repeat_none)
+            boolean repeat_none,
+            boolean swizzle,
+            boolean set_alpha)
 {
+   struct ureg_src imm0 = { 0 };
+
+   if (repeat_none || set_alpha)
+      imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
+
    if (repeat_none) {
       struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);
       struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);
-      struct ureg_src imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
       ureg_SGT(ureg, tmp1, ureg_swizzle(coords,
                                         TGSI_SWIZZLE_X,
                                         TGSI_SWIZZLE_Y,
@@ -381,11 +387,37 @@ xrender_tex(struct ureg_program *ureg,
       ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),
                ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));
       ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);
+      if (swizzle)
+         ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),
+                                           TGSI_SWIZZLE_Z,
+                                           TGSI_SWIZZLE_Y,
+                                           TGSI_SWIZZLE_X,
+                                           TGSI_SWIZZLE_W));
+      if (set_alpha)
+         ureg_MOV(ureg,
+                  ureg_writemask(tmp1, TGSI_WRITEMASK_W),
+                  ureg_scalar(imm0, TGSI_SWIZZLE_W));
       ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));
       ureg_release_temporary(ureg, tmp0);
       ureg_release_temporary(ureg, tmp1);
-   } else
-      ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
+   } else {
+      if (swizzle) {
+         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
+         ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);
+         ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),
+                                          TGSI_SWIZZLE_Z,
+                                          TGSI_SWIZZLE_Y,
+                                          TGSI_SWIZZLE_X,
+                                          TGSI_SWIZZLE_W));
+         ureg_release_temporary(ureg, tmp);
+      } else {
+         ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
+      }
+      if (set_alpha)
+         ureg_MOV(ureg,
+                  ureg_writemask(dst, TGSI_WRITEMASK_W),
+                  ureg_scalar(imm0, TGSI_SWIZZLE_W));
+   }
 }
 
 static void *
@@ -407,6 +439,10 @@ create_fs(struct pipe_context *pipe,
    unsigned is_yuv = (fs_traits & FS_YUV) != 0;
    unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;
    unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;
+   unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;
+   unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;
+   unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;
+   unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
 
    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    if (ureg == NULL)
@@ -463,7 +499,7 @@ create_fs(struct pipe_context *pipe,
       else
          src = out;
       xrender_tex(ureg, src, src_input, src_sampler,
-                  src_repeat_none);
+                  src_repeat_none, src_swizzle, src_set_alpha);
    } else if (is_fill) {
       if (is_solid) {
          if (has_mask)
@@ -503,7 +539,7 @@ create_fs(struct pipe_context *pipe,
    if (has_mask) {
       mask = ureg_DECL_temporary(ureg);
       xrender_tex(ureg, mask, mask_pos, mask_sampler,
-                  mask_repeat_none);
+                  mask_repeat_none, mask_swizzle, mask_set_alpha);
       /* src IN mask */
       src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), comp_alpha);
       ureg_release_temporary(ureg, mask);
index c038dc2..062de94 100644 (file)
@@ -28,6 +28,10 @@ enum xorg_fs_traits {
    FS_YUV              = 1 << 7,
    FS_SRC_REPEAT_NONE  = 1 << 8,
    FS_MASK_REPEAT_NONE = 1 << 9,
+   FS_SRC_SWIZZLE_RGB  = 1 << 10,
+   FS_MASK_SWIZZLE_RGB = 1 << 11,
+   FS_SRC_SET_ALPHA    = 1 << 12,
+   FS_MASK_SET_ALPHA   = 1 << 13,
 
    FS_FILL             = (FS_SOLID_FILL |
                           FS_LINGRAD_FILL |