summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2015-08-13 13:53:43 -0400
committerRob Clark <[email protected]>2015-08-15 12:09:06 -0400
commit868b66fce7a156efda840c00088f89f4ba6163c9 (patch)
tree2c7bfacef55b8373902b5dc4f4394e312121f9ca
parentdd412c8fcb1c44846419523bb0e3956f38f578b5 (diff)
freedreno/a4xx: fix srgb render targets
Also fixes mipmap level generation for srgb textures. Signed-off-by: Rob Clark <[email protected]>
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_emit.h1
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_gmem.c22
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_program.c7
3 files changed, 22 insertions, 8 deletions
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
index ab7850e50b0..3a1d4b617d3 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
@@ -56,6 +56,7 @@ struct fd4_emit {
uint32_t sprite_coord_enable; /* bitmask */
bool sprite_coord_mode;
bool rasterflat;
+ bool no_decode_srgb;
/* cached to avoid repeated lookups of same variants: */
struct ir3_shader_variant *vp, *fp;
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c b/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
index 81c37f72565..3f8bbf3a124 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
@@ -46,7 +46,8 @@
static void
emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
- struct pipe_surface **bufs, uint32_t *bases, uint32_t bin_w)
+ struct pipe_surface **bufs, uint32_t *bases,
+ uint32_t bin_w, bool decode_srgb)
{
enum a4xx_tile_mode tile_mode;
unsigned i;
@@ -60,6 +61,7 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
for (i = 0; i < A4XX_MAX_RENDER_TARGETS; i++) {
enum a4xx_color_fmt format = 0;
enum a3xx_color_swap swap = WZYX;
+ bool srgb = false;
struct fd_resource *rsc = NULL;
struct fd_resource_slice *slice = NULL;
uint32_t stride = 0;
@@ -68,10 +70,9 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
if ((i < nr_bufs) && bufs[i]) {
struct pipe_surface *psurf = bufs[i];
- enum pipe_format pformat = 0;
+ enum pipe_format pformat = psurf->format;
rsc = fd_resource(psurf->texture);
- pformat = psurf->format;
/* In case we're drawing to Z32F_S8, the "color" actually goes to
* the stencil
@@ -86,6 +87,11 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
format = fd4_pipe2color(pformat);
swap = fd4_pipe2swap(pformat);
+ if (decode_srgb)
+ srgb = util_format_is_srgb(pformat);
+ else
+ pformat = util_format_linear(pformat);
+
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
offset = fd_resource_offset(rsc, psurf->u.tex.level,
@@ -108,7 +114,8 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
OUT_RING(ring, A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |
- A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
+ A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |
+ COND(srgb, A4XX_RB_MRT_BUF_INFO_COLOR_SRGB));
if (bin_w || (i >= nr_bufs) || !bufs[i]) {
OUT_RING(ring, base);
OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(stride));
@@ -282,7 +289,7 @@ emit_mem2gmem_surf(struct fd_context *ctx, uint32_t *bases,
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_surface *zsbufs[2];
- emit_mrt(ring, nr_bufs, bufs, bases, bin_w);
+ emit_mrt(ring, nr_bufs, bufs, bases, bin_w, false);
if (bufs[0] && (bufs[0]->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)) {
/* The gmem_restore_tex logic will put the first buffer's stencil
@@ -315,6 +322,7 @@ fd4_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile)
.key = {
.half_precision = fd_half_precision(pfb),
},
+ .no_decode_srgb = true,
};
unsigned char mrt_comp[A4XX_MAX_RENDER_TARGETS] = {0};
float x0, y0, x1, y1;
@@ -520,7 +528,7 @@ fd4_emit_sysmem_prep(struct fd_context *ctx)
OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
- emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0);
+ emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0, true);
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);
@@ -677,7 +685,7 @@ fd4_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile)
OUT_RING(ring, CP_SET_BIN_1_X1(x1) | CP_SET_BIN_1_Y1(y1));
OUT_RING(ring, CP_SET_BIN_2_X2(x2) | CP_SET_BIN_2_Y2(y2));
- emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem->cbuf_base, gmem->bin_w);
+ emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem->cbuf_base, gmem->bin_w, true);
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_program.c b/src/gallium/drivers/freedreno/a4xx/fd4_program.c
index 1a6d0142132..a3d7123ccee 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_program.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_program.c
@@ -450,10 +450,15 @@ fd4_program_emit(struct fd_ringbuffer *ring, struct fd4_emit *emit,
OUT_PKT0(ring, REG_A4XX_SP_FS_MRT_REG(0), 8);
for (i = 0; i < 8; i++) {
enum a4xx_color_fmt format = 0;
- if (i < nr)
+ bool srgb = false;
+ if (i < nr) {
format = fd4_emit_format(bufs[i]);
+ if (bufs[i] && !emit->no_decode_srgb)
+ srgb = util_format_is_srgb(bufs[i]->format);
+ }
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(color_regid[i]) |
A4XX_SP_FS_MRT_REG_MRTFORMAT(format) |
+ COND(srgb, A4XX_SP_FS_MRT_REG_COLOR_SRGB) |
COND(emit->key.half_precision,
A4XX_SP_FS_MRT_REG_HALF_PRECISION));
}