From 0610c7ba841638c1109aa104ecc5c31438b422d4 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 15 Mar 2021 13:42:37 -0700 Subject: [PATCH] freedreno/a6xx: Fix sRGB/snorm vs sysmem clear path This shows up when, thanks to the next patch, we decide to start doing bypass instead of GMEM for some dEQP's Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/a6xx/fd6_blitter.c | 49 ++++++++++++++++--- src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 4 +- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c index e3012fab3cc..97c7c501ea3 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c @@ -27,6 +27,7 @@ #include "util/u_dump.h" #include "util/half_float.h" +#include "util/format_srgb.h" #include "freedreno_blitter.h" #include "freedreno_fence.h" @@ -720,10 +721,18 @@ emit_clear_color(struct fd_ringbuffer *ring, switch (fd6_ifmt(fd6_pipe2color(pfmt))) { case R2D_UNORM8: case R2D_UNORM8_SRGB: - OUT_RING(ring, float_to_ubyte(color->f[0])); - OUT_RING(ring, float_to_ubyte(color->f[1])); - OUT_RING(ring, float_to_ubyte(color->f[2])); - OUT_RING(ring, float_to_ubyte(color->f[3])); + /* The r2d ifmt is badly named, it also covers the signed case: */ + if (util_format_is_snorm(pfmt)) { + OUT_RING(ring, float_to_byte_tex(color->f[0])); + OUT_RING(ring, float_to_byte_tex(color->f[1])); + OUT_RING(ring, float_to_byte_tex(color->f[2])); + OUT_RING(ring, float_to_byte_tex(color->f[3])); + } else { + OUT_RING(ring, float_to_ubyte(color->f[0])); + OUT_RING(ring, float_to_ubyte(color->f[1])); + OUT_RING(ring, float_to_ubyte(color->f[2])); + OUT_RING(ring, float_to_ubyte(color->f[3])); + } break; case R2D_FLOAT16: OUT_RING(ring, _mesa_float_to_half(color->f[0])); @@ -744,6 +753,32 @@ emit_clear_color(struct fd_ringbuffer *ring, } } +/** + * Handle conversion of clear color + */ +static union pipe_color_union +convert_color(enum pipe_format format, union pipe_color_union *pcolor) +{ + union pipe_color_union color = *pcolor; + + /* For solid-fill blits, the hw isn't going to convert from + * linear to srgb for us: + */ + if (util_format_is_srgb(format)) { + for (int i = 0; i < 3; i++) + color.f[i] = util_format_linear_to_srgb_float(color.f[i]); + } + + if (util_format_is_snorm(format)) { + for (int i = 0; i < 3; i++) + color.f[i] = CLAMP(color.f[i], -1.0f, 1.0f); + } + + /* Note that float_to_ubyte() already clamps, for the unorm case */ + + return color; +} + void fd6_clear_surface(struct fd_context *ctx, struct fd_ringbuffer *ring, struct pipe_surface *psurf, @@ -761,8 +796,10 @@ fd6_clear_surface(struct fd_context *ctx, OUT_RING(ring, A6XX_GRAS_2D_DST_BR_X(width * nr_samples - 1) | A6XX_GRAS_2D_DST_BR_Y(height - 1)); - emit_clear_color(ring, psurf->format, color); - emit_blit_setup(ring, psurf->format, false, color); + union pipe_color_union clear_color = convert_color(psurf->format, color); + + emit_clear_color(ring, psurf->format, &clear_color); + emit_blit_setup(ring, psurf->format, false, &clear_color); for (unsigned i = psurf->u.tex.first_layer; i <= psurf->u.tex.last_layer; i++) { emit_blit_dst(ring, psurf->texture, psurf->format, psurf->u.tex.level, i); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c index 2a6966e6e84..3a9ea601e19 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -1344,7 +1344,7 @@ emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring) if (buffers & PIPE_CLEAR_COLOR) { for (int i = 0; i < pfb->nr_cbufs; i++) { - union pipe_color_union *color = &batch->clear_color[i]; + union pipe_color_union color = batch->clear_color[i]; if (!pfb->cbufs[i]) continue; @@ -1353,7 +1353,7 @@ emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring) continue; fd6_clear_surface(ctx, ring, - pfb->cbufs[i], pfb->width, pfb->height, color); + pfb->cbufs[i], pfb->width, pfb->height, &color); } } if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {