[Mesa-dev] [PATCH 02/24] mesa: add support for memory object creation/import/delete

Samuel Pitoiset samuel.pitoiset at gmail.com
Wed Jul 26 14:36:12 UTC 2017



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().

> +   _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...

> +      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. :)

> +      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