[Mesa-dev] [PATCH 2/3] panfrost: Allocate scanout BOs in panfrost device

Tomeu Vizoso tomeu.vizoso at collabora.com
Thu Jul 4 08:04:42 UTC 2019


In preparation for using AFBC for BOs that could be scanned out (though
they are likely to be only shared with the compositor for now), use the
buffer allocation UABI of the GPU driver, as dumb buffers cannot be
allocated for AFBC.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
---
 src/gallium/drivers/panfrost/pan_resource.c   | 71 +++++++++----------
 .../winsys/kmsro/drm/kmsro_drm_winsys.c       |  2 +-
 2 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c
index beef26a5ded0..54497d3de2bb 100644
--- a/src/gallium/drivers/panfrost/pan_resource.c
+++ b/src/gallium/drivers/panfrost/pan_resource.c
@@ -47,6 +47,13 @@
 #include "pan_util.h"
 #include "pan_tiling.h"
 
+static void
+panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size);
+
+static void
+panfrost_resource_destroy(struct pipe_screen *screen,
+                          struct pipe_resource *pt);
+
 static uint32_t
 u32_hash(const void *key)
 {
@@ -83,8 +90,12 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
         prsc->screen = pscreen;
 
 	rsc->bo = panfrost_drm_import_bo(screen, whandle->handle);
-	rsc->slices[0].stride = whandle->stride;
-	rsc->slices[0].initialized = true;
+
+        size_t bo_size;
+        panfrost_setup_slices(rsc, &bo_size);
+        assert(bo_size == rsc->bo->size);
+        for (unsigned l = 0; l <= rsc->base.last_level; ++l)
+                rsc->slices[l].initialized = true;
 
 	if (screen->ro) {
 		rsc->scanout =
@@ -198,37 +209,6 @@ panfrost_surface_destroy(struct pipe_context *pipe,
         ralloc_free(surf);
 }
 
-static struct pipe_resource *
-panfrost_create_scanout_res(struct pipe_screen *screen,
-                            const struct pipe_resource *template)
-{
-        struct panfrost_screen *pscreen = pan_screen(screen);
-        struct pipe_resource scanout_templat = *template;
-        struct renderonly_scanout *scanout;
-        struct winsys_handle handle;
-        struct pipe_resource *res;
-
-        scanout = renderonly_scanout_for_resource(&scanout_templat,
-                                                  pscreen->ro, &handle);
-        if (!scanout)
-                return NULL;
-
-        assert(handle.type == WINSYS_HANDLE_TYPE_FD);
-        /* TODO: handle modifiers? */
-        res = screen->resource_from_handle(screen, template, &handle,
-                                           PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
-        close(handle.handle);
-        if (!res)
-                return NULL;
-
-        struct panfrost_resource *pres = pan_resource(res);
-
-        pres->scanout = scanout;
-        pscreen->display_target = pres;
-
-        return res;
-}
-
 /* Computes sizes for checksumming, which is 8 bytes per 16x16 tile */
 
 #define CHECKSUM_TILE_WIDTH 16
@@ -382,11 +362,14 @@ panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_reso
 
         /* Tiling textures is almost always faster, unless we only use it once */
 
+#define SCANOUT (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET)
+
+        bool is_scanout = (res->bind & SCANOUT);
         bool is_texture = (res->bind & PIPE_BIND_SAMPLER_VIEW);
         bool is_2d = res->depth0 == 1 && res->array_size == 1;
-        bool is_streaming = (res->usage != PIPE_USAGE_STREAM);
+        bool is_streaming = (res->usage == PIPE_USAGE_STREAM);
 
-        bool should_tile = is_streaming && is_texture && is_2d;
+        bool should_tile = !is_streaming && is_texture && is_2d && !is_scanout;
 
         /* Depth/stencil can't be tiled, only linear or AFBC */
         should_tile &= !(res->bind & PIPE_BIND_DEPTH_STENCIL);
@@ -425,10 +408,6 @@ panfrost_resource_create(struct pipe_screen *screen,
                         assert(0);
         }
 
-        if (template->bind &
-            (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED))
-                return panfrost_create_scanout_res(screen, template);
-
         struct panfrost_resource *so = rzalloc(screen, struct panfrost_resource);
         struct panfrost_screen *pscreen = (struct panfrost_screen *) screen;
 
@@ -440,6 +419,20 @@ panfrost_resource_create(struct pipe_screen *screen,
         util_range_init(&so->valid_buffer_range);
 
         panfrost_resource_create_bo(pscreen, so);
+
+        /* Set up the "scanout resource" (the dmabuf export of our buffer to
+         * the KMS handle) if the buffer might ever have
+         * resource_get_handle(WINSYS_HANDLE_TYPE_KMS) called on it.
+         */
+        if (template->bind & PIPE_BIND_SCANOUT) {
+                so->scanout =
+                        renderonly_scanout_for_resource(&so->base, pscreen->ro, NULL);
+                if (!so->scanout) {
+                        panfrost_resource_destroy(screen, &so->base);
+                        return NULL;
+                }
+        }
+
         return (struct pipe_resource *)so;
 }
 
diff --git a/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c b/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c
index bf599a1497c9..5b316a2b1f37 100644
--- a/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c
+++ b/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c
@@ -90,7 +90,7 @@ struct pipe_screen *kmsro_drm_screen_create(int fd,
    ro.gpu_fd = drmOpenWithType("panfrost", NULL, DRM_NODE_RENDER);
 
    if (ro.gpu_fd >= 0) {
-      ro.create_for_resource = renderonly_create_kms_dumb_buffer_for_resource,
+      ro.create_for_resource = renderonly_create_gpu_import_for_resource,
       screen = panfrost_drm_screen_create_renderonly(&ro);
       if (!screen)
          close(ro.gpu_fd);
-- 
2.20.1



More information about the mesa-dev mailing list