summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/i915/i915_state_emit.c
diff options
context:
space:
mode:
authorStéphane Marchesin <marcheu@chromium.org>2013-09-04 17:55:21 -0700
committerStéphane Marchesin <marcheu@chromium.org>2013-09-04 19:48:18 -0700
commit8709e2b6c564435111545c470da8796c81f020c4 (patch)
tree7baa8736e5c2ae7cca8d8cfcc28a34d68b59e6f5 /src/gallium/drivers/i915/i915_state_emit.c
parentb1461acf15ab450fa0d360ec5e03c90d0797a6d4 (diff)
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.
Diffstat (limited to 'src/gallium/drivers/i915/i915_state_emit.c')
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 554e967fcc0..9c16e590003 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]);
- }
}
}
}