freedreno: add renderonly scanout
authorJonathan Marek <jonathan@marek.ca>
Wed, 16 Jan 2019 15:22:53 +0000 (10:22 -0500)
committerRob Clark <robdclark@gmail.com>
Sat, 26 Jan 2019 15:47:21 +0000 (10:47 -0500)
This allows creating a fd_screen with a renderonly object which will be
used to allocated scanout resources.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
Reviewed-by: Eric Anholt <eric@anholt.net>
[slight tweak to fix uninitialized 'prsc' in debug print]
Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/auxiliary/target-helpers/drm_helper.h
src/gallium/drivers/freedreno/freedreno_resource.c
src/gallium/drivers/freedreno/freedreno_resource.h
src/gallium/drivers/freedreno/freedreno_screen.c
src/gallium/drivers/freedreno/freedreno_screen.h
src/gallium/targets/pipe-loader/pipe_msm.c
src/gallium/winsys/freedreno/drm/freedreno_drm_public.h
src/gallium/winsys/freedreno/drm/freedreno_drm_winsys.c

index 7eefa6e..bb5c579 100644 (file)
@@ -248,7 +248,7 @@ pipe_freedreno_create_screen(int fd, const struct pipe_screen_config *config)
 {
    struct pipe_screen *screen;
 
-   screen = fd_drm_screen_create(fd);
+   screen = fd_drm_screen_create(fd, NULL);
    return screen ? debug_screen_wrap(screen) : NULL;
 }
 
index ca48fc9..11319a4 100644 (file)
@@ -663,6 +663,9 @@ fd_resource_destroy(struct pipe_screen *pscreen,
        fd_bc_invalidate_resource(rsc, true);
        if (rsc->bo)
                fd_bo_del(rsc->bo);
+       if (rsc->scanout)
+               renderonly_scanout_destroy(rsc->scanout, fd_screen(pscreen)->ro);
+
        util_range_destroy(&rsc->valid_buffer_range);
        FREE(rsc);
 }
@@ -688,7 +691,7 @@ fd_resource_get_handle(struct pipe_screen *pscreen,
 
        handle->modifier = fd_resource_modifier(rsc);
 
-       return fd_screen_bo_get_handle(pscreen, rsc->bo,
+       return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->scanout,
                        rsc->slices[0].pitch * rsc->cpp, handle);
 }
 
