[PATCH 8/8] etnaviv: handle YUV textures with the 2D GPU

Lucas Stach l.stach at pengutronix.de
Fri Apr 12 17:38:20 UTC 2019


This allows color space conversion and tiling in a single step, as
well as handling multi-planar formats like NV12, which are really
useful when dealing with hardware video decoders.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 .../drivers/etnaviv/etnaviv_clear_blit.c      |  2 +-
 src/gallium/drivers/etnaviv/etnaviv_format.c  |  5 +++-
 .../drivers/etnaviv/etnaviv_resource.c        | 16 ++++++++----
 src/gallium/drivers/etnaviv/etnaviv_rs.c      |  5 ++++
 src/gallium/drivers/etnaviv/etnaviv_screen.c  |  5 +++-
 src/gallium/drivers/etnaviv/etnaviv_texture.c | 25 ++++++++++++++++---
 6 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
index 45c30cbf5076..5214162d8798 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 29e81c4a8b04..0879ddd6a6c8 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_format.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_format.c
@@ -282,8 +282,11 @@ static struct etna_format formats[PIPE_FORMAT_COUNT] = {
    _T(ASTC_12x12_SRGB, ASTC_SRGB8_ALPHA8_12x12 | ASTC_FORMAT,          SWIZ(X, Y, Z, W), NONE, NONE),
 
    /* YUV */
-   _T(YUYV, YUY2, SWIZ(X, Y, Z, W), YUY2, NONE),
+   _T(YUYV, X8B8G8R8, SWIZ(X, Y, Z, W), NONE, NONE),
    _T(UYVY, UYVY, SWIZ(X, Y, Z, W), NONE, NONE),
+
+   /* multi-planar YUV */
+   _T(NV12, X8B8G8R8, SWIZ(X, Y, Z, W), NONE, NONE),
 };
 
 uint32_t
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index 650c8e7eb7f5..5ba3eba5bd33 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -560,6 +560,17 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
                                                                   level->padded_height);
    level->size = level->layer_stride;
 
+   rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer,
+                                       _mesa_key_pointer_equal);
+   if (!rsc->pending_ctx)
+      goto fail;
+
+   /* YUV resources are handled by the 2D GPU, so the below constraint checks
+    * are invalid.
+    */
+   if (util_format_is_yuv(tmpl->format))
+      return prsc;
+
    /* The DDX must give us a BO which conforms to our padding size.
     * The stride of the BO must be greater or equal to our padded
     * stride. The size of the BO must accomodate the padded height. */
@@ -576,11 +587,6 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
       goto fail;
    }
 
-   rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer,
-                                       _mesa_key_pointer_equal);
-   if (!rsc->pending_ctx)
-      goto fail;
-
    if (rsc->layout == ETNA_LAYOUT_LINEAR) {
       /*
        * Both sampler and pixel pipes can't handle linear, create a compatible
diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c
index fcc2342aedc3..22d07d8f9726 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_rs.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c
@@ -26,6 +26,7 @@
 
 #include "etnaviv_rs.h"
 
+#include "etnaviv_2d.h"
 #include "etnaviv_clear_blit.h"
 #include "etnaviv_context.h"
 #include "etnaviv_emit.h"
@@ -775,6 +776,10 @@ etna_blit_rs(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
       return;
    }
 
+   if (util_format_is_yuv(blit_info->src.format) &&
+       etna_try_2d_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 0dea6056c75a..b0630e27b507 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
@@ -535,6 +535,9 @@ gpu_supports_texure_format(struct etna_screen *screen, uint32_t fmt,
       supported = screen->specs.tex_astc;
    }
 
+   if (util_format_is_yuv(format))
+      supported = !!screen->gpu2d;
+
    if (!supported)
       return false;
 
@@ -658,7 +661,7 @@ etna_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
       if (modifiers)
          modifiers[num_modifiers] = supported_modifiers[i];
       if (external_only)
-         external_only[num_modifiers] = util_format_is_yuv(format) ? 1 : 0;
+         external_only[num_modifiers] = 0;
       num_modifiers++;
    }
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c
index c4d533240547..16c3314a1df0 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c
@@ -164,6 +164,9 @@ etna_update_sampler_source(struct pipe_sampler_view *view, int num)
 static bool
 etna_resource_sampler_compatible(struct etna_resource *res)
 {
+   if (util_format_is_yuv(res->base.format))
+      return false;
+
    if (util_format_is_compressed(res->base.format))
       return true;
 
@@ -194,19 +197,33 @@ etna_resource_sampler_compatible(struct etna_resource *res)
 struct etna_resource *
 etna_texture_handle_incompatible(struct pipe_context *pctx, struct pipe_resource *prsc)
 {
+   struct etna_screen *screen = etna_screen(pctx->screen);
    struct etna_resource *res = etna_resource(prsc);
+
    if (!etna_resource_sampler_compatible(res)) {
       /* The original resource is not compatible with the sampler.
        * Allocate an appropriately tiled texture. */
       if (!res->texture) {
          struct pipe_resource templat = *prsc;
+         unsigned int layout = ETNA_LAYOUT_TILED;
+         enum etna_resource_addressing_mode mode = ETNA_ADDRESSING_MODE_TILED;
 
          templat.bind &= ~(PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
                            PIPE_BIND_BLENDABLE);
-         res->texture =
-            etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED,
-                                ETNA_ADDRESSING_MODE_TILED,
-                                DRM_FORMAT_MOD_LINEAR, &templat);
+
+         if (util_format_is_yuv(prsc->format)) {
+            templat.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+            /* If the 2D GPU does not support tiling the blit destination
+               prefer a linear texture to avoid a double blit when possible. */
+            if (!VIV_2D_FEATURE(screen, chipMinorFeatures2, 2D_TILING) &&
+                VIV_FEATURE(screen, chipMinorFeatures1, LINEAR_TEXTURE_SUPPORT)) {
+               layout = ETNA_LAYOUT_LINEAR;
+               mode = ETNA_ADDRESSING_MODE_LINEAR;
+            }
+         }
+
+         res->texture = etna_resource_alloc(pctx->screen, layout, mode,
+                                            DRM_FORMAT_MOD_LINEAR, &templat);
       }
 
       if (!res->texture) {
-- 
2.20.1



More information about the etnaviv mailing list