summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Rodriguez <andresx7@gmail.com>2017-07-12 18:45:07 -0400
committerTimothy Arceri <tarceri@itsqueeze.com>2017-08-06 12:42:06 +1000
commit8b7c5744791fe403375dd1d61c4a99b882044415 (patch)
treeec5728914a1f98d8d55c9919d304f479e225481e
parent322ee1b3636a38c22bc65009f13667a9d5f438cf (diff)
mesa: add support for memory object creation/import/delete
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>
-rw-r--r--src/mesa/drivers/common/driverfuncs.c4
-rw-r--r--src/mesa/main/dd.h36
-rw-r--r--src/mesa/main/externalobjects.c138
-rw-r--r--src/mesa/main/externalobjects.h31
-rw-r--r--src/mesa/main/mtypes.h9
-rw-r--r--src/mesa/main/shared.c17
6 files changed, 233 insertions, 2 deletions
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 5008ae8fea..ddb4bb6d6a 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 462829d755..6d6bdecb4d 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 *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);
+ /*@}*/
};
diff --git a/src/mesa/main/externalobjects.c b/src/mesa/main/externalobjects.c
index 86404d2a8d..6c5b07d110 100644
--- a/src/mesa/main/externalobjects.c
+++ b/src/mesa/main/externalobjects.c
@@ -21,24 +21,146 @@
* 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
diff --git a/src/mesa/main/externalobjects.h b/src/mesa/main/externalobjects.h
index f70be8e8ab..a9a12b821f 100644
--- a/src/mesa/main/externalobjects.h
+++ b/src/mesa/main/externalobjects.h
@@ -35,6 +35,37 @@
#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);
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 1dec89c544..8ef1183785 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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.
*
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index 6926d40570..2cce47e226 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);