diff --git a/src/gallium/drivers/v3d/v3d_resource.c b/src/gallium/drivers/v3d/v3d_resource.c index 45e2edf5ab6..39529c10c4c 100644 --- a/src/gallium/drivers/v3d/v3d_resource.c +++ b/src/gallium/drivers/v3d/v3d_resource.c @@ -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) { diff --git a/src/gallium/drivers/v3d/v3d_resource.h b/src/gallium/drivers/v3d/v3d_resource.h index 95ee0eb7d9c..80b1d6eb9ad 100644 --- a/src/gallium/drivers/v3d/v3d_resource.h +++ b/src/gallium/drivers/v3d/v3d_resource.h @@ -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; diff --git a/src/gallium/drivers/v3d/v3d_screen.c b/src/gallium/drivers/v3d/v3d_screen.c index 1d59dbfc12a..4ed40ff855d 100644 --- a/src/gallium/drivers/v3d/v3d_screen.c +++ b/src/gallium/drivers/v3d/v3d_screen.c @@ -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); diff --git a/src/gallium/drivers/v3d/v3d_screen.h b/src/gallium/drivers/v3d/v3d_screen.h index 4d30ef30bce..6cb33429067 100644 --- a/src/gallium/drivers/v3d/v3d_screen.h +++ b/src/gallium/drivers/v3d/v3d_screen.h @@ -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); diff --git a/src/gallium/winsys/v3d/drm/v3d_drm_public.h b/src/gallium/winsys/v3d/drm/v3d_drm_public.h index 46aed9d4e18..1813825436b 100644 --- a/src/gallium/winsys/v3d/drm/v3d_drm_public.h +++ b/src/gallium/winsys/v3d/drm/v3d_drm_public.h @@ -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__ */ diff --git a/src/gallium/winsys/v3d/drm/v3d_drm_winsys.c b/src/gallium/winsys/v3d/drm/v3d_drm_winsys.c index 63b7a5717f5..a4786068bba 100644 --- a/src/gallium/winsys/v3d/drm/v3d_drm_winsys.c +++ b/src/gallium/winsys/v3d/drm/v3d_drm_winsys.c @@ -31,5 +31,11 @@ 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); }