Reviewed-by: Samuel Pitoiset <samuel.pitoi...@gmail.com>

On 07/27/2017 03:08 PM, Timothy Arceri wrote:
From: Andres Rodriguez <andre...@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

Signed-off-by: Andres Rodriguez <andre...@gmail.com>
Reviewed-by: Timothy Arceri <tarc...@itsqueeze.com>
---
  src/mesa/drivers/common/driverfuncs.c |   4 +
  src/mesa/main/dd.h                    |  36 +++++++++
  src/mesa/main/externalobjects.c       | 140 +++++++++++++++++++++++++++++++++-
  src/mesa/main/externalobjects.h       |  28 +++++++
  src/mesa/main/mtypes.h                |   9 +++
  src/mesa/main/shared.c                |  17 +++++
  6 files changed, 232 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 8e382e1e9a..e06899d04f 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..4cbada3f4e 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);
+
+   if (memoryObject == 0)
+      return GL_FALSE;
+
+   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;
+         }
+
+         /* 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,34 @@ _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;
+   }
+
+   if (memory == 0)
+      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..0219a076a0 100644
--- a/src/mesa/main/externalobjects.h
+++ b/src/mesa/main/externalobjects.h
@@ -28,20 +28,48 @@
  /**
   * \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 id)
+{
+   return (struct gl_memory_object *)
+      _mesa_HashLookup(ctx->Shared->MemoryObjects, id);
+}
+
+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 0d0536c775..642cd72d29 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -3268,20 +3268,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
@@ -4634,20 +4638,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.

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to