@@ -845,11 +848,37 @@ fd_resource_create_with_modifiers(struct pipe_screen *pscreen,
                const uint64_t *modifiers, int count)
 {
        struct fd_screen *screen = fd_screen(pscreen);
-       struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
-       struct pipe_resource *prsc = &rsc->base;
+       struct fd_resource *rsc;
+       struct pipe_resource *prsc;
        enum pipe_format format = tmpl->format;
        uint32_t size;
 
+       if (screen->ro && (tmpl->bind & PIPE_BIND_SCANOUT)) {
+               struct pipe_resource scanout_templat = *tmpl;
+               struct renderonly_scanout *scanout;
+               struct winsys_handle handle;
+
+               scanout = renderonly_scanout_for_resource(&scanout_templat,
+                                                                                                 screen->ro, &handle);
+               if (!scanout)
+                       return NULL;
+
+               renderonly_scanout_destroy(scanout, screen->ro);
+
+               assert(handle.type == WINSYS_HANDLE_TYPE_FD);
+               rsc = fd_resource(pscreen->resource_from_handle(pscreen, tmpl,
+                                                                                                               &handle,
+                                                                                                               PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
+               close(handle.handle);
+               if (!rsc)
+                       return NULL;
+
+               return &rsc->base;
+       }
+
+       rsc = CALLOC_STRUCT(fd_resource);
+       prsc = &rsc->base;
+
        DBG("%p: target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
                        "nr_samples=%u, usage=%u, bind=%x, flags=%x", prsc,
                        tmpl->target, util_format_name(format),
@@ -1050,6 +1079,12 @@ fd_resource_from_handle(struct pipe_screen *pscreen,
 
        assert(rsc->cpp);
 
+       if (screen->ro) {
+               rsc->scanout =
+                       renderonly_create_gpu_import_for_resource(prsc, screen->ro, NULL);
+               /* failure is expected in some cases.. */
+       }
+
        return prsc;
 
 fail:
index 8370824..10ab8bf 100644 (file)
@@ -72,6 +72,7 @@ struct fd_resource {
        /* buffer range that has been initialized */
        struct util_range valid_buffer_range;
        bool valid;
+       struct renderonly_scanout *scanout;
 
        /* reference to the resource holding stencil data for a z32_s8 texture */
        /* TODO rename to secondary or auxiliary? */
index b372d5c..e596a4e 100644 (file)
@@ -147,6 +147,9 @@ fd_screen_destroy(struct pipe_screen *pscreen)
        if (screen->dev)
                fd_device_del(screen->dev);
 
+       if (screen->ro)
+               FREE(screen->ro);
+
        fd_bc_fini(&screen->batch_cache);
 
        slab_destroy_parent(&screen->transfer_pool);
@@ -637,6 +640,7 @@ fd_get_compiler_options(struct pipe_screen *pscreen,
 boolean
 fd_screen_bo_get_handle(struct pipe_screen *pscreen,
                struct fd_bo *bo,
+               struct renderonly_scanout *scanout,
                unsigned stride,
                struct winsys_handle *whandle)
 {
@@ -645,6 +649,8 @@ fd_screen_bo_get_handle(struct pipe_screen *pscreen,
        if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) {
                return fd_bo_get_name(bo, &whandle->handle) == 0;
        } else if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
+               if (renderonly_get_handle(scanout, whandle))
+                       return TRUE;
                whandle->handle = fd_bo_handle(bo);
                return TRUE;
        } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) {
@@ -713,7 +719,7 @@ fd_screen_bo_from_handle(struct pipe_screen *pscreen,
 }
 
 struct pipe_screen *
-fd_screen_create(struct fd_device *dev)
+fd_screen_create(struct fd_device *dev, struct renderonly *ro)
 {
        struct fd_screen *screen = CALLOC_STRUCT(fd_screen);
        struct pipe_screen *pscreen;
@@ -734,6 +740,14 @@ fd_screen_create(struct fd_device *dev)
        screen->dev = dev;
        screen->refcnt = 1;
 
+       if (ro) {
+               screen->ro = renderonly_dup(ro);
+               if (!screen->ro) {
+                       DBG("could not create renderonly object");
+                       goto fail;
+               }
+       }
+
        // maybe this should be in context?
        screen->pipe = fd_pipe_new(screen->dev, FD_PIPE_3D);
        if (!screen->pipe) {
index 1060f46..7c45739 100644 (file)
@@ -34,6 +34,7 @@
 #include "util/u_memory.h"
 #include "util/slab.h"
 #include "os/os_thread.h"
+#include "renderonly/renderonly.h"
 
 #include "freedreno_batch_cache.h"
 #include "freedreno_perfcntr.h"
@@ -101,6 +102,8 @@ struct fd_screen {
 
        unsigned num_supported_modifiers;
        const uint64_t *supported_modifiers;
+
+       struct renderonly *ro;
 };
 
 static inline struct fd_screen *
@@ -111,12 +114,14 @@ fd_screen(struct pipe_screen *pscreen)
 
 boolean fd_screen_bo_get_handle(struct pipe_screen *pscreen,
                struct fd_bo *bo,
+               struct renderonly_scanout *scanout,
                unsigned stride,
                struct winsys_handle *whandle);
 struct fd_bo * fd_screen_bo_from_handle(struct pipe_screen *pscreen,
                struct winsys_handle *whandle);
 
-struct pipe_screen * fd_screen_create(struct fd_device *dev);
+struct pipe_screen *
+fd_screen_create(struct fd_device *dev, struct renderonly *ro);
 
 static inline boolean
 is_a20x(struct fd_screen *screen)
index 886fbdf..6833325 100644 (file)
@@ -8,7 +8,7 @@ create_screen(int fd, const struct pipe_screen_config *config)
 {
    struct pipe_screen *screen;
 
-   screen = fd_drm_screen_create(fd);
+   screen = fd_drm_screen_create(fd, NULL);
    if (!screen)
       return NULL;
 
index a7ba207..2f5591e 100644 (file)
@@ -3,7 +3,8 @@
 #define __FREEDRENO_DRM_PUBLIC_H__
 
 struct pipe_screen;
+struct renderonly;
 
-struct pipe_screen *fd_drm_screen_create(int drmFD);
+struct pipe_screen *fd_drm_screen_create(int drmFD, struct renderonly *ro);
 
 #endif
index a65583f..dff6209 100644 (file)
@@ -85,7 +85,7 @@ static int compare_fd(void *key1, void *key2)
 }
 
 struct pipe_screen *
-fd_drm_screen_create(int fd)
+fd_drm_screen_create(int fd, struct renderonly *ro)
 {
        struct pipe_screen *pscreen = NULL;
 
@@ -104,7 +104,7 @@ fd_drm_screen_create(int fd)
                if (!dev)
                        goto unlock;
 
-               pscreen = fd_screen_create(dev);
+               pscreen = fd_screen_create(dev, ro);
                if (pscreen) {
                        int fd = fd_device_fd(dev);