etnaviv: Bypass BGRA-internal optimization for shared resources

The rb-swap rework (commit a5766e75e48) uses A8R8G8B8 as the texture
format for RB_SWAP pipe formats and performs R<->B conversion during
transfer blits. This breaks dmabuf import/export: external producers
write RGBA bytes, but A8R8G8B8 interprets them as BGRA; transfer blits
incorrectly swap R<->B on data already in the correct byte order.

For shared/imported resources, bypass the optimization: use the native
texture format (A8B8G8R8) so the sampler reads RGBA bytes correctly in
both the descriptor and state-based texture paths, skip the R<->B
swizzle in BLT and RS transfer blits since shared resources already
store data in standard byte order, and re-enable the texture shadow
shortcut for shared RB_SWAP resources since the BLT swap is no longer
applied.

Internal-only resources continue using the BGRA-internal optimization
unchanged.

Fixes: a5766e75e48 ("etnaviv: Use BGRA-internal texture format with BLT/RS R/B swizzle")
Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40029>
This commit is contained in:
Christian Gmeiner 2026-02-21 00:41:07 +01:00 committed by Marge Bot
parent fee5106b53
commit 377f2ec49c
7 changed files with 39 additions and 5 deletions

View file

@ -791,7 +791,8 @@ etna_try_blt_blit(struct pipe_context *pctx,
/* For transfer blits of RB_SWAP formats, apply R<->B swizzle on the
* linear side to convert between GPU-internal BGRA and CPU RGBA. */
if (ctx->in_transfer_blit &&
translate_pe_format_rb_swap(blit_info->src.format)) {
translate_pe_format_rb_swap(blit_info->src.format) &&
!src->shared && !dst->shared) {
bool src_linear = src->layout == ETNA_LAYOUT_LINEAR;
bool dst_linear = dst->layout == ETNA_LAYOUT_LINEAR;

View file

@ -395,6 +395,21 @@ translate_pe_format_rb_swap(enum pipe_format fmt)
return formats[fmt].pe & PE_FORMAT_RB_SWAP;
}
/* For shared resources with RB_SWAP formats, remaps the HW texture format
* back to the one matching the actual byte order in memory (e.g., A8B8G8R8
* for RGBA data). Normally we use A8R8G8B8 to match PE-internal BGRA byte
* order, but shared resources store data in the standard byte order.
*/
uint32_t
remap_texture_format_rb_swap(uint32_t format)
{
switch (format) {
case TEXTURE_FORMAT_A8R8G8B8: return TEXTURE_FORMAT_A8B8G8R8;
case TEXTURE_FORMAT_X8R8G8B8: return TEXTURE_FORMAT_X8B8G8R8;
default: return format;
}
}
enum pipe_format
translate_pe_internal_format(enum pipe_format fmt)
{

View file

@ -56,6 +56,9 @@ translate_pe_format(enum pipe_format fmt);
int
translate_pe_format_rb_swap(enum pipe_format fmt);
uint32_t
remap_texture_format_rb_swap(uint32_t format);
enum pipe_format
translate_pe_internal_format(enum pipe_format fmt);

View file

@ -884,7 +884,8 @@ etna_try_rs_blit(struct pipe_context *pctx,
.downsample_x = downsample_x,
.downsample_y = downsample_y,
.swap_rb = ctx->in_transfer_blit &&
translate_pe_format_rb_swap(blit_info->src.format),
translate_pe_format_rb_swap(blit_info->src.format) &&
!src->shared && !dst->shared,
.dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit?
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED,
.width = width,

View file

@ -137,7 +137,14 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
const struct util_format_description *desc = util_format_description(so->format);
struct etna_sampler_view_desc *sv = CALLOC_STRUCT(etna_sampler_view_desc);
struct etna_context *ctx = etna_context(pctx);
const uint32_t format = translate_texture_format(so->format);
uint32_t format = translate_texture_format(so->format);
/* Shared resources store data in standard byte order (e.g., RGBA for
* R8G8B8A8_UNORM). Use the native texture format to read them correctly,
* bypassing the BGRA-internal optimization used for internal resources. */
if (etna_resource(prsc)->shared && translate_pe_format_rb_swap(so->format))
format = remap_texture_format_rb_swap(format);
const bool ext = !!(format & EXT_FORMAT);
const bool astc = !!(format & ASTC_FORMAT);
const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r,

View file

@ -164,7 +164,14 @@ etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *
struct etna_sampler_view *sv = CALLOC_STRUCT(etna_sampler_view);
struct etna_context *ctx = etna_context(pctx);
struct etna_screen *screen = ctx->screen;
const uint32_t format = translate_texture_format(so->format);
uint32_t format = translate_texture_format(so->format);
/* Shared resources store data in standard byte order (e.g., RGBA for
* R8G8B8A8_UNORM). Use the native texture format to read them correctly,
* bypassing the BGRA-internal optimization used for internal resources. */
if (etna_resource(prsc)->shared && translate_pe_format_rb_swap(so->format))
format = remap_texture_format_rb_swap(format);
const bool ext = !!(format & EXT_FORMAT);
const bool astc = !!(format & ASTC_FORMAT);
const bool srgb = util_format_is_srgb(so->format);

View file

@ -347,7 +347,7 @@ etna_texture_map(struct pipe_context *pctx, struct pipe_resource *prsc,
}
if (rsc->texture && !etna_resource_newer(rsc, etna_resource(rsc->texture)) &&
!translate_pe_format_rb_swap(prsc->format)) {
(!translate_pe_format_rb_swap(prsc->format) || rsc->shared)) {
/* We have a texture resource which is the same age or newer than the
* render resource. Use the texture resource, which avoids bouncing
* pixels between the two resources, and we can de-tile it in s/w. */