mesa: add support for memory object creation/import/delete
authorAndres Rodriguez <andresx7@gmail.com>
Wed, 12 Jul 2017 22:45:07 +0000 (18:45 -0400)
committerTimothy Arceri <tarceri@itsqueeze.com>
Sun, 6 Aug 2017 02:42:06 +0000 (12:42 +1000)
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)

V3 (Timothy Arceri):
 - rename mo -> memObj
 - check that the object is not NULL before initializing
 - add missing "EXT" in function error message

V4 (Timothy Arceri):
 - remove checks for (memory objecy id == 0) and catch in
   _mesa_lookup_memory_object() instead.

Signed-off-by: Andres Rodriguez <andresx7@gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
src/mesa/drivers/common/driverfuncs.c
src/mesa/main/dd.h
src/mesa/main/externalobjects.c
src/mesa/main/externalobjects.h
src/mesa/main/mtypes.h
src/mesa/main/shared.c

index 5008ae8feafb3070797dc11d5e35a4de3e5c27c9..ddb4bb6d6a10b6813b60d95432b9ef2c4b585b23 100644 (file)
@@ -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;
index 462829d755daad7d8e1264df9f5d1cdd24621e5e..6d6bdecb4dd99f6a698c5d29a4cf498ecc8e3b94 100644 (file)
@@ -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 *memObj);
+   /*@}*/
+
+   /**
+    * \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 *memObj,
+                                GLuint64 size,
+                                int fd);
+   /*@}*/
 };
 
 
index 86404d2a8d3efbbb46e343e97e7b00e306d10913..6c5b07d110ebc380bdf23189bda2960d4f132b99 100644 (file)
  * 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);
+   if (!obj)
+      return NULL;
+
+   _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 *memObj)
+{
+   free(memObj);
+}
+
+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, "glDeleteMemoryObjectsEXT(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);
+   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) {
+      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);
+            _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
+            return;
+         }
+
+         /* insert into hash table */
+         _mesa_HashInsertLocked(ctx->Shared->MemoryObjects,
+                                memoryObjects[i],
+                                memObj);
+      }
+   }
+
+   _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
 }
 
 void GLAPIENTRY
@@ -245,7 +367,19 @@ _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);
+      return;
+   }
+
+   struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
+   if (!memObj)
+      return;
 
+   ctx->Driver.ImportMemoryObjectFd(ctx, memObj, size, fd);
 }
 
 void GLAPIENTRY
index f70be8e8ab9f0b7dd0ad6ebc51a2535b89384769..a9a12b821f7194c58eb26a20ca2015188527352a 100644 (file)
 #define EXTERNALOBJECTS_H
 
 #include "glheader.h"
+#include "hash.h"
+
+static inline struct gl_memory_object *
+_mesa_lookup_memory_object(struct gl_context *ctx, GLuint memory)
+{
+   if (!memory)
+      return NULL;
+
+   return (struct gl_memory_object *)
+      _mesa_HashLookup(ctx->Shared->MemoryObjects, memory);
+}
+
+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);
index 1dec89c54456ca94477ab5de438a58bd595c2765..8ef1183785c3c2ac4650780dfb4b3167dd118e34 100644 (file)
@@ -3274,6 +3274,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;
+
 };
 
 
@@ -4640,6 +4644,11 @@ struct gl_image_handle_object
    GLuint64 handle;
 };
 
+struct gl_memory_object
+{
+   GLuint Name;          /**< hash table ID/name */
+};
+
 /**
  * Mesa rendering context.
  *
index 6926d40570b37baf2348cc296eaafeb044b6ebd3..2cce47e2268fe50e45ae8543f6e56b0d89cf3928 100644 (file)
@@ -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);