[PATCH 07/11] etnaviv: implement resource import with modifier

Lucas Stach l.stach at pengutronix.de
Fri Jun 23 15:50:24 UTC 2017


This implements resource import with modifier, deriving the correct
internal layout from the modifier and constructing a render compatible
base resource if needed.

This removes the special cases for DDX and renderonly scanout allocated
buffers, as the linear modifier is enough to trigger correct handling
of those buffers.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 src/gallium/drivers/etnaviv/etnaviv_resource.c | 112 +++++++++++++++++--------
 1 file changed, 78 insertions(+), 34 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index 43f63f8908a0..f006d24a1bba 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -36,6 +36,29 @@
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 
+#include <drm_fourcc.h>
+
+#ifndef DRM_FORMAT_MOD_INVALID
+#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
+#endif
+
+static unsigned int modifier_to_layout(uint64_t modifier)
+{
+   switch (modifier) {
+   case DRM_FORMAT_MOD_VIVANTE_TILED:
+      return ETNA_LAYOUT_TILED;
+   case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
+      return ETNA_LAYOUT_SUPER_TILED;
+   case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
+      return ETNA_LAYOUT_MULTI_TILED;
+   case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
+      return ETNA_LAYOUT_MULTI_SUPERTILED;
+   case DRM_FORMAT_MOD_LINEAR:
+   default:
+      return ETNA_LAYOUT_LINEAR;
+   }
+}
+
 /* A tile is 4x4 pixels, having 'screen->specs.bits_per_tile' of tile status.
  * So, in a buffer of N pixels, there are N / (4 * 4) tiles.
  * We need N * screen->specs.bits_per_tile / (4 * 4) bits of tile status, or
@@ -141,6 +164,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
                     const struct pipe_resource *templat)
 {
    struct etna_screen *screen = etna_screen(pscreen);
+   struct etna_resource *rsc;
    unsigned size;
 
    DBG_F(ETNA_DBG_RESOURCE_MSGS,
@@ -186,8 +210,36 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
          paddingY = min_paddingY;
    }
 
-   struct etna_resource *rsc = CALLOC_STRUCT(etna_resource);
+   if (templat->bind & PIPE_BIND_SCANOUT) {
+      struct pipe_resource scanout_templat = *templat;
+      struct renderonly_scanout *scanout;
+      struct winsys_handle handle;
+      unsigned padX, padY;
 
+      /* pad scanout buffer size to be compatible with the RS */
+      padX = ETNA_RS_WIDTH_MASK + 1;
+      padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
+      scanout_templat.width0 = align(scanout_templat.width0, padX);
+      scanout_templat.height0 = align(scanout_templat.height0, padY);
+
+      scanout = renderonly_scanout_for_resource(&scanout_templat,
+                                                screen->ro, &handle);
+      if (!scanout)
+         return NULL;
+
+      rsc = etna_resource(pscreen->resource_from_handle(pscreen, templat,
+                                                        &handle,
+                                                        PIPE_HANDLE_USAGE_WRITE));
+      close(handle.handle);
+      if (!rsc)
+         return NULL;
+
+      rsc->scanout = scanout;
+
+      return &rsc->base;
+   }
+
+   rsc = CALLOC_STRUCT(etna_resource);
    if (!rsc)
       return NULL;
 
@@ -214,30 +266,6 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
    rsc->bo = bo;
    rsc->ts_bo = 0; /* TS is only created when first bound to surface */
 
-   if (templat->bind & PIPE_BIND_SCANOUT) {
-      struct pipe_resource scanout_templat = *templat;
-      struct winsys_handle handle;
-      unsigned padX, padY;
-
-      /* pad scanout buffer size to be compatible with the RS */
-      padX = ETNA_RS_WIDTH_MASK + 1;
-      padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
-      scanout_templat.width0 = align(scanout_templat.width0, padX);
-      scanout_templat.height0 = align(scanout_templat.height0, padY);
-
-      rsc->scanout = renderonly_scanout_for_resource(&scanout_templat,
-                                                     screen->ro, &handle);
-      if (!rsc->scanout)
-         goto free_rsc;
-
-      rsc->external = pscreen->resource_from_handle(pscreen, &rsc->base,
-                                                    &handle,
-                                                    PIPE_HANDLE_USAGE_WRITE);
-      close(handle.handle);
-      if (!rsc->external)
-         goto free_rsc;
-   }
-
    if (DBG_ENABLED(ETNA_DBG_ZERO)) {
       void *map = etna_bo_map(bo);
       memset(map, 0, size);
@@ -370,14 +398,21 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
       goto fail;
 
    rsc->seqno = 1;
+   rsc->layout = modifier_to_layout(handle->modifier);
+   rsc->halign = TEXTURE_HALIGN_FOUR;
+
 
    level->width = tmpl->width0;
    level->height = tmpl->height0;
 
-   /* We will be using the RS to copy with this resource, so we must
-    * ensure that it is appropriately aligned for the RS requirements. */
-   unsigned paddingX = ETNA_RS_WIDTH_MASK + 1;
-   unsigned paddingY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
+   /* Determine padding of the imported resource. */
+   unsigned paddingX = 0, paddingY = 0;
+   etna_layout_multiple(rsc->layout, screen->specs.pixel_pipes,
+                        VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN),
+                        &paddingX, &paddingY, &rsc->halign);
+
+   if (paddingY < 4 * screen->specs.pixel_pipes)
+      paddingY = 4 * screen->specs.pixel_pipes;
 
    level->padded_width = align(level->width, paddingX);
    level->padded_height = align(level->height, paddingY);
@@ -396,12 +431,21 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
       goto fail;
    }
 
-   if (handle->type == DRM_API_HANDLE_TYPE_SHARED && tmpl->bind & PIPE_BIND_RENDER_TARGET) {
-      /* Render targets are linear in Xorg but must be tiled
-      * here. It would be nice if dri_drawable_get_format()
-      * set scanout for these buffers too. */
+   if (rsc->layout == ETNA_LAYOUT_LINEAR) {
+      /*
+       * Both sampler and pixel pipes can't handle linear, create a compatible
+       * base resource, where we can attach the imported buffer as an external
+       * resource.
+       */
+      struct pipe_resource tiled_templat = *tmpl;
+
+      /*
+       * Remove BIND_SCANOUT to avoid recursion, as etna_resource_create uses
+       * this function to import the scanout buffer and get a tiled resource.
+       */
+      tiled_templat.bind &= ~PIPE_BIND_SCANOUT;
 
-      ptiled = etna_resource_create(pscreen, tmpl);
+      ptiled = etna_resource_create(pscreen, &tiled_templat);
       if (!ptiled)
          goto fail;
 
-- 
2.11.0



More information about the etnaviv mailing list