mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 00:00:11 +01:00
etnaviv: Add multi-planar YUV support
This enables support for NV12, which are really useful when dealing with hardware video decoders. This patch makes use of the integrated YUV tiler to convert multi-planar to YUYV. The binary blob uses the same method to deal with multi-planar YUV formats. Other formarts will be added in a follow-up patch. Tested with kmscube (nv12-1img) and the following gstreamer pipeline: gst-launch-1.0 filesrc location=/tmp/test.mp4 ! qtdemux ! v4l2slh264dec ! video/x-raw,format=NV12 ! glimagesink Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com> Signed-off-by: Peter Frühberger Signed-off-by: Marek Vasut <marex@denx.de> Acked-by: Daniel Stone <daniels@collabora.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3418>
This commit is contained in:
parent
58f8143da3
commit
042138093f
13 changed files with 199 additions and 1 deletions
|
|
@ -65,6 +65,7 @@ enum etna_feature {
|
|||
ETNA_FEATURE_DEC400,
|
||||
ETNA_FEATURE_VIP_V7,
|
||||
ETNA_FEATURE_NN_XYDP0,
|
||||
ETNA_FEATURE_YUV420_TILER,
|
||||
ETNA_FEATURE_NUM,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ query_features_from_kernel(struct etna_gpu *gpu)
|
|||
ETNA_FEATURE(chipFeatures, DXT_TEXTURE_COMPRESSION);
|
||||
ETNA_FEATURE(chipFeatures, ETC1_TEXTURE_COMPRESSION);
|
||||
ETNA_FEATURE(chipFeatures, NO_EARLY_Z);
|
||||
ETNA_FEATURE(chipFeatures, YUV420_TILER);
|
||||
|
||||
ETNA_FEATURE(chipMinorFeatures0, MC20);
|
||||
ETNA_FEATURE(chipMinorFeatures0, RENDERTARGET_8K);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ etna_query_feature_db(struct etna_core_info *info)
|
|||
ETNA_FEATURE(REG_Halti5, HALTI5);
|
||||
ETNA_FEATURE(REG_RAWriteDepth, RA_WRITE_DEPTH);
|
||||
|
||||
ETNA_FEATURE(REG_YUV420Tiler, YUV420_TILER);
|
||||
|
||||
ETNA_FEATURE(CACHE128B256BPERLINE, CACHE128B256BPERLINE);
|
||||
ETNA_FEATURE(NEW_GPIPE, NEW_GPIPE);
|
||||
ETNA_FEATURE(NO_ASTC, NO_ASTC);
|
||||
|
|
|
|||
|
|
@ -622,6 +622,32 @@ etna_try_blt_blit(struct pipe_context *pctx,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
etna_emit_yuv_tiler_state_blt(struct etna_context *ctx, struct etna_yuv_config *config)
|
||||
{
|
||||
struct etna_cmd_stream *stream = ctx->stream;
|
||||
|
||||
etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000001);
|
||||
etna_set_state(stream, VIVS_BLT_YUV_CONFIG,
|
||||
VIVS_BLT_YUV_CONFIG_SOURCE_FORMAT(config->format) | VIVS_BLT_YUV_CONFIG_ENABLE);
|
||||
etna_set_state(stream, VIVS_BLT_YUV_WINDOW_SIZE,
|
||||
VIVS_BLT_YUV_WINDOW_SIZE_HEIGHT(config->height) |
|
||||
VIVS_BLT_YUV_WINDOW_SIZE_WIDTH(config->width));
|
||||
|
||||
etna_yuv_emit_plane(ctx, config->planes[0], ETNA_PENDING_READ, VIVS_BLT_YUV_SRC_YADDR, VIVS_BLT_YUV_SRC_YSTRIDE);
|
||||
etna_yuv_emit_plane(ctx, config->planes[1], ETNA_PENDING_READ, VIVS_BLT_YUV_SRC_UADDR, VIVS_BLT_YUV_SRC_USTRIDE);
|
||||
etna_yuv_emit_plane(ctx, config->planes[2], ETNA_PENDING_READ, VIVS_BLT_YUV_SRC_VADDR, VIVS_BLT_YUV_SRC_VSTRIDE);
|
||||
etna_yuv_emit_plane(ctx, config->dst, ETNA_PENDING_WRITE, VIVS_BLT_YUV_DEST_ADDR, VIVS_BLT_YUV_DEST_STRIDE);
|
||||
|
||||
/* trigger resolve */
|
||||
etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);
|
||||
etna_set_state(stream, VIVS_BLT_COMMAND, VIVS_BLT_COMMAND_COMMAND_YUV_TILE);
|
||||
etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);
|
||||
etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000000);
|
||||
|
||||
etna_stall(stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_BLT);
|
||||
}
|
||||
|
||||
void
|
||||
etna_clear_blit_blt_init(struct pipe_context *pctx)
|
||||
{
|
||||
|
|
@ -630,4 +656,5 @@ etna_clear_blit_blt_init(struct pipe_context *pctx)
|
|||
DBG("etnaviv: Using BLT blit engine");
|
||||
pctx->clear = etna_clear_blt;
|
||||
ctx->blit = etna_try_blt_blit;
|
||||
ctx->emit_yuv_tiler_state = etna_emit_yuv_tiler_state_blt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "etnaviv_rs.h"
|
||||
#include "etnaviv_surface.h"
|
||||
#include "etnaviv_translate.h"
|
||||
#include "etnaviv_yuv.h"
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
|
@ -111,6 +112,10 @@ etna_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
|
|||
if (ctx->blit(pctx, &info))
|
||||
goto success;
|
||||
|
||||
if (etna_format_needs_yuv_tiler(blit_info->src.format) &&
|
||||
etna_try_yuv_blit(pctx, blit_info))
|
||||
goto success;
|
||||
|
||||
if (util_try_blit_via_copy_region(pctx, &info, false))
|
||||
goto success;
|
||||
|
||||
|
|
@ -210,7 +215,7 @@ etna_copy_resource(struct pipe_context *pctx, struct pipe_resource *dst,
|
|||
struct etna_resource *src_priv = etna_resource(src);
|
||||
struct etna_resource *dst_priv = etna_resource(dst);
|
||||
|
||||
assert(src->format == dst->format);
|
||||
assert(src->format == dst->format || util_format_is_yuv(src->format));
|
||||
assert(src->array_size == dst->array_size);
|
||||
assert(last_level <= dst->last_level && last_level <= src->last_level);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "etnaviv_resource.h"
|
||||
#include "etnaviv_tiling.h"
|
||||
#include "etnaviv_yuv.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/format/u_formats.h"
|
||||
|
|
@ -117,6 +118,8 @@ struct etna_context {
|
|||
struct etna_sampler_ts *(*ts_for_sampler_view)(struct pipe_sampler_view *pview);
|
||||
/* GPU-specific blit implementation */
|
||||
bool (*blit)(struct pipe_context *pipe, const struct pipe_blit_info *info);
|
||||
/* GPU-specific implementation to emit yuv tiler state */
|
||||
void (*emit_yuv_tiler_state)(struct etna_context *ctx, struct etna_yuv_config *config);
|
||||
|
||||
struct etna_screen *screen;
|
||||
struct etna_cmd_stream *stream;
|
||||
|
|
|
|||
|
|
@ -255,6 +255,9 @@ static struct etna_format formats[PIPE_FORMAT_COUNT] = {
|
|||
/* YUV */
|
||||
_T(YUYV, YUY2, YUY2),
|
||||
_T(UYVY, UYVY, NONE),
|
||||
|
||||
/* multi-planar YUV */
|
||||
_T(NV12, YUY2, NONE),
|
||||
};
|
||||
|
||||
uint32_t
|
||||
|
|
|
|||
|
|
@ -904,6 +904,33 @@ manual:
|
|||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
etna_emit_yuv_tiler_state_rs(struct etna_context *ctx, struct etna_yuv_config *config)
|
||||
{
|
||||
struct etna_cmd_stream *stream = ctx->stream;
|
||||
|
||||
etna_set_state(stream, VIVS_YUV_CONFIG,
|
||||
VIVS_YUV_CONFIG_SOURCE_FORMAT(config->format) | VIVS_YUV_CONFIG_ENABLE);
|
||||
etna_set_state(stream, VIVS_YUV_WINDOW_SIZE,
|
||||
VIVS_YUV_WINDOW_SIZE_HEIGHT(config->height) |
|
||||
VIVS_YUV_WINDOW_SIZE_WIDTH(config->width));
|
||||
|
||||
etna_yuv_emit_plane(ctx, config->planes[0], ETNA_PENDING_READ, VIVS_YUV_Y_BASE, VIVS_YUV_Y_STRIDE);
|
||||
etna_yuv_emit_plane(ctx, config->planes[1], ETNA_PENDING_READ, VIVS_YUV_U_BASE, VIVS_YUV_U_STRIDE);
|
||||
etna_yuv_emit_plane(ctx, config->planes[2], ETNA_PENDING_READ, VIVS_YUV_V_BASE, VIVS_YUV_V_STRIDE);
|
||||
etna_yuv_emit_plane(ctx, config->dst, ETNA_PENDING_WRITE, VIVS_YUV_DEST_BASE, VIVS_YUV_DEST_STRIDE);
|
||||
|
||||
/* configure RS */
|
||||
etna_set_state(stream, VIVS_RS_SOURCE_STRIDE, 0);
|
||||
etna_set_state(stream, VIVS_RS_CLEAR_CONTROL, 0);
|
||||
|
||||
/* trigger resolve */
|
||||
etna_set_state(stream, VIVS_RS_KICKER, 0xbadabeeb);
|
||||
|
||||
/* disable yuv tiller */
|
||||
etna_set_state(stream, VIVS_YUV_CONFIG, 0x0);
|
||||
}
|
||||
|
||||
void
|
||||
etna_align_box_for_rs(const struct etna_screen *screen,
|
||||
const struct etna_resource *rsc,
|
||||
|
|
@ -929,4 +956,5 @@ etna_clear_blit_rs_init(struct pipe_context *pctx)
|
|||
DBG("etnaviv: Using RS blit engine");
|
||||
pctx->clear = etna_clear_rs;
|
||||
ctx->blit = etna_try_rs_blit;
|
||||
ctx->emit_yuv_tiler_state = etna_emit_yuv_tiler_state_rs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "etnaviv_query.h"
|
||||
#include "etnaviv_resource.h"
|
||||
#include "etnaviv_translate.h"
|
||||
#include "etnaviv_yuv.h"
|
||||
|
||||
#include "util/hash_table.h"
|
||||
#include "util/os_time.h"
|
||||
|
|
@ -407,6 +408,9 @@ gpu_supports_texture_format(struct etna_screen *screen, uint32_t fmt,
|
|||
supported = VIV_FEATURE(screen, ETNA_FEATURE_HALTI2);
|
||||
|
||||
|
||||
if (etna_format_needs_yuv_tiler(format))
|
||||
supported = VIV_FEATURE(screen, ETNA_FEATURE_YUV420_TILER);
|
||||
|
||||
if (!supported)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "etnaviv_texture_desc.h"
|
||||
#include "etnaviv_texture_state.h"
|
||||
#include "etnaviv_translate.h"
|
||||
#include "etnaviv_yuv.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
|
|
@ -203,6 +204,9 @@ etna_update_sampler_source(struct pipe_sampler_view *view, int num)
|
|||
static bool
|
||||
etna_resource_sampler_compatible(struct etna_resource *res)
|
||||
{
|
||||
if (etna_format_needs_yuv_tiler(res->base.format))
|
||||
return false;
|
||||
|
||||
if (util_format_is_compressed(res->base.format))
|
||||
return true;
|
||||
|
||||
|
|
@ -243,6 +247,12 @@ etna_texture_handle_incompatible(struct pipe_context *pctx, struct pipe_resource
|
|||
|
||||
templat.bind &= ~(PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
|
||||
PIPE_BIND_BLENDABLE);
|
||||
|
||||
if (util_format_is_yuv(prsc->format)) {
|
||||
templat.format = PIPE_FORMAT_YUYV;
|
||||
templat.next = NULL;
|
||||
}
|
||||
|
||||
res->texture =
|
||||
etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED,
|
||||
DRM_FORMAT_MOD_LINEAR, &templat);
|
||||
|
|
|
|||
76
src/gallium/drivers/etnaviv/etnaviv_yuv.c
Normal file
76
src/gallium/drivers/etnaviv/etnaviv_yuv.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2024 Igalia, S.L.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "etnaviv_context.h"
|
||||
#include "etnaviv_emit.h"
|
||||
#include "etnaviv_yuv.h"
|
||||
|
||||
void
|
||||
etna_yuv_emit_plane(struct etna_context *ctx, struct etna_resource *plane,
|
||||
enum etna_resource_status status, uint32_t base, uint32_t stride)
|
||||
{
|
||||
if (!plane)
|
||||
return;
|
||||
|
||||
uint32_t flags = (status == ETNA_PENDING_WRITE) ? ETNA_RELOC_WRITE : ETNA_RELOC_READ;
|
||||
|
||||
etna_resource_used(ctx, &plane->base, status);
|
||||
etna_set_state_reloc(ctx->stream, base, &(struct etna_reloc) {
|
||||
.bo = plane->bo,
|
||||
.offset = plane->levels[0].offset,
|
||||
.flags = flags,
|
||||
});
|
||||
etna_set_state(ctx->stream, stride, plane->levels[0].stride);
|
||||
}
|
||||
|
||||
bool
|
||||
etna_try_yuv_blit(struct pipe_context *pctx,
|
||||
const struct pipe_blit_info *blit_info)
|
||||
{
|
||||
struct etna_context *ctx = etna_context(pctx);
|
||||
struct etna_cmd_stream *stream = ctx->stream;
|
||||
struct pipe_resource *src = blit_info->src.resource;
|
||||
struct etna_yuv_config config = { 0 };
|
||||
ASSERTED unsigned num_planes;
|
||||
int idx = 0;
|
||||
|
||||
assert(util_format_is_yuv(blit_info->src.format));
|
||||
assert(blit_info->dst.format == PIPE_FORMAT_YUYV);
|
||||
assert(blit_info->src.level == 0);
|
||||
assert(blit_info->dst.level == 0);
|
||||
|
||||
config.dst = etna_resource(blit_info->dst.resource);
|
||||
config.height = blit_info->dst.box.height;
|
||||
config.width = blit_info->dst.box.width;
|
||||
|
||||
switch (blit_info->src.format) {
|
||||
case PIPE_FORMAT_NV12:
|
||||
config.format = 0x1;
|
||||
num_planes = 2;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
while (src) {
|
||||
config.planes[idx++] = etna_resource(src);
|
||||
src = src->next;
|
||||
}
|
||||
|
||||
assert(idx == num_planes);
|
||||
|
||||
etna_set_state(stream, VIVS_GL_FLUSH_CACHE,
|
||||
VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH);
|
||||
etna_stall(stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
|
||||
|
||||
etna_set_state(stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);
|
||||
etna_set_state(stream, VIVS_TS_MEM_CONFIG, 0);
|
||||
|
||||
ctx->emit_yuv_tiler_state(ctx, &config);
|
||||
|
||||
ctx->dirty |= ETNA_DIRTY_TS;
|
||||
|
||||
return true;
|
||||
}
|
||||
36
src/gallium/drivers/etnaviv/etnaviv_yuv.h
Normal file
36
src/gallium/drivers/etnaviv/etnaviv_yuv.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2024 Igalia, S.L.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef H_ETNA_YUV
|
||||
#define H_ETNA_YUV
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "etnaviv_context.h"
|
||||
|
||||
struct etna_yuv_config {
|
||||
struct etna_resource *planes[3];
|
||||
struct etna_resource *dst;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t format;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
etna_format_needs_yuv_tiler(enum pipe_format format)
|
||||
{
|
||||
return format == PIPE_FORMAT_NV12;
|
||||
}
|
||||
|
||||
void
|
||||
etna_yuv_emit_plane(struct etna_context *ctx, struct etna_resource *plane,
|
||||
enum etna_resource_status status, uint32_t base, uint32_t stride);
|
||||
|
||||
bool
|
||||
etna_try_yuv_blit(struct pipe_context *pctx,
|
||||
const struct pipe_blit_info *blit_info);
|
||||
|
||||
#endif
|
||||
|
|
@ -83,6 +83,8 @@ files_etnaviv = files(
|
|||
'etnaviv_uniforms.c',
|
||||
'etnaviv_uniforms.h',
|
||||
'etnaviv_util.h',
|
||||
'etnaviv_yuv.c',
|
||||
'etnaviv_yuv.h',
|
||||
'etnaviv_zsa.c',
|
||||
'etnaviv_zsa.h',
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue