From af16ec6e0c98c70f64fccd9901dd1d869a72fec8 Mon Sep 17 00:00:00 2001 From: Thomas Wagner Date: Mon, 1 Jul 2024 17:55:02 +0200 Subject: [PATCH] llvmpipe: Fix external memory object reference Make the external memory object a reference counted object. Without that deleting the memory object in OpenGL would also delete and unmap the memfd, which causes any operation on a texture or buffer that is bound to that memory object to access invalid memory. Fixes: 1608a815e33 ("llvmpipe: add support for EXT_memory_object(_fd)") Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/llvmpipe/lp_texture.c | 23 +++++++++++++++++------ src/gallium/drivers/llvmpipe/lp_texture.h | 4 +++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 043bacdaa75..db155d9a60b 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -449,6 +449,7 @@ llvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen, { #ifdef PIPE_MEMORY_FD struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object); + pipe_reference_init(&memobj->reference, 1); if (handle->type == WINSYS_HANDLE_TYPE_FD && pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size, false)) { @@ -467,10 +468,13 @@ llvmpipe_memobj_destroy(struct pipe_screen *pscreen, if (!memobj) return; struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj); + if (pipe_reference(&lpmo->reference, NULL)) + { #ifdef PIPE_MEMORY_FD - pscreen->free_memory_fd(pscreen, lpmo->data); + pscreen->free_memory_fd(pscreen, lpmo->data); #endif - free(lpmo); + free(lpmo); + } } @@ -526,7 +530,8 @@ llvmpipe_resource_from_memobj(struct pipe_screen *pscreen, lpr->data = lpmo->data; } lpr->id = id_counter++; - lpr->imported_memory = true; + lpr->imported_memory = &lpmo->b; + pipe_reference(NULL, &lpmo->reference); #if MESA_DEBUG simple_mtx_lock(&resource_list_mutex); @@ -556,13 +561,19 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, } else if (llvmpipe_resource_is_texture(pt)) { /* free linear image data */ if (lpr->tex_data) { - if (!lpr->imported_memory) + if (lpr->imported_memory) + llvmpipe_memobj_destroy(pscreen, lpr->imported_memory); + else align_free(lpr->tex_data); lpr->tex_data = NULL; + lpr->imported_memory = NULL; } } else if (lpr->data) { - if (!lpr->imported_memory) - align_free(lpr->data); + if (lpr->imported_memory) + llvmpipe_memobj_destroy(pscreen, lpr->imported_memory); + else + align_free(lpr->data); + lpr->imported_memory = NULL; } } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 594e4c410b1..0db5a37b21e 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -53,6 +53,7 @@ enum llvmpipe_memory_fd_type struct pipe_context; struct pipe_screen; +struct pipe_memory_object; struct llvmpipe_context; struct llvmpipe_screen; @@ -113,7 +114,7 @@ struct llvmpipe_resource struct llvmpipe_memory_allocation *dmabuf_alloc; #endif bool backable; - bool imported_memory; + struct pipe_memory_object *imported_memory; bool dmabuf; #if MESA_DEBUG struct list_head list; @@ -142,6 +143,7 @@ struct llvmpipe_memory_allocation struct llvmpipe_memory_object { struct pipe_memory_object b; + struct pipe_reference reference; struct pipe_memory_allocation *data; uint64_t size; };