etnaviv: blt: Don't sRGB-roundtrip same-encoding copies
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

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: 99400f272d ("etnaviv: blt: Add BLT format conversion support")
Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41892>
This commit is contained in:
Christian Gmeiner 2026-05-29 23:31:06 +02:00 committed by Marge Bot
parent 08f801d6db
commit 9ec5e9a34e

View file

@ -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)