v3d: Allow the UIF modifier with renderonly.
authorEric Anholt <eric@anholt.net>
Mon, 18 Mar 2019 21:19:36 +0000 (14:19 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 19 Mar 2019 15:54:46 +0000 (08:54 -0700)
We ask the other side to make a buffer with the right number of pages, and
then just store the UIF in it.  This avoids an extra silent copy of the
buffer from linear to UIF if it gets used for texturing (X11 copy-based
swapbuffers, GL compositors).

src/gallium/drivers/v3d/v3d_resource.c

index 61432a09d2f88d9555099495b413840b0c748308..10abee4e8f68e7933f13ed55f7308772262ed0b2 100644 (file)
@@ -403,7 +403,9 @@ v3d_resource_get_handle(struct pipe_screen *pscreen,
         case WINSYS_HANDLE_TYPE_KMS:
                 if (screen->ro) {
                         assert(rsc->scanout);
-                        return renderonly_get_handle(rsc->scanout, whandle);
+                        bool ok = renderonly_get_handle(rsc->scanout, whandle);
+                        whandle->stride = rsc->slices[0].stride;
+                        return ok;
                 }
                 whandle->handle = bo->handle;
                 return TRUE;
@@ -696,41 +698,6 @@ v3d_resource_create_with_modifiers(struct pipe_screen *pscreen,
 {
         struct v3d_screen *screen = v3d_screen(pscreen);
 
-        /* If we're in a renderonly setup, use the other device to perform our
-         * (linear) allocation 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.
-         *
-         * We always allocate this way for SHARED, because get_handle will
-         * need a resource on the display fd.
-         */
-        if (screen->ro && (tmpl->bind & (PIPE_BIND_SCANOUT |
-                                         PIPE_BIND_SHARED))) {
-                struct winsys_handle handle;
-                struct pipe_resource scanout_tmpl = *tmpl;
-                struct renderonly_scanout *scanout =
-                        renderonly_scanout_for_resource(&scanout_tmpl,
-                                                        screen->ro,
-                                                        &handle);
-                if (!scanout) {
-                        fprintf(stderr, "Failed to create scanout resource\n");
-                        return NULL;
-                }
-                assert(handle.type == WINSYS_HANDLE_TYPE_FD);
-                /* The fd is all we need.  Destroy the old scanout (and its
-                 * GEM handle on kms_fd) before resource_from_handle()'s
-                 * renderonly_create_gpu_import_for_resource() call which will
-                 * also get a kms_fd GEM handle for the fd.
-                 */
-                renderonly_scanout_destroy(scanout, screen->ro);
-                struct pipe_resource *prsc =
-                        pscreen->resource_from_handle(pscreen, tmpl,
-                                                      &handle,
-                                                      PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
-                close(handle.handle);
-                return prsc;
-        }
-
         bool linear_ok = drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count);
         struct v3d_resource *rsc = v3d_resource_setup(pscreen, tmpl);
         struct pipe_resource *prsc = &rsc->base;
@@ -758,6 +725,12 @@ v3d_resource_create_with_modifiers(struct pipe_screen *pscreen,
             tmpl->bind & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT))
                 should_tile = false;
 
+        /* If using the old-school SCANOUT flag, we don't know what the screen
+         * might support other than linear. Just force linear.
+         */
+        if (tmpl->bind & PIPE_BIND_SCANOUT)
+                should_tile = false;
+
         /* No user-specified modifier; determine our own. */
         if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) {
                 linear_ok = true;
@@ -777,8 +750,49 @@ v3d_resource_create_with_modifiers(struct pipe_screen *pscreen,
 
         v3d_setup_slices(rsc, 0, tmpl->bind & PIPE_BIND_SHARED);
 
-        if (!v3d_resource_bo_alloc(rsc))
-           goto fail;
+        /* If we're in a renderonly setup, use the other device to perform our
+         * allocation 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.
+         *
+         * We always allocate this way for SHARED, because get_handle will
+         * need a resource on the display fd.
+         */
+        if (screen->ro && (tmpl->bind & (PIPE_BIND_SCANOUT |
+                                         PIPE_BIND_SHARED))) {
+                struct winsys_handle handle;
+                struct pipe_resource scanout_tmpl = {
+                        .target = prsc->target,
+                        .format = PIPE_FORMAT_RGBA8888_UNORM,
+                        .width0 = 1024, /* one page */
+                        .height0 = align(rsc->size, 4096) / 4096,
+                        .depth0 = 1,
+                        .array_size = 1,
+                };
+
+                rsc->scanout =
+                        renderonly_scanout_for_resource(&scanout_tmpl,
+                                                        screen->ro,
+                                                        &handle);
+
+                if (!rsc->scanout) {
+                        fprintf(stderr, "Failed to create scanout resource\n");
+                        return NULL;
+                }
+                assert(handle.type == WINSYS_HANDLE_TYPE_FD);
+                rsc->bo = v3d_bo_open_dmabuf(screen, handle.handle);
+                close(handle.handle);
+
+                if (!rsc->bo)
+                        goto fail;
+
+                v3d_debug_resource_layout(rsc, "renderonly");
+
+                return prsc;
+        } else {
+                if (!v3d_resource_bo_alloc(rsc))
+                        goto fail;
+        }
 
         return prsc;
 fail: