Mesa (master): i915g: Implement writemask fixup

Stephane Marchesin marcheu at kemper.freedesktop.org
Thu Sep 5 02:49:38 UTC 2013


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

Author: Stéphane Marchesin <marcheu at chromium.org>
Date:   Wed Sep  4 17:55:21 2013 -0700

i915g: Implement writemask fixup

The fixup code emulates non-BGRA render targets by adding an
extra instruction at the end of fragment shaders to swizzle the
output. To do this, we also swizzle the blend function. However
an oversight until now was that the writemask wasn't getting
swizzled. This patch fixes that which fixes a bunch of piglit
tests.

---

 src/gallium/drivers/i915/i915_state.c        |   15 ++---
 src/gallium/drivers/i915/i915_state_emit.c   |   85 +++++++++++++++++++++-----
 src/gallium/drivers/i915/i915_state_static.c |   28 ++++----
 3 files changed, 90 insertions(+), 38 deletions(-)

diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index 06d4d3b..8ca69fc 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -94,7 +94,6 @@ static unsigned translate_mip_filter( unsigned filter )
    }
 }
 
-
 /* None of this state is actually used for anything yet.
  */
 static void *
@@ -117,10 +116,10 @@ i915_create_blend_state(struct pipe_context *pipe,
        */
 
       if (srcA != srcRGB ||
-	  dstA != dstRGB ||
-	  eqA != eqRGB) {
+          dstA != dstRGB ||
+          eqA != eqRGB) {
 
-	 cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+         cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
                           IAB_MODIFY_ENABLE |
                           IAB_ENABLE |
                           IAB_MODIFY_FUNC |
@@ -131,7 +130,7 @@ i915_create_blend_state(struct pipe_context *pipe,
                           (i915_translate_blend_func(eqA) << IAB_FUNC_SHIFT));
       }
       else {
-	 cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+         cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
                           IAB_MODIFY_ENABLE |
                           0);
       }
