[2/3] panfrost: Allocate scanout BOs in panfrost device

Submitted by Tomeu Vizoso on July 4, 2019, 8:04 a.m.

Details

Message ID 20190704080443.4153-2-tomeu.vizoso@collabora.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Tomeu Vizoso July 4, 2019, 8:04 a.m.
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@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(-)

Patch hide | download patch | download mbox

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);

Comments

On Thu,  4 Jul 2019 10:04:42 +0200
Tomeu Vizoso <tomeu.vizoso@collabora.com> wrote:

> @@ -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) {

That's probably intentional but I thought I'd mention it just to be
sure this is what you intend to do: the scanout obj is now only created
when PIPE_BIND_SCANOUT is set while it was previously created for
PIPE_BIND_SHARED and PIPE_BIND_DISPLAY_TARGET too.

> +                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);

On Fri, 5 Jul 2019 at 14:38, Alyssa Rosenzweig
<alyssa.rosenzweig@collabora.com> wrote:
> > +        bool should_tile = !is_streaming && is_texture && is_2d && !is_scanout;
>
> I'm not opposed, but why can't we tile PIPE_BIND_SHARED textures? lima
> does exactly that. If we can't tile them, we certainly can't AFBC them.

We can't tile USE_SHARED unless it's explicitly listed in the modifiers.

If we don't have modifiers, then USE_SHARED means we'd be sending it
to a different process or subsystem (KMS, V4L, whatever) which isn't
going to know that it's tiled, because we aren't using modifiers to
tell it.

Cheers,
Daniel