freedreno/a4xx: fix srgb render targets
authorRob Clark <robclark@freedesktop.org>
Thu, 13 Aug 2015 17:53:43 +0000 (13:53 -0400)
committerRob Clark <robclark@freedesktop.org>
Sat, 15 Aug 2015 16:09:06 +0000 (12:09 -0400)
Also fixes mipmap level generation for srgb textures.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
src/gallium/drivers/freedreno/a4xx/fd4_emit.h
src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
src/gallium/drivers/freedreno/a4xx/fd4_program.c

index ab7850e50b0afc69ff4cf63d4493faa73bc98142..3a1d4b617d325c3b861600742f87d6b041068dc0 100644 (file)
@@ -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;
index 81c37f72565e3dd789dd06f0aa28bc0e91c9a144..3f8bbf3a1249c6188ad0dd8feecd960fb6812e26 100644 (file)
@@ -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);
index 1a6d01421322b17ed84d62d13a83a3089d42d077..a3d7123ccee3902d4e1047ca3882f2cc6d3f17cc 100644 (file)
@@ -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));
        }