[Mesa-dev] [PATCH 02/23] mesa: add support for memory object creation/import/delete
Samuel Pitoiset
samuel.pitoiset at gmail.com
Fri Aug 4 08:36:00 UTC 2017
On 08/04/2017 03:54 AM, 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)
>
> 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 at gmail.com>
> Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>
> Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com> (v3)
> ---
> src/mesa/drivers/common/driverfuncs.c | 4 +
> src/mesa/main/dd.h | 36 +++++++++
> src/mesa/main/externalobjects.c | 138 +++++++++++++++++++++++++++++++++-
> src/mesa/main/externalobjects.h | 31 ++++++++
> src/mesa/main/mtypes.h | 9 +++
> src/mesa/main/shared.c | 17 +++++
> 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
> @@ -42,20 +42,21 @@
> #include "main/teximage.h"
> #include "main/texobj.h"
> #include "main/texstorage.h"
> #include "main/texstore.h"
> #include "main/bufferobj.h"
> #include "main/fbobject.h"
> #include "main/samplerobj.h"
> #include "main/syncobj.h"
> #include "main/barrier.h"
> #include "main/transformfeedback.h"
> +#include "main/externalobjects.h"
>
> #include "program/program.h"
> #include "tnl/tnl.h"
> #include "swrast/swrast.h"
> #include "swrast/s_renderbuffer.h"
>
> #include "driverfuncs.h"
> #include "meta.h"
>
>
> @@ -159,20 +160,23 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
> driver->Viewport = NULL;
>
> /* buffer objects */
> _mesa_init_buffer_object_functions(driver);
>
> /* query objects */
> _mesa_init_query_object_functions(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;
> driver->UnmapRenderbuffer = _swrast_unmap_soft_renderbuffer;
> driver->RenderTexture = _swrast_render_texture;
> driver->FinishRenderTexture = _swrast_finish_render_texture;
> driver->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
> driver->ValidateFramebuffer = _mesa_validate_framebuffer;
>
> driver->BlitFramebuffer = _swrast_BlitFramebuffer;
> 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
> @@ -1062,20 +1062,56 @@ struct dd_function_table {
> struct gl_sampler_object *sampObj);
> void (*DeleteTextureHandle)(struct gl_context *ctx, GLuint64 handle);
> void (*MakeTextureHandleResident)(struct gl_context *ctx, GLuint64 handle,
> bool resident);
> GLuint64 (*NewImageHandle)(struct gl_context *ctx,
> struct gl_image_unit *imgObj);
> void (*DeleteImageHandle)(struct gl_context *ctx, GLuint64 handle);
> 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);
> + /*@}*/
> };
>
>
> /**
> * Per-vertex functions.
> *
> * These are the functions which can appear between glBegin and glEnd.
> * Depending on whether we're inside or outside a glBegin/End pair
> * and whether we're in immediate mode or building a display list, these
> * functions behave differently. This structure allows us to switch
> diff --git a/src/mesa/main/externalobjects.c b/src/mesa/main/externalobjects.c
> index 86404d2a8d..6bc07a5015 100644
> --- a/src/mesa/main/externalobjects.c
> +++ b/src/mesa/main/externalobjects.c
> @@ -14,38 +14,160 @@
> *
> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> * 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);
> + goto out_unlock;
Can you please remove the goto and move _mesa_HashUnlockMutex() here?
With that fixed, this patch is:
Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
> + }
> +
> + /* insert into hash table */
> + _mesa_HashInsertLocked(ctx->Shared->MemoryObjects,
> + memoryObjects[i],
> + memObj);
> + }
> + }
> +
> +out_unlock:
> + _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
> }
>
> void GLAPIENTRY
> _mesa_MemoryObjectParameterivEXT(GLuint memoryObject,
> GLenum pname,
> const GLint *params)
> {
>
> }
>
> @@ -238,20 +360,32 @@ _mesa_SignalSemaphoreEXT(GLuint semaphore,
> {
>
> }
>
> void GLAPIENTRY
> _mesa_ImportMemoryFdEXT(GLuint memory,
> GLuint64 size,
> 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
> _mesa_ImportSemaphoreFdEXT(GLuint semaphore,
> GLenum handleType,
> GLint fd)
> {
>
> }
> 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
> @@ -28,20 +28,51 @@
> /**
> * \file externalobjects.h
> *
> * Declarations of functions related to the API interop extensions.
> */
>
> #ifndef EXTERNALOBJECTS_H
> #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);
>
> extern GLboolean GLAPIENTRY
> _mesa_IsMemoryObjectEXT(GLuint memoryObject);
>
> extern void GLAPIENTRY
> _mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects);
>
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index 404d586ff7..b5ec6168a1 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -3267,20 +3267,24 @@ struct gl_shared_state
> /**
> * Some context in this share group was affected by a GPU reset
> *
> * On the next call to \c glGetGraphicsResetStatus, contexts that have not
> * been affected by a GPU reset must also return
> * \c GL_INNOCENT_CONTEXT_RESET_ARB.
> *
> * Once this field becomes true, it is never reset to false.
> */
> bool ShareGroupReset;
> +
> + /** EXT_external_objects */
> + struct _mesa_HashTable *MemoryObjects;
> +
> };
>
>
>
> /**
> * Renderbuffers represent drawing surfaces such as color, depth and/or
> * stencil. A framebuffer object has a set of renderbuffers.
> * Drivers will typically derive subclasses of this type.
> */
> struct gl_renderbuffer
> @@ -4633,20 +4637,25 @@ struct gl_texture_handle_object
> struct gl_sampler_object *sampObj;
> GLuint64 handle;
> };
>
> struct gl_image_handle_object
> {
> struct gl_image_unit imgObj;
> GLuint64 handle;
> };
>
> +struct gl_memory_object
> +{
> + GLuint Name; /**< hash table ID/name */
> +};
> +
> /**
> * Mesa rendering context.
> *
> * This is the central context data structure for Mesa. Almost all
> * OpenGL state is contained in this structure.
> * Think of this as a base class from which device drivers will derive
> * sub classes.
> */
> struct gl_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
> @@ -123,20 +123,21 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
> /* Mutex and timestamp for texobj state validation */
> mtx_init(&shared->TexMutex, mtx_recursive);
> shared->TextureStateStamp = 0;
>
> shared->FrameBuffers = _mesa_NewHashTable();
> shared->RenderBuffers = _mesa_NewHashTable();
>
> shared->SyncObjects = _mesa_set_create(NULL, _mesa_hash_pointer,
> _mesa_key_pointer_equal);
>
> + shared->MemoryObjects = _mesa_NewHashTable();
> return shared;
> }
>
>
> /**
> * Callback for deleting a display list. Called by _mesa_HashDeleteAll().
> */
> static void
> delete_displaylist_cb(GLuint id, void *data, void *userData)
> {
> @@ -288,20 +289,31 @@ delete_renderbuffer_cb(GLuint id, void *data, void *userData)
> * Callback for deleting a sampler object. Called by _mesa_HashDeleteAll()
> */
> static void
> delete_sampler_object_cb(GLuint id, void *data, void *userData)
> {
> struct gl_context *ctx = (struct gl_context *) userData;
> struct gl_sampler_object *sampObj = (struct gl_sampler_object *) data;
> _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.
> *
> * \param ctx GL context.
> * \param shared shared state pointer.
> *
> * Frees the display lists, the texture objects (calling the driver texture
> * deletion callback to free its private data) and the vertex programs, as well
> * as their hash tables.
> @@ -372,20 +384,25 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
> for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
> ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]);
> }
>
> /* all other textures */
> _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
> _mesa_DeleteHashTable(shared->TexObjects);
>
> _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);
>
> free(shared);
> }
>
>
> /**
> * gl_shared_state objects are ref counted.
> * If ptr's refcount goes to zero, free the shared state.
>
More information about the mesa-dev
mailing list