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>
This commit is contained in:

committed by
Timothy Arceri

parent
322ee1b363
commit
8b7c574479
@@ -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;
|
||||
|
@@ -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);
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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.
|
||||
*
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user