summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/i915/i915_clear.c2
-rw-r--r--src/gallium/drivers/i915/i915_context.h2
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c29
-rw-r--r--src/gallium/drivers/i915/i915_state_static.c8
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;
}