aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStéphane Marchesin <[email protected]>2011-06-30 02:05:50 -0700
committerStéphane Marchesin <[email protected]>2011-06-30 02:13:28 -0700
commita9cb01f35597797a83ac940b0230a8f74f99a1b8 (patch)
tree1370e52de0ff80bc61c72095c8c2ee4e1c4839bd
parent2adf02b45639d9d91400d081277783d5bbd20a33 (diff)
i915g: Implement surface format fixup without adding an extra instruction.
We also avoid writing output color twice, which might not work when we run out of phases.
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c85
1 files changed, 54 insertions, 31 deletions
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 257a8347bbe..39fb13aec7e 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -130,7 +130,7 @@ validate_immediate(struct i915_context *i915, unsigned *batch_space)
static void
emit_immediate(struct i915_context *i915)
{
- /* remove unwatned bits and S7 */
+ /* remove unwanted bits and S7 */
unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
@@ -346,18 +346,22 @@ emit_constants(struct i915_context *i915)
static const struct
{
enum pipe_format format;
- uint hw_swizzle;
+ uint hw_shift_R;
+ uint hw_shift_G;
+ uint hw_shift_B;
+ uint hw_shift_A;
} fixup_formats[] = {
- { PIPE_FORMAT_R8G8B8A8_UNORM, 0x21030000 /* BGRA */},
- { PIPE_FORMAT_L8_UNORM, 0x00030000 /* RRRR */},
- { PIPE_FORMAT_I8_UNORM, 0x00030000 /* RRRR */},
- { PIPE_FORMAT_A8_UNORM, 0x33330000 /* AAAA */},
- { PIPE_FORMAT_NONE, 0x00000000},
+ { PIPE_FORMAT_R8G8B8A8_UNORM, 20, 24, 28, 16 /* BGRA */},
+ { PIPE_FORMAT_L8_UNORM, 28, 28, 28, 16 /* RRRA */},
+ { PIPE_FORMAT_I8_UNORM, 28, 28, 28, 16 /* RRRA */},
+ { PIPE_FORMAT_A8_UNORM, 16, 16, 16, 16 /* AAAA */},
+ { PIPE_FORMAT_NONE, 0, 0, 0, 0},
};
static boolean need_fixup(struct pipe_surface* p)
{
enum pipe_format f;
+
/* if we don't have a surface bound yet, we don't need to fixup the shader */
if (!p)
return FALSE;
@@ -370,22 +374,32 @@ static boolean need_fixup(struct pipe_surface* p)
return FALSE;
}
-static uint fixup_swizzle(enum pipe_format f)
+static uint fixup_swizzle(enum pipe_format f, uint v)
{
- for(int i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
+ int i;
+
+ for(i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
if (fixup_formats[i].format == f)
- return fixup_formats[i].hw_swizzle;
+ break;
+
+ if (fixup_formats[i].format == PIPE_FORMAT_NONE)
+ return v;
- return 0;
+ uint rgba = v & 0xFFFF0000;
+
+ v &= 0xFFFF;
+ v |= ((rgba >> fixup_formats[i].hw_shift_R) & 0xF) << 28;
+ v |= ((rgba >> fixup_formats[i].hw_shift_G) & 0xF) << 24;
+ v |= ((rgba >> fixup_formats[i].hw_shift_B) & 0xF) << 20;
+ v |= ((rgba >> fixup_formats[i].hw_shift_A) & 0xF) << 16;
+
+ return v;
}
static void
validate_program(struct i915_context *i915, unsigned *batch_space)
{
- struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
-
- /* we need more batch space if we want to emulate rgba framebuffers */
- *batch_space = i915->fs->program_len + (need_fixup(cbuf_surface) ? 3 : 0);
+ *batch_space = i915->fs->program_len;
}
static void
@@ -393,27 +407,36 @@ emit_program(struct i915_context *i915)
{
struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
boolean need_format_fixup = need_fixup(cbuf_surface);
- uint i;
+ int i;
+ int fixup_offset = -1;
/* we should always have, at least, a pass-through program */
assert(i915->fs->program_len > 0);
- for (i = 0; i < i915->fs->program_len; i++) {
- if ((i == 0) && need_format_fixup)
- OUT_BATCH(i915->fs->program[i] + 3);
- else
- OUT_BATCH(i915->fs->program[i]);
- }
- /* we emit an additional mov with swizzle to fake RGBA framebuffers */
if (need_format_fixup) {
- /* mov out_color, out_color.zyxw */
- OUT_BATCH(A0_MOV |
- (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
- A0_DEST_CHANNEL_ALL |
- (REG_TYPE_OC << A0_SRC0_TYPE_SHIFT) |
- (T_DIFFUSE << A0_SRC0_NR_SHIFT));
- OUT_BATCH(fixup_swizzle(cbuf_surface->format));
- OUT_BATCH(0);
+ /* Find where we emit the output color */
+ for (i = i915->fs->program_len - 3; i>0; i-=3) {
+ uint instr = i915->fs->program[i];
+ if ((instr & (REG_NR_MASK << A0_DEST_TYPE_SHIFT)) ==
+ (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) ) {
+ /* Found it! */
+ fixup_offset = i + 1;
+ break;
+ }
+ }
+ if (fixup_offset == -1) {
+ need_format_fixup = FALSE;
+ debug_printf("couldn't find fixup offset\n");
+ }
+ }
+
+ /* emit the program to the hw */
+ for (i = 0; i < i915->fs->program_len; i++) {
+ if (need_format_fixup && (i == fixup_offset) ) {
+ uint v = fixup_swizzle(cbuf_surface->format, i915->fs->program[i]);
+ OUT_BATCH(v);
+ } else
+ OUT_BATCH(i915->fs->program[i]);
}
}