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
|
static void
|
||||||
emit_immediate(struct i915_context *i915)
|
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 |
|
unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
|
||||||
1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
|
1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
|
||||||
1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
|
1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
|
||||||
@@ -346,18 +346,22 @@ emit_constants(struct i915_context *i915)
|
|||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
enum pipe_format format;
|
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[] = {
|
} fixup_formats[] = {
|
||||||
{ PIPE_FORMAT_R8G8B8A8_UNORM, 0x21030000 /* BGRA */},
|
{ PIPE_FORMAT_R8G8B8A8_UNORM, 20, 24, 28, 16 /* BGRA */},
|
||||||
{ PIPE_FORMAT_L8_UNORM, 0x00030000 /* RRRR */},
|
{ PIPE_FORMAT_L8_UNORM, 28, 28, 28, 16 /* RRRA */},
|
||||||
{ PIPE_FORMAT_I8_UNORM, 0x00030000 /* RRRR */},
|
{ PIPE_FORMAT_I8_UNORM, 28, 28, 28, 16 /* RRRA */},
|
||||||
{ PIPE_FORMAT_A8_UNORM, 0x33330000 /* AAAA */},
|
{ PIPE_FORMAT_A8_UNORM, 16, 16, 16, 16 /* AAAA */},
|
||||||
{ PIPE_FORMAT_NONE, 0x00000000},
|
{ PIPE_FORMAT_NONE, 0, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static boolean need_fixup(struct pipe_surface* p)
|
static boolean need_fixup(struct pipe_surface* p)
|
||||||
{
|
{
|
||||||
enum pipe_format f;
|
enum pipe_format f;
|
||||||
|
|
||||||
/* if we don't have a surface bound yet, we don't need to fixup the shader */
|
/* if we don't have a surface bound yet, we don't need to fixup the shader */
|
||||||
if (!p)
|
if (!p)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -370,22 +374,32 @@ static boolean need_fixup(struct pipe_surface* p)
|
|||||||
return FALSE;
|
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;
|
||||||
if (fixup_formats[i].format == f)
|
|
||||||
return fixup_formats[i].hw_swizzle;
|
|
||||||
|
|
||||||
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
|
static void
|
||||||
validate_program(struct i915_context *i915, unsigned *batch_space)
|
validate_program(struct i915_context *i915, unsigned *batch_space)
|
||||||
{
|
{
|
||||||
struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
|
*batch_space = i915->fs->program_len;
|
||||||
|
|
||||||
/* we need more batch space if we want to emulate rgba framebuffers */
|
|
||||||
*batch_space = i915->fs->program_len + (need_fixup(cbuf_surface) ? 3 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -393,27 +407,36 @@ emit_program(struct i915_context *i915)
|
|||||||
{
|
{
|
||||||
struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
|
struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
|
||||||
boolean need_format_fixup = need_fixup(cbuf_surface);
|
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 */
|
/* we should always have, at least, a pass-through program */
|
||||||
assert(i915->fs->program_len > 0);
|
assert(i915->fs->program_len > 0);
|
||||||
for (i = 0; i < i915->fs->program_len; i++) {
|
|
||||||
if ((i == 0) && need_format_fixup)
|
if (need_format_fixup) {
|
||||||
OUT_BATCH(i915->fs->program[i] + 3);
|
/* Find where we emit the output color */
|
||||||
else
|
for (i = i915->fs->program_len - 3; i>0; i-=3) {
|
||||||
OUT_BATCH(i915->fs->program[i]);
|
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 */
|
/* emit the program to the hw */
|
||||||
if (need_format_fixup) {
|
for (i = 0; i < i915->fs->program_len; i++) {
|
||||||
/* mov out_color, out_color.zyxw */
|
if (need_format_fixup && (i == fixup_offset) ) {
|
||||||
OUT_BATCH(A0_MOV |
|
uint v = fixup_swizzle(cbuf_surface->format, i915->fs->program[i]);
|
||||||
(REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
|
OUT_BATCH(v);
|
||||||
A0_DEST_CHANNEL_ALL |
|
} else
|
||||||
(REG_TYPE_OC << A0_SRC0_TYPE_SHIFT) |
|
OUT_BATCH(i915->fs->program[i]);
|
||||||
(T_DIFFUSE << A0_SRC0_NR_SHIFT));
|
|
||||||
OUT_BATCH(fixup_swizzle(cbuf_surface->format));
|
|
||||||
OUT_BATCH(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user