}
/* correctly swizzle clear value */
- if (i915->current.target_fixup_format)
+ if (i915->current.fixup_swizzle)
util_pack_color(color->f, cbuf->format, &u_color);
else
util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &u_color);
unsigned dst_buf_vars;
uint32_t draw_offset;
uint32_t draw_size;
- uint32_t target_fixup_format;
+
+ /* Reswizzle for OC writes in PIXEL_SHADER_PROGRAM, or 0 if unnecessary. */
uint32_t fixup_swizzle;
unsigned id; /* track lost context events */
struct i915_surface {
struct pipe_surface templ;
uint32_t buf_info; /* _3DSTATE_BUF_INFO_CMD flags */
+
+ /* PIXEL_SHADER_PROGRAM swizzle for OC buffer to handle the cbuf format (or 0 if none). */
+ uint32_t oc_swizzle;
+ /* cbuf swizzle from dst r/g/b/a channels in memory to channels of gallium API. */
+ uint8_t color_swizzle[4];
};
struct i915_velems_state {
* and therefore we need to use the color factor for alphas. */
uint srcRGB;
- if (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM) {
+ if (i915->framebuffer.cbufs[0] &&
+ i915->framebuffer.cbufs[0]->format == PIPE_FORMAT_A8_UNORM) {
srcRGB = (imm >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
if (srcRGB == BLENDFACT_DST_ALPHA)
srcRGB = BLENDFACT_DST_COLR;
{
uint additional_size = 0;
- additional_size += i915->current.target_fixup_format ? 3 : 0;
+ additional_size += i915->current.fixup_swizzle ? 3 : 0;
/* we need more batch space if we want to emulate rgba framebuffers */
*batch_space = i915->fs->decl_len + i915->fs->program_len + additional_size;
}
/* we emit an additional mov with swizzle to fake RGBA framebuffers */
- if (i915->current.target_fixup_format) {
+ if (i915->current.fixup_swizzle) {
/* mov out_color, out_color.zyxw */
OUT_BATCH(A0_MOV |
(REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
unsigned x, y;
int layer;
uint32_t draw_offset, draw_size;
+ uint32_t oc_swizzle = 0;
if (cbuf_surface) {
struct i915_surface *surf = i915_surface(cbuf_surface);
x = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksx;
y = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksy;
+
+ oc_swizzle = surf->oc_swizzle;
} else {
i915->current.cbuf_bo = NULL;
x = y = 0;
i915->hardware_dirty |= I915_HW_STATIC;
+ if (i915->current.fixup_swizzle != oc_swizzle) {
+ i915->current.fixup_swizzle = oc_swizzle;
+ i915->hardware_dirty |= I915_HW_PROGRAM;
+ }
+
/* flush the cache in case we sample from the old renderbuffers */
i915_set_flush_dirty(i915, I915_FLUSH_CACHE);
}
I915_NEW_FRAMEBUFFER
};
-static uint32_t need_target_fixup(struct pipe_surface* p, uint32_t *fixup)
-{
- const struct
- {
- enum pipe_format format;
- uint hw_swizzle;
- } fixup_formats[] = {
- { PIPE_FORMAT_R8G8B8A8_UNORM, 0x21030000 /* BGRA */},
- { PIPE_FORMAT_R8G8B8X8_UNORM, 0x21030000 /* BGRX */},
- { PIPE_FORMAT_L8_UNORM, 0x00030000 /* RRRA */},
- { PIPE_FORMAT_I8_UNORM, 0x00030000 /* RRRA */},
- { PIPE_FORMAT_A8_UNORM, 0x33330000 /* AAAA */},
- { PIPE_FORMAT_NONE, 0x00000000},
- };
-
- enum pipe_format f;
- /* if we don't have a surface bound yet, we don't need to fixup the shader */
- if (!p)
- return 0;
-
- f = p->format;
- 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 f;
- }
-
- *fixup = 0;
- return 0;
-}
-
static void update_dst_buf_vars(struct i915_context *i915)
{
struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
struct pipe_surface *depth_surface = i915->framebuffer.zsbuf;
uint32_t dst_buf_vars, cformat, zformat;
uint32_t early_z = 0;
- uint32_t fixup = 0;
- int need_fixup;
if (cbuf_surface)
cformat = cbuf_surface->format;
i915->hardware_dirty |= I915_HW_STATIC;
}
- need_fixup = need_target_fixup(cbuf_surface, &fixup);
- if (i915->current.target_fixup_format != need_fixup ||
- i915->current.fixup_swizzle != fixup) {
- i915->current.target_fixup_format = need_fixup;
- i915->current.fixup_swizzle = fixup;
- /* we also send a new program to make sure the fixup for RGBA surfaces happens */
- i915->hardware_dirty |= I915_HW_PROGRAM;
- }
}
struct i915_tracked_state i915_hw_dst_buf_vars = {
* Screen surface functions
*/
+static void i915_set_color_surface_swizzle(struct i915_surface *surf)
+{
+ const struct {
+ enum pipe_format format;
+ uint8_t color_swizzle[4];
+ uint32_t oc_swizzle;
+ } fixup_formats[] = {
+ { PIPE_FORMAT_R8G8B8A8_UNORM, {2, 1, 0, 3 }, 0x21030000 /* BGRA */},
+ { PIPE_FORMAT_R8G8B8X8_UNORM, {2, 1, 0, 3 }, 0x21030000 /* BGRX */},
+ { PIPE_FORMAT_L8_UNORM, {0, 0, 0, 0 }, 0x00030000 /* RRRA */},
+ { PIPE_FORMAT_I8_UNORM, {0, 0, 0, 0 }, 0x00030000 /* RRRA */},
+ { PIPE_FORMAT_A8_UNORM, {3, 3, 3, 3 }, 0x33330000 /* AAAA */},
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(fixup_formats); i++) {
+ if (fixup_formats[i].format == surf->templ.format) {
+ memcpy(surf->color_swizzle, fixup_formats[i].color_swizzle, sizeof(surf->color_swizzle));
+ surf->oc_swizzle = fixup_formats[i].oc_swizzle;
+ return;
+ }
+ }
+
+ for (int i = 0; i < 4; i++)
+ surf->color_swizzle[i] = i;
+}
static struct pipe_surface *
i915_create_surface_custom(struct pipe_context *ctx,
surf->buf_info = BUF_3D_ID_DEPTH;
} else {
surf->buf_info = BUF_3D_ID_COLOR_BACK;
+
+ i915_set_color_surface_swizzle(surf);
}
surf->buf_info |= BUF_3D_PITCH(tex->stride); /* pitch in bytes */