Mesa (master): i915g: Fix the blending for the A8 destination buffer case.

Stephane Marchesin marcheu at kemper.freedesktop.org
Mon Jan 16 07:43:48 UTC 2012


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

Author: Stéphane Marchesin <marcheu at chromium.org>
Date:   Sun Jan 15 23:32:59 2012 -0800

i915g: Fix the blending for the A8 destination buffer case.

The i915 GPU can't do A8 dst, so we abuse GREEN8 buffers for that
purpose. However, things get hairy as we start to do blending,
because then GL_DST_*_ALPHA should be replaced with GL_DST_*_COLOR.
This is what we do here.

Fixes piglt fbo-alpha.

---

 src/gallium/drivers/i915/i915_clear.c        |    2 +-
 src/gallium/drivers/i915/i915_context.h      |    2 +-
 src/gallium/drivers/i915/i915_state_emit.c   |   29 ++++++++++++++++++++-----
 src/gallium/drivers/i915/i915_state_static.c |    8 +++---
 4 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c
index 7341156..d6e6f56 100644
--- a/src/gallium/drivers/i915/i915_clear.c
+++ b/src/gallium/drivers/i915/i915_clear.c
@@ -74,7 +74,7 @@ i915_clear_emit(struct pipe_context *pipe, unsigned buffers,
       }
 
       /* correctly swizzle clear value */
-      if (i915->current.need_target_fixup)
+      if (i915->current.target_fixup_format)
          util_pack_color(color->f, cbuf->format, &u_color);
       else
          util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &u_color);
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index fb51185..e39c7cc 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -167,7 +167,7 @@ struct i915_state
    unsigned dst_buf_vars;
    uint32_t draw_offset;
    uint32_t draw_size;
-   unsigned need_target_fixup;
+   uint32_t target_fixup_format;
    uint32_t fixup_swizzle;
 
    unsigned id;			/* track lost context events */
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 426c683..9d487cf 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -151,8 +151,25 @@ emit_immediate(struct i915_context *i915)
    }
 
    for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
-      if (dirty & (1 << i))
-         OUT_BATCH(i915->current.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 {
+            OUT_BATCH(i915->current.immediate[i]);
+         }
+      }
    }
 }
 
@@ -346,7 +363,7 @@ emit_constants(struct i915_context *i915)
 static void
 validate_program(struct i915_context *i915, unsigned *batch_space)
 {
-   uint additional_size = i915->current.need_target_fixup;
+   uint additional_size = i915->current.target_fixup_format ? 1 : 0;
 
    /* we need more batch space if we want to emulate rgba framebuffers */
    *batch_space = i915->fs->program_len + 3 * additional_size;
@@ -355,7 +372,7 @@ validate_program(struct i915_context *i915, unsigned *batch_space)
 static void
 emit_program(struct i915_context *i915)
 {
-   uint target_fixup = i915->current.need_target_fixup;
+   uint need_target_fixup = i915->current.target_fixup_format ? 1 : 0;
    uint i;
 
    /* we should always have, at least, a pass-through program */
@@ -364,7 +381,7 @@ emit_program(struct i915_context *i915)
    {
       /* first word has the size, we have to adjust that */
       uint size = (i915->fs->program[0]);
-      size += target_fixup * 3;
+      size += need_target_fixup * 3;
       OUT_BATCH(size);
    }
 
@@ -373,7 +390,7 @@ emit_program(struct i915_context *i915)
       OUT_BATCH(i915->fs->program[i]);
 
    /* we emit an additional mov with swizzle to fake RGBA framebuffers */
-   if (target_fixup) {
+   if (need_target_fixup) {
       /* mov out_color, out_color.zyxw */
       OUT_BATCH(A0_MOV |
                 (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
diff --git a/src/gallium/drivers/i915/i915_state_static.c b/src/gallium/drivers/i915/i915_state_static.c
index 9370f3d..9587dec 100644
--- a/src/gallium/drivers/i915/i915_state_static.c
+++ b/src/gallium/drivers/i915/i915_state_static.c
@@ -177,7 +177,7 @@ static const struct
    { PIPE_FORMAT_NONE,           0x00000000},
 };
 
-static uint need_target_fixup(struct pipe_surface* p, uint32_t *fixup)
+static uint32_t need_target_fixup(struct pipe_surface* p, uint32_t *fixup)
 {
    enum pipe_format f;
    /* if we don't have a surface bound yet, we don't need to fixup the shader */
@@ -188,7 +188,7 @@ static uint need_target_fixup(struct pipe_surface* p, uint32_t *fixup)
    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 1;
+         return f;
       }
 
    *fixup = 0;
@@ -240,9 +240,9 @@ static void update_dst_buf_vars(struct i915_context *i915)
    }
 
    need_fixup = need_target_fixup(cbuf_surface, &fixup);
-   if (i915->current.need_target_fixup != need_fixup ||
+   if (i915->current.target_fixup_format != need_fixup ||
          i915->current.fixup_swizzle != fixup) {
-      i915->current.need_target_fixup = need_fixup;
+      i915->current.target_fixup_format = need_fixup;
       i915->current.fixup_swizzle = fixup;
       i915->hardware_dirty |= I915_HW_PROGRAM;
    }




More information about the mesa-commit mailing list