[Mesa-dev] [PATCH 02/24] mesa: add support for memory object creation/import/delete
Timothy Arceri
tarceri at itsqueeze.com
Wed Jul 26 22:57:25 UTC 2017
On 27/07/17 00:36, Samuel Pitoiset wrote:
> On 07/26/2017 01:46 PM, Timothy Arceri wrote:
>> From: Andres Rodriguez <andresx7 at gmail.com>
>>
>> Used by EXT_external_objects and EXT_external_objects_fd
>>
>> V2 (Timothy Arceri):
>> - Throw GL_OUT_OF_MEMORY error if CreateMemoryObjectsEXT()
>> fails.
>> - C99 tidy ups
>> - remove void cast (Constantine Kharlamov)
>>
>> Signed-off-by: Andres Rodriguez <andresx7 at gmail.com>
>> Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>
>> ---
>> src/mesa/drivers/common/driverfuncs.c | 4 +
>> src/mesa/main/dd.h | 36 +++++++++
>> src/mesa/main/externalobjects.c | 137
>> +++++++++++++++++++++++++++++++++-
>> src/mesa/main/externalobjects.h | 28 +++++++
>> src/mesa/main/mtypes.h | 9 +++
>> src/mesa/main/shared.c | 17 +++++
>> 6 files changed, 229 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/mesa/drivers/common/driverfuncs.c
>> b/src/mesa/drivers/common/driverfuncs.c
>> index 5008ae8..ddb4bb6 100644
>> --- a/src/mesa/drivers/common/driverfuncs.c
>> +++ b/src/mesa/drivers/common/driverfuncs.c
>> @@ -49,6 +49,7 @@
>> #include "main/syncobj.h"
>> #include "main/barrier.h"
>> #include "main/transformfeedback.h"
>> +#include "main/externalobjects.h"
>> #include "program/program.h"
>> #include "tnl/tnl.h"
>> @@ -166,6 +167,9 @@ _mesa_init_driver_functions(struct
>> dd_function_table *driver)
>> _mesa_init_sync_object_functions(driver);
>> + /* memory objects */
>> + _mesa_init_memory_object_functions(driver);
>> +
>> driver->NewFramebuffer = _mesa_new_framebuffer;
>> driver->NewRenderbuffer = _swrast_new_soft_renderbuffer;
>> driver->MapRenderbuffer = _swrast_map_soft_renderbuffer;
>> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
>> index 8e382e1..97ef5b8 100644
>> --- a/src/mesa/main/dd.h
>> +++ b/src/mesa/main/dd.h
>> @@ -1069,6 +1069,42 @@ struct dd_function_table {
>> void (*MakeImageHandleResident)(struct gl_context *ctx, GLuint64
>> handle,
>> GLenum access, bool resident);
>> /*@}*/
>> +
>> +
>> + /**
>> + * \name GL_EXT_external_objects interface
>> + */
>> + /*@{*/
>> + /**
>> + * Called to allocate a new memory object. Drivers will usually
>> + * allocate/return a subclass of gl_memory_object.
>> + */
>> + struct gl_memory_object * (*NewMemoryObject)(struct gl_context *ctx,
>> + GLuint name);
>> + /**
>> + * Called to delete/free a memory object. Drivers should free the
>> + * object and any image data it contains.
>> + */
>> + void (*DeleteMemoryObject)(struct gl_context *ctx,
>> + struct gl_memory_object *mem_obj);
>> + /*@}*/
>> +
>> + /**
>> + * \name GL_EXT_external_objects_fd interface
>> + */
>> + /*@{*/
>> + /**
>> + * Called to import a memory object. The caller relinquishes
>> ownership
>> + * of fd after the call returns.
>> + *
>> + * Accessing fd after ImportMemoryObjectFd returns results in
>> undefined
>> + * behaviour. This is consistent with EXT_external_object_fd.
>> + */
>> + void (*ImportMemoryObjectFd)(struct gl_context *ctx,
>> + struct gl_memory_object *mem_obj,
>> + GLuint64 size,
>> + int fd);
>> + /*@}*/
>> };
>> diff --git a/src/mesa/main/externalobjects.c
>> b/src/mesa/main/externalobjects.c
>> index 86404d2..01fb19a 100644
>> --- a/src/mesa/main/externalobjects.c
>> +++ b/src/mesa/main/externalobjects.c
>> @@ -21,24 +21,143 @@
>> * DEALINGS IN THE SOFTWARE.
>> */
>> +#include "macros.h"
>> +#include "mtypes.h"
>> #include "externalobjects.h"
>> +/**
>> + * Allocate and initialize a new memory object. But don't put it
>> into the
>> + * memory object hash table.
>> + *
>> + * Called via ctx->Driver.NewMemoryObject, unless overridden by a device
>> + * driver.
>> + *
>> + * \return pointer to new memory object.
>> + */
>> +static struct gl_memory_object *
>> +_mesa_new_memory_object(struct gl_context *ctx, GLuint name)
>> +{
>> + struct gl_memory_object *obj = MALLOC_STRUCT(gl_memory_object);
>
> We usually check that the object is not NULL before initializing it, see
> others _mesa_new_XXX_object().
texobj does, seems bufferobj (where it looks like this was copied from)
didn't, fix sent.
>
>> + _mesa_initialize_memory_object(ctx, obj, name);
>> +
>> + return obj;
>> +}
>> +
>> +/**
>> + * Delete a memory object. Called via ctx->Driver.DeleteMemory().
>> + * Not removed from hash table here.
>> + */
>> +void
>> +_mesa_delete_memory_object(struct gl_context *ctx, struct
>> gl_memory_object *mo)
>
> How about memObj for gl_memory_object type? (this applies everywhere).
>
>> +{
>> + free(mo);
>> +}
>> +
>> +void
>> +_mesa_init_memory_object_functions(struct dd_function_table *driver)
>> +{
>> + driver->NewMemoryObject = _mesa_new_memory_object;
>> + driver->DeleteMemoryObject = _mesa_delete_memory_object;
>> +}
>> +
>> +/**
>> + * Initialize a buffer object to default values.
>> + */
>> +void
>> +_mesa_initialize_memory_object(struct gl_context *ctx,
>> + struct gl_memory_object *obj,
>> + GLuint name)
>> +{
>> + memset(obj, 0, sizeof(struct gl_memory_object));
>> + obj->Name = name;
>> +}
>> +
>> void GLAPIENTRY
>> _mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects)
>> {
>> -
>> + GET_CURRENT_CONTEXT(ctx);
>> +
>> + if (MESA_VERBOSE & (VERBOSE_API))
>> + _mesa_debug(ctx, "glDeleteMemoryObjectsEXT(%d, %p)\n", n,
>> memoryObjects);
>> +
>> + if (n < 0) {
>> + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjects(n <
>> 0)");
>> + return;
>> + }
>> +
>> + if (!memoryObjects)
>> + return;
>> +
>> + _mesa_HashLockMutex(ctx->Shared->MemoryObjects);
>> + for (GLint i = 0; i < n; i++) {
>> + if (memoryObjects[i] > 0) {
>> + struct gl_memory_object *delObj
>> + = _mesa_lookup_memory_object_locked(ctx, memoryObjects[i]);
>> +
>> + if (delObj) {
>> + _mesa_HashRemoveLocked(ctx->Shared->MemoryObjects,
>> memoryObjects[i]);
>> + ctx->Driver.DeleteMemoryObject(ctx, delObj);
>> + }
>> + }
>> + }
>> + _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
>> }
>> GLboolean GLAPIENTRY
>> _mesa_IsMemoryObjectEXT(GLuint memoryObject)
>> {
>> - return GL_FALSE;
>> + GET_CURRENT_CONTEXT(ctx);
>> +
>> + if (memoryObject == 0)
>> + return GL_FALSE;
>> +
>> + struct gl_memory_object *obj = _mesa_lookup_memory_object(ctx,
>> memoryObject);
>> +
>> + return obj ? GL_TRUE : GL_FALSE;
>> }
>> void GLAPIENTRY
>> _mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects)
>> {
>> + GET_CURRENT_CONTEXT(ctx);
>> +
>> + const char *func = "glCreateMemoryObjectsEXT";
>> +
>> + if (MESA_VERBOSE & (VERBOSE_API))
>> + _mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects);
>> +
>> + if (n < 0) {
>> + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
>> + return;
>> + }
>> + if (!memoryObjects)
>> + return;
>> +
>> + _mesa_HashLockMutex(ctx->Shared->MemoryObjects);
>> + GLuint first =
>> _mesa_HashFindFreeKeyBlock(ctx->Shared->MemoryObjects, n);
>> + if (first) {
>
> Why do you check this? I think HashFindFreeKeyBlock() prevents 0 to be
> returned...
It seems HashFindFreeKeyBlock() returns 0 when it fails to to find a
free block. It seems we just don't bother to check this anywhere else.
>
>> + for (GLsizei i = 0; i < n; i++) {
>> + struct gl_memory_object *memObj;
>> +
>> + memoryObjects[i] = first + i;
>> +
>> + /* allocate memory object */
>> + memObj = ctx->Driver.NewMemoryObject(ctx, memoryObjects[i]);
>> + if (!memObj) {
>> + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func);
>> + goto out_unlock;
>> + }
>> +
>> + /* insert into hash table */
>> + _mesa_HashInsertLocked(ctx->Shared->MemoryObjects,
>> + memoryObjects[i],
>> + memObj);
>> + }
>> + }
>> +
>> +out_unlock:
>> + _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
>> }
>> void GLAPIENTRY
>> @@ -245,7 +364,21 @@ _mesa_ImportMemoryFdEXT(GLuint memory,
>> GLenum handleType,
>> GLint fd)
>> {
>> + GET_CURRENT_CONTEXT(ctx);
>> +
>> + if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
>> + _mesa_error(ctx, GL_INVALID_VALUE,
>> "glImportMemoryFdEXT(handleType=%u)", handleType);
>
> Would be nice to be consistent about GL function names, sometimes you
> add EXT, sometimes not. :)
Yeah I already fixed one of these will double check and fix the others.
Thanks.
>
>> + return;
>> + }
>> +
>> + if (memory == 0)
>> + return;
>> +
>> + struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx,
>> memory);
>> + if (!memObj)
>> + return;
>> + ctx->Driver.ImportMemoryObjectFd(ctx, memObj, size, fd);
>> }
>> void GLAPIENTRY
>> diff --git a/src/mesa/main/externalobjects.h
>> b/src/mesa/main/externalobjects.h
>> index f70be8e..0219a07 100644
>> --- a/src/mesa/main/externalobjects.h
>> +++ b/src/mesa/main/externalobjects.h
>> @@ -35,6 +35,34 @@
>> #define EXTERNALOBJECTS_H
>> #include "glheader.h"
>> +#include "hash.h"
>> +
>> +static inline struct gl_memory_object *
>> +_mesa_lookup_memory_object(struct gl_context *ctx, GLuint id)
>> +{
>> + return (struct gl_memory_object *)
>> + _mesa_HashLookup(ctx->Shared->MemoryObjects, id);
>> +}
>> +
>> +static inline struct gl_memory_object *
>> +_mesa_lookup_memory_object_locked(struct gl_context *ctx, GLuint memory)
>> +{
>> + if (!memory)
>> + return NULL;
>> +
>> + return (struct gl_memory_object *)
>> + _mesa_HashLookupLocked(ctx->Shared->MemoryObjects, memory);
>> +}
>> +
>> +extern void
>> +_mesa_init_memory_object_functions(struct dd_function_table *driver);
>> +
>> +extern void
>> +_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);
>> 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 0d0536c..642cd72 100644
>> --- a/src/mesa/main/mtypes.h
>> +++ b/src/mesa/main/mtypes.h
>> @@ -3275,6 +3275,10 @@ struct gl_shared_state
>> * Once this field becomes true, it is never reset to false.
>> */
>> bool ShareGroupReset;
>> +
>> + /** EXT_external_objects */
>> + struct _mesa_HashTable *MemoryObjects;
>> +
>> };
>> @@ -4641,6 +4645,11 @@ struct gl_image_handle_object
>> GLuint64 handle;
>> };
>> +struct gl_memory_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 6926d40..2cce47e 100644
>> --- a/src/mesa/main/shared.c
>> +++ b/src/mesa/main/shared.c
>> @@ -130,6 +130,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
>> shared->SyncObjects = _mesa_set_create(NULL, _mesa_hash_pointer,
>> _mesa_key_pointer_equal);
>> + shared->MemoryObjects = _mesa_NewHashTable();
>> return shared;
>> }
>> @@ -295,6 +296,17 @@ delete_sampler_object_cb(GLuint id, void *data,
>> void *userData)
>> _mesa_reference_sampler_object(ctx, &sampObj, NULL);
>> }
>> +/**
>> + * Callback for deleting a memory object. Called by
>> _mesa_HashDeleteAll().
>> + */
>> +static void
>> +delete_memory_object_cb(GLuint id, void *data, void *userData)
>> +{
>> + struct gl_memory_object *memObj = (struct gl_memory_object *) data;
>> + struct gl_context *ctx = (struct gl_context *) userData;
>> + ctx->Driver.DeleteMemoryObject(ctx, memObj);
>> +}
>> +
>> /**
>> * Deallocate a shared state object and all children structures.
>> @@ -379,6 +391,11 @@ free_shared_state(struct gl_context *ctx, struct
>> gl_shared_state *shared)
>> _mesa_free_shared_handles(shared);
>> + if (shared->MemoryObjects) {
>> + _mesa_HashDeleteAll(shared->MemoryObjects,
>> delete_memory_object_cb, ctx);
>> + _mesa_DeleteHashTable(shared->MemoryObjects);
>> + }
>> +
>> mtx_destroy(&shared->Mutex);
>> mtx_destroy(&shared->TexMutex);
>>
More information about the mesa-dev
mailing list