@@ -147,7 +146,7 @@ i915_create_blend_state(struct pipe_context *pipe,
    if (blend->dither)
       cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE;
 
-   /* XXX here take the target fixup into account */
+   /* We potentially do some fixup at emission for non-BGRA targets */
    if ((blend->rt[0].colormask & PIPE_MASK_R) == 0)
       cso_data->LIS5 |= S5_WRITEDISABLE_RED;
 
@@ -276,7 +275,7 @@ i915_create_sampler_state(struct pipe_context *pipe,
       maxlod = CLAMP(maxlod, 0, 16 * 11);
 
       if (minlod > maxlod)
-	 maxlod = minlod;
+         maxlod = minlod;
 
       cso->minlod = minlod;
       cso->maxlod = maxlod;
@@ -499,7 +498,7 @@ i915_create_depth_stencil_state(struct pipe_context *pipe,
                           (func << S6_DEPTH_TEST_FUNC_SHIFT));
 
       if (depth_stencil->depth.writemask)
-	 cso->depth_LIS6 |= S6_DEPTH_WRITE_ENABLE;
+         cso->depth_LIS6 |= S6_DEPTH_WRITE_ENABLE;
    }
 
    if (depth_stencil->alpha.enabled) {
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 554e967..9c16e59 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -128,6 +128,70 @@ validate_immediate(struct i915_context *i915, unsigned *batch_space)
    *batch_space = 1 + util_bitcount(dirty);
 }
 
+static uint target_fixup(struct pipe_surface *p, int component)
+{
+   const struct
+   {
+      enum pipe_format format;
+      uint hw_mask[4];
+   } fixup_mask[] = {
+      { PIPE_FORMAT_R8G8B8A8_UNORM, { S5_WRITEDISABLE_BLUE, S5_WRITEDISABLE_GREEN, S5_WRITEDISABLE_RED, S5_WRITEDISABLE_ALPHA}},
+      { PIPE_FORMAT_R8G8B8X8_UNORM, { S5_WRITEDISABLE_BLUE, S5_WRITEDISABLE_GREEN, S5_WRITEDISABLE_RED, S5_WRITEDISABLE_ALPHA}},
+      { PIPE_FORMAT_L8_UNORM,       { S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | S5_WRITEDISABLE_BLUE, 0, 0, S5_WRITEDISABLE_ALPHA}},
+      { PIPE_FORMAT_I8_UNORM,       { S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | S5_WRITEDISABLE_BLUE, 0, 0, S5_WRITEDISABLE_ALPHA}},
+      { PIPE_FORMAT_A8_UNORM,       { 0, 0, 0, S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA}},
+      { 0,                          { S5_WRITEDISABLE_RED, S5_WRITEDISABLE_GREEN, S5_WRITEDISABLE_BLUE, S5_WRITEDISABLE_ALPHA}}
+   };
+   int i = sizeof(fixup_mask) / sizeof(*fixup_mask);
+
+   if (p)
+      for(i = 0; fixup_mask[i].format != 0; i++)
+         if (p->format == fixup_mask[i].format)
+            return fixup_mask[i].hw_mask[component];
+
+   /* Just return default masks */
+   return fixup_mask[i].hw_mask[component];
+}
+
+static void emit_immediate_s5(struct i915_context *i915, uint imm)
+{
+   /* Fixup write mask for non-BGRA render targets */
+   uint fixup_imm = imm & ~( S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN |
+                             S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA );
+   struct pipe_surface *surf = i915->framebuffer.cbufs[0];
+
+   if (imm & S5_WRITEDISABLE_RED)
+      fixup_imm |= target_fixup(surf, 0);
+   if (imm & S5_WRITEDISABLE_GREEN)
+      fixup_imm |= target_fixup(surf, 1);
+   if (imm & S5_WRITEDISABLE_BLUE)
+      fixup_imm |= target_fixup(surf, 2);
+   if (imm & S5_WRITEDISABLE_ALPHA)
+      fixup_imm |= target_fixup(surf, 3);
+
+   OUT_BATCH(fixup_imm);
+}
+
+static void emit_immediate_s6(struct i915_context *i915, uint imm)
+{
+   /* Fixup blend function for A8 dst buffers.
+    * When we blend to an A8 buffer, the GPU thinks it's a G8 buffer,
+    * and therefore we need to use the color factor for alphas. */
+   uint srcRGB;
+
+   if (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM) {
+      srcRGB = (imm >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
+      if (srcRGB == BLENDFACT_DST_ALPHA)
+         srcRGB = BLENDFACT_DST_COLR;
+      else if (srcRGB == BLENDFACT_INV_DST_ALPHA)
+         srcRGB = BLENDFACT_INV_DST_COLR;
+      imm &= ~SRC_BLND_FACT(BLENDFACT_MASK);
+      imm |= SRC_BLND_FACT(srcRGB);
+   }
+
+   OUT_BATCH(imm);
+}
+
 static void
 emit_immediate(struct i915_context *i915)
 {
@@ -153,23 +217,12 @@ emit_immediate(struct i915_context *i915)
 
    for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
       if (dirty & (1 << i)) {
-         /* Fixup blend function for A8 dst buffers.
-          * When we blend to an A8 buffer, the GPU thinks it's a G8 buffer,
-          * and therefore we need to use the color factor for alphas. */
-         if ((i == I915_IMMEDIATE_S6) &&
-             (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM)) {
-            uint32_t imm = i915->current.immediate[i];
-            uint32_t srcRGB = (imm >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
-            if (srcRGB == BLENDFACT_DST_ALPHA)
-               srcRGB = BLENDFACT_DST_COLR;
-            else if (srcRGB == BLENDFACT_INV_DST_ALPHA)
-               srcRGB = BLENDFACT_INV_DST_COLR;
-            imm &= ~SRC_BLND_FACT(BLENDFACT_MASK);
-            imm |= SRC_BLND_FACT(srcRGB);
-            OUT_BATCH(imm);
-         } else {
+         if (i == I915_IMMEDIATE_S5)
+            emit_immediate_s5(i915, i915->current.immediate[i]);
+         else if (i == I915_IMMEDIATE_S6)
+            emit_immediate_s6(i915, i915->current.immediate[i]);
+         else
             OUT_BATCH(i915->current.immediate[i]);
-         }
       }
    }
 }
diff --git a/src/gallium/drivers/i915/i915_state_static.c b/src/gallium/drivers/i915/i915_state_static.c
index 41fe222..9a7ea22 100644
--- a/src/gallium/drivers/i915/i915_state_static.c
+++ b/src/gallium/drivers/i915/i915_state_static.c
@@ -163,28 +163,28 @@ struct i915_tracked_state i915_hw_framebuffer = {
    I915_NEW_FRAMEBUFFER
 };
 
-static const struct
-{
-   enum pipe_format format;
-   uint hw_swizzle;
-} fixup_formats[] = {
-   { PIPE_FORMAT_R8G8B8A8_UNORM, 0x21030000 /* BGRA */},
-   { PIPE_FORMAT_R8G8B8X8_UNORM, 0x21030000 /* BGRX */},
-   { PIPE_FORMAT_L8_UNORM,       0x00030000 /* RRRA */},
-   { PIPE_FORMAT_I8_UNORM,       0x00030000 /* RRRA */},
-   { PIPE_FORMAT_A8_UNORM,       0x33330000 /* AAAA */},
-   { PIPE_FORMAT_NONE,           0x00000000},
-};
-
 static uint32_t need_target_fixup(struct pipe_surface* p, uint32_t *fixup)
 {
+   const struct
+   {
+      enum pipe_format format;
+      uint hw_swizzle;
+   } fixup_formats[] = {
+      { PIPE_FORMAT_R8G8B8A8_UNORM, 0x21030000 /* BGRA */},
+      { PIPE_FORMAT_R8G8B8X8_UNORM, 0x21030000 /* BGRX */},
+      { PIPE_FORMAT_L8_UNORM,       0x00030000 /* RRRA */},
+      { PIPE_FORMAT_I8_UNORM,       0x00030000 /* RRRA */},
+      { PIPE_FORMAT_A8_UNORM,       0x33330000 /* AAAA */},
+      { PIPE_FORMAT_NONE,           0x00000000},
+   };
+
    enum pipe_format f;
    /* if we don't have a surface bound yet, we don't need to fixup the shader */
    if (!p)
       return 0;
 
    f = p->format;
-   for(int i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
+   for(int i = 0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
       if (fixup_formats[i].format == f) {
          *fixup = fixup_formats[i].hw_swizzle;
          return f;




More information about the mesa-commit mailing list