[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