From cdb5a727644e9fd0195519f81ce34f79a99ae432 Mon Sep 17 00:00:00 2001 From: "Juan A. Suarez Romero" Date: Thu, 26 Mar 2020 16:16:25 +0100 Subject: [PATCH] iris: hook up memory object creation from handle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: use iris_bo_import_dmabuf (Tapani) v3: included "util/u_memory.h" to fixed compilation errors caused by using the CALLOC_STRUCT macro v4: implemented iris_memobj_destroy (pscreen->memobj_destroy) callback v5: removed iris_bo_from_handle and changed the approach for setting the tiling: Instead of querying the kernel and call iris_bo_import_dmabuf to create the bo, we call iris_bo_import_dmabuf_no_mods that imports the bo but without setting the tiling mode. We are going to update it when we create the resource. Also: implemented the iris_bo_import_dmabuf_no_mods. v6: rebase to iris_bo_import_dmabuf changes and take a reference to memobj->bo (Tapani Pälli) Signed-off-by: Juan A. Suarez Romero Signed-off-by: Eleni Maria Stea Co-authored-by: Eleni Maria Stea Reviewed-by: Rohan Garg Reviewed-by: Tapani Pälli Part-of: --- src/gallium/drivers/iris/iris_bufmgr.c | 54 ++++++++++++++++++++ src/gallium/drivers/iris/iris_bufmgr.h | 3 ++ src/gallium/drivers/iris/iris_resource.c | 63 ++++++++++++++++++++++++ src/gallium/drivers/iris/iris_resource.h | 8 +++ 4 files changed, 128 insertions(+) diff --git a/src/gallium/drivers/iris/iris_bufmgr.c b/src/gallium/drivers/iris/iris_bufmgr.c index 24fcb22cb36..d3f8295de97 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.c +++ b/src/gallium/drivers/iris/iris_bufmgr.c @@ -1480,6 +1480,60 @@ err: return NULL; } +struct iris_bo * +iris_bo_import_dmabuf_no_mods(struct iris_bufmgr *bufmgr, + int prime_fd) +{ + uint32_t handle; + struct iris_bo *bo; + + mtx_lock(&bufmgr->lock); + int ret = drmPrimeFDToHandle(bufmgr->fd, prime_fd, &handle); + if (ret) { + DBG("import_dmabuf: failed to obtain handle from fd: %s\n", + strerror(errno)); + mtx_unlock(&bufmgr->lock); + return NULL; + } + + /* + * See if the kernel has already returned this buffer to us. Just as + * for named buffers, we must not create two bo's pointing at the same + * kernel object + */ + bo = find_and_ref_external_bo(bufmgr->handle_table, handle); + if (bo) + goto out; + + bo = bo_calloc(); + if (!bo) + goto out; + + p_atomic_set(&bo->refcount, 1); + + /* Determine size of bo. The fd-to-handle ioctl really should + * return the size, but it doesn't. If we have kernel 3.12 or + * later, we can lseek on the prime fd to get the size. Older + * kernels will just fail, in which case we fall back to the + * provided (estimated or guess size). */ + ret = lseek(prime_fd, 0, SEEK_END); + if (ret != -1) + bo->size = ret; + + bo->bufmgr = bufmgr; + bo->name = "prime"; + bo->reusable = false; + bo->external = true; + bo->kflags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS | EXEC_OBJECT_PINNED; + bo->gtt_offset = vma_alloc(bufmgr, IRIS_MEMZONE_OTHER, bo->size, 1); + bo->gem_handle = handle; + _mesa_hash_table_insert(bufmgr->handle_table, &bo->gem_handle, bo); + +out: + mtx_unlock(&bufmgr->lock); + return bo; +} + static void iris_bo_make_external_locked(struct iris_bo *bo) { diff --git a/src/gallium/drivers/iris/iris_bufmgr.h b/src/gallium/drivers/iris/iris_bufmgr.h index 91c03ab35e3..7991e3cbaac 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.h +++ b/src/gallium/drivers/iris/iris_bufmgr.h @@ -410,6 +410,9 @@ struct iris_bo *iris_bo_import_dmabuf(struct iris_bufmgr *bufmgr, int prime_fd, int iris_bo_export_gem_handle_for_device(struct iris_bo *bo, int drm_fd, uint32_t *out_handle); +struct iris_bo *iris_bo_import_dmabuf_no_mods(struct iris_bufmgr *bufmgr, + int prime_fd); + uint32_t iris_bo_export_gem_handle(struct iris_bo *bo); int iris_reg_read(struct iris_bufmgr *bufmgr, uint32_t offset, uint64_t *out); diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index 632085aeb46..95c4c1ee6cb 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -38,6 +38,7 @@ #include "util/u_cpu_detect.h" #include "util/u_inlines.h" #include "util/format/u_format.h" +#include "util/u_memory.h" #include "util/u_threaded_context.h" #include "util/u_transfer.h" #include "util/u_transfer_helper.h" @@ -293,6 +294,66 @@ iris_image_view_get_format(struct iris_context *ice, return isl_fmt; } +static struct pipe_memory_object * +iris_memobj_create_from_handle(struct pipe_screen *pscreen, + struct winsys_handle *whandle, + bool dedicated) +{ + struct iris_screen *screen = (struct iris_screen *)pscreen; + struct iris_memory_object *memobj = CALLOC_STRUCT(iris_memory_object); + struct iris_bo *bo; + const struct isl_drm_modifier_info *mod_inf; + + if (!memobj) + return NULL; + + switch (whandle->type) { + case WINSYS_HANDLE_TYPE_SHARED: + bo = iris_bo_gem_create_from_name(screen->bufmgr, "winsys image", + whandle->handle); + break; + case WINSYS_HANDLE_TYPE_FD: + mod_inf = isl_drm_modifier_get_info(whandle->modifier); + if (mod_inf) { + bo = iris_bo_import_dmabuf(screen->bufmgr, whandle->handle, + whandle->modifier); + } else { + /* If we can't get information about the tiling from the + * kernel we ignore it. We are going to set it when we + * create the resource. + */ + bo = iris_bo_import_dmabuf_no_mods(screen->bufmgr, + whandle->handle); + } + + break; + default: + unreachable("invalid winsys handle type"); + } + + if (!bo) { + free(memobj); + return NULL; + } + + memobj->b.dedicated = dedicated; + memobj->bo = bo; + + iris_bo_reference(memobj->bo); + + return &memobj->b; +} + +static void +iris_memobj_destroy(struct pipe_screen *pscreen, + struct pipe_memory_object *pmemobj) +{ + struct iris_memory_object *memobj = (struct iris_memory_object *)pmemobj; + + iris_bo_unreference(memobj->bo); + free(memobj); +} + struct pipe_resource * iris_resource_get_separate_stencil(struct pipe_resource *p_res) { @@ -2289,6 +2350,8 @@ iris_init_screen_resource_functions(struct pipe_screen *pscreen) pscreen->resource_get_handle = iris_resource_get_handle; pscreen->resource_get_param = iris_resource_get_param; pscreen->resource_destroy = u_transfer_helper_resource_destroy; + pscreen->memobj_create_from_handle = iris_memobj_create_from_handle; + pscreen->memobj_destroy = iris_memobj_destroy; pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, true, true, false, true); } diff --git a/src/gallium/drivers/iris/iris_resource.h b/src/gallium/drivers/iris/iris_resource.h index caed44ab2ac..69867e0741e 100644 --- a/src/gallium/drivers/iris/iris_resource.h +++ b/src/gallium/drivers/iris/iris_resource.h @@ -277,6 +277,14 @@ struct iris_transfer { void (*unmap)(struct iris_transfer *); }; +/** + * Memory Object + */ +struct iris_memory_object { + struct pipe_memory_object b; + struct iris_bo *bo; +}; + /** * Unwrap a pipe_resource to get the underlying iris_bo (for convenience). */