[574/906] memory: implement transperent upload/download for data
authorMatthew Waters <ystreet00@gmail.com>
Sun, 16 Sep 2012 11:36:09 +0000 (21:36 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:25 +0000 (19:31 +0000)
(not async yet)

gst-libs/gst/gl/gstglmemory.c
gst-libs/gst/gl/gstglmemory.h

index 9e9aae0..1b60bcf 100644 (file)
@@ -26,9 +26,8 @@
 
 #include "gstglmemory.h"
 
-/*GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
 #define GST_CAT_DEFUALT GST_CAT_GL_MEMORY
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_MEMORY);*/
 
 static GstAllocator *_gl_allocator;
 
@@ -40,23 +39,38 @@ typedef struct
 
 static void
 _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
-    GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height)
+    GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height,
+    gpointer user_data, GDestroyNotify notify)
 {
+  gsize maxsize;
+  GstVideoInfo info;
+
+  gst_video_info_set_format (&info, v_format, width, height);
+
+  maxsize = info.size;
+
   gst_memory_init (GST_MEMORY_CAST (mem), GST_MEMORY_FLAG_NO_SHARE,
-      allocator, parent, 0, 0, 0, 0);
+      allocator, parent, maxsize, 0, 0, maxsize);
 
   mem->display = g_object_ref (display);
   mem->gl_format = GL_RGBA;
   mem->v_format = v_format;
   mem->width = width;
   mem->height = height;
-
-  GST_DEBUG ("new GL memory");
+  mem->notify = notify;
+  mem->user_data = user_data;
+  mem->wrapped = FALSE;
+  mem->upload = gst_gl_display_find_upload (display, v_format, width, height);
+  mem->download =
+      gst_gl_display_find_download (display, v_format, width, height);
+
+  GST_DEBUG ("new GL texture memory");
 }
 
 static GstGLMemory *
 _gl_mem_new (GstAllocator * allocator, GstMemory * parent,
-    GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height)
+    GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height,
+    gpointer user_data, GDestroyNotify notify)
 {
   GstGLMemory *mem;
   GLuint tex_id;
@@ -69,7 +83,8 @@ _gl_mem_new (GstAllocator * allocator, GstMemory * parent,
   GST_TRACE ("created texture %u", tex_id);
 
   mem = g_slice_alloc (sizeof (GstGLMemory));
-  _gl_mem_init (mem, allocator, parent, display, v_format, width, height);
+  _gl_mem_init (mem, allocator, parent, display, v_format, width, height,
+      user_data, notify);
 
   mem->tex_id = tex_id;
 
@@ -79,13 +94,59 @@ _gl_mem_new (GstAllocator * allocator, GstMemory * parent,
 gpointer
 _gl_mem_map (GstGLMemory * gl_mem, gsize maxsize, GstMapFlags flags)
 {
-  /* should we perform a {up,down}load? */
-  return NULL;
+  gpointer data;
+
+  g_return_val_if_fail (maxsize == gl_mem->mem.maxsize, NULL);
+
+  if ((flags & GST_MAP_GL) == GST_MAP_GL) {
+    if ((flags & GST_MAP_READ) == GST_MAP_READ) {
+      if (GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD)) {
+        if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem,
+                GST_GL_MEMORY_FLAG_UPLOAD_INITTED)) {
+          gst_gl_upload_init_format (gl_mem->upload, gl_mem->v_format,
+              gl_mem->width, gl_mem->height);
+          GST_GL_MEMORY_FLAG_SET (gl_mem, GST_GL_MEMORY_FLAG_UPLOAD_INITTED);
+        }
+
+        gst_gl_upload_perform_with_memory (gl_mem->upload, gl_mem);
+      }
+    }
+
+    data = &gl_mem->tex_id;
+  } else {                      /* not GL */
+    if ((flags & GST_MAP_READ) == GST_MAP_READ) {
+      if (GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD)) {
+        if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem,
+                GST_GL_MEMORY_FLAG_DOWNLOAD_INITTED)) {
+          gst_gl_download_init_format (gl_mem->download, gl_mem->v_format,
+              gl_mem->width, gl_mem->height);
+          GST_GL_MEMORY_FLAG_SET (gl_mem, GST_GL_MEMORY_FLAG_DOWNLOAD_INITTED);
+        }
+
+        gst_gl_download_perform_with_memory (gl_mem->download, gl_mem);
+      }
+    }
+
+    data = gl_mem->data;
+  }
+
+  gl_mem->map_flags = flags;
+
+  return data;
 }
 
 void
 _gl_mem_unmap (GstGLMemory * gl_mem)
 {
+  if ((gl_mem->map_flags & GST_MAP_WRITE) == GST_MAP_WRITE) {
+    if ((gl_mem->map_flags & GST_MAP_GL) == GST_MAP_GL) {
+      GST_GL_MEMORY_FLAG_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
+    } else {
+      GST_GL_MEMORY_FLAG_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
+    }
+  }
+
+  gl_mem->map_flags = 0;
 }
 
 void
