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 45e2edf5ab65569a8d3bb2915767a8ff5e3998ea..39529c10c4c1eb5ee89e2e8f01b72324b01085ca 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 95ee0eb7d9cdda1b1b091c7273f58cbfe0ebc29f..80b1d6eb9adac9f8534eb38b85aa66a7dc2ccf8d 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 1d59dbfc12aedaaaefc7bf8bc269f2c6117addfc..4ed40ff855d13944b278fb2f9138983828665577 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 4d30ef30bce347e82cf45b1f0459ef91a1c0d353..6cb33429067fc0c539a669d0d4767cbb6036dd81 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 46aed9d4e180d9575ab44aae214783f1a75d9a4e..1813825436b109bef189aed03190babbee57994e 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 63b7a5717f5530cd8cf900ed9aa3d0a8dbe0fb9e..a4786068bbae640d4d8cb67bc4d5e820de3dbd93 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);
 }