Commit 8b7c5744 authored by Andres Rodriguez's avatar Andres Rodriguez Committed by Timothy Arceri

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's avatarAndres Rodriguez <andresx7@gmail.com>
Reviewed-by: Samuel Pitoiset's avatarSamuel Pitoiset <samuel.pitoiset@gmail.com>
parent 322ee1b3
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment