From 67d5d08682c4975a025182a7bf58a4768753e677 Mon Sep 17 00:00:00 2001 From: Andres Rodriguez Date: Fri, 6 Oct 2017 17:17:54 -0400 Subject: [PATCH] mesa: add support for semaphore object creation/import/delete v3 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Used by EXT_semmaphore and EXT_semaphore_fd v2: Removed unnecessary dummy callback initialization v3: Fixed attempting to free the DummySemaphoreObject Signed-off-by: Andres Rodriguez Reviewed-by: Marek Olšák --- src/mesa/main/dd.h | 34 ++++++++++ src/mesa/main/externalobjects.c | 134 +++++++++++++++++++++++++++++++++++++++- src/mesa/main/externalobjects.h | 31 +++++++++- src/mesa/main/mtypes.h | 8 +++ src/mesa/main/shared.c | 17 +++++ 5 files changed, 222 insertions(+), 2 deletions(-) diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 4fd4d86..c80af0b 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -1133,6 +1133,40 @@ struct dd_function_table { struct gl_shader_program *shProg, struct gl_program *prog); /*@}*/ + + /** + * \name GL_EXT_semaphore interface + */ + /*@{*/ + /** + * Called to allocate a new semaphore object. Drivers will usually + * allocate/return a subclass of gl_semaphore_object. + */ + struct gl_semaphore_object * (*NewSemaphoreObject)(struct gl_context *ctx, + GLuint name); + /** + * Called to delete/free a semaphore object. Drivers should free the + * object and any associated resources. + */ + void (*DeleteSemaphoreObject)(struct gl_context *ctx, + struct gl_semaphore_object *semObj); + /*@}*/ + + /** + * \name GL_EXT_semaphore_fd interface + */ + /*@{*/ + /** + * Called to import a semaphore object. The caller relinquishes ownership + * of fd after the call returns. + * + * Accessing fd after ImportSemaphoreFd returns results in undefined + * behaviour. This is consistent with EXT_semaphore_fd. + */ + void (*ImportSemaphoreFd)(struct gl_context *ctx, + struct gl_semaphore_object *semObj, + int fd); + /*@}*/ }; diff --git a/src/mesa/main/externalobjects.c b/src/mesa/main/externalobjects.c index 4e9f8f8..8b5ecb2 100644 --- a/src/mesa/main/externalobjects.c +++ b/src/mesa/main/externalobjects.c @@ -545,22 +545,126 @@ _mesa_TextureStorageMem1DEXT(GLuint texture, memory, offset, "glTextureStorageMem1DEXT"); } +/** + * Used as a placeholder for semaphore objects between glGenSemaphoresEXT() + * and glImportSemaphoreFdEXT(), so that glIsSemaphoreEXT() can work correctly. + */ +static struct gl_semaphore_object DummySemaphoreObject; + +/** + * Delete a semaphore object. Called via ctx->Driver.DeleteSemaphore(). + * Not removed from hash table here. + */ +void +_mesa_delete_semaphore_object(struct gl_context *ctx, + struct gl_semaphore_object *semObj) +{ + if (semObj != &DummySemaphoreObject) + free(semObj); +} + +/** + * Initialize a semaphore object to default values. + */ +void +_mesa_initialize_semaphore_object(struct gl_context *ctx, + struct gl_semaphore_object *obj, + GLuint name) +{ + memset(obj, 0, sizeof(struct gl_semaphore_object)); + obj->Name = name; +} + void GLAPIENTRY _mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores) { + GET_CURRENT_CONTEXT(ctx); + + const char *func = "glGenSemaphoresEXT"; + + if (MESA_VERBOSE & (VERBOSE_API)) + _mesa_debug(ctx, "%s(%d, %p)", func, n, semaphores); + if (!ctx->Extensions.EXT_semaphore) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); + return; + } + + if (!semaphores) + return; + + _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects); + GLuint first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SemaphoreObjects, n); + if (first) { + for (GLsizei i = 0; i < n; i++) { + semaphores[i] = first + i; + _mesa_HashInsertLocked(ctx->Shared->SemaphoreObjects, + semaphores[i], &DummySemaphoreObject); + } + } + + _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects); } void GLAPIENTRY _mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores) { + GET_CURRENT_CONTEXT(ctx); + + const char *func = "glDeleteSemaphoresEXT"; + + if (MESA_VERBOSE & (VERBOSE_API)) { + _mesa_debug(ctx, "%s(%d, %p)\n", func, n, semaphores); + } + + if (!ctx->Extensions.EXT_semaphore) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); + return; + } + + if (!semaphores) + return; + + _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects); + for (GLint i = 0; i < n; i++) { + if (semaphores[i] > 0) { + struct gl_semaphore_object *delObj + = _mesa_lookup_semaphore_object_locked(ctx, semaphores[i]); + + if (delObj) { + _mesa_HashRemoveLocked(ctx->Shared->SemaphoreObjects, + semaphores[i]); + ctx->Driver.DeleteSemaphoreObject(ctx, delObj); + } + } + } + _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects); } GLboolean GLAPIENTRY _mesa_IsSemaphoreEXT(GLuint semaphore) { - return GL_FALSE; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_semaphore) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glIsSemaphoreEXT(unsupported)"); + return GL_FALSE; + } + + struct gl_semaphore_object *obj = + _mesa_lookup_semaphore_object(ctx, semaphore); + + return obj ? GL_TRUE : GL_FALSE; } void GLAPIENTRY @@ -634,5 +738,33 @@ _mesa_ImportSemaphoreFdEXT(GLuint semaphore, GLenum handleType, GLint fd) { + GET_CURRENT_CONTEXT(ctx); + + const char *func = "glImportSemaphoreFdEXT"; + + if (!ctx->Extensions.EXT_semaphore_fd) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + + if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(handleType=%u)", func, handleType); + return; + } + + struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx, + semaphore); + if (!semObj) + return; + + if (semObj == &DummySemaphoreObject) { + semObj = ctx->Driver.NewSemaphoreObject(ctx, semaphore); + if (!semObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + return; + } + _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj); + } + ctx->Driver.ImportSemaphoreFd(ctx, semObj, fd); } diff --git a/src/mesa/main/externalobjects.h b/src/mesa/main/externalobjects.h index a9a12b8..75b0bc2 100644 --- a/src/mesa/main/externalobjects.h +++ b/src/mesa/main/externalobjects.h @@ -57,6 +57,26 @@ _mesa_lookup_memory_object_locked(struct gl_context *ctx, GLuint memory) _mesa_HashLookupLocked(ctx->Shared->MemoryObjects, memory); } +static inline struct gl_semaphore_object * +_mesa_lookup_semaphore_object(struct gl_context *ctx, GLuint semaphore) +{ + if (!semaphore) + return NULL; + + return (struct gl_semaphore_object *) + _mesa_HashLookup(ctx->Shared->SemaphoreObjects, semaphore); +} + +static inline struct gl_semaphore_object * +_mesa_lookup_semaphore_object_locked(struct gl_context *ctx, GLuint semaphore) +{ + if (!semaphore) + return NULL; + + return (struct gl_semaphore_object *) + _mesa_HashLookupLocked(ctx->Shared->SemaphoreObjects, semaphore); +} + extern void _mesa_init_memory_object_functions(struct dd_function_table *driver); @@ -65,7 +85,16 @@ _mesa_initialize_memory_object(struct gl_context *ctx, struct gl_memory_object *obj, GLuint name); extern void -_mesa_delete_memory_object(struct gl_context *ctx, struct gl_memory_object *mo); +_mesa_delete_memory_object(struct gl_context *ctx, + struct gl_memory_object *semObj); + +extern void +_mesa_initialize_semaphore_object(struct gl_context *ctx, + struct gl_semaphore_object *obj, + GLuint name); +extern void +_mesa_delete_semaphore_object(struct gl_context *ctx, + struct gl_semaphore_object *semObj); extern void GLAPIENTRY _mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index c4be760..35fafa5 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -3339,6 +3339,9 @@ struct gl_shared_state /** EXT_external_objects */ struct _mesa_HashTable *MemoryObjects; + /** EXT_semaphore */ + struct _mesa_HashTable *SemaphoreObjects; + /** * Some context in this share group was affected by a disjoint * operation. This operation can be anything that has effects on @@ -4720,6 +4723,11 @@ struct gl_memory_object GLboolean Dedicated; /**< import memory from a dedicated allocation */ }; +struct gl_semaphore_object +{ + GLuint Name; /**< hash table ID/name */ +}; + /** * Mesa rendering context. * diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c index e3417a4..b0338d7 100644 --- a/src/mesa/main/shared.c +++ b/src/mesa/main/shared.c @@ -136,6 +136,8 @@ _mesa_alloc_shared_state(struct gl_context *ctx) _mesa_key_pointer_equal); shared->MemoryObjects = _mesa_NewHashTable(); + shared->SemaphoreObjects = _mesa_NewHashTable(); + return shared; fail: @@ -316,6 +318,16 @@ delete_memory_object_cb(GLuint id, void *data, void *userData) ctx->Driver.DeleteMemoryObject(ctx, memObj); } +/** + * Callback for deleting a memory object. Called by _mesa_HashDeleteAll(). + */ +static void +delete_semaphore_object_cb(GLuint id, void *data, void *userData) +{ + struct gl_semaphore_object *semObj = (struct gl_semaphore_object *) data; + struct gl_context *ctx = (struct gl_context *) userData; + ctx->Driver.DeleteSemaphoreObject(ctx, semObj); +} /** * Deallocate a shared state object and all children structures. @@ -435,6 +447,11 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) _mesa_DeleteHashTable(shared->MemoryObjects); } + if (shared->SemaphoreObjects) { + _mesa_HashDeleteAll(shared->SemaphoreObjects, delete_semaphore_object_cb, ctx); + _mesa_DeleteHashTable(shared->SemaphoreObjects); + } + simple_mtx_destroy(&shared->Mutex); mtx_destroy(&shared->TexMutex); -- 2.7.4