[PATCH 6/6] etnaviv: add multi-planar YUV support

Christian Gmeiner christian.gmeiner at gmail.com
Wed Apr 24 06:36:23 UTC 2019


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.gmeiner at 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.gmeiner at 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.gmeiner at 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



More information about the etnaviv mailing list