diff options
-rw-r--r-- | src/gallium/drivers/i915/i915_clear.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_emit.c | 29 | ||||
-rw-r--r-- | 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 7341156310d..d6e6f567b89 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 fb511853e72..e39c7cc137f 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 426c683502a..9d487cfcdc1 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 9370f3dc2d3..9587dec4b90 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; } |