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). Signed-off-by: Christian Gmeiner <christian.gmei...@gmail.com> --- .../drivers/etnaviv/etnaviv_clear_blit.c | 2 +- src/gallium/drivers/etnaviv/etnaviv_format.c | 3 + src/gallium/drivers/etnaviv/etnaviv_rs.c | 5 + src/gallium/drivers/etnaviv/etnaviv_screen.c | 4 + src/gallium/drivers/etnaviv/etnaviv_texture.c | 8 ++ src/gallium/drivers/etnaviv/etnaviv_yuv.c | 123 ++++++++++++++++++ src/gallium/drivers/etnaviv/etnaviv_yuv.h | 44 +++++++ src/gallium/drivers/etnaviv/meson.build | 2 + 8 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/gallium/drivers/etnaviv/etnaviv_yuv.c create mode 100644 src/gallium/drivers/etnaviv/etnaviv_yuv.h diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index 45c30cbf507..5214162d879 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -159,7 +159,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); diff --git a/src/gallium/drivers/etnaviv/etnaviv_format.c b/src/gallium/drivers/etnaviv/etnaviv_format.c index 7633274e3c2..3b1174e6521 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_format.c +++ b/src/gallium/drivers/etnaviv/etnaviv_format.c @@ -284,6 +284,9 @@ static struct etna_format formats[PIPE_FORMAT_COUNT] = { /* YUV */ _T(YUYV, YUY2, SWIZ(X, Y, Z, W), YUY2, NONE), _T(UYVY, UYVY, SWIZ(X, Y, Z, W), YUY2, NONE), + + /* multi-planar YUV */ + _T(NV12, YUY2, SWIZ(X, Y, Z, W), NONE, NONE), }; uint32_t diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index a9d3872ad41..6e64586ed0b 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -36,6 +36,7 @@ #include "etnaviv_tiling.h" #include "etnaviv_translate.h" #include "etnaviv_util.h" +#include "etnaviv_yuv.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" @@ -775,6 +776,10 @@ etna_blit_rs(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) return; } + if (etna_format_needs_yuv_tiler(blit_info->src.format) && + etna_try_yuv_blit(pctx, blit_info)) + return; + if (etna_try_rs_blit(pctx, blit_info)) return; diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index 62b6f1c80fa..00fa31f8d33 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -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" @@ -529,6 +530,9 @@ gpu_supports_texure_format(struct etna_screen *screen, uint32_t fmt, supported = screen->specs.tex_astc; } + if (etna_format_needs_yuv_tiler(format)) + supported = VIV_FEATURE(screen, chipFeatures, YUV420_TILER); + if (!supported) return false; diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c index c4d53324054..99ca1f53f53 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_texture.c +++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c @@ -34,6 +34,7 @@ #include "etnaviv_format.h" #include "etnaviv_texture_state.h" #include "etnaviv_translate.h" +#include "etnaviv_yuv.h" #include "util/u_inlines.h" #include "util/u_memory.h" @@ -164,6 +165,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; @@ -203,6 +207,10 @@ 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; + res->texture = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED, ETNA_ADDRESSING_MODE_TILED, diff --git a/src/gallium/drivers/etnaviv/etnaviv_yuv.c b/src/gallium/drivers/etnaviv/etnaviv_yuv.c new file mode 100644 index 00000000000..55750f836c9 --- /dev/null +++ b/src/gallium/drivers/etnaviv/etnaviv_yuv.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2019 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Christian Gmeiner <christian.gmei...@gmail.com> + */ + +#include "etnaviv_context.h" +#include "etnaviv_emit.h" +#include "etnaviv_yuv.h" +#include "util/u_format.h" + +bool +etna_format_needs_yuv_tiler(enum pipe_format format) +{ + bool needs_tiler; + + switch (format) { + case PIPE_FORMAT_NV12: + needs_tiler = true; + break; + + default: + needs_tiler = false; + break; + } + + return needs_tiler; +} + +static void +emit_plane(struct etna_context *ctx, struct etna_resource *plane, + enum etna_resource_status status, uint32_t base, uint32_t stride) +{ + if (!plane) + return; + + 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 = ETNA_RELOC_READ, + }); + 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_resource *dst = etna_resource(blit_info->dst.resource); + struct etna_resource *planes[3] = { 0 }; + int idx = 0; + unsigned num_planes; + uint32_t format; + + 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); + + switch (blit_info->src.format) { + case PIPE_FORMAT_NV12: + format = 0x1; + num_planes = 2; + break; + default: + return false; + } + + while (src) { + planes[idx++] = etna_resource(src); + src = src->next; + } + + assert(idx == num_planes); + + etna_set_state(stream, VIVS_YUV_CONFIG, + VIVS_YUV_CONFIG_SOURCE_FORMAT(format) | VIVS_YUV_CONFIG_ENABLE); + etna_set_state(stream, VIVS_YUV_WINDOW_SIZE, + VIVS_YUV_WINDOW_SIZE_HEIGHT(blit_info->dst.box.height) | + VIVS_YUV_WINDOW_SIZE_WIDTH(blit_info->dst.box.width)); + + emit_plane(ctx, planes[0], ETNA_PENDING_READ, VIVS_YUV_Y_BASE, VIVS_YUV_Y_STRIDE); + emit_plane(ctx, planes[1], ETNA_PENDING_READ, VIVS_YUV_U_BASE, VIVS_YUV_U_STRIDE); + emit_plane(ctx, planes[2], ETNA_PENDING_READ, VIVS_YUV_V_BASE, VIVS_YUV_V_STRIDE); + emit_plane(ctx, 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); + + return true; +} diff --git a/src/gallium/drivers/etnaviv/etnaviv_yuv.h b/src/gallium/drivers/etnaviv/etnaviv_yuv.h new file mode 100644 index 00000000000..e68d6756c82 --- /dev/null +++ b/src/gallium/drivers/etnaviv/etnaviv_yuv.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Christian Gmeiner <christian.gmei...@gmail.com> + */ + +#ifndef H_ETNA_YUV +#define H_ETNA_YUV + +#include <stdbool.h> + +#include "pipe/p_format.h" + +struct pipe_context; +struct pipe_blit_info; + +bool +etna_format_needs_yuv_tiler(enum pipe_format format); + +bool +etna_try_yuv_blit(struct pipe_context *pctx, + const struct pipe_blit_info *blit_info); + +#endif diff --git a/src/gallium/drivers/etnaviv/meson.build b/src/gallium/drivers/etnaviv/meson.build index 75ed93eccc7..3051115000e 100644 --- a/src/gallium/drivers/etnaviv/meson.build +++ b/src/gallium/drivers/etnaviv/meson.build @@ -85,6 +85,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', ) -- 2.20.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev