From 9ec5e9a34ec58fe212918f340a6083cc80a4ab2e Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 29 May 2026 23:31:06 +0200 Subject: [PATCH] etnaviv: blt: Don't sRGB-roundtrip same-encoding copies etna_try_blt_blit(..) derived the BLT sRGB decode (on read) and encode (on write) flags independently from the source and destination formats. A copy between two sRGB formats - such as the glReadPixels resolve of an SRGB8_ALPHA8 framebuffer - therefore decoded to linear and re-encoded. That roundtrip through the hardware is not bit-preserving and loses up to 2/255 at low values, corrupting the readback of the conversions r32f, rg32f and rgba32f to srgb8_alpha8. Apply the sRGB conversion only when the copy crosses the sRGB/linear boundary. Same-encoding copies stay a plain bit copy. Fixes dEQP-GLES3.functional.fbo.blit.conversion.{r32f,rg32f,rgba32f}_to_srgb8_alpha8 Fixes: 99400f272d4 ("etnaviv: blt: Add BLT format conversion support") Signed-off-by: Christian Gmeiner Part-of: --- src/gallium/drivers/etnaviv/etnaviv_blt.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_blt.c b/src/gallium/drivers/etnaviv/etnaviv_blt.c index 240424842de..8da3757477f 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_blt.c +++ b/src/gallium/drivers/etnaviv/etnaviv_blt.c @@ -851,8 +851,15 @@ etna_try_blt_blit(struct pipe_context *pctx, op.src.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride; op.src.addr.flags = ETNA_RELOC_READ; op.src.bpp = util_format_get_blocksize(blit_info->src.format); + + /* Only convert across the sRGB<->linear boundary. A same-encoding copy is + * bit-preserving and a decode+encode roundtrip would only lose precision. + */ + const bool src_is_srgb = util_format_is_srgb(src_fmt); + const bool dst_is_srgb = util_format_is_srgb(dst_fmt); + op.src.format = src_format; - op.src.srgb = util_format_is_srgb(src_fmt); + op.src.srgb = src_is_srgb && !dst_is_srgb; op.src.stride = src_lev->stride; op.src.tiling = src->layout; op.src.downsample_x = downsample_x; @@ -877,7 +884,7 @@ etna_try_blt_blit(struct pipe_context *pctx, op.dest.addr.offset = dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride; op.dest.addr.flags = ETNA_RELOC_WRITE; op.dest.format = dst_format; - op.dest.srgb = util_format_is_srgb(dst_fmt); + op.dest.srgb = dst_is_srgb && !src_is_srgb; op.dest.stride = dst_lev->stride; op.dest.tiling = dst->layout; if (has_conversion)