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.
This commit is contained in:
@@ -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++)
|
||||
if (fixup_formats[i].format == f)
|
||||
return fixup_formats[i].hw_swizzle;
|
||||
int i;
|
||||
|
||||
return 0;
|
||||
for(i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++)
|
||||
if (fixup_formats[i].format == f)
|
||||
break;
|
||||
|
||||
if (fixup_formats[i].format == PIPE_FORMAT_NONE)
|
||||
return v;
|
||||
|
||||
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]);
|
||||
|
||||
if (need_format_fixup) {
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* 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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user