@@ -219,22 +280,21 @@ _gl_mem_copy (GstGLMemory * src, gssize offset, gssize size)
 
   dest = g_slice_alloc (sizeof (GstGLMemory));
   _gl_mem_init (dest, src->mem.allocator, NULL, src->display, src->v_format,
-      src->width, src->height);
+      src->width, src->height, NULL, NULL);
 
   if (!copy_params.tex_id)
     GST_WARNING ("Could not copy GL Memory");
 
   dest->tex_id = copy_params.tex_id;
+  dest->data = g_malloc (src->mem.maxsize);
+  if (dest->data == NULL) {
+    gst_memory_unref ((GstMemory *) dest);
+    return NULL;
+  }
 
   return (GstMemory *) dest;
 }
 
-GstGLMemory *
-gst_gl_memory_copy (GstGLMemory * src)
-{
-  return (GstGLMemory *) _gl_mem_copy (src, 0, 0);
-}
-
 GstMemory *
 _gl_mem_share (GstGLMemory * mem, gssize offset, gssize size)
 {
@@ -262,10 +322,19 @@ _gl_mem_free (GstAllocator * allocator, GstMemory * mem)
 {
   GstGLMemory *gl_mem = (GstGLMemory *) mem;
 
-  gst_gl_display_del_texture (gl_mem->display, &gl_mem->tex_id);
+  if (gl_mem->tex_id)
+    gst_gl_display_del_texture (gl_mem->display, &gl_mem->tex_id);
 
   g_object_unref (gl_mem->display);
 
+  if (gl_mem->notify)
+    gl_mem->notify (gl_mem->user_data);
+
+  if (gl_mem->data && !gl_mem->wrapped) {
+    g_free (gl_mem->data);
+    gl_mem->data = NULL;
+  }
+
   g_slice_free (GstGLMemory, gl_mem);
 }
 
@@ -283,8 +352,49 @@ GstMemory *
 gst_gl_memory_alloc (GstGLDisplay * display, GstVideoFormat format,
     gsize width, gsize height)
 {
-  return (GstMemory *) _gl_mem_new (_gl_allocator, NULL, display, format, width,
-      height);
+  GstGLMemory *mem;
+
+  mem = _gl_mem_new (_gl_allocator, NULL, display, format, width, height,
+      NULL, NULL);
+
+  mem->data = g_malloc (mem->mem.maxsize);
+  if (mem->data == NULL) {
+    gst_memory_unref ((GstMemory *) mem);
+    return NULL;
+  }
+
+  return (GstMemory *) mem;
+}
+
+/**
+ * gst_gl_memory_wrapped
+ * @display:a #GstGLDisplay
+ * @format: the format for the texture
+ * @width: width of the texture
+ * @height: height of the texture
+ * @data: the data to wrap
+ * @user_data: data called with for @notify
+ * @notify: function called with @user_data when @data needs to be freed
+ * 
+ * Returns: a GstMemory object with a GL texture specified by @format, @width and @height
+ *          from @display and contents specified by @data
+ */
+GstGLMemory *
+gst_gl_memory_wrapped (GstGLDisplay * display, GstVideoFormat format,
+    guint width, guint height, gpointer data,
+    gpointer user_data, GDestroyNotify notify)
+{
+  GstGLMemory *mem;
+
+  mem = _gl_mem_new (_gl_allocator, NULL, display, format, width, height,
+      user_data, notify);
+
+  mem->data = data;
+  mem->wrapped = TRUE;
+
+  GST_GL_MEMORY_FLAG_SET (mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
+
+  return mem;
 }
 
 G_DEFINE_TYPE (GstGLAllocator, gst_gl_allocator, GST_TYPE_ALLOCATOR);
@@ -325,6 +435,8 @@ gst_gl_memory_init (void)
   static volatile gsize _init = 0;
 
   if (g_once_init_enter (&_init)) {
+    GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_MEMORY, "glmemory", 0, "OpenGL Memory");
+
     _gl_allocator = g_object_new (gst_gl_allocator_get_type (), NULL);
 
     gst_allocator_register (GST_GL_MEMORY_ALLOCATOR,
@@ -333,8 +445,14 @@ gst_gl_memory_init (void)
   }
 }
 
+/**
+ * gst_is_gl_memory:
+ * @mem:a #GstMemory
+ * 
+ * Returns: whether the memory in @mem is a #GstGLMemory
+ */
 gboolean
 gst_is_gl_memory (GstMemory * mem)
 {
-  return mem->allocator == _gl_allocator;
+  return mem != NULL && mem->allocator == _gl_allocator;
 }
index 8407759..55880d3 100644 (file)
 #include <gst/gstallocator.h>
 
 #include "gstgldisplay.h"
+#include "gstgldownload.h"
+#include "gstglupload.h"
 
 G_BEGIN_DECLS
 
+typedef struct _GstGLUpload GstGLUpload;
+typedef struct _GstGLDownload GstGLDownload;
+
 #define GST_TYPE_GL_ALLOCATOR (gst_gl_allocator_get_type())
 GType gst_gl_allocator_get_type(void);
 
@@ -43,6 +48,25 @@ typedef struct _GstGLMemory GstGLMemory;
 typedef struct _GstGLAllocator GstGLAllocator;
 typedef struct _GstGLAllocatorClass GstGLAllocatorClass;
 
+typedef enum
+{
+  GST_GL_MEMORY_FLAG_DOWNLOAD_INITTED = (GST_MEMORY_FLAG_LAST << 0),
+  GST_GL_MEMORY_FLAG_UPLOAD_INITTED   = (GST_MEMORY_FLAG_LAST << 1),
+  GST_GL_MEMORY_FLAG_NEED_DOWNLOAD   = (GST_MEMORY_FLAG_LAST << 2),
+  GST_GL_MEMORY_FLAG_NEED_UPLOAD     = (GST_MEMORY_FLAG_LAST << 3)
+} GstGLMemoryFlags;
+
+/**
+ * GST_MAP_GL:
+ *
+ * Flag indicating that we should map the GL object instead of to system memory.
+ *
+ * Combining #GST_MAP_GL with #GST_MAP_WRITE has the same semantics as though
+ * you are writing to OpenGL. Conversely, combining #GST_MAP_GL with
+ * #GST_MAP_READ has the same semantics as though you are reading from OpenGL.
+ */
+#define GST_MAP_GL GST_MAP_FLAG_LAST << 1
+
 /**
  * GstGLMemory:
  * @mem: the parent object
@@ -64,15 +88,35 @@ struct _GstGLMemory
   GLenum             gl_format;
   GLuint             width;
   GLuint             height;
+
+  GstGLDownload     *download;
+  GLenum             render_target;
+  GstGLUpload       *upload;
+
+  GstMapFlags        map_flags;
+  gpointer           data;
+
+  gboolean           wrapped;
+  GDestroyNotify     notify;
+  gpointer           user_data;
 };
 
 #define GST_GL_MEMORY_ALLOCATOR   "GLMemory"
 
+#define GST_GL_MEMORY_FLAGS(mem) GST_MEMORY_FLAGS(mem)
+#define GST_GL_MEMORY_FLAG_IS_SET(mem,flag) GST_MEMORY_FLAG_IS_SET(mem,flag)
+#define GST_GL_MEMORY_FLAG_SET(mem,flag) GST_MINI_OBJECT_FLAG_SET(mem,flag)
+#define GST_GL_MEMORY_FLAG_UNSET(mem,flag) GST_MEMORY_FLAG_UNSET(mem,flag)
+
 void gst_gl_memory_init (void);
 
 GstMemory * gst_gl_memory_alloc (GstGLDisplay * display, GstVideoFormat format,
                                  gsize width, gsize height);
 
+GstGLMemory * gst_gl_memory_wrapped (GstGLDisplay * display, GstVideoFormat format,
+                                     guint width, guint height, gpointer data,
+                                     gpointer user_data, GDestroyNotify notify);
+
 gboolean gst_is_gl_memory (GstMemory * mem);
 
 struct _GstGLAllocator