v3d: Add renderonly support.
authorEric Anholt <eric@anholt.net>
Sat, 27 Oct 2018 01:02:20 +0000 (18:02 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 27 Nov 2018 23:03:02 +0000 (15:03 -0800)
I've been using this with the kmsro series to test v3d on VKMS without my
old KMS hack in the v3d kernel driver.  KMSRO still needs some cleanup,
but v3d RO support seems reasonable.

src/gallium/drivers/v3d/v3d_resource.c
src/gallium/drivers/v3d/v3d_resource.h
src/gallium/drivers/v3d/v3d_screen.c
src/gallium/drivers/v3d/v3d_screen.h
src/gallium/winsys/v3d/drm/v3d_drm_public.h
src/gallium/winsys/v3d/drm/v3d_drm_winsys.c

index 45e2edf..39529c1 100644 (file)
@@ -299,8 +299,12 @@ static void
 v3d_resource_destroy(struct pipe_screen *pscreen,
                      struct pipe_resource *prsc)
 {
+        struct v3d_screen *screen = v3d_screen(pscreen);
         struct v3d_resource *rsc = v3d_resource(prsc);
 
+        if (rsc->scanout)
+                renderonly_scanout_destroy(rsc->scanout, screen->ro);
+
         v3d_bo_unreference(&rsc->bo);
         free(rsc);
 }
@@ -312,6 +316,7 @@ v3d_resource_get_handle(struct pipe_screen *pscreen,
                         struct winsys_handle *whandle,
                         unsigned usage)
 {
+        struct v3d_screen *screen = v3d_screen(pscreen);
         struct v3d_resource *rsc = v3d_resource(prsc);
         struct v3d_bo *bo = rsc->bo;
 
@@ -339,6 +344,10 @@ v3d_resource_get_handle(struct pipe_screen *pscreen,
         case WINSYS_HANDLE_TYPE_SHARED:
                 return v3d_bo_flink(bo, &whandle->handle);
         case WINSYS_HANDLE_TYPE_KMS:
+                if (screen->ro) {
+                        assert(rsc->scanout);
+                        return renderonly_get_handle(rsc->scanout, whandle);
+                }
                 whandle->handle = bo->handle;
                 return TRUE;
         case WINSYS_HANDLE_TYPE_FD:
@@ -633,6 +642,7 @@ v3d_resource_create_with_modifiers(struct pipe_screen *pscreen,
                                    const uint64_t *modifiers,
                                    int count)
 {
+        struct v3d_screen *screen = v3d_screen(pscreen);
         bool linear_ok = find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count);
         struct v3d_resource *rsc = v3d_resource_setup(pscreen, tmpl);
         struct pipe_resource *prsc = &rsc->base;
@@ -648,6 +658,10 @@ v3d_resource_create_with_modifiers(struct pipe_screen *pscreen,
         if (tmpl->bind & (PIPE_BIND_LINEAR | PIPE_BIND_CURSOR))
                 should_tile = false;
 
+        /* No tiling when we're sharing with another device (pl111). */
+        if (screen->ro && (tmpl->bind & PIPE_BIND_SCANOUT))
+                should_tile = false;
+
         /* 1D and 1D_ARRAY textures are always raster-order. */
         if (tmpl->target == PIPE_TEXTURE_1D ||
             tmpl->target == PIPE_TEXTURE_1D_ARRAY)
@@ -678,8 +692,32 @@ v3d_resource_create_with_modifiers(struct pipe_screen *pscreen,
         rsc->internal_format = prsc->format;
 
         v3d_setup_slices(rsc, 0);
-        if (!v3d_resource_bo_alloc(rsc))
-                goto fail;
+
+        /* If we're in a renderonly setup, use the other device to perform our
+         * (linear) allocaton and just import it to v3d.  The other device may
+         * be using CMA, and V3D can import from CMA but doesn't do CMA
+         * allocations on its own.
+         *
+         * Note that DRI3 doesn't give us tmpl->bind flags, so we have to use
+         * the modifiers to see if we're allocating a scanout object.
+         */
+        if (screen->ro &&
+            ((tmpl->bind & PIPE_BIND_SCANOUT) ||
+             (count == 1 && modifiers[0] == DRM_FORMAT_MOD_LINEAR))) {
+                struct winsys_handle handle;
+                rsc->scanout =
+                   renderonly_scanout_for_resource(prsc, screen->ro, &handle);
+                if (!rsc->scanout) {
+                        fprintf(stderr, "Failed to create scanout resource\n");
+                        goto fail;
+                }
+                assert(handle.type == WINSYS_HANDLE_TYPE_FD);
+                rsc->bo = v3d_bo_open_dmabuf(screen, handle.handle);
+                v3d_debug_resource_layout(rsc, "scanout");
+        } else {
+                if (!v3d_resource_bo_alloc(rsc))
+                        goto fail;
+        }
 
         return prsc;
 fail:
@@ -753,6 +791,21 @@ v3d_resource_from_handle(struct pipe_screen *pscreen,
         v3d_setup_slices(rsc, whandle->stride);
         v3d_debug_resource_layout(rsc, "import");
 
+        if (screen->ro) {
+                /* Make sure that renderonly has a handle to our buffer in the
+                 * display's fd, so that a later renderonly_get_handle()
+                 * returns correct handles or GEM names.
+                 */
+                rsc->scanout =
+                        renderonly_create_gpu_import_for_resource(prsc,
+                                                                  screen->ro,
+                                                                  NULL);
+                if (!rsc->scanout) {
+                        fprintf(stderr, "Failed to create scanout resource.\n");
+                        goto fail;
+                }
+        }
+
         if (whandle->stride != slice->stride) {
                 static bool warned = false;
                 if (!warned) {
index 95ee0eb..80b1d6e 100644 (file)
@@ -122,6 +122,7 @@ struct v3d_surface {
 struct v3d_resource {
         struct pipe_resource base;
         struct v3d_bo *bo;
+        struct renderonly_scanout *scanout;
         struct v3d_resource_slice slices[VC5_MAX_MIP_LEVELS];
         uint32_t cube_map_stride;
         uint32_t size;
index 1d59dbf..4ed40ff 100644 (file)
@@ -465,7 +465,7 @@ v3d_screen_get_compiler_options(struct pipe_screen *pscreen,
 }
 
 struct pipe_screen *
-v3d_screen_create(int fd)
+v3d_screen_create(int fd, struct renderonly *ro)
 {
         struct v3d_screen *screen = rzalloc(NULL, struct v3d_screen);
         struct pipe_screen *pscreen;
@@ -480,6 +480,14 @@ v3d_screen_create(int fd)
         pscreen->is_format_supported = v3d_screen_is_format_supported;
 
         screen->fd = fd;
+        if (ro) {
+                screen->ro = renderonly_dup(ro);
+                if (!screen->ro) {
+                        fprintf(stderr, "Failed to dup renderonly object\n");
+                        ralloc_free(screen);
+                        return NULL;
+                }
+        }
         list_inithead(&screen->bo_cache.time_list);
         (void)mtx_init(&screen->bo_handles_mutex, mtx_plain);
         screen->bo_handles = util_hash_table_create(handle_hash, handle_compare);
index 4d30ef3..6cb3342 100644 (file)
@@ -25,6 +25,7 @@
 #define VC5_SCREEN_H
 
 #include "pipe/p_screen.h"
+#include "renderonly/renderonly.h"
 #include "os/os_thread.h"
 #include "state_tracker/drm_driver.h"
 #include "util/list.h"
@@ -55,6 +56,7 @@ struct v3d_simulator_file;
 
 struct v3d_screen {
         struct pipe_screen base;
+        struct renderonly *ro;
         int fd;
 
         struct v3d_device_info devinfo;
@@ -90,7 +92,7 @@ v3d_screen(struct pipe_screen *screen)
         return (struct v3d_screen *)screen;
 }
 
-struct pipe_screen *v3d_screen_create(int fd);
+struct pipe_screen *v3d_screen_create(int fd, struct renderonly *ro);
 
 void
 v3d_fence_init(struct v3d_screen *screen);
index 46aed9d..1813825 100644 (file)
@@ -25,7 +25,9 @@
 #define __VC5_DRM_PUBLIC_H__
 
 struct pipe_screen;
+struct renderonly;
 
 struct pipe_screen *v3d_drm_screen_create(int drmFD);
+struct pipe_screen *v3d_drm_screen_create_renderonly(struct renderonly *ro);
 
 #endif /* __VC5_DRM_PUBLIC_H__ */
index 63b7a57..a478606 100644 (file)
 struct pipe_screen *
 v3d_drm_screen_create(int fd)
 {
-       return v3d_screen_create(fcntl(fd, F_DUPFD_CLOEXEC, 3));
+       return v3d_screen_create(fcntl(fd, F_DUPFD_CLOEXEC, 3), NULL);
+}
+
+struct pipe_screen *
+v3d_drm_screen_create_renderonly(struct renderonly *ro)
+{
+       return v3d_screen_create(fcntl(ro->gpu_fd, F_DUPFD_CLOEXEC, 3), ro);
 }