summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/libs/gst-plugins-bad-libs.types1
-rw-r--r--ext/gl/gstgldownloadelement.c3
-rw-r--r--ext/gl/gstgloverlay.c4
-rw-r--r--ext/qt/gstqsgtexture.cc2
-rw-r--r--gst-libs/gst/gl/Makefile.am4
-rw-r--r--gst-libs/gst/gl/gl.h2
-rw-r--r--gst-libs/gst/gl/gstgl_fwd.h8
-rw-r--r--gst-libs/gst/gl/gstglbufferpool.c19
-rw-r--r--gst-libs/gst/gl/gstglcolorconvert.c9
-rw-r--r--gst-libs/gst/gl/gstgldisplay.c2
-rw-r--r--gst-libs/gst/gl/gstglformat.c358
-rw-r--r--gst-libs/gst/gl/gstglformat.h58
-rw-r--r--gst-libs/gst/gl/gstglmemory.c1357
-rw-r--r--gst-libs/gst/gl/gstglmemory.h223
-rw-r--r--gst-libs/gst/gl/gstglmemorypbo.c1030
-rw-r--r--gst-libs/gst/gl/gstglmemorypbo.h139
-rw-r--r--gst-libs/gst/gl/gstgloverlaycompositor.c6
-rw-r--r--gst-libs/gst/gl/gstglupload.c34
-rw-r--r--gst-libs/gst/gl/gstglviewconvert.c10
-rw-r--r--tests/check/libs/gstglmemory.c81
20 files changed, 2019 insertions, 1331 deletions
diff --git a/docs/libs/gst-plugins-bad-libs.types b/docs/libs/gst-plugins-bad-libs.types
index 83eebef20..d0d844a36 100644
--- a/docs/libs/gst-plugins-bad-libs.types
+++ b/docs/libs/gst-plugins-bad-libs.types
@@ -27,6 +27,7 @@ gst_insert_bin_get_type
gst_gl_buffer_allocator_get_type
+gst_gl_memory_allocator_get_type
gst_gl_base_filter_get_type
gst_gl_buffer_pool_get_type
gst_gl_color_convert_get_type
diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c
index 94a6e7a8e..917bdc7aa 100644
--- a/ext/gl/gstgldownloadelement.c
+++ b/ext/gl/gstgldownloadelement.c
@@ -176,7 +176,8 @@ gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt,
if (gst_is_gl_memory (mem)) {
if (!features || gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) {
- gst_gl_memory_download_transfer ((GstGLMemory *) mem);
+ if (gst_is_gl_memory_pbo (mem))
+ gst_gl_memory_pbo_download_transfer ((GstGLMemoryPBO *) mem);
}
}
}
diff --git a/ext/gl/gstgloverlay.c b/ext/gl/gstgloverlay.c
index a152fc22c..c26135237 100644
--- a/ext/gl/gstgloverlay.c
+++ b/ext/gl/gstgloverlay.c
@@ -696,7 +696,7 @@ gst_gl_overlay_load_jpeg (GstGLOverlay * overlay, FILE * fp)
gst_video_info_align (&v_info, &v_align);
overlay->image_memory = (GstGLMemory *)
- gst_gl_memory_alloc (GST_GL_BASE_FILTER (overlay)->context,
+ gst_gl_memory_pbo_alloc (GST_GL_BASE_FILTER (overlay)->context,
GST_GL_TEXTURE_TARGET_2D, NULL, &v_info, 0, &v_align);
if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info,
@@ -801,7 +801,7 @@ gst_gl_overlay_load_png (GstGLOverlay * overlay, FILE * fp)
gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, width, height);
overlay->image_memory = (GstGLMemory *)
- gst_gl_memory_alloc (GST_GL_BASE_FILTER (overlay)->context,
+ gst_gl_memory_pbo_alloc (GST_GL_BASE_FILTER (overlay)->context,
GST_GL_TEXTURE_TARGET_2D, NULL, &v_info, 0, NULL);
if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info,
diff --git a/ext/qt/gstqsgtexture.cc b/ext/qt/gstqsgtexture.cc
index 0986a82bb..13208c05f 100644
--- a/ext/qt/gstqsgtexture.cc
+++ b/ext/qt/gstqsgtexture.cc
@@ -111,7 +111,7 @@ GstQSGTexture::bind ()
mem = gst_buffer_peek_memory (this->buffer_, 0);
g_assert (gst_is_gl_memory (mem));
- context = ((GstGLBaseBuffer *)mem)->context;
+ context = ((GstGLBaseMemory *)mem)->context;
sync_meta = gst_buffer_get_gl_sync_meta (this->sync_buffer_);
if (!sync_meta)
diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am
index bc83ce387..77baef79c 100644
--- a/gst-libs/gst/gl/Makefile.am
+++ b/gst-libs/gst/gl/Makefile.am
@@ -16,8 +16,10 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \
gstglbasememory.c \
gstglbuffer.c \
gstglmemory.c \
+ gstglmemorypbo.c \
gstglbufferpool.c \
gstglfilter.c \
+ gstglformat.c \
gstglbasefilter.c \
gstglshader.c \
gstglshaderstrings.c \
@@ -46,8 +48,10 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \
gstglbasememory.h \
gstglbuffer.h \
gstglmemory.h \
+ gstglmemorypbo.h \
gstglbufferpool.h \
gstglfilter.h \
+ gstglformat.h \
gstglbasefilter.h \
gstglshader.h \
gstglshaderstrings.h \
diff --git a/gst-libs/gst/gl/gl.h b/gst-libs/gst/gl/gl.h
index 44dbbecf5..ae05c499e 100644
--- a/gst-libs/gst/gl/gl.h
+++ b/gst-libs/gst/gl/gl.h
@@ -33,6 +33,7 @@
#include <gst/gl/gstglcontext.h>
#include <gst/gl/gstgldebug.h>
#include <gst/gl/gstglfeature.h>
+#include <gst/gl/gstglformat.h>
#include <gst/gl/gstglutils.h>
#include <gst/gl/gstglwindow.h>
#include <gst/gl/gstglslstage.h>
@@ -44,6 +45,7 @@
#include <gst/gl/gstglbasememory.h>
#include <gst/gl/gstglbuffer.h>
#include <gst/gl/gstglmemory.h>
+#include <gst/gl/gstglmemorypbo.h>
#include <gst/gl/gstglbufferpool.h>
#include <gst/gl/gstglframebuffer.h>
#include <gst/gl/gstglbasefilter.h>
diff --git a/gst-libs/gst/gl/gstgl_fwd.h b/gst-libs/gst/gl/gstgl_fwd.h
index 0f45d0ee1..860483d12 100644
--- a/gst-libs/gst/gl/gstgl_fwd.h
+++ b/gst-libs/gst/gl/gstgl_fwd.h
@@ -52,8 +52,12 @@ typedef struct _GstGLBufferAllocator GstGLBufferAllocator;
typedef struct _GstGLBufferAllocatorClass GstGLBufferAllocatorClass;
typedef struct _GstGLMemory GstGLMemory;
-typedef struct _GstGLAllocator GstGLAllocator;
-typedef struct _GstGLAllocatorClass GstGLAllocatorClass;
+typedef struct _GstGLMemoryAllocator GstGLMemoryAllocator;
+typedef struct _GstGLMemoryAllocatorClass GstGLMemoryAllocatorClass;
+
+typedef struct _GstGLMemoryPBO GstGLMemoryPBO;
+typedef struct _GstGLMemoryPBOAllocator GstGLMemoryPBOAllocator;
+typedef struct _GstGLMemoryPBOAllocatorClass GstGLMemoryPBOAllocatorClass;
typedef struct _GstGLSLStage GstGLSLStage;
typedef struct _GstGLSLStagePrivate GstGLSLStagePrivate;
diff --git a/gst-libs/gst/gl/gstglbufferpool.c b/gst-libs/gst/gl/gstglbufferpool.c
index 12261f036..a2de0cfc7 100644
--- a/gst-libs/gst/gl/gstglbufferpool.c
+++ b/gst-libs/gst/gl/gstglbufferpool.c
@@ -120,10 +120,7 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
if (priv->allocator)
gst_object_unref (priv->allocator);
- if (!allocator) {
- gst_gl_memory_init ();
- priv->allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
- } else {
+ if (allocator) {
priv->allocator = gst_object_ref (allocator);
}
@@ -142,12 +139,14 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
GST_BUFFER_POOL_OPTION_GL_SYNC_META);
#if GST_GL_HAVE_PLATFORM_EGL
- g_assert (priv->allocator != NULL);
- priv->want_eglimage =
- (g_strcmp0 (priv->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0);
-#else
- priv->want_eglimage = FALSE;
+ if (priv->allocator) {
+ priv->want_eglimage =
+ (g_strcmp0 (priv->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0);
+ } else
#endif
+ {
+ priv->want_eglimage = FALSE;
+ }
max_align = alloc_params.align;
@@ -299,7 +298,7 @@ gst_gl_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
}
#endif
- if (!gst_gl_memory_setup_buffer (glpool->context, priv->tex_target,
+ if (!gst_gl_memory_pbo_setup_buffer (glpool->context, priv->tex_target,
&priv->params, info, valign, buf))
goto mem_create_failed;
diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c
index 9fd640e5b..eaf1ad71b 100644
--- a/gst-libs/gst/gl/gstglcolorconvert.c
+++ b/gst-libs/gst/gl/gstglcolorconvert.c
@@ -2013,7 +2013,7 @@ _do_convert_one_view (GstGLContext * context, GstGLColorConvert * convert,
if (!convert->priv->out_tex[j])
convert->priv->out_tex[j] =
- (GstGLMemory *) gst_gl_memory_alloc (context,
+ (GstGLMemory *) gst_gl_memory_pbo_alloc (context,
convert->priv->to_texture_target, NULL, &temp_info, 0, NULL);
} else {
convert->priv->out_tex[j] = out_tex;
@@ -2069,10 +2069,9 @@ out:
res = FALSE;
continue;
}
- gst_gl_memory_copy_into_texture (convert->priv->out_tex[j],
+ gst_gl_memory_copy_into (convert->priv->out_tex[j],
out_tex->tex_id, convert->priv->to_texture_target, out_tex->tex_type,
- mem_width, mem_height, GST_VIDEO_INFO_PLANE_STRIDE (&out_tex->info,
- out_tex->plane), FALSE);
+ mem_width, mem_height);
gst_memory_unmap ((GstMemory *) convert->priv->out_tex[j], &from_info);
gst_memory_unmap ((GstMemory *) out_tex, &to_info);
} else {
@@ -2120,7 +2119,7 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert)
gst_gl_sync_meta_wait (sync_meta, convert->context);
convert->outbuf = gst_buffer_new ();
- if (!gst_gl_memory_setup_buffer (convert->context,
+ if (!gst_gl_memory_pbo_setup_buffer (convert->context,
convert->priv->to_texture_target, NULL, &convert->out_info, NULL,
convert->outbuf)) {
convert->priv->result = FALSE;
diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c
index 10e9ef78e..79c173662 100644
--- a/gst-libs/gst/gl/gstgldisplay.c
+++ b/gst-libs/gst/gl/gstgldisplay.c
@@ -140,8 +140,8 @@ gst_gl_display_init (GstGLDisplay * display)
GST_TRACE ("init %p", display);
gst_gl_base_buffer_init_once ();
- gst_gl_memory_init ();
gst_gl_buffer_init_once ();
+ gst_gl_memory_pbo_init_once ();
#if GST_GL_HAVE_PLATFORM_EGL
gst_egl_image_memory_init ();
diff --git a/gst-libs/gst/gl/gstglformat.c b/gst-libs/gst/gl/gstglformat.c
new file mode 100644
index 000000000..6d9f4a908
--- /dev/null
+++ b/gst-libs/gst/gl/gstglformat.c
@@ -0,0 +1,358 @@
+/*
+ * GStreamer
+ * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gl/gstglformat.h>
+#include <gst/gl/gstglcontext.h>
+
+#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
+#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
+#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
+#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
+#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
+
+#ifndef GL_RGBA8
+#define GL_RGBA8 0x8058
+#endif
+#ifndef GL_RED
+#define GL_RED 0x1903
+#endif
+#ifndef GL_RG
+#define GL_RG 0x8227
+#endif
+#ifndef GL_R8
+#define GL_R8 0x8229
+#endif
+#ifndef GL_RG8
+#define GL_RG8 0x822B
+#endif
+
+static inline guint
+_gl_format_n_components (guint format)
+{
+ switch (format) {
+ case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
+ case GL_RGBA:
+ return 4;
+ case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
+ case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
+ case GL_RGB:
+ return 3;
+ case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
+ case GST_VIDEO_GL_TEXTURE_TYPE_RG:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RG:
+ return 2;
+ case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
+ case GST_VIDEO_GL_TEXTURE_TYPE_R:
+ case GL_LUMINANCE:
+ case GL_RED:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline guint
+_gl_type_n_components (guint type)
+{
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ return 1;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return 3;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+static inline guint
+_gl_type_n_bytes (guint type)
+{
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ return 1;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return 2;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+guint
+gst_gl_format_type_n_bytes (guint format, guint type)
+{
+ return _gl_format_n_components (format) / _gl_type_n_components (type) *
+ _gl_type_n_bytes (type);
+}
+
+guint
+gst_gl_texture_type_n_bytes (GstVideoGLTextureType tex_format)
+{
+ guint format, type;
+
+ format = gst_gl_format_from_gl_texture_type (tex_format);
+ type = GL_UNSIGNED_BYTE;
+ if (tex_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ type = GL_UNSIGNED_SHORT_5_6_5;
+
+ return gst_gl_format_type_n_bytes (format, type);
+}
+
+guint
+gst_gl_format_from_gl_texture_type (GstVideoGLTextureType tex_format)
+{
+ switch (tex_format) {
+ case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
+ return GL_LUMINANCE_ALPHA;
+ case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
+ return GL_LUMINANCE;
+ case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
+ return GL_RGBA;
+ case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
+ case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
+ return GL_RGB;
+ case GST_VIDEO_GL_TEXTURE_TYPE_RG:
+ return GL_RG;
+ case GST_VIDEO_GL_TEXTURE_TYPE_R:
+ return GL_RED;
+ default:
+ return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
+ }
+}
+
+GstVideoGLTextureType
+gst_gl_texture_type_from_format (GstGLContext * context,
+ GstVideoFormat v_format, guint plane)
+{
+ gboolean texture_rg =
+ gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
+ || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)
+ || gst_gl_context_check_feature (context, "GL_ARB_texture_rg")
+ || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0);
+ guint n_plane_components;
+
+ switch (v_format) {
+ case GST_VIDEO_FORMAT_RGBx:
+ case GST_VIDEO_FORMAT_BGRx:
+ case GST_VIDEO_FORMAT_xRGB:
+ case GST_VIDEO_FORMAT_xBGR:
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_AYUV:
+ n_plane_components = 4;
+ break;
+ case GST_VIDEO_FORMAT_RGB:
+ case GST_VIDEO_FORMAT_BGR:
+ n_plane_components = 3;
+ break;
+ case GST_VIDEO_FORMAT_RGB16:
+ case GST_VIDEO_FORMAT_BGR16:
+ return GST_VIDEO_GL_TEXTURE_TYPE_RGB16;
+ case GST_VIDEO_FORMAT_GRAY16_BE:
+ case GST_VIDEO_FORMAT_GRAY16_LE:
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_UYVY:
+ n_plane_components = 2;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV21:
+ n_plane_components = plane == 0 ? 1 : 2;
+ break;
+ case GST_VIDEO_FORMAT_GRAY8:
+ case GST_VIDEO_FORMAT_Y444:
+ case GST_VIDEO_FORMAT_Y42B:
+ case GST_VIDEO_FORMAT_Y41B:
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
+ n_plane_components = 1;
+ break;
+ default:
+ n_plane_components = 4;
+ g_assert_not_reached ();
+ break;
+ }
+
+ switch (n_plane_components) {
+ case 4:
+ return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
+ break;
+ case 3:
+ return GST_VIDEO_GL_TEXTURE_TYPE_RGB;
+ break;
+ case 2:
+ return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_RG :
+ GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA;
+ break;
+ case 1:
+ return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_R :
+ GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
+}
+
+guint
+gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
+ guint format, guint type)
+{
+ gboolean ext_texture_rg =
+ gst_gl_context_check_feature (context, "GL_EXT_texture_rg");
+
+ switch (format) {
+ case GL_RGBA:
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ return USING_GLES2 (context)
+ && !USING_GLES3 (context) ? GL_RGBA : GL_RGBA8;
+ break;
+ }
+ break;
+ case GL_RGB:
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ return GL_RGB8;
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return GL_RGB;
+ break;
+ }
+ break;
+ case GL_RG:
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
+ return GL_RG;
+ return GL_RG8;
+ break;
+ }
+ break;
+ case GL_RED:
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
+ return GL_RED;
+ return GL_R8;
+ break;
+ }
+ break;
+ case GL_LUMINANCE:
+ return GL_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ return GL_LUMINANCE_ALPHA;
+ break;
+ case GL_ALPHA:
+ return GL_ALPHA;
+ break;
+ default:
+ break;
+ }
+
+ g_assert_not_reached ();
+ return 0;
+}
+
+const gchar *
+gst_gl_texture_target_to_string (GstGLTextureTarget target)
+{
+ switch (target) {
+ case GST_GL_TEXTURE_TARGET_2D:
+ return GST_GL_TEXTURE_TARGET_2D_STR;
+ case GST_GL_TEXTURE_TARGET_RECTANGLE:
+ return GST_GL_TEXTURE_TARGET_RECTANGLE_STR;
+ case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
+ return GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR;
+ default:
+ return NULL;
+ }
+}
+
+GstGLTextureTarget
+gst_gl_texture_target_from_string (const gchar * str)
+{
+ if (!str)
+ return GST_GL_TEXTURE_TARGET_NONE;
+
+ if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_2D_STR) == 0)
+ return GST_GL_TEXTURE_TARGET_2D;
+ if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_RECTANGLE_STR) == 0)
+ return GST_GL_TEXTURE_TARGET_RECTANGLE;
+ if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR) == 0)
+ return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
+
+ return GST_GL_TEXTURE_TARGET_NONE;
+}
+
+guint
+gst_gl_texture_target_to_gl (GstGLTextureTarget target)
+{
+ switch (target) {
+ case GST_GL_TEXTURE_TARGET_2D:
+ return GL_TEXTURE_2D;
+ case GST_GL_TEXTURE_TARGET_RECTANGLE:
+ return GL_TEXTURE_RECTANGLE;
+ case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
+ return GL_TEXTURE_EXTERNAL_OES;
+ default:
+ return 0;
+ }
+}
+
+GstGLTextureTarget
+gst_gl_texture_target_from_gl (guint target)
+{
+ switch (target) {
+ case GL_TEXTURE_2D:
+ return GST_GL_TEXTURE_TARGET_2D;
+ case GL_TEXTURE_RECTANGLE:
+ return GST_GL_TEXTURE_TARGET_RECTANGLE;
+ case GL_TEXTURE_EXTERNAL_OES:
+ return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
+ default:
+ return GST_GL_TEXTURE_TARGET_NONE;
+ }
+}
+
+const gchar *
+gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target)
+{
+ switch (target) {
+ case GST_GL_TEXTURE_TARGET_2D:
+ return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D;
+ case GST_GL_TEXTURE_TARGET_RECTANGLE:
+ return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE;
+ case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
+ return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES;
+ default:
+ return NULL;
+ }
+}
diff --git a/gst-libs/gst/gl/gstglformat.h b/gst-libs/gst/gl/gstglformat.h
new file mode 100644
index 000000000..c8e67645f
--- /dev/null
+++ b/gst-libs/gst/gl/gstglformat.h
@@ -0,0 +1,58 @@
+/*
+ * GStreamer
+ * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _GST_GL_FORMAT_H_
+#define _GST_GL_FORMAT_H_
+
+#include <gst/gst.h>
+
+#include <gst/gl/gstgl_fwd.h>
+#include <gst/video/video.h>
+
+#define GST_GL_TEXTURE_TARGET_2D_STR "2D"
+#define GST_GL_TEXTURE_TARGET_RECTANGLE_STR "rectangle"
+#define GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR "external-oes"
+
+#define GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D "GstBufferPoolOptionGLTextureTarget2D"
+#define GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE "GstBufferPoolOptionGLTextureTargetRectangle"
+#define GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES "GstBufferPoolOptionGLTextureTargetExternalOES"
+
+G_BEGIN_DECLS
+
+guint gst_gl_format_type_n_bytes (guint format,
+ guint type);
+guint gst_gl_texture_type_n_bytes (GstVideoGLTextureType tex_format);
+guint gst_gl_format_from_gl_texture_type (GstVideoGLTextureType tex_format);
+GstVideoGLTextureType gst_gl_texture_type_from_format (GstGLContext * context,
+ GstVideoFormat v_format,
+ guint plane);
+guint gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
+ guint format,
+ guint type);
+
+GstGLTextureTarget gst_gl_texture_target_from_string (const gchar * str);
+const gchar * gst_gl_texture_target_to_string (GstGLTextureTarget target);
+guint gst_gl_texture_target_to_gl (GstGLTextureTarget target);
+GstGLTextureTarget gst_gl_texture_target_from_gl (guint target);
+const gchar * gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target);
+
+G_END_DECLS
+
+#endif /* _GST_GL_FORMAT_H_ */
diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c
index c8bd9179f..51930cf55 100644
--- a/gst-libs/gst/gl/gstglmemory.c
+++ b/gst-libs/gst/gl/gstglmemory.c
@@ -1,6 +1,6 @@
/*
* GStreamer
- * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
+ * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -26,8 +26,8 @@
#include <gst/video/video.h>
-#include "gstglmemory.h"
-#include "gstglutils.h"
+#include <gst/gl/gstglbasememory.h>
+#include <gst/gl/gstglmemory.h>
/**
* SECTION:gstglmemory
@@ -60,50 +60,10 @@
#define GL_MEM_HEIGHT(gl_mem) _get_plane_height (&gl_mem->info, gl_mem->plane)
#define GL_MEM_STRIDE(gl_mem) GST_VIDEO_INFO_PLANE_STRIDE (&gl_mem->info, gl_mem->plane)
-#define CONTEXT_SUPPORTS_PBO_UPLOAD(context) \
- (gst_gl_context_check_gl_version (context, \
- GST_GL_API_OPENGL | GST_GL_API_OPENGL3, 2, 1) \
- || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
-#define CONTEXT_SUPPORTS_PBO_DOWNLOAD(context) \
- (gst_gl_context_check_gl_version (context, \
- GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2, 3, 0))
-
GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
#define GST_CAT_DEFAULT GST_CAT_GL_MEMORY
-static GstAllocator *_gl_allocator;
-
/* compatability definitions... */
-#ifndef GL_RGBA8
-#define GL_RGBA8 0x8058
-#endif
-#ifndef GL_RED
-#define GL_RED 0x1903
-#endif
-#ifndef GL_RG
-#define GL_RG 0x8227
-#endif
-#ifndef GL_R8
-#define GL_R8 0x8229
-#endif
-#ifndef GL_RG8
-#define GL_RG8 0x822B
-#endif
-#ifndef GL_PIXEL_PACK_BUFFER
-#define GL_PIXEL_PACK_BUFFER 0x88EB
-#endif
-#ifndef GL_PIXEL_UNPACK_BUFFER
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
-#endif
-#ifndef GL_STREAM_READ
-#define GL_STREAM_READ 0x88E1
-#endif
-#ifndef GL_STREAM_DRAW
-#define GL_STREAM_DRAW 0x88E0
-#endif
-#ifndef GL_STREAM_COPY
-#define GL_STREAM_COPY 0x88E2
-#endif
#ifndef GL_UNPACK_ROW_LENGTH
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif
@@ -115,8 +75,8 @@ static GstAllocator *_gl_allocator;
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#endif
-G_DEFINE_TYPE (GstGLAllocator, gst_gl_allocator,
- GST_TYPE_GL_BASE_BUFFER_ALLOCATOR);
+G_DEFINE_ABSTRACT_TYPE (GstGLMemoryAllocator, gst_gl_memory_allocator,
+ GST_TYPE_GL_BASE_MEMORY_ALLOCATOR);
typedef struct
{
@@ -124,9 +84,8 @@ typedef struct
GstGLMemory *src;
GstVideoGLTextureType out_format;
guint out_width, out_height;
- guint out_stride;
- gboolean respecify;
GstGLTextureTarget tex_target;
+ GstVideoGLTextureType tex_type;
/* inout */
guint tex_id;
/* out */
@@ -134,316 +93,6 @@ typedef struct
} GstGLMemoryCopyParams;
static inline guint
-_gl_format_n_components (guint format)
-{
- switch (format) {
- case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
- case GL_RGBA:
- return 4;
- case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
- case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
- case GL_RGB:
- return 3;
- case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
- case GST_VIDEO_GL_TEXTURE_TYPE_RG:
- case GL_LUMINANCE_ALPHA:
- case GL_RG:
- return 2;
- case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
- case GST_VIDEO_GL_TEXTURE_TYPE_R:
- case GL_LUMINANCE:
- case GL_RED:
- return 1;
- default:
- return 0;
- }
-}
-
-static inline guint
-_gl_type_n_components (guint type)
-{
- switch (type) {
- case GL_UNSIGNED_BYTE:
- return 1;
- case GL_UNSIGNED_SHORT_5_6_5:
- return 3;
- default:
- g_assert_not_reached ();
- return 0;
- }
-}
-
-static inline guint
-_gl_type_n_bytes (guint type)
-{
- switch (type) {
- case GL_UNSIGNED_BYTE:
- return 1;
- case GL_UNSIGNED_SHORT_5_6_5:
- return 2;
- default:
- g_assert_not_reached ();
- return 0;
- }
-}
-
-static inline guint
-_gl_format_type_n_bytes (guint format, guint type)
-{
- return _gl_format_n_components (format) / _gl_type_n_components (type) *
- _gl_type_n_bytes (type);
-}
-
-static inline guint
-_gl_texture_type_n_bytes (GstVideoGLTextureType tex_format)
-{
- guint format, type;
-
- format = gst_gl_format_from_gl_texture_type (tex_format);
- type = GL_UNSIGNED_BYTE;
- if (tex_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
- type = GL_UNSIGNED_SHORT_5_6_5;
-
- return _gl_format_type_n_bytes (format, type);
-}
-
-guint
-gst_gl_format_from_gl_texture_type (GstVideoGLTextureType tex_format)
-{
- switch (tex_format) {
- case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
- return GL_LUMINANCE_ALPHA;
- case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
- return GL_LUMINANCE;
- case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
- return GL_RGBA;
- case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
- case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
- return GL_RGB;
- case GST_VIDEO_GL_TEXTURE_TYPE_RG:
- return GL_RG;
- case GST_VIDEO_GL_TEXTURE_TYPE_R:
- return GL_RED;
- default:
- return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
- }
-}
-
-GstVideoGLTextureType
-gst_gl_texture_type_from_format (GstGLContext * context,
- GstVideoFormat v_format, guint plane)
-{
- gboolean texture_rg =
- gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
- || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)
- || gst_gl_context_check_feature (context, "GL_ARB_texture_rg")
- || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0);
- guint n_plane_components;
-
- switch (v_format) {
- case GST_VIDEO_FORMAT_RGBx:
- case GST_VIDEO_FORMAT_BGRx:
- case GST_VIDEO_FORMAT_xRGB:
- case GST_VIDEO_FORMAT_xBGR:
- case GST_VIDEO_FORMAT_RGBA:
- case GST_VIDEO_FORMAT_BGRA:
- case GST_VIDEO_FORMAT_ARGB:
- case GST_VIDEO_FORMAT_ABGR:
- case GST_VIDEO_FORMAT_AYUV:
- n_plane_components = 4;
- break;
- case GST_VIDEO_FORMAT_RGB:
- case GST_VIDEO_FORMAT_BGR:
- n_plane_components = 3;
- break;
- case GST_VIDEO_FORMAT_RGB16:
- case GST_VIDEO_FORMAT_BGR16:
- return GST_VIDEO_GL_TEXTURE_TYPE_RGB16;
- case GST_VIDEO_FORMAT_GRAY16_BE:
- case GST_VIDEO_FORMAT_GRAY16_LE:
- case GST_VIDEO_FORMAT_YUY2:
- case GST_VIDEO_FORMAT_UYVY:
- n_plane_components = 2;
- break;
- case GST_VIDEO_FORMAT_NV12:
- case GST_VIDEO_FORMAT_NV21:
- n_plane_components = plane == 0 ? 1 : 2;
- break;
- case GST_VIDEO_FORMAT_GRAY8:
- case GST_VIDEO_FORMAT_Y444:
- case GST_VIDEO_FORMAT_Y42B:
- case GST_VIDEO_FORMAT_Y41B:
- case GST_VIDEO_FORMAT_I420:
- case GST_VIDEO_FORMAT_YV12:
- n_plane_components = 1;
- break;
- default:
- n_plane_components = 4;
- g_assert_not_reached ();
- break;
- }
-
- switch (n_plane_components) {
- case 4:
- return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
- break;
- case 3:
- return GST_VIDEO_GL_TEXTURE_TYPE_RGB;
- break;
- case 2:
- return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_RG :
- GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA;
- break;
- case 1:
- return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_R :
- GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
-}
-
-guint
-gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
- guint format, guint type)
-{
- gboolean ext_texture_rg =
- gst_gl_context_check_feature (context, "GL_EXT_texture_rg");
-
- switch (format) {
- case GL_RGBA:
- switch (type) {
- case GL_UNSIGNED_BYTE:
- return USING_GLES2 (context)
- && !USING_GLES3 (context) ? GL_RGBA : GL_RGBA8;
- break;
- }
- break;
- case GL_RGB:
- switch (type) {
- case GL_UNSIGNED_BYTE:
- return GL_RGB8;
- break;
- case GL_UNSIGNED_SHORT_5_6_5:
- return GL_RGB;
- break;
- }
- break;
- case GL_RG:
- switch (type) {
- case GL_UNSIGNED_BYTE:
- if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
- return GL_RG;
- return GL_RG8;
- break;
- }
- break;
- case GL_RED:
- switch (type) {
- case GL_UNSIGNED_BYTE:
- if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
- return GL_RED;
- return GL_R8;
- break;
- }
- break;
- case GL_LUMINANCE:
- return GL_LUMINANCE;
- break;
- case GL_LUMINANCE_ALPHA:
- return GL_LUMINANCE_ALPHA;
- break;
- case GL_ALPHA:
- return GL_ALPHA;
- break;
- default:
- break;
- }
-
- g_assert_not_reached ();
- return 0;
-}
-
-const gchar *
-gst_gl_texture_target_to_string (GstGLTextureTarget target)
-{
- switch (target) {
- case GST_GL_TEXTURE_TARGET_2D:
- return GST_GL_TEXTURE_TARGET_2D_STR;
- case GST_GL_TEXTURE_TARGET_RECTANGLE:
- return GST_GL_TEXTURE_TARGET_RECTANGLE_STR;
- case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
- return GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR;
- default:
- return NULL;
- }
-}
-
-GstGLTextureTarget
-gst_gl_texture_target_from_string (const gchar * str)
-{
- if (!str)
- return GST_GL_TEXTURE_TARGET_NONE;
-
- if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_2D_STR) == 0)
- return GST_GL_TEXTURE_TARGET_2D;
- if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_RECTANGLE_STR) == 0)
- return GST_GL_TEXTURE_TARGET_RECTANGLE;
- if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR) == 0)
- return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
-
- return GST_GL_TEXTURE_TARGET_NONE;
-}
-
-guint
-gst_gl_texture_target_to_gl (GstGLTextureTarget target)
-{
- switch (target) {
- case GST_GL_TEXTURE_TARGET_2D:
- return GL_TEXTURE_2D;
- case GST_GL_TEXTURE_TARGET_RECTANGLE:
- return GL_TEXTURE_RECTANGLE;
- case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
- return GL_TEXTURE_EXTERNAL_OES;
- default:
- return 0;
- }
-}
-
-GstGLTextureTarget
-gst_gl_texture_target_from_gl (guint target)
-{
- switch (target) {
- case GL_TEXTURE_2D:
- return GST_GL_TEXTURE_TARGET_2D;
- case GL_TEXTURE_RECTANGLE:
- return GST_GL_TEXTURE_TARGET_RECTANGLE;
- case GL_TEXTURE_EXTERNAL_OES:
- return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
- default:
- return GST_GL_TEXTURE_TARGET_NONE;
- }
-}
-
-const gchar *
-gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target)
-{
- switch (target) {
- case GST_GL_TEXTURE_TARGET_2D:
- return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D;
- case GST_GL_TEXTURE_TARGET_RECTANGLE:
- return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE;
- case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
- return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES;
- default:
- return NULL;
- }
-}
-
-static inline guint
_get_plane_width (GstVideoInfo * info, guint plane)
{
if (GST_VIDEO_INFO_IS_YUV (info))
@@ -467,96 +116,6 @@ _get_plane_height (GstVideoInfo * info, guint plane)
return GST_VIDEO_INFO_HEIGHT (info);
}
-typedef struct _GenTexture
-{
- guint width, height;
- GLenum gl_target;
- GLenum gl_format;
- GLenum gl_type;
- guint result;
-} GenTexture;
-
-/* find the difference between the start of the plane and where the video
- * data starts in the plane */
-static gsize
-_find_plane_frame_start (GstGLMemory * gl_mem)
-{
- gsize plane_start;
- gint i;
-
- /* find the start of the plane data including padding */
- plane_start = 0;
- for (i = 0; i < gl_mem->plane; i++) {
- plane_start +=
- gst_gl_get_plane_data_size (&gl_mem->info, &gl_mem->valign, i);
- }
-
- /* offset between the plane data start and where the video frame starts */
- return (GST_VIDEO_INFO_PLANE_OFFSET (&gl_mem->info,
- gl_mem->plane)) - plane_start + gl_mem->mem.mem.offset;
-}
-
-static void
-_upload_memory (GstGLMemory * gl_mem, GstMapInfo * info, gsize maxsize)
-{
- GstGLContext *context = gl_mem->mem.context;
- const GstGLFuncs *gl;
- GLenum gl_format, gl_type, gl_target;
- gpointer data;
- gsize plane_start;
-
- if ((gl_mem->transfer_state & GST_GL_MEMORY_TRANSFER_NEED_UPLOAD) == 0)
- return;
-
- gl = context->gl_vtable;
-
- gl_type = GL_UNSIGNED_BYTE;
- if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
- gl_type = GL_UNSIGNED_SHORT_5_6_5;
-
- gl_format = gst_gl_format_from_gl_texture_type (gl_mem->tex_type);
- gl_target = gst_gl_texture_target_to_gl (gl_mem->tex_target);
-
- if (USING_OPENGL (context) || USING_GLES3 (context)
- || USING_OPENGL3 (context)) {
- gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->unpack_length);
- } else if (USING_GLES2 (context)) {
- gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->unpack_length);
- }
-
- GST_LOG ("upload for texture id:%u, with pbo %u %ux%u",
- gl_mem->tex_id, gl_mem->mem.id, gl_mem->tex_width,
- GL_MEM_HEIGHT (gl_mem));
-
- /* find the start of the plane data including padding */
- plane_start = _find_plane_frame_start (gl_mem);
-
- if (gl_mem->mem.id && CONTEXT_SUPPORTS_PBO_UPLOAD (context)) {
- gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, gl_mem->mem.id);
- data = (void *) plane_start;
- } else {
- data = (gpointer) ((gintptr) plane_start + (gintptr) gl_mem->mem.data);
- }
-
- gl->BindTexture (gl_target, gl_mem->tex_id);
- gl->TexSubImage2D (gl_target, 0, 0, 0, gl_mem->tex_width,
- GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, data);
-
- if (gl_mem->mem.id && CONTEXT_SUPPORTS_PBO_UPLOAD (context))
- gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
-
- /* Reset to default values */
- if (USING_OPENGL (context) || USING_GLES3 (context)) {
- gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0);
- } else if (USING_GLES2 (context)) {
- gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4);
- }
-
- gl->BindTexture (gl_target, 0);
-
- gl_mem->transfer_state &= ~GST_GL_MEMORY_TRANSFER_NEED_UPLOAD;
-}
-
static inline void
_calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
{
@@ -567,7 +126,7 @@ _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
gl_mem->unpack_length = 1;
gl_mem->tex_width = GL_MEM_WIDTH (gl_mem);
- n_gl_bytes = _gl_texture_type_n_bytes (gl_mem->tex_type);
+ n_gl_bytes = gst_gl_texture_type_n_bytes (gl_mem->tex_type);
if (n_gl_bytes == 0) {
GST_ERROR ("Unsupported texture type %d", gl_mem->tex_type);
return;
@@ -585,8 +144,8 @@ _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
((GL_MEM_WIDTH (gl_mem) * n_gl_bytes) + j - 1) & ~(j - 1);
if (round_up_j == GL_MEM_STRIDE (gl_mem)) {
- GST_LOG ("Found alignment of %u based on width "
- "(with plane width:%u, plane stride:%u and pixel stride:%u. "
+ GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on "
+ "width (with plane width:%u, plane stride:%u and pixel stride:%u. "
"RU%u(%u*%u) = %u)", j, GL_MEM_WIDTH (gl_mem),
GL_MEM_STRIDE (gl_mem), n_gl_bytes, j, GL_MEM_WIDTH (gl_mem),
n_gl_bytes, round_up_j);
@@ -608,8 +167,8 @@ _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
guint round_up_j = ((GL_MEM_STRIDE (gl_mem)) + j - 1) & ~(j - 1);
if (round_up_j == (GL_MEM_STRIDE (gl_mem))) {
- GST_LOG ("Found alignment of %u based on "
- "stride (with plane stride:%u and pixel stride:%u. "
+ GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based "
+ "on stride (with plane stride:%u and pixel stride:%u. "
"RU%u(%u) = %u)", j, GL_MEM_STRIDE (gl_mem), n_gl_bytes, j,
GL_MEM_STRIDE (gl_mem), round_up_j);
@@ -624,11 +183,10 @@ _calculate_unpack_length (GstGLMemory * gl_mem, GstGLContext * context)
}
if (j < n_gl_bytes) {
- GST_ERROR
- ("Failed to find matching alignment. Image may "
- "look corrupted. plane width:%u, plane stride:%u and pixel "
- "stride:%u", GL_MEM_WIDTH (gl_mem), GL_MEM_STRIDE (gl_mem),
- n_gl_bytes);
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to find matching "
+ "alignment. Image may look corrupted. plane width:%u, "
+ "plane stride:%u and pixel stride:%u", GL_MEM_WIDTH (gl_mem),
+ GL_MEM_STRIDE (gl_mem), n_gl_bytes);
}
}
}
@@ -670,10 +228,9 @@ _new_texture (GstGLContext * context, guint target, guint internal_format,
}
static gboolean
-_gl_mem_create (GstGLMemory * gl_mem, GError ** error)
+_gl_tex_create (GstGLMemory * gl_mem, GError ** error)
{
GstGLContext *context = gl_mem->mem.context;
- const GstGLFuncs *gl = context->gl_vtable;
GLenum internal_format;
GLenum tex_format;
GLenum tex_type;
@@ -683,9 +240,6 @@ _gl_mem_create (GstGLMemory * gl_mem, GError ** error)
if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
tex_type = GL_UNSIGNED_SHORT_5_6_5;
- GST_TRACE ("Generating texture format:%u type:%u dimensions:%ux%u",
- tex_format, tex_type, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem));
-
internal_format =
gst_gl_sized_gl_format_from_gl_format_type (context, tex_format,
tex_type);
@@ -695,31 +249,20 @@ _gl_mem_create (GstGLMemory * gl_mem, GError ** error)
_new_texture (context, gst_gl_texture_target_to_gl (gl_mem->tex_target),
internal_format, tex_format, tex_type, gl_mem->tex_width,
GL_MEM_HEIGHT (gl_mem));
- }
- GST_LOG ("generated texture id:%d", gl_mem->tex_id);
-
- if (USING_OPENGL (context) || USING_OPENGL3 (context)
- || USING_GLES3 (context)) {
- /* FIXME: lazy init this for resource constrained platforms
- * Will need to fix pbo detection based on the existence of the mem.id then */
- gl->GenBuffers (1, &gl_mem->mem.id);
- gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, gl_mem->mem.id);
- gl->BufferData (GL_PIXEL_UNPACK_BUFFER, gl_mem->mem.mem.maxsize, NULL,
- GL_STREAM_DRAW);
- gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
- GST_LOG ("generated pbo %u", gl_mem->mem.id);
+ GST_TRACE ("Generating texture id:%u format:%u type:%u dimensions:%ux%u",
+ gl_mem->tex_id, tex_format, tex_type, gl_mem->tex_width,
+ GL_MEM_HEIGHT (gl_mem));
}
return TRUE;
}
-static void
-_gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
- GstGLContext * context, GstGLTextureTarget target,
- GstAllocationParams * params, GstVideoInfo * info,
- GstVideoAlignment * valign, guint plane, gpointer user_data,
- GDestroyNotify notify)
+void
+gst_gl_memory_init (GstGLMemory * mem, GstAllocator * allocator,
+ GstMemory * parent, GstGLContext * context, GstGLTextureTarget target,
+ GstAllocationParams * params, GstVideoInfo * info, guint plane,
+ GstVideoAlignment * valign, GDestroyNotify notify, gpointer user_data)
{
const gchar *target_str;
gsize size;
@@ -749,47 +292,27 @@ _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
size = gst_gl_get_plane_data_size (info, valign, plane);
- /* we always operate on 2D textures unless we're dealing with wrapped textures */
mem->tex_target = target;
mem->tex_type =
gst_gl_texture_type_from_format (context, GST_VIDEO_INFO_FORMAT (info),
plane);
mem->plane = plane;
- mem->notify = notify;
- mem->user_data = user_data;
_calculate_unpack_length (mem, context);
- /* calls _gl_mem_create() */
- gst_gl_base_buffer_init ((GstGLBaseBuffer *) mem, allocator, parent, context,
- params, size);
+ gst_gl_base_memory_init ((GstGLBaseMemory *) mem, allocator, parent, context,
+ params, size, notify, user_data);
target_str = gst_gl_texture_target_to_string (target);
- GST_DEBUG ("new GL texture context:%" GST_PTR_FORMAT " memory:%p target:%s "
- "format:%u dimensions:%ux%u stride:%u size:%" G_GSIZE_FORMAT, context,
- mem, target_str, mem->tex_type, mem->tex_width, GL_MEM_HEIGHT (mem),
- GL_MEM_STRIDE (mem), mem->mem.mem.size);
-}
-
-static GstGLMemory *
-_gl_mem_new (GstAllocator * allocator, GstMemory * parent,
- GstGLContext * context, GstGLTextureTarget target,
- GstAllocationParams * params, GstVideoInfo * info,
- GstVideoAlignment * valign, guint plane, gpointer user_data,
- GDestroyNotify notify)
-{
- GstGLMemory *mem;
- mem = g_slice_new0 (GstGLMemory);
- mem->texture_wrapped = FALSE;
-
- _gl_mem_init (mem, allocator, parent, context, target, params, info, valign,
- plane, user_data, notify);
-
- return mem;
+ GST_CAT_DEBUG (GST_CAT_GL_MEMORY, "new GL texture context:%"
+ GST_PTR_FORMAT " memory:%p target:%s format:%u dimensions:%ux%u "
+ "stride:%u size:%" G_GSIZE_FORMAT, context, mem, target_str,
+ mem->tex_type, mem->tex_width, GL_MEM_HEIGHT (mem), GL_MEM_STRIDE (mem),
+ mem->mem.mem.size);
}
-static gboolean
-_gl_mem_read_pixels (GstGLMemory * gl_mem, gpointer read_pointer)
+gboolean
+gst_gl_memory_read_pixels (GstGLMemory * gl_mem, gpointer read_pointer)
{
GstGLContext *context = gl_mem->mem.context;
const GstGLFuncs *gl = context->gl_vtable;
@@ -825,64 +348,8 @@ _gl_mem_read_pixels (GstGLMemory * gl_mem, gpointer read_pointer)
return TRUE;
}
-static gboolean
-_read_pixels_to_pbo (GstGLMemory * gl_mem)
-{
- const GstGLFuncs *gl = gl_mem->mem.context->gl_vtable;
-
- if (!gl_mem->mem.id || !CONTEXT_SUPPORTS_PBO_DOWNLOAD (gl_mem->mem.context)
- || gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
- || gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA)
- /* unsupported */
- return FALSE;
-
- if (gl_mem->transfer_state & GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD) {
- /* copy texture data into into the pbo and map that */
- gsize plane_start = _find_plane_frame_start (gl_mem);
-
- gl->BindBuffer (GL_PIXEL_PACK_BUFFER, gl_mem->mem.id);
-
- if (!_gl_mem_read_pixels (gl_mem, (gpointer) plane_start)) {
- gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
- return FALSE;
- }
-
- gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
- gl_mem->transfer_state &= ~GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD;
- }
-
- return TRUE;
-}
-
-static gpointer
-_pbo_download_transfer (GstGLMemory * gl_mem, GstMapInfo * info, gsize size)
-{
- GstGLBaseBufferAllocatorClass *alloc_class;
- gpointer data = NULL;
-
- alloc_class =
- GST_GL_BASE_BUFFER_ALLOCATOR_CLASS (gst_gl_allocator_parent_class);
-
- /* texture -> pbo */
- if (info->flags & GST_MAP_READ
- && gl_mem->transfer_state & GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD) {
- GST_CAT_TRACE (GST_CAT_GL_MEMORY, "attempting download of texture %u "
- "using pbo %u", gl_mem->tex_id, gl_mem->mem.id);
-
- if (!_read_pixels_to_pbo (gl_mem))
- return NULL;
- }
-
- /* get a cpu accessible mapping from the pbo */
- gl_mem->mem.target = GL_PIXEL_PACK_BUFFER;
- /* pbo -> data */
- data = alloc_class->map_buffer ((GstGLBaseBuffer *) gl_mem, info, size);
-
- return data;
-}
-
static gpointer
-_gl_mem_download_get_tex_image (GstGLMemory * gl_mem, GstMapInfo * info,
+_gl_tex_download_get_tex_image (GstGLMemory * gl_mem, GstMapInfo * info,
gsize size)
{
GstGLContext *context = gl_mem->mem.context;
@@ -900,7 +367,8 @@ _gl_mem_download_get_tex_image (GstGLMemory * gl_mem, GstMapInfo * info,
return NULL;
if (info->flags & GST_MAP_READ
- && gl_mem->transfer_state & GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD) {
+ && GST_MEMORY_FLAG_IS_SET (gl_mem,
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)) {
guint format, type;
guint target;
@@ -922,17 +390,19 @@ _gl_mem_download_get_tex_image (GstGLMemory * gl_mem, GstMapInfo * info,
}
static gpointer
-_gl_mem_download_read_pixels (GstGLMemory * gl_mem, GstMapInfo * info,
+_gl_tex_download_read_pixels (GstGLMemory * gl_mem, GstMapInfo * info,
gsize size)
{
if (size != -1 && size != ((GstMemory *) gl_mem)->maxsize)
return NULL;
if (info->flags & GST_MAP_READ
- && gl_mem->transfer_state & GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD) {
- GST_CAT_TRACE (GST_CAT_GL_MEMORY, "attempting download of texture %u "
- "using glReadPixels", gl_mem->tex_id);
- if (!_gl_mem_read_pixels (gl_mem, gl_mem->mem.data))
+ && GST_MEMORY_FLAG_IS_SET (gl_mem,
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)) {
+ GST_CAT_TRACE (GST_CAT_GL_MEMORY,
+ "attempting download of texture %u " "using glReadPixels",
+ gl_mem->tex_id);
+ if (!gst_gl_memory_read_pixels (gl_mem, gl_mem->mem.data))
return NULL;
}
@@ -940,410 +410,297 @@ _gl_mem_download_read_pixels (GstGLMemory * gl_mem, GstMapInfo * info,
}
static gpointer
-_gl_mem_map_cpu_access (GstGLMemory * gl_mem, GstMapInfo * info, gsize size)
+_gl_tex_map_cpu_access (GstGLMemory * gl_mem, GstMapInfo * info, gsize size)
{
gpointer data = NULL;
- gst_gl_base_buffer_alloc_data ((GstGLBaseBuffer *) gl_mem);
+ if (!gst_gl_base_memory_alloc_data (GST_GL_BASE_MEMORY_CAST (gl_mem)))
+ return NULL;
- if (!data && gl_mem->mem.id
- && CONTEXT_SUPPORTS_PBO_DOWNLOAD (gl_mem->mem.context))
- data = _pbo_download_transfer (gl_mem, info, size);
if (!data)
- data = _gl_mem_download_get_tex_image (gl_mem, info, size);
+ data = _gl_tex_download_get_tex_image (gl_mem, info, size);
if (!data)
- data = _gl_mem_download_read_pixels (gl_mem, info, size);
+ data = _gl_tex_download_read_pixels (gl_mem, info, size);
return data;
}
-static gpointer
-_gl_mem_map_buffer (GstGLMemory * gl_mem, GstMapInfo * info, gsize maxsize)
+static void
+_upload_cpu_write (GstGLMemory * gl_mem, GstMapInfo * info, gsize maxsize)
{
- GstGLBaseBufferAllocatorClass *alloc_class;
+ GstGLContext *context = gl_mem->mem.context;
+ const GstGLFuncs *gl;
+ GLenum gl_format, gl_type, gl_target;
gpointer data;
+ gsize plane_start;
- alloc_class =
- GST_GL_BASE_BUFFER_ALLOCATOR_CLASS (gst_gl_allocator_parent_class);
+ if (!GST_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD))
+ return;
- if ((info->flags & GST_MAP_GL) == GST_MAP_GL) {
- if (gl_mem->tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
- return &gl_mem->tex_id;
+ gl = context->gl_vtable;
- if ((info->flags & GST_MAP_READ) == GST_MAP_READ) {
- GST_TRACE ("mapping GL texture:%u for reading", gl_mem->tex_id);
+ gl_type = GL_UNSIGNED_BYTE;
+ if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ gl_type = GL_UNSIGNED_SHORT_5_6_5;
- if (gl_mem->mem.id && CONTEXT_SUPPORTS_PBO_UPLOAD (gl_mem->mem.context)) {
- gl_mem->mem.target = GL_PIXEL_UNPACK_BUFFER;
- /* data -> pbo */
- alloc_class->map_buffer ((GstGLBaseBuffer *) gl_mem, info, maxsize);
- }
- /* pbo -> texture */
- _upload_memory (gl_mem, info, maxsize);
- }
+ gl_format = gst_gl_format_from_gl_texture_type (gl_mem->tex_type);
+ gl_target = gst_gl_texture_target_to_gl (gl_mem->tex_target);
- if ((info->flags & GST_MAP_WRITE) == GST_MAP_WRITE) {
- GST_TRACE ("mapping GL texture:%u for writing", gl_mem->tex_id);
- gl_mem->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD;
- }
- gl_mem->transfer_state &= ~GST_GL_MEMORY_TRANSFER_NEED_UPLOAD;
+ if (USING_OPENGL (context) || USING_GLES3 (context)
+ || USING_OPENGL3 (context)) {
+ gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->unpack_length);
+ } else if (USING_GLES2 (context)) {
+ gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->unpack_length);
+ }
+
+ GST_CAT_LOG (GST_CAT_GL_MEMORY, "upload for texture id:%u, %ux%u",
+ gl_mem->tex_id, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem));
- data = &gl_mem->tex_id;
+ /* find the start of the plane data including padding */
+ plane_start =
+ gst_gl_get_plane_start (&gl_mem->info, &gl_mem->valign,
+ gl_mem->plane) + gl_mem->mem.mem.offset;
+
+ data = (gpointer) ((gintptr) plane_start + (gintptr) gl_mem->mem.data);
+
+ gl->BindTexture (gl_target, gl_mem->tex_id);
+ gl->TexSubImage2D (gl_target, 0, 0, 0, gl_mem->tex_width,
+ GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, data);
+
+ /* Reset to default values */
+ if (USING_OPENGL (context) || USING_GLES3 (context)) {
+ gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+ } else if (USING_GLES2 (context)) {
+ gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ }
+
+ gl->BindTexture (gl_target, 0);
+}
+
+static gpointer
+_default_gl_tex_map (GstGLMemory * gl_mem, GstMapInfo * info, gsize size)
+{
+ if ((info->flags & GST_MAP_GL) == GST_MAP_GL) {
+ _upload_cpu_write (gl_mem, info, size);
+ return &gl_mem->tex_id;
+ } else {
+ return _gl_tex_map_cpu_access (gl_mem, info, size);
+ }
+}
+
+static gpointer
+_gl_tex_map (GstGLMemory * gl_mem, GstMapInfo * info, gsize maxsize)
+{
+ GstGLMemoryAllocatorClass *alloc_class;
+ gpointer data;
+
+ alloc_class = GST_GL_MEMORY_ALLOCATOR_GET_CLASS (gl_mem->mem.mem.allocator);
+
+ if ((info->flags & GST_MAP_GL) == GST_MAP_GL) {
+ if (gl_mem->tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+ return &gl_mem->tex_id;
} else { /* not GL */
if (gl_mem->tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot map External OES textures");
return NULL;
}
-
- data = _gl_mem_map_cpu_access (gl_mem, info, maxsize);
- if (info->flags & GST_MAP_WRITE)
- gl_mem->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_UPLOAD;
- gl_mem->transfer_state &= ~GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD;
}
+ g_return_val_if_fail (alloc_class->map != NULL, NULL);
+ data = alloc_class->map (GST_GL_BASE_MEMORY_CAST (gl_mem), info, maxsize);
+
return data;
}
static void
-_gl_mem_unmap_cpu_access (GstGLMemory * gl_mem, GstMapInfo * info)
+_default_gl_tex_unmap (GstGLMemory * gl_mem, GstMapInfo * info)
{
- GstGLBaseBufferAllocatorClass *alloc_class;
- const GstGLFuncs *gl;
-
- alloc_class =
- GST_GL_BASE_BUFFER_ALLOCATOR_CLASS (gst_gl_allocator_parent_class);
- gl = gl_mem->mem.context->gl_vtable;
-
- if (!gl_mem->mem.id)
- /* PBO's not supported */
- return;
-
- gl_mem->mem.target = GL_PIXEL_PACK_BUFFER;
- alloc_class->unmap_buffer ((GstGLBaseBuffer *) gl_mem, info);
- gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
}
static void
-_gl_mem_unmap_buffer (GstGLMemory * gl_mem, GstMapInfo * info)
+_gl_tex_unmap (GstGLMemory * gl_mem, GstMapInfo * info)
{
- if ((info->flags & GST_MAP_GL) == 0) {
- _gl_mem_unmap_cpu_access (gl_mem, info);
- if (info->flags & GST_MAP_WRITE)
- gl_mem->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_UPLOAD;
- } else {
- if (info->flags & GST_MAP_WRITE)
- gl_mem->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD;
- }
+ GstGLMemoryAllocatorClass *alloc_class;
+
+ alloc_class = GST_GL_MEMORY_ALLOCATOR_GET_CLASS (gl_mem->mem.mem.allocator);
+ g_return_if_fail (alloc_class->unmap != NULL);
+
+ alloc_class->unmap (GST_GL_BASE_MEMORY_CAST (gl_mem), info);
}
-static void
-_gl_mem_copy_thread (GstGLContext * context, gpointer data)
+gboolean
+gst_gl_memory_copy_teximage (GstGLMemory * src, guint tex_id,
+ GstGLTextureTarget out_target, GstVideoGLTextureType out_tex_type,
+ gint out_width, gint out_height)
{
const GstGLFuncs *gl;
- GstGLMemoryCopyParams *copy_params;
- GstGLMemory *src;
- guint tex_id;
- guint out_tex_target;
- GLuint fboId;
- gsize out_width, out_height, out_stride;
- GLuint out_gl_format, out_gl_type;
- GLuint in_gl_format, in_gl_type;
- gsize in_size, out_size;
-
- copy_params = (GstGLMemoryCopyParams *) data;
- src = copy_params->src;
- tex_id = copy_params->tex_id;
- out_tex_target = gst_gl_texture_target_to_gl (copy_params->tex_target);
- out_width = copy_params->out_width;
- out_height = copy_params->out_height;
- out_stride = copy_params->out_stride;
+ guint out_gl_format, out_tex_target;
+ GstMapInfo sinfo;
+ guint src_tex_id;
+ guint fbo;
- gl = context->gl_vtable;
- out_gl_format = gst_gl_format_from_gl_texture_type (copy_params->out_format);
- out_gl_type = GL_UNSIGNED_BYTE;
- if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
- out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
- in_gl_format = gst_gl_format_from_gl_texture_type (src->tex_type);
- in_gl_type = GL_UNSIGNED_BYTE;
- if (src->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
- in_gl_type = GL_UNSIGNED_SHORT_5_6_5;
+ gl = src->mem.context->gl_vtable;
+ out_tex_target = gst_gl_texture_target_to_gl (out_target);
+ out_gl_format = gst_gl_format_from_gl_texture_type (out_tex_type);
if (!gl->GenFramebuffers) {
- gst_gl_context_set_error (context,
- "Context, EXT_framebuffer_object not supported");
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Framebuffer objects not supported");
goto error;
}
- in_size = GL_MEM_HEIGHT (src) * GL_MEM_STRIDE (src);
- out_size = out_height * out_stride;
-
- if (copy_params->respecify) {
- if (in_size != out_size) {
- GST_ERROR ("Cannot copy between textures with backing data of different"
- "sizes. input %" G_GSIZE_FORMAT " output %" G_GSIZE_FORMAT, in_size,
- out_size);
- goto error;
- }
- }
-
- if (!tex_id) {
- guint internal_format;
- guint out_gl_type;
-
- out_gl_type = GL_UNSIGNED_BYTE;
- if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
- out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
-
- internal_format =
- gst_gl_sized_gl_format_from_gl_format_type (context, out_gl_format,
- out_gl_type);
-
- tex_id =
- _new_texture (context, out_tex_target,
- internal_format, out_gl_format, out_gl_type, copy_params->out_width,
- copy_params->out_height);
- }
-
- if (!tex_id) {
- GST_WARNING ("Could not create GL texture with context:%p", context);
+ if (!gst_memory_map (GST_MEMORY_CAST (src), &sinfo,
+ GST_MAP_READ | GST_MAP_GL)) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY,
+ "Failed to map source memory for copying");
+ goto error;
}
+ src_tex_id = *(guint *) sinfo.data;
- GST_LOG ("copying memory %p, tex %u into texture %i",
- src, src->tex_id, tex_id);
+ GST_CAT_LOG (GST_CAT_GL_MEMORY, "copying memory %p, tex %u into "
+ "texture %i", src, src_tex_id, tex_id);
/* FIXME: try and avoid creating and destroying fbo's every copy... */
/* create a framebuffer object */
- gl->GenFramebuffers (1, &fboId);
- gl->BindFramebuffer (GL_FRAMEBUFFER, fboId);
+ gl->GenFramebuffers (1, &fbo);
+ gl->BindFramebuffer (GL_FRAMEBUFFER, fbo);
gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- gst_gl_texture_target_to_gl (src->tex_target), src->tex_id, 0);
+ gst_gl_texture_target_to_gl (src->tex_target), src_tex_id, 0);
// if (!gst_gl_context_check_framebuffer_status (src->context))
// goto fbo_error;
gl->BindTexture (out_tex_target, tex_id);
- if (copy_params->respecify) {
- if (!gl->GenBuffers || !src->mem.id) {
- gst_gl_context_set_error (context, "Cannot reinterpret texture contents "
- "without pixel buffer objects");
- gl->BindTexture (out_tex_target, 0);
- goto fbo_error;
- }
-
- if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2
- && (in_gl_format != GL_RGBA || in_gl_type != GL_UNSIGNED_BYTE)) {
- gst_gl_context_set_error (context, "Cannot copy non RGBA/UNSIGNED_BYTE "
- "textures on GLES2");
- gl->BindTexture (out_tex_target, 0);
- goto fbo_error;
- }
-
- GST_TRACE ("copying texture data with size of %u*%u*%u",
- _gl_format_type_n_bytes (in_gl_format, in_gl_type), src->tex_width,
- GL_MEM_HEIGHT (src));
-
- /* copy tex */
- gl->BindBuffer (GL_PIXEL_PACK_BUFFER, src->mem.id);
- gl->BufferData (GL_PIXEL_PACK_BUFFER, in_size, NULL, GL_STREAM_COPY);
- gl->ReadPixels (0, 0, src->tex_width, GL_MEM_HEIGHT (src), in_gl_format,
- in_gl_type, 0);
- gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
-
- gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, src->mem.id);
- gl->TexSubImage2D (out_tex_target, 0, 0, 0, out_width, out_height,
- out_gl_format, out_gl_type, 0);
-
- gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
- } else { /* different sizes */
- gl->CopyTexImage2D (out_tex_target, 0, out_gl_format, 0, 0, out_width,
- out_height, 0);
- }
+ gl->CopyTexImage2D (out_tex_target, 0, out_gl_format, 0, 0, out_width,
+ out_height, 0);
gl->BindTexture (out_tex_target, 0);
gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
- gl->DeleteFramebuffers (1, &fboId);
-
- copy_params->tex_id = tex_id;
- copy_params->result = TRUE;
-
- return;
+ gl->DeleteFramebuffers (1, &fbo);
-/* ERRORS */
-fbo_error:
- {
- gl->DeleteFramebuffers (1, &fboId);
+ gst_memory_unmap (GST_MEMORY_CAST (src), &sinfo);
- copy_params->tex_id = 0;
- copy_params->result = FALSE;
- return;
- }
+ return TRUE;
error:
- {
- copy_params->result = FALSE;
- return;
- }
+ return FALSE;
}
-static GstMemory *
-_gl_mem_copy (GstGLMemory * src, gssize offset, gssize size)
+static void
+_gl_tex_copy_thread (GstGLContext * context, gpointer data)
{
- GstGLAllocator *allocator = (GstGLAllocator *) src->mem.mem.allocator;
- GstMemory *ret = NULL;
+ GstGLMemoryCopyParams *copy_params;
- if (src->tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
- GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot copy External OES textures");
- return NULL;
+ copy_params = (GstGLMemoryCopyParams *) data;
+
+ if (!copy_params->tex_id) {
+ guint internal_format, out_gl_format, out_gl_type, out_tex_target;
+
+ out_tex_target = gst_gl_texture_target_to_gl (copy_params->tex_target);
+ out_gl_format =
+ gst_gl_format_from_gl_texture_type (copy_params->src->tex_type);
+ out_gl_type = GL_UNSIGNED_BYTE;
+ if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
+
+ internal_format =
+ gst_gl_sized_gl_format_from_gl_format_type (context, out_gl_format,
+ out_gl_type);
+
+ copy_params->tex_id =
+ _new_texture (context, out_tex_target,
+ internal_format, out_gl_format, out_gl_type, copy_params->out_width,
+ copy_params->out_height);
}
- /* If not doing a full copy, then copy to sysmem, the 2D represention of the
- * texture would become wrong */
- if (offset > 0 || size < src->mem.mem.size) {
- ret = allocator->fallback_mem_copy (&src->mem.mem, offset, size);
- } else if (GST_MEMORY_FLAG_IS_SET (src, GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD)) {
- GstAllocationParams params = { 0, src->mem.mem.align, 0, 0 };
- GstGLMemory *dest;
+ copy_params->result = gst_gl_memory_copy_teximage (copy_params->src,
+ copy_params->tex_id, copy_params->tex_target, copy_params->tex_type,
+ copy_params->out_width, copy_params->out_height);
+}
- dest = _gl_mem_new (src->mem.mem.allocator, NULL, src->mem.context,
- src->tex_target, &params, &src->info, &src->valign, src->plane, NULL,
- NULL);
- dest = (GstGLMemory *) gst_gl_base_buffer_alloc_data ((GstGLBaseBuffer *)
- dest);
+static GstMemory *
+_default_gl_tex_copy (GstGLMemory * src, gssize offset, gssize size)
+{
+ return NULL;
+}
- if (dest == NULL) {
- GST_WARNING ("Could not copy GL Memory");
- goto done;
- }
+static GstMemory *
+_gl_tex_copy (GstGLMemory * src, gssize offset, gssize size)
+{
+ GstGLMemoryAllocatorClass *alloc_class;
- memcpy (dest->mem.data, (guint8 *) src->mem.data + src->mem.mem.offset,
- src->mem.mem.size);
- GST_MINI_OBJECT_FLAG_SET (dest, GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD);
- dest->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_UPLOAD;
- ret = (GstMemory *) dest;
- } else {
- GstAllocationParams params = { 0, src->mem.mem.align, 0, 0 };
- GstGLMemoryCopyParams copy_params;
- GstGLMemory *dest;
-
- copy_params.src = src;
- copy_params.tex_id = 0;
- copy_params.out_format = src->tex_type;
- copy_params.tex_target = src->tex_target;
- copy_params.out_width = src->tex_width;
- copy_params.out_height = GL_MEM_HEIGHT (src);
- copy_params.out_stride = GL_MEM_STRIDE (src);
- copy_params.respecify = FALSE;
-
- _gl_mem_copy_thread (src->mem.context, &copy_params);
-
- if (!copy_params.result) {
- GST_WARNING ("Could not copy GL Memory");
- goto done;
- }
+ alloc_class = GST_GL_MEMORY_ALLOCATOR_GET_CLASS (src->mem.mem.allocator);
- dest = g_slice_new0 (GstGLMemory);
- /* don't create our own texture */
- dest->texture_wrapped = TRUE;
- _gl_mem_init (dest, src->mem.mem.allocator, NULL, src->mem.context,
- src->tex_target, &params, &src->info, &src->valign, src->plane, NULL,
- NULL);
- dest->texture_wrapped = FALSE;
-
- dest->tex_id = copy_params.tex_id;
- dest->tex_target = copy_params.tex_target;
- dest = (GstGLMemory *) gst_gl_base_buffer_alloc_data ((GstGLBaseBuffer *)
- dest);
- GST_MINI_OBJECT_FLAG_SET (dest, GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD);
- dest->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD;
- ret = (GstMemory *) dest;
+ if (src->tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot copy External OES textures");
+ return NULL;
}
-done:
- return ret;
+ g_return_val_if_fail (alloc_class->copy, NULL);
+ return (GstMemory *) alloc_class->copy (GST_GL_BASE_MEMORY_CAST (src), offset,
+ size);
}
static GstMemory *
-_gl_mem_alloc (GstAllocator * allocator, gsize size,
+_gl_tex_alloc (GstAllocator * allocator, gsize size,
GstAllocationParams * params)
{
- g_warning ("use gst_gl_memory_alloc () to allocate from this "
- "GstGLMemory allocator");
+ g_warning ("Subclass needs to override GstAllocatorClass::alloc");
return NULL;
}
static void
-_gl_mem_destroy (GstGLMemory * gl_mem)
+_gl_tex_destroy (GstGLMemory * gl_mem)
{
const GstGLFuncs *gl = gl_mem->mem.context->gl_vtable;
if (gl_mem->tex_id && !gl_mem->texture_wrapped)
gl->DeleteTextures (1, &gl_mem->tex_id);
-
- if (gl_mem->mem.id)
- gl->DeleteBuffers (1, &gl_mem->mem.id);
-}
-
-static void
-_gl_mem_free (GstAllocator * allocator, GstMemory * mem)
-{
- GstGLMemory *gl_mem = (GstGLMemory *) mem;
-
- GST_ALLOCATOR_CLASS (gst_gl_allocator_parent_class)->free (allocator, mem);
-
- if (gl_mem->notify)
- gl_mem->notify (gl_mem->user_data);
-
- g_slice_free (GstGLMemory, gl_mem);
}
static void
-gst_gl_allocator_class_init (GstGLAllocatorClass * klass)
+gst_gl_memory_allocator_class_init (GstGLMemoryAllocatorClass * klass)
{
- GstGLBaseBufferAllocatorClass *gl_base;
+ GstGLBaseMemoryAllocatorClass *gl_base;
GstAllocatorClass *allocator_class;
- gl_base = (GstGLBaseBufferAllocatorClass *) klass;
+ gl_base = (GstGLBaseMemoryAllocatorClass *) klass;
allocator_class = (GstAllocatorClass *) klass;
- gl_base->create = (GstGLBaseBufferAllocatorCreateFunction) _gl_mem_create;
- gl_base->map_buffer =
- (GstGLBaseBufferAllocatorMapBufferFunction) _gl_mem_map_buffer;
- gl_base->unmap_buffer =
- (GstGLBaseBufferAllocatorUnmapBufferFunction) _gl_mem_unmap_buffer;
- gl_base->copy = (GstGLBaseBufferAllocatorCopyFunction) _gl_mem_copy;
- gl_base->destroy = (GstGLBaseBufferAllocatorDestroyFunction) _gl_mem_destroy;
+ klass->map = (GstGLBaseMemoryAllocatorMapFunction) _default_gl_tex_map;
+ klass->unmap = (GstGLBaseMemoryAllocatorUnmapFunction) _default_gl_tex_unmap;
+ klass->copy = (GstGLBaseMemoryAllocatorCopyFunction) _default_gl_tex_copy;
+
+ gl_base->create = (GstGLBaseMemoryAllocatorCreateFunction) _gl_tex_create;
+ gl_base->map = (GstGLBaseMemoryAllocatorMapFunction) _gl_tex_map;
+ gl_base->unmap = (GstGLBaseMemoryAllocatorUnmapFunction) _gl_tex_unmap;
+ gl_base->copy = (GstGLBaseMemoryAllocatorCopyFunction) _gl_tex_copy;
+ gl_base->destroy = (GstGLBaseMemoryAllocatorDestroyFunction) _gl_tex_destroy;
- allocator_class->alloc = _gl_mem_alloc;
- allocator_class->free = _gl_mem_free;
+ allocator_class->alloc = _gl_tex_alloc;
}
static void
-gst_gl_allocator_init (GstGLAllocator * allocator)
+gst_gl_memory_allocator_init (GstGLMemoryAllocator * allocator)
{
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
- /* Keep the fallback copy function around, we will need it when copying with
- * at an offset or smaller size */
- allocator->fallback_mem_copy = alloc->mem_copy;
-
- alloc->mem_type = GST_GL_MEMORY_ALLOCATOR;
+ alloc->mem_type = GST_GL_MEMORY_ALLOCATOR_NAME;
GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
}
/**
- * gst_gl_memory_copy_into_texture:
+ * gst_gl_memory_copy_into:
* @gl_mem:a #GstGLMemory
* @tex_id:OpenGL texture id
- * @tex_type: a #GstVideoGLTextureType
+ * @taget: the #GstGLTextureTarget
+ * @tex_type: the #GstVideoGLTextureType
* @width: width of @tex_id
* @height: height of @tex_id
- * @stride: stride of the backing texture data
- * @respecify: whether to copy the data or copy per texel
*
* Copies @gl_mem into the texture specfified by @tex_id. The format of @tex_id
* is specified by @tex_type, @width and @height.
@@ -1362,216 +719,81 @@ gst_gl_allocator_init (GstGLAllocator * allocator)
* Returns: Whether the copy suceeded
*/
gboolean
-gst_gl_memory_copy_into_texture (GstGLMemory * gl_mem, guint tex_id,
+gst_gl_memory_copy_into (GstGLMemory * gl_mem, guint tex_id,
GstGLTextureTarget target, GstVideoGLTextureType tex_type, gint width,
- gint height, gint stride, gboolean respecify)
+ gint height)
{
GstGLMemoryCopyParams copy_params;
copy_params.src = gl_mem;
- copy_params.tex_target = target;
copy_params.tex_id = tex_id;
- copy_params.out_format = tex_type;
+ copy_params.tex_target = target;
+ copy_params.tex_type = tex_type;
copy_params.out_width = width;
copy_params.out_height = height;
- copy_params.out_stride = stride;
- copy_params.respecify = respecify;
- gst_gl_context_thread_add (gl_mem->mem.context, _gl_mem_copy_thread,
+ gst_gl_context_thread_add (gl_mem->mem.context, _gl_tex_copy_thread,
&copy_params);
return copy_params.result;
}
-/**
- * gst_gl_memory_wrapped_texture:
- * @context: a #GstGLContext
- * @texture_id: the GL texture handle
- * @texture_target: the GL texture target
- * @info: the #GstVideoInfo of the memory
- * @plane: The plane this memory will represent
- * @user_data: user data
- * @notify: Destroy callback for the user data
- *
- * Wraps a texture handle into a #GstGLMemory.
- *
- * Returns: a newly allocated #GstGLMemory
- */
-GstGLMemory *
-gst_gl_memory_wrapped_texture (GstGLContext * context,
- guint texture_id, GstGLTextureTarget target,
- GstVideoInfo * info, guint plane, GstVideoAlignment * valign,
- gpointer user_data, GDestroyNotify notify)
-{
- GstGLMemory *mem;
-
- mem = g_slice_new0 (GstGLMemory);
-
- mem->tex_id = texture_id;
- mem->texture_wrapped = TRUE;
-
- _gl_mem_init (mem, _gl_allocator, NULL, context, target, NULL, info, valign,
- plane, user_data, notify);
-
- mem = (GstGLMemory *) gst_gl_base_buffer_alloc_data ((GstGLBaseBuffer *) mem);
- GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD);
- mem->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD;
-
- return mem;
-}
-
-/**
- * gst_gl_memory_alloc:
- * @context:a #GstGLContext
- * @params: a #GstAllocationParams
- * @info: the #GstVideoInfo of the memory
- * @plane: the plane this memory will represent
- * @valign: the #GstVideoAlignment applied to @info
- *
- * Allocated a new #GstGlMemory.
- *
- * Returns: a #GstMemory object with a GL texture specified by @vinfo
- * from @context
- */
-GstMemory *
-gst_gl_memory_alloc (GstGLContext * context, GstGLTextureTarget target,
- GstAllocationParams * params, GstVideoInfo * info, guint plane,
- GstVideoAlignment * valign)
-{
- GstGLMemory *mem;
-
- mem =
- _gl_mem_new (_gl_allocator, NULL, context, target, params, info, valign,
- plane, NULL, NULL);
- mem = (GstGLMemory *) gst_gl_base_buffer_alloc_data ((GstGLBaseBuffer *) mem);
-
- return (GstMemory *) mem;
-}
-
-/**
- * gst_gl_memory_wrapped:
- * @context:a #GstGLContext
- * @info: the #GstVideoInfo of the memory and data
- * @plane: the plane this memory will represent
- * @valign: the #GstVideoAlignment applied to @info
- * @data: the data to wrap
- * @user_data: data called with for @notify
- * @notify: function called with @user_data when @data needs to be freed
- *
- * Wrapped @data into a #GstGLMemory. This version will account for padding
- * added to the allocation and expressed through @valign.
- *
- * Returns: a #GstGLMemory object with a GL texture specified by @v_info
- * from @context and contents specified by @data
- */
-GstGLMemory *
-gst_gl_memory_wrapped (GstGLContext * context, GstGLTextureTarget target,
- GstVideoInfo * info, guint plane, GstVideoAlignment * valign, gpointer data,
- gpointer user_data, GDestroyNotify notify)
-{
- GstGLMemory *mem;
-
- mem = _gl_mem_new (_gl_allocator, NULL, context, target, NULL, info, valign,
- plane, user_data, notify);
- if (!mem)
- return NULL;
-
- mem->mem.data = data;
-
- GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD);
- mem->transfer_state |= GST_GL_MEMORY_TRANSFER_NEED_UPLOAD;
-
- return mem;
-}
-
-static void
-_download_transfer (GstGLContext * context, GstGLMemory * gl_mem)
+gint
+gst_gl_memory_get_texture_width (GstGLMemory * gl_mem)
{
- GstGLBaseBuffer *mem = (GstGLBaseBuffer *) gl_mem;
+ g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
- g_mutex_lock (&mem->lock);
- if (_read_pixels_to_pbo (gl_mem))
- GST_CAT_TRACE (GST_CAT_GL_MEMORY, "optimistic download of texture %u "
- "using pbo %u", gl_mem->tex_id, gl_mem->mem.id);
- g_mutex_unlock (&mem->lock);
+ return gl_mem->tex_width;
}
-void
-gst_gl_memory_download_transfer (GstGLMemory * gl_mem)
+gint
+gst_gl_memory_get_texture_height (GstGLMemory * gl_mem)
{
- g_return_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem));
-
- gst_gl_context_thread_add (gl_mem->mem.context,
- (GstGLContextThreadFunc) _download_transfer, gl_mem);
-}
+ g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
-static void
-_upload_transfer (GstGLContext * context, GstGLMemory * gl_mem)
-{
- GstGLBaseBufferAllocatorClass *alloc_class;
- GstGLBaseBuffer *mem = (GstGLBaseBuffer *) gl_mem;
- GstMapInfo info;
-
- alloc_class =
- GST_GL_BASE_BUFFER_ALLOCATOR_CLASS (gst_gl_allocator_parent_class);
-
- info.flags = GST_MAP_READ | GST_MAP_GL;
- info.memory = (GstMemory *) mem;
- /* from gst_memory_map() */
- info.size = mem->mem.size;
- info.maxsize = mem->mem.maxsize - mem->mem.offset;
-
- g_mutex_lock (&mem->lock);
- mem->target = GL_PIXEL_UNPACK_BUFFER;
- alloc_class->map_buffer (mem, &info, mem->mem.maxsize);
- alloc_class->unmap_buffer (mem, &info);
- g_mutex_unlock (&mem->lock);
+ return _get_plane_height (&gl_mem->info, gl_mem->plane);
}
-void
-gst_gl_memory_upload_transfer (GstGLMemory * gl_mem)
+GstVideoGLTextureType
+gst_gl_memory_get_texture_type (GstGLMemory * gl_mem)
{
- g_return_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem));
+ g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
- if (CONTEXT_SUPPORTS_PBO_UPLOAD (gl_mem->mem.context))
- gst_gl_context_thread_add (gl_mem->mem.context,
- (GstGLContextThreadFunc) _upload_transfer, gl_mem);
+ return gl_mem->tex_type;
}
-gint
-gst_gl_memory_get_texture_width (GstGLMemory * gl_mem)
+GstGLTextureTarget
+gst_gl_memory_get_texture_target (GstGLMemory * gl_mem)
{
g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
- return gl_mem->tex_width;
+ return gl_mem->tex_target;
}
-gint
-gst_gl_memory_get_texture_height (GstGLMemory * gl_mem)
+guint
+gst_gl_memory_get_texture_id (GstGLMemory * gl_mem)
{
g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
- return _get_plane_height (&gl_mem->info, gl_mem->plane);
+ return gl_mem->tex_id;
}
/**
- * gst_gl_memory_init:
+ * gst_gl_memory_init_once:
*
- * Initializes the GL Memory allocator. It is safe to call this function
+ * Initializes the GL Base Texture allocator. It is safe to call this function
* multiple times. This must be called before any other GstGLMemory operation.
*/
void
-gst_gl_memory_init (void)
+gst_gl_memory_init_once (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_gl_base_memory_init_once ();
- gst_allocator_register (GST_GL_MEMORY_ALLOCATOR,
- gst_object_ref (_gl_allocator));
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_MEMORY, "glbasetexture", 0,
+ "OpenGL Base Texture Memory");
g_once_init_leave (&_init, 1);
}
}
@@ -1586,87 +808,6 @@ gboolean
gst_is_gl_memory (GstMemory * mem)
{
return mem != NULL && mem->allocator != NULL
- && g_type_is_a (G_OBJECT_TYPE (mem->allocator), GST_TYPE_GL_ALLOCATOR);
-}
-
-/**
- * gst_gl_memory_setup_buffer:
- * @context: a #GstGLContext
- * @params: a #GstAllocationParams
- * @info: a #GstVideoInfo
- * @valign: the #GstVideoAlignment applied to @info
- * @buffer: a #GstBuffer
- *
- * Adds the required #GstGLMemory<!-- -->s with the correct configuration to
- * @buffer based on @info. This version handles padding through @valign.
- *
- * Returns: whether the memory's were sucessfully added.
- */
-gboolean
-gst_gl_memory_setup_buffer (GstGLContext * context, GstGLTextureTarget target,
- GstAllocationParams * params, GstVideoInfo * info,
- GstVideoAlignment * valign, GstBuffer * buffer)
-{
- GstGLMemory *gl_mem[GST_VIDEO_MAX_PLANES] = { NULL, };
- guint n_mem, i, v, views;
-
- n_mem = GST_VIDEO_INFO_N_PLANES (info);
-
- if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) ==
- GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
- views = info->views;
- else
- views = 1;
-
- for (v = 0; v < views; v++) {
- for (i = 0; i < n_mem; i++) {
- gl_mem[i] =
- (GstGLMemory *) gst_gl_memory_alloc (context, target, params, info, i,
- valign);
- if (gl_mem[i] == NULL)
- return FALSE;
-
- gst_buffer_append_memory (buffer, (GstMemory *) gl_mem[i]);
- }
-
- gst_buffer_add_video_meta_full (buffer, v,
- GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
- GST_VIDEO_INFO_HEIGHT (info), n_mem, info->offset, info->stride);
- }
-
- return TRUE;
-}
-
-/**
- * gst_gl_memory_setup_wrapped:
- * @context: a #GstGLContext
- * @info: a #GstVideoInfo
- * @valign: a #GstVideoInfo
- * @data: a list of per plane data pointers
- * @textures: (transfer out): a list of #GstGLMemory
- * @user_data: user data for the destroy function
- * @notify: A function called each time a memory is freed
- *
- * Wraps per plane data pointer in @data into the corresponding entry in
- * @textures based on @info and padding from @valign. Note that the @notify
- * will be called as many time as there is planes.
- *
- * Returns: whether the memory's were sucessfully created.
- */
-gboolean
-gst_gl_memory_setup_wrapped (GstGLContext * context, GstGLTextureTarget target,
- GstVideoInfo * info, GstVideoAlignment * valign,
- gpointer data[GST_VIDEO_MAX_PLANES],
- GstGLMemory * textures[GST_VIDEO_MAX_PLANES], gpointer user_data,
- GDestroyNotify notify)
-{
- gint i;
-
- for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
- textures[i] =
- (GstGLMemory *) gst_gl_memory_wrapped (context, target, info, i, valign,
- data[i], user_data, notify);
- }
-
- return TRUE;
+ && g_type_is_a (G_OBJECT_TYPE (mem->allocator),
+ GST_TYPE_GL_MEMORY_ALLOCATOR);
}
diff --git a/gst-libs/gst/gl/gstglmemory.h b/gst-libs/gst/gl/gstglmemory.h
index fe8593d99..de026971c 100644
--- a/gst-libs/gst/gl/gstglmemory.h
+++ b/gst-libs/gst/gl/gstglmemory.h
@@ -1,6 +1,6 @@
/*
* GStreamer
- * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
+ * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -26,39 +26,27 @@
#include <gst/gstmemory.h>
#include <gst/video/video.h>
-#include <gst/gl/gstglbasebuffer.h>
-#include <gst/gl/gl.h>
+#include <gst/gl/gstglbasememory.h>
G_BEGIN_DECLS
-#define GST_TYPE_GL_ALLOCATOR (gst_gl_allocator_get_type())
-GType gst_gl_allocator_get_type(void);
+#define GST_TYPE_GL_MEMORY_ALLOCATOR (gst_gl_memory_allocator_get_type())
+GType gst_gl_memory_allocator_get_type(void);
-#define GST_IS_GL_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_ALLOCATOR))
-#define GST_IS_GL_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GL_ALLOCATOR))
-#define GST_GL_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GL_ALLOCATOR, GstGLAllocatorClass))
-#define GST_GL_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_ALLOCATOR, GstGLAllocator))
-#define GST_GL_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GL_ALLOCATOR, GstGLAllocatorClass))
-#define GST_GL_ALLOCATOR_CAST(obj) ((GstGLAllocator *)(obj))
+#define GST_IS_GL_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_MEMORY_ALLOCATOR))
+#define GST_IS_GL_MEMORY_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GL_MEMORY_ALLOCATOR))
+#define GST_GL_MEMORY_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GL_MEMORY_ALLOCATOR, GstGLMemoryAllocatorClass))
+#define GST_GL_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_MEMORY_ALLOCATOR, GstGLMemoryAllocator))
+#define GST_GL_MEMORY_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GL_MEMORY_ALLOCATOR, GstGLMemoryAllocatorClass))
+#define GST_GL_MEMORY_ALLOCATOR_CAST(obj) ((GstGLMemoryAllocator *)(obj))
-typedef enum _GstGLMemoryTransfer
-{
- /* force a transfer between the texture and the PBO (if available) */
- GST_GL_MEMORY_TRANSFER_NEED_UPLOAD = (1 << 0),
- GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD = (1 << 1),
-} GstGLMemoryTransfer;
-
-#define GST_GL_MEMORY_ADD_TRANSFER(mem,state) ((GstGLMemory *)mem)->transfer_state |= state
-
-#define GST_GL_TEXTURE_TARGET_2D_STR "2D"
-#define GST_GL_TEXTURE_TARGET_RECTANGLE_STR "rectangle"
-#define GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR "external-oes"
+#define GST_GL_MEMORY_CAST(obj) ((GstGLMemory *) obj)
-#define GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D "GstBufferPoolOptionGLTextureTarget2D"
-#define GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE "GstBufferPoolOptionGLTextureTargetRectangle"
-#define GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES "GstBufferPoolOptionGLTextureTargetExternalOES"
-
-const gchar * gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target);
+#define GST_CAPS_FEATURE_MEMORY_GL_MEMORY "memory:GLMemory"
+#define GST_GL_MEMORY_VIDEO_FORMATS_STR \
+ "{ RGBA, BGRA, RGBx, BGRx, ARGB, ABGR, xRGB, xBGR, RGB, BGR, RGB16, BGR16, " \
+ "AYUV, I420, YV12, NV12, NV21, YUY2, UYVY, Y41B, Y42B, Y444, " \
+ "GRAY8, GRAY16_LE, GRAY16_BE }"
/**
* GstGLMemory:
@@ -76,129 +64,92 @@ const gchar * gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget ta
*/
struct _GstGLMemory
{
- GstGLBaseBuffer mem;
-
- guint tex_id;
- GstGLTextureTarget tex_target;
- GstVideoGLTextureType tex_type;
- GstVideoInfo info;
- GstVideoAlignment valign;
- guint plane;
- gfloat tex_scaling[2];
-
- /* <private> */
- GstGLMemoryTransfer transfer_state;
- gboolean texture_wrapped;
- GDestroyNotify notify;
- gpointer user_data;
- guint unpack_length;
- guint tex_width;
+ GstGLBaseMemory mem;
+
+ guint tex_id;
+ GstGLTextureTarget tex_target;
+ GstVideoGLTextureType tex_type;
+ GstVideoInfo info;
+ GstVideoAlignment valign;
+ guint plane;
+ gfloat tex_scaling[2];
+
+ /* <protected> */
+ gboolean texture_wrapped;
+ guint unpack_length;
+ guint tex_width;
};
-#define GST_CAPS_FEATURE_MEMORY_GL_MEMORY "memory:GLMemory"
-#define GST_GL_MEMORY_VIDEO_FORMATS_STR \
- "{ RGBA, BGRA, RGBx, BGRx, ARGB, ABGR, xRGB, xBGR, RGB, BGR, RGB16, BGR16, " \
- "AYUV, I420, YV12, NV12, NV21, YUY2, UYVY, Y41B, Y42B, Y444, " \
- "GRAY8, GRAY16_LE, GRAY16_BE }"
-
/**
- * GST_GL_MEMORY_ALLOCATOR:
+ * GstGLMemoryAllocator
*
- * The name of the GL memory allocator
+ * Opaque #GstGLMemoryAllocator struct
*/
-#define GST_GL_MEMORY_ALLOCATOR "GLMemory"
-
-void gst_gl_memory_init (void);
-gboolean gst_is_gl_memory (GstMemory * mem);
-
-GstMemory * gst_gl_memory_alloc (GstGLContext * context,
- GstGLTextureTarget target,
- GstAllocationParams *params,
- GstVideoInfo * info,
- guint plane,
- GstVideoAlignment *valign);
-GstGLMemory * gst_gl_memory_wrapped (GstGLContext * context,
- GstGLTextureTarget target,
- GstVideoInfo * info,
- guint plane,
- GstVideoAlignment *valign,
- gpointer data,
- gpointer user_data,
- GDestroyNotify notify);
-GstGLMemory * gst_gl_memory_wrapped_texture (GstGLContext * context,
- guint texture_id,
- GstGLTextureTarget target,
- GstVideoInfo * info,
- guint plane,
- GstVideoAlignment *valign,
- gpointer user_data,
- GDestroyNotify notify);
-
-void gst_gl_memory_download_transfer (GstGLMemory * gl_mem);
-void gst_gl_memory_upload_transfer (GstGLMemory * gl_mem);
-
-gboolean gst_gl_memory_copy_into_texture (GstGLMemory *gl_mem,
- guint tex_id,
- GstGLTextureTarget target,
- GstVideoGLTextureType tex_type,
- gint width,
- gint height,
- gint stride,
- gboolean respecify);
-
-gboolean gst_gl_memory_setup_buffer (GstGLContext * context,
- GstGLTextureTarget target,
- GstAllocationParams * params,
- GstVideoInfo * info,
- GstVideoAlignment *valign,
- GstBuffer * buffer);
-gboolean gst_gl_memory_setup_wrapped (GstGLContext * context,
- GstGLTextureTarget target,
- GstVideoInfo * info,
- GstVideoAlignment *valign,
- gpointer data[GST_VIDEO_MAX_PLANES],
- GstGLMemory *textures[GST_VIDEO_MAX_PLANES],
- gpointer user_data,
- GDestroyNotify notify);
-
-gint gst_gl_memory_get_texture_width (GstGLMemory * gl_mem);
-gint gst_gl_memory_get_texture_height (GstGLMemory * gl_mem);
-
-/* utility functions */
-GstVideoGLTextureType gst_gl_texture_type_from_format (GstGLContext *context,
- GstVideoFormat v_format,
- guint plane);
-guint gst_gl_format_from_gl_texture_type (GstVideoGLTextureType tex_format);
-guint gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
- guint format,
- guint type);
-
-const gchar * gst_gl_texture_target_to_string (GstGLTextureTarget target);
-GstGLTextureTarget gst_gl_texture_target_from_string (const gchar * str);
-GstGLTextureTarget gst_gl_texture_target_from_gl (guint target);
-guint gst_gl_texture_target_to_gl (GstGLTextureTarget target);
-
+struct _GstGLMemoryAllocator
+{
+ GstGLBaseMemoryAllocator parent;
+};
/**
- * GstGLAllocator
+ * GstGLMemoryAllocatorClass:
*
- * Opaque #GstGLAllocator struct
+ * The #GstGLMemoryAllocatorClass only contains private data
*/
-struct _GstGLAllocator
+struct _GstGLMemoryAllocatorClass
{
- GstGLBaseBufferAllocator parent;
- GstMemoryCopyFunction fallback_mem_copy;
+ GstGLBaseMemoryAllocatorClass parent_class;
+
+ GstGLBaseMemoryAllocatorMapFunction map;
+ GstGLBaseMemoryAllocatorCopyFunction copy;
+ GstGLBaseMemoryAllocatorUnmapFunction unmap;
};
+#include <gst/gl/gstglbasememory.h>
+
/**
- * GstGLAllocatorClass:
+ * GST_GL_MEMORY_ALLOCATOR_NAME:
*
- * The #GstGLAllocatorClass only contains private data
+ * The name of the GL memory allocator
*/
-struct _GstGLAllocatorClass
-{
- GstGLBaseBufferAllocatorClass parent_class;
-};
+#define GST_GL_MEMORY_ALLOCATOR_NAME "GLMemory"
+
+void gst_gl_memory_init_once (void);
+gboolean gst_is_gl_memory (GstMemory * mem);
+
+void gst_gl_memory_init (GstGLMemory * mem,
+ GstAllocator * allocator,
+ GstMemory * parent,
+ GstGLContext * context,
+ GstGLTextureTarget target,
+ GstAllocationParams *params,
+ GstVideoInfo * info,
+ guint plane,
+ GstVideoAlignment *valign,
+ GDestroyNotify notify,
+ gpointer user_data);
+
+gboolean gst_gl_memory_copy_into (GstGLMemory *gl_mem,
+ guint tex_id,
+ GstGLTextureTarget target,
+ GstVideoGLTextureType tex_type,
+ gint width,
+ gint height);
+gboolean gst_gl_memory_copy_teximage (GstGLMemory * src,
+ guint tex_id,
+ GstGLTextureTarget out_target,
+ GstVideoGLTextureType out_tex_type,
+ gint width,
+ gint height);
+
+gboolean gst_gl_memory_read_pixels (GstGLMemory * gl_mem,
+ gpointer read_pointer);
+
+/* accessors */
+gint gst_gl_memory_get_texture_width (GstGLMemory * gl_mem);
+gint gst_gl_memory_get_texture_height (GstGLMemory * gl_mem);
+GstVideoGLTextureType gst_gl_memory_get_texture_type (GstGLMemory * gl_mem);
+GstGLTextureTarget gst_gl_memory_get_texture_target (GstGLMemory * gl_mem);
+guint gst_gl_memory_get_texture_id (GstGLMemory * gl_mem);
G_END_DECLS
diff --git a/gst-libs/gst/gl/gstglmemorypbo.c b/gst-libs/gst/gl/gstglmemorypbo.c
new file mode 100644
index 000000000..6ef0e3968
--- /dev/null
+++ b/gst-libs/gst/gl/gstglmemorypbo.c
@@ -0,0 +1,1030 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
+ * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <gst/video/video.h>
+
+#include <gst/gl/gstglmemorypbo.h>
+
+/**
+ * SECTION:gstglmemorypbo
+ * @short_description: memory subclass for GL textures
+ * @see_also: #GstMemory, #GstAllocator, #GstGLBufferPool
+ *
+ * GstGLMemoryPBO is a #GstGLMemory subclass providing support for the mapping of
+ * GL textures.
+ *
+ * #GstGLMemoryPBO is created through gst_gl_memory_pbo_alloc() or system memory can
+ * be wrapped through gst_gl_memory_pbo_wrapped().
+ *
+ * Data is uploaded or downloaded from the GPU as is necessary.
+ */
+
+/* Implementation notes
+ *
+ * PBO transfer's are implemented using GstGLBuffer. We just need to
+ * ensure that the texture data is written/read to/from before/after calling
+ * map (mem->pbo, READ) which performs the pbo buffer transfer.
+ */
+
+#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
+#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
+#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
+#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
+#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
+
+#define GL_MEM_WIDTH(gl_mem) _get_plane_width (&gl_mem->mem.info, gl_mem->mem.plane)
+#define GL_MEM_HEIGHT(gl_mem) _get_plane_height (&gl_mem->mem.info, gl_mem->mem.plane)
+#define GL_MEM_STRIDE(gl_mem) GST_VIDEO_INFO_PLANE_STRIDE (&gl_mem->mem.info, gl_mem->mem.plane)
+
+#define CONTEXT_SUPPORTS_PBO_UPLOAD(context) \
+ (gst_gl_context_check_gl_version (context, \
+ GST_GL_API_OPENGL | GST_GL_API_OPENGL3, 2, 1) \
+ || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
+#define CONTEXT_SUPPORTS_PBO_DOWNLOAD(context) \
+ (gst_gl_context_check_gl_version (context, \
+ GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2, 3, 0))
+
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
+#define GST_CAT_DEFAULT GST_CAT_GL_MEMORY
+
+static GstAllocator *_gl_allocator;
+
+/* compatability definitions... */
+#ifndef GL_PIXEL_PACK_BUFFER
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#endif
+#ifndef GL_PIXEL_UNPACK_BUFFER
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#endif
+#ifndef GL_STREAM_READ
+#define GL_STREAM_READ 0x88E1
+#endif
+#ifndef GL_STREAM_DRAW
+#define GL_STREAM_DRAW 0x88E0
+#endif
+#ifndef GL_STREAM_COPY
+#define GL_STREAM_COPY 0x88E2
+#endif
+#ifndef GL_UNPACK_ROW_LENGTH
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#endif
+
+#ifndef GL_TEXTURE_RECTANGLE
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#endif
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#endif
+
+#define parent_class gst_gl_memory_pbo_allocator_parent_class
+G_DEFINE_TYPE (GstGLMemoryPBOAllocator, gst_gl_memory_pbo_allocator,
+ GST_TYPE_GL_MEMORY_ALLOCATOR);
+
+typedef struct
+{
+ /* in */
+ GstGLMemoryPBO *src;
+ GstVideoGLTextureType out_format;
+ guint out_width, out_height;
+ guint out_stride;
+ gboolean respecify;
+ GstGLTextureTarget tex_target;
+ /* inout */
+ guint tex_id;
+ /* out */
+ gboolean result;
+} GstGLMemoryPBOCopyParams;
+
+static inline guint
+_get_plane_width (GstVideoInfo * info, guint plane)
+{
+ if (GST_VIDEO_INFO_IS_YUV (info))
+ /* For now component width and plane width are the same and the
+ * plane-component mapping matches
+ */
+ return GST_VIDEO_INFO_COMP_WIDTH (info, plane);
+ else /* RGB, GRAY */
+ return GST_VIDEO_INFO_WIDTH (info);
+}
+
+static inline guint
+_get_plane_height (GstVideoInfo * info, guint plane)
+{
+ if (GST_VIDEO_INFO_IS_YUV (info))
+ /* For now component width and plane width are the same and the
+ * plane-component mapping matches
+ */
+ return GST_VIDEO_INFO_COMP_HEIGHT (info, plane);
+ else /* RGB, GRAY */
+ return GST_VIDEO_INFO_HEIGHT (info);
+}
+
+static void
+_upload_pbo_memory (GstGLMemoryPBO * gl_mem, GstMapInfo * info,
+ GstGLBuffer * pbo, GstMapInfo * pbo_info)
+{
+ GstGLContext *context = gl_mem->mem.mem.context;
+ const GstGLFuncs *gl;
+ guint gl_format, gl_type, gl_target;
+ guint pbo_id;
+ gsize plane_start;
+
+ if (!GST_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD))
+ return;
+
+ g_return_if_fail (CONTEXT_SUPPORTS_PBO_UPLOAD (context));
+
+ gl = context->gl_vtable;
+ pbo_id = *(guint *) pbo_info->data;
+
+ gl_type = GL_UNSIGNED_BYTE;
+ if (gl_mem->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ gl_type = GL_UNSIGNED_SHORT_5_6_5;
+
+ gl_format = gst_gl_format_from_gl_texture_type (gl_mem->mem.tex_type);
+ gl_target = gst_gl_texture_target_to_gl (gl_mem->mem.tex_target);
+
+ if (USING_OPENGL (context) || USING_GLES3 (context)
+ || USING_OPENGL3 (context)) {
+ gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->mem.unpack_length);
+ } else if (USING_GLES2 (context)) {
+ gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->mem.unpack_length);
+ }
+
+ GST_CAT_LOG (GST_CAT_GL_MEMORY, "upload for texture id:%u, with pbo %u %ux%u",
+ gl_mem->mem.tex_id, pbo_id, gl_mem->mem.tex_width,
+ GL_MEM_HEIGHT (gl_mem));
+
+ /* find the start of the plane data including padding */
+ plane_start =
+ gst_gl_get_plane_start (&gl_mem->mem.info, &gl_mem->mem.valign,
+ gl_mem->mem.plane) + GST_MEMORY_CAST (gl_mem)->offset;
+
+ gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo_id);
+ gl->BindTexture (gl_target, gl_mem->mem.tex_id);
+ gl->TexSubImage2D (gl_target, 0, 0, 0, gl_mem->mem.tex_width,
+ GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, (void *) plane_start);
+ gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
+ gl->BindTexture (gl_target, 0);
+
+ /* Reset to default values */
+ if (USING_OPENGL (context) || USING_GLES3 (context)) {
+ gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+ } else if (USING_GLES2 (context)) {
+ gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ }
+}
+
+static guint
+_new_texture (GstGLContext * context, guint target, guint internal_format,
+ guint format, guint type, guint width, guint height)
+{
+ const GstGLFuncs *gl = context->gl_vtable;
+ guint tex_id;
+
+ gl->GenTextures (1, &tex_id);
+ gl->BindTexture (target, tex_id);
+ if (target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE)
+ gl->TexImage2D (target, 0, internal_format, width, height, 0, format, type,
+ NULL);
+
+ gl->TexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl->TexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl->TexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ gl->BindTexture (target, 0);
+
+ return tex_id;
+}
+
+static gboolean
+_gl_mem_create (GstGLMemoryPBO * gl_mem, GError ** error)
+{
+ GstGLContext *context = gl_mem->mem.mem.context;
+ GstGLBaseMemoryAllocatorClass *alloc_class;
+
+ alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class);
+ if (!alloc_class->create ((GstGLBaseMemory *) gl_mem, error))
+ return FALSE;
+
+ if (USING_OPENGL (context) || USING_OPENGL3 (context)
+ || USING_GLES3 (context)) {
+ GstAllocationParams params = { 0, GST_MEMORY_CAST (gl_mem)->align, 0, 0 };
+
+ /* FIXME: lazy init this for resource constrained platforms
+ * Will need to fix pbo detection based on the existence of the mem.id then */
+ gl_mem->pbo = gst_gl_buffer_alloc (context, GL_PIXEL_UNPACK_BUFFER,
+ GL_STREAM_DRAW, &params, GST_MEMORY_CAST (gl_mem)->size);
+ GST_CAT_LOG (GST_CAT_GL_MEMORY, "generated pbo %u", gl_mem->pbo->id);
+ }
+
+ return TRUE;
+}
+
+static void
+_gl_mem_init (GstGLMemoryPBO * mem, GstAllocator * allocator,
+ GstMemory * parent, GstGLContext * context, GstGLTextureTarget target,
+ GstAllocationParams * params, GstVideoInfo * info,
+ GstVideoAlignment * valign, guint plane, gpointer user_data,
+ GDestroyNotify notify)
+{
+ gst_gl_memory_init ((GstGLMemory *) mem, allocator, parent,
+ context, target, params, info, plane, valign, notify, user_data);
+}
+
+static GstGLMemoryPBO *
+_gl_mem_new (GstAllocator * allocator, GstMemory * parent,
+ GstGLContext * context, GstGLTextureTarget target,
+ GstAllocationParams * params, GstVideoInfo * info,
+ GstVideoAlignment * valign, guint plane, gpointer user_data,
+ GDestroyNotify notify)
+{
+ GstGLMemoryPBO *mem;
+ mem = g_slice_new0 (GstGLMemoryPBO);
+ mem->mem.texture_wrapped = FALSE;
+
+ _gl_mem_init (mem, allocator, parent, context, target, params, info, valign,
+ plane, user_data, notify);
+
+ return mem;
+}
+
+static gboolean
+_read_pixels_to_pbo (GstGLMemoryPBO * gl_mem)
+{
+ if (!gl_mem->pbo || !CONTEXT_SUPPORTS_PBO_DOWNLOAD (gl_mem->mem.mem.context)
+ || gl_mem->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
+ || gl_mem->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA)
+ /* unsupported */
+ return FALSE;
+
+ if (GST_MEMORY_FLAG_IS_SET (gl_mem,
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)) {
+ /* copy texture data into into the pbo and map that */
+ gsize plane_start;
+ GstMapInfo pbo_info;
+
+ plane_start =
+ gst_gl_get_plane_start (&gl_mem->mem.info, &gl_mem->mem.valign,
+ gl_mem->mem.plane) + GST_MEMORY_CAST (gl_mem)->offset;
+
+ gl_mem->pbo->target = GL_PIXEL_PACK_BUFFER;
+ if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info,
+ GST_MAP_WRITE | GST_MAP_GL)) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo for writing");
+ return FALSE;
+ }
+
+ if (!gst_gl_memory_read_pixels ((GstGLMemory *) gl_mem,
+ (gpointer) plane_start)) {
+ gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info);
+ return FALSE;
+ }
+
+ gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info);
+ }
+
+ return TRUE;
+}
+
+static gpointer
+_pbo_download_transfer (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize size)
+{
+ GstMapInfo *pbo_info;
+
+ /* texture -> pbo */
+ if (info->flags & GST_MAP_READ
+ && GST_MEMORY_FLAG_IS_SET (gl_mem,
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD)) {
+ GST_CAT_TRACE (GST_CAT_GL_MEMORY,
+ "attempting download of texture %u " "using pbo %u", gl_mem->mem.tex_id,
+ gl_mem->pbo->id);
+
+ if (!_read_pixels_to_pbo (gl_mem))
+ return NULL;
+ }
+
+ pbo_info = g_new0 (GstMapInfo, 1);
+
+ /* pbo -> data */
+ gl_mem->pbo->target = GL_PIXEL_PACK_BUFFER;
+ /* get a cpu accessible mapping from the pbo */
+ if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), pbo_info, info->flags)) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo");
+ g_free (pbo_info);
+ return NULL;
+ }
+ info->user_data[0] = pbo_info;
+
+ return pbo_info->data;
+}
+
+static gpointer
+_gl_mem_map_cpu_access (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize size)
+{
+ gpointer data = NULL;
+
+ gst_gl_base_memory_alloc_data ((GstGLBaseMemory *) gl_mem);
+
+ if (!data && gl_mem->pbo
+ && CONTEXT_SUPPORTS_PBO_DOWNLOAD (gl_mem->mem.mem.context))
+ data = _pbo_download_transfer (gl_mem, info, size);
+
+ if (!data) {
+ GstGLMemoryAllocatorClass *alloc_class;
+
+ alloc_class = GST_GL_MEMORY_ALLOCATOR_CLASS (parent_class);
+
+ data = alloc_class->map ((GstGLBaseMemory *) gl_mem, info, size);
+ }
+
+ return data;
+}
+
+static gpointer
+_gl_mem_map_gpu_access (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize size)
+{
+ gpointer data = &gl_mem->mem.tex_id;
+
+ if ((info->flags & GST_MAP_READ) == GST_MAP_READ) {
+ if (gl_mem->pbo && CONTEXT_SUPPORTS_PBO_UPLOAD (gl_mem->mem.mem.context)) {
+ GstMapInfo pbo_info;
+
+ /* data -> pbo */
+ if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info,
+ GST_MAP_READ | GST_MAP_GL)) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo");
+ return NULL;
+ }
+
+ /* pbo -> texture */
+ _upload_pbo_memory (gl_mem, info, gl_mem->pbo, &pbo_info);
+
+ gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &pbo_info);
+ } else {
+ GstGLMemoryAllocatorClass *alloc_class;
+
+ alloc_class = GST_GL_MEMORY_ALLOCATOR_CLASS (parent_class);
+
+ data = alloc_class->map ((GstGLBaseMemory *) gl_mem, info, size);
+ }
+ }
+
+ return data;
+}
+
+static gpointer
+_gl_mem_map (GstGLMemoryPBO * gl_mem, GstMapInfo * info, gsize maxsize)
+{
+ gpointer data;
+
+ if ((info->flags & GST_MAP_GL) == GST_MAP_GL) {
+ if (gl_mem->mem.tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+ return &gl_mem->mem.tex_id;
+
+ data = _gl_mem_map_gpu_access (gl_mem, info, maxsize);
+ } else { /* not GL */
+ if (gl_mem->mem.tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot map External OES textures");
+ return NULL;
+ }
+
+ data = _gl_mem_map_cpu_access (gl_mem, info, maxsize);
+ }
+
+ return data;
+}
+
+static void
+_gl_mem_unmap_cpu_access (GstGLMemoryPBO * gl_mem, GstMapInfo * info)
+{
+ if (!gl_mem->pbo || !CONTEXT_SUPPORTS_PBO_DOWNLOAD (gl_mem->mem.mem.context))
+ /* PBO's not supported */
+ return;
+
+ gl_mem->pbo->target = GL_PIXEL_PACK_BUFFER;
+ gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo),
+ (GstMapInfo *) info->user_data[0]);
+ g_free (info->user_data[0]);
+}
+
+static void
+_gl_mem_unmap (GstGLMemoryPBO * gl_mem, GstMapInfo * info)
+{
+ if ((info->flags & GST_MAP_GL) == 0) {
+ _gl_mem_unmap_cpu_access (gl_mem, info);
+ }
+}
+
+static void
+_gl_mem_copy_thread (GstGLContext * context, gpointer data)
+{
+ const GstGLFuncs *gl;
+ GstGLMemoryPBOCopyParams *copy_params;
+ GstGLMemoryPBO *src;
+ guint tex_id;
+ guint out_tex_target;
+ GLuint fboId;
+ gsize out_width, out_height, out_stride;
+ GLuint out_gl_format, out_gl_type;
+ GLuint in_gl_format, in_gl_type;
+ gsize in_size, out_size;
+
+ copy_params = (GstGLMemoryPBOCopyParams *) data;
+ src = copy_params->src;
+ tex_id = copy_params->tex_id;
+ out_tex_target = gst_gl_texture_target_to_gl (copy_params->tex_target);
+ out_width = copy_params->out_width;
+ out_height = copy_params->out_height;
+ out_stride = copy_params->out_stride;
+
+ gl = context->gl_vtable;
+ out_gl_format = gst_gl_format_from_gl_texture_type (copy_params->out_format);
+ out_gl_type = GL_UNSIGNED_BYTE;
+ if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
+ in_gl_format = gst_gl_format_from_gl_texture_type (src->mem.tex_type);
+ in_gl_type = GL_UNSIGNED_BYTE;
+ if (src->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ in_gl_type = GL_UNSIGNED_SHORT_5_6_5;
+
+ if (!gl->GenFramebuffers) {
+ gst_gl_context_set_error (context,
+ "Context, EXT_framebuffer_object not supported");
+ goto error;
+ }
+
+ in_size = GL_MEM_HEIGHT (src) * GL_MEM_STRIDE (src);
+ out_size = out_height * out_stride;
+
+ if (copy_params->respecify) {
+ if (in_size != out_size) {
+ GST_ERROR ("Cannot copy between textures with backing data of different"
+ "sizes. input %" G_GSIZE_FORMAT " output %" G_GSIZE_FORMAT, in_size,
+ out_size);
+ goto error;
+ }
+ }
+
+ if (!tex_id) {
+ guint internal_format;
+ guint out_gl_type;
+
+ out_gl_type = GL_UNSIGNED_BYTE;
+ if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
+ out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
+
+ internal_format =
+ gst_gl_sized_gl_format_from_gl_format_type (context, out_gl_format,
+ out_gl_type);
+
+ tex_id =
+ _new_texture (context, out_tex_target,
+ internal_format, out_gl_format, out_gl_type, copy_params->out_width,
+ copy_params->out_height);
+ }
+
+ if (!tex_id) {
+ GST_WARNING ("Could not create GL texture with context:%p", context);
+ }
+
+ GST_LOG ("copying memory %p, tex %u into texture %i",
+ src, src->mem.tex_id, tex_id);
+
+ /* FIXME: try and avoid creating and destroying fbo's every copy... */
+ /* create a framebuffer object */
+ gl->GenFramebuffers (1, &fboId);
+ gl->BindFramebuffer (GL_FRAMEBUFFER, fboId);
+
+ gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ gst_gl_texture_target_to_gl (src->mem.tex_target), src->mem.tex_id, 0);
+
+// if (!gst_gl_context_check_framebuffer_status (src->mem.mem.context))
+// goto fbo_error;
+
+ gl->BindTexture (out_tex_target, tex_id);
+ if (copy_params->respecify) {
+ GstMapInfo pbo_info;
+
+ if (!gl->GenBuffers || !src->pbo) {
+ gst_gl_context_set_error (context, "Cannot reinterpret texture contents "
+ "without pixel buffer objects");
+ gl->BindTexture (out_tex_target, 0);
+ goto fbo_error;
+ }
+
+ if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2
+ && (in_gl_format != GL_RGBA || in_gl_type != GL_UNSIGNED_BYTE)) {
+ gst_gl_context_set_error (context, "Cannot copy non RGBA/UNSIGNED_BYTE "
+ "textures on GLES2");
+ gl->BindTexture (out_tex_target, 0);
+ goto fbo_error;
+ }
+
+ GST_TRACE ("copying texture data with size of %u*%u*%u",
+ gst_gl_format_type_n_bytes (in_gl_format, in_gl_type),
+ src->mem.tex_width, GL_MEM_HEIGHT (src));
+
+ /* copy tex */
+ _read_pixels_to_pbo (src);
+
+ src->pbo->target = GL_PIXEL_UNPACK_BUFFER;
+ if (!gst_memory_map (GST_MEMORY_CAST (src->pbo), &pbo_info,
+ GST_MAP_READ | GST_MAP_GL)) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo for reading");
+ goto fbo_error;
+ }
+ gl->TexSubImage2D (out_tex_target, 0, 0, 0, out_width, out_height,
+ out_gl_format, out_gl_type, 0);
+ gst_memory_unmap (GST_MEMORY_CAST (src->pbo), &pbo_info);
+ } else { /* different sizes */
+ gst_gl_memory_copy_teximage (GST_GL_MEMORY_CAST (src),
+ tex_id, copy_params->tex_target, copy_params->out_format, out_width,
+ out_height);
+ }
+
+ gl->BindTexture (out_tex_target, 0);
+ gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+
+ gl->DeleteFramebuffers (1, &fboId);
+
+ copy_params->tex_id = tex_id;
+ copy_params->result = TRUE;
+
+ return;
+
+/* ERRORS */
+fbo_error:
+ {
+ gl->DeleteFramebuffers (1, &fboId);
+
+ copy_params->tex_id = 0;
+ copy_params->result = FALSE;
+ return;
+ }
+
+error:
+ {
+ copy_params->result = FALSE;
+ return;
+ }
+}
+
+static GstMemory *
+_gl_mem_copy (GstGLMemoryPBO * src, gssize offset, gssize size)
+{
+ GstAllocationParams params = { 0, GST_MEMORY_CAST (src)->align, 0, 0 };
+ GstGLBaseMemoryAllocator *base_mem_allocator;
+ GstAllocator *allocator;
+ GstMemory *dest = NULL;
+
+ allocator = GST_MEMORY_CAST (src)->allocator;
+ base_mem_allocator = (GstGLBaseMemoryAllocator *) allocator;
+
+ if (src->mem.tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
+ GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Cannot copy External OES textures");
+ return NULL;
+ }
+
+ /* If not doing a full copy, then copy to sysmem, the 2D represention of the
+ * texture would become wrong */
+ if (offset > 0 || size < GST_MEMORY_CAST (src)->size) {
+ return base_mem_allocator->fallback_mem_copy (GST_MEMORY_CAST (src), offset,
+ size);
+ }
+
+ dest = (GstMemory *) _gl_mem_new (allocator, NULL, src->mem.mem.context,
+ src->mem.tex_target, &params, &src->mem.info, &src->mem.valign,
+ src->mem.plane, NULL, NULL);
+
+ if (GST_MEMORY_FLAG_IS_SET (src, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)) {
+ if (!gst_gl_base_memory_memcpy ((GstGLBaseMemory *) src,
+ (GstGLBaseMemory *) dest, offset, size)) {
+ GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory");
+ gst_memory_unref (GST_MEMORY_CAST (dest));
+ return NULL;
+ }
+ } else {
+ GstMapInfo dinfo;
+
+ if (!gst_memory_map (GST_MEMORY_CAST (dest), &dinfo,
+ GST_MAP_WRITE | GST_MAP_GL)) {
+ GST_CAT_WARNING (GST_CAT_GL_MEMORY,
+ "Failed not map destination " "for writing");
+ gst_memory_unref (GST_MEMORY_CAST (dest));
+ return NULL;
+ }
+
+ if (!gst_gl_memory_copy_into ((GstGLMemory *) src,
+ ((GstGLMemory *) dest)->tex_id, src->mem.tex_target,
+ src->mem.tex_type, src->mem.tex_width, GL_MEM_HEIGHT (src))) {
+ GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory");
+ gst_memory_unmap (GST_MEMORY_CAST (dest), &dinfo);
+ gst_memory_unref (GST_MEMORY_CAST (dest));
+ return NULL;
+ }
+
+ gst_memory_unmap (GST_MEMORY_CAST (dest), &dinfo);
+ }
+
+ return dest;
+}
+
+static GstMemory *
+_gl_mem_alloc (GstAllocator * allocator, gsize size,
+ GstAllocationParams * params)
+{
+ g_warning ("use gst_gl_memory_pbo_alloc () to allocate from this "
+ "GstGLMemoryPBO allocator");
+
+ return NULL;
+}
+
+static void
+_gl_mem_destroy (GstGLMemoryPBO * gl_mem)
+{
+ if (gl_mem->pbo)
+ gst_memory_unref (GST_MEMORY_CAST (gl_mem->pbo));
+ gl_mem->pbo = NULL;
+
+ GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class)->destroy ((GstGLBaseMemory
+ *) gl_mem);
+}
+
+static void
+_gl_mem_free (GstAllocator * allocator, GstMemory * mem)
+{
+ GST_ALLOCATOR_CLASS (parent_class)->free (allocator, mem);
+}
+
+static void
+gst_gl_memory_pbo_allocator_class_init (GstGLMemoryPBOAllocatorClass * klass)
+{
+ GstGLBaseMemoryAllocatorClass *gl_base;
+ GstGLMemoryAllocatorClass *gl_tex;
+ GstAllocatorClass *allocator_class;
+
+ gl_tex = (GstGLMemoryAllocatorClass *) klass;
+ gl_base = (GstGLBaseMemoryAllocatorClass *) klass;
+ allocator_class = (GstAllocatorClass *) klass;
+
+ gl_base->create = (GstGLBaseMemoryAllocatorCreateFunction) _gl_mem_create;
+ gl_tex->map = (GstGLBaseMemoryAllocatorMapFunction) _gl_mem_map;
+ gl_tex->unmap = (GstGLBaseMemoryAllocatorUnmapFunction) _gl_mem_unmap;
+ gl_tex->copy = (GstGLBaseMemoryAllocatorCopyFunction) _gl_mem_copy;
+ gl_base->destroy = (GstGLBaseMemoryAllocatorDestroyFunction) _gl_mem_destroy;
+
+ allocator_class->alloc = _gl_mem_alloc;
+ allocator_class->free = _gl_mem_free;
+}
+
+static void
+gst_gl_memory_pbo_allocator_init (GstGLMemoryPBOAllocator * allocator)
+{
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ alloc->mem_type = GST_GL_MEMORY_PBO_ALLOCATOR_NAME;
+
+ GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+}
+
+/**
+ * gst_gl_memory_pbo_copy_into_texture:
+ * @gl_mem:a #GstGLMemoryPBO
+ * @tex_id:OpenGL texture id
+ * @tex_type: a #GstVideoGLTextureType
+ * @width: width of @tex_id
+ * @height: height of @tex_id
+ * @stride: stride of the backing texture data
+ * @respecify: whether to copy the data or copy per texel
+ *
+ * Copies @gl_mem into the texture specfified by @tex_id. The format of @tex_id
+ * is specified by @tex_type, @width and @height.
+ *
+ * If @respecify is %TRUE, then the copy is performed in terms of the texture
+ * data. This is useful for splitting RGBA textures into RG or R textures or
+ * vice versa. The requirement for this to succeed is that the backing texture
+ * data must be the same size, i.e. say a RGBA8 texture is converted into a RG8
+ * texture, then the RG texture must have twice as many pixels available for
+ * output as the RGBA texture.
+ *
+ * Otherwise, if @respecify is %FALSE, then the copy is performed per texel
+ * using glCopyTexImage. See the OpenGL specification for details on the
+ * mappings between texture formats.
+ *
+ * Returns: Whether the copy suceeded
+ */
+gboolean
+gst_gl_memory_pbo_copy_into_texture (GstGLMemoryPBO * gl_mem, guint tex_id,
+ GstGLTextureTarget target, GstVideoGLTextureType tex_type, gint width,
+ gint height, gint stride, gboolean respecify)
+{
+ GstGLMemoryPBOCopyParams copy_params;
+
+ copy_params.src = gl_mem;
+ copy_params.tex_target = target;
+ copy_params.tex_id = tex_id;
+ copy_params.out_format = tex_type;
+ copy_params.out_width = width;
+ copy_params.out_height = height;
+ copy_params.out_stride = stride;
+ copy_params.respecify = respecify;
+
+ gst_gl_context_thread_add (gl_mem->mem.mem.context, _gl_mem_copy_thread,
+ &copy_params);
+
+ return copy_params.result;
+}
+
+/**
+ * gst_gl_memory_pbo_wrapped_texture:
+ * @context: a #GstGLContext
+ * @texture_id: the GL texture handle
+ * @texture_target: the GL texture target
+ * @info: the #GstVideoInfo of the memory
+ * @plane: The plane this memory will represent
+ * @user_data: user data
+ * @notify: Destroy callback for the user data
+ *
+ * Wraps a texture handle into a #GstGLMemoryPBO.
+ *
+ * Returns: a newly allocated #GstGLMemoryPBO
+ */
+GstGLMemoryPBO *
+gst_gl_memory_pbo_wrapped_texture (GstGLContext * context,
+ guint texture_id, GstGLTextureTarget target,
+ GstVideoInfo * info, guint plane, GstVideoAlignment * valign,
+ gpointer user_data, GDestroyNotify notify)
+{
+ GstGLMemoryPBO *mem;
+
+ mem = g_slice_new0 (GstGLMemoryPBO);
+
+ mem->mem.tex_id = texture_id;
+ mem->mem.texture_wrapped = TRUE;
+
+ _gl_mem_init (mem, _gl_allocator, NULL, context, target, NULL, info, valign,
+ plane, user_data, notify);
+
+ GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
+
+ return mem;
+}
+
+/**
+ * gst_gl_memory_pbo_alloc:
+ * @context:a #GstGLContext
+ * @params: a #GstAllocationParams
+ * @info: the #GstVideoInfo of the memory
+ * @plane: the plane this memory will represent
+ * @valign: the #GstVideoAlignment applied to @info
+ *
+ * Allocated a new #GstGlMemory.
+ *
+ * Returns: a #GstMemory object with a GL texture specified by @vinfo
+ * from @context
+ */
+GstMemory *
+gst_gl_memory_pbo_alloc (GstGLContext * context, GstGLTextureTarget target,
+ GstAllocationParams * params, GstVideoInfo * info, guint plane,
+ GstVideoAlignment * valign)
+{
+ GstGLMemoryPBO *mem;
+
+ mem =
+ _gl_mem_new (_gl_allocator, NULL, context, target, params, info, valign,
+ plane, NULL, NULL);
+
+ return (GstMemory *) mem;
+}
+
+/**
+ * gst_gl_memory_pbo_wrapped:
+ * @context:a #GstGLContext
+ * @info: the #GstVideoInfo of the memory and data
+ * @plane: the plane this memory will represent
+ * @valign: the #GstVideoAlignment applied to @info
+ * @data: the data to wrap
+ * @user_data: data called with for @notify
+ * @notify: function called with @user_data when @data needs to be freed
+ *
+ * Wrapped @data into a #GstGLMemoryPBO. This version will account for padding
+ * added to the allocation and expressed through @valign.
+ *
+ * Returns: a #GstGLMemoryPBO object with a GL texture specified by @v_info
+ * from @context and contents specified by @data
+ */
+GstGLMemoryPBO *
+gst_gl_memory_pbo_wrapped (GstGLContext * context, GstGLTextureTarget target,
+ GstVideoInfo * info, guint plane, GstVideoAlignment * valign, gpointer data,
+ gpointer user_data, GDestroyNotify notify)
+{
+ GstGLMemoryPBO *mem;
+
+ mem = _gl_mem_new (_gl_allocator, NULL, context, target, NULL, info, valign,
+ plane, user_data, notify);
+ if (!mem)
+ return NULL;
+
+ mem->pbo->mem.data = data;
+
+ GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
+ if (mem->pbo)
+ GST_MINI_OBJECT_FLAG_SET (mem->pbo,
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
+
+ return mem;
+}
+
+static void
+_download_transfer (GstGLContext * context, GstGLMemoryPBO * gl_mem)
+{
+ GstGLBaseMemory *mem = (GstGLBaseMemory *) gl_mem;
+
+ g_mutex_lock (&mem->lock);
+ if (_read_pixels_to_pbo (gl_mem))
+ GST_CAT_TRACE (GST_CAT_GL_MEMORY, "optimistic download of texture %u "
+ "using pbo %u", gl_mem->mem.tex_id, gl_mem->pbo->id);
+ g_mutex_unlock (&mem->lock);
+}
+
+void
+gst_gl_memory_pbo_download_transfer (GstGLMemoryPBO * gl_mem)
+{
+ g_return_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem));
+
+ gst_gl_context_thread_add (gl_mem->mem.mem.context,
+ (GstGLContextThreadFunc) _download_transfer, gl_mem);
+}
+
+static void
+_upload_transfer (GstGLContext * context, GstGLMemoryPBO * gl_mem)
+{
+ GstGLBaseMemory *mem = (GstGLBaseMemory *) gl_mem;
+ GstMapInfo info;
+
+ g_mutex_lock (&mem->lock);
+ gl_mem->pbo->target = GL_PIXEL_UNPACK_BUFFER;
+ if (!gst_memory_map (GST_MEMORY_CAST (gl_mem->pbo), &info,
+ GST_MAP_READ | GST_MAP_GL)) {
+ GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Failed to map pbo for reading");
+ } else {
+ gst_memory_unmap (GST_MEMORY_CAST (gl_mem->pbo), &info);
+ }
+ g_mutex_unlock (&mem->lock);
+}
+
+void
+gst_gl_memory_pbo_upload_transfer (GstGLMemoryPBO * gl_mem)
+{
+ g_return_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem));
+
+ if (gl_mem->pbo && CONTEXT_SUPPORTS_PBO_UPLOAD (gl_mem->mem.mem.context))
+ gst_gl_context_thread_add (gl_mem->mem.mem.context,
+ (GstGLContextThreadFunc) _upload_transfer, gl_mem);
+}
+
+/**
+ * gst_gl_memory_pbo_init:
+ *
+ * Initializes the GL Memory allocator. It is safe to call this function
+ * multiple times. This must be called before any other GstGLMemoryPBO operation.
+ */
+void
+gst_gl_memory_pbo_init_once (void)
+{
+ static volatile gsize _init = 0;
+
+ if (g_once_init_enter (&_init)) {
+ gst_gl_memory_init_once ();
+
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_MEMORY, "glmemory", 0, "OpenGL Memory");
+
+ _gl_allocator = g_object_new (GST_TYPE_GL_MEMORY_PBO_ALLOCATOR, NULL);
+
+ gst_allocator_register (GST_GL_MEMORY_PBO_ALLOCATOR_NAME,
+ gst_object_ref (_gl_allocator));
+ g_once_init_leave (&_init, 1);
+ }
+}
+
+/**
+ * gst_is_gl_memory:
+ * @mem:a #GstMemory
+ *
+ * Returns: whether the memory at @mem is a #GstGLMemoryPBO
+ */
+gboolean
+gst_is_gl_memory_pbo (GstMemory * mem)
+{
+ return mem != NULL && mem->allocator != NULL
+ && g_type_is_a (G_OBJECT_TYPE (mem->allocator),
+ GST_TYPE_GL_MEMORY_PBO_ALLOCATOR);
+}
+
+/**
+ * gst_gl_memory_pbo_setup_buffer:
+ * @context: a #GstGLContext
+ * @params: a #GstAllocationParams
+ * @info: a #GstVideoInfo
+ * @valign: the #GstVideoAlignment applied to @info
+ * @buffer: a #GstBuffer
+ *
+ * Adds the required #GstGLMemoryPBO<!-- -->s with the correct configuration to
+ * @buffer based on @info. This version handles padding through @valign.
+ *
+ * Returns: whether the memory's were sucessfully added.
+ */
+gboolean
+gst_gl_memory_pbo_setup_buffer (GstGLContext * context,
+ GstGLTextureTarget target, GstAllocationParams * params,
+ GstVideoInfo * info, GstVideoAlignment * valign, GstBuffer * buffer)
+{
+ GstGLMemoryPBO *gl_mem[GST_VIDEO_MAX_PLANES] = { NULL, };
+ guint n_mem, i, v, views;
+
+ n_mem = GST_VIDEO_INFO_N_PLANES (info);
+
+ if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) ==
+ GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
+ views = info->views;
+ else
+ views = 1;
+
+ for (v = 0; v < views; v++) {
+ for (i = 0; i < n_mem; i++) {
+ gl_mem[i] =
+ (GstGLMemoryPBO *) gst_gl_memory_pbo_alloc (context, target, params,
+ info, i, valign);
+ if (gl_mem[i] == NULL)
+ return FALSE;
+
+ gst_buffer_append_memory (buffer, (GstMemory *) gl_mem[i]);
+ }
+
+ gst_buffer_add_video_meta_full (buffer, v,
+ GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
+ GST_VIDEO_INFO_HEIGHT (info), n_mem, info->offset, info->stride);
+ }
+
+ return TRUE;
+}
+
+/**
+ * gst_gl_memory_pbo_setup_wrapped:
+ * @context: a #GstGLContext
+ * @info: a #GstVideoInfo
+ * @valign: a #GstVideoInfo
+ * @data: a list of per plane data pointers
+ * @textures: (transfer out): a list of #GstGLMemoryPBO
+ * @user_data: user data for the destroy function
+ * @notify: A function called each time a memory is freed
+ *
+ * Wraps per plane data pointer in @data into the corresponding entry in
+ * @textures based on @info and padding from @valign. Note that the @notify
+ * will be called as many time as there is planes.
+ *
+ * Returns: whether the memory's were sucessfully created.
+ */
+gboolean
+gst_gl_memory_pbo_setup_wrapped (GstGLContext * context,
+ GstGLTextureTarget target, GstVideoInfo * info, GstVideoAlignment * valign,
+ gpointer data[GST_VIDEO_MAX_PLANES],
+ GstGLMemoryPBO * textures[GST_VIDEO_MAX_PLANES], gpointer user_data,
+ GDestroyNotify notify)
+{
+ gint i;
+
+ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
+ textures[i] =
+ (GstGLMemoryPBO *) gst_gl_memory_pbo_wrapped (context, target, info, i,
+ valign, data[i], user_data, notify);
+ }
+
+ return TRUE;
+}
diff --git a/gst-libs/gst/gl/gstglmemorypbo.h b/gst-libs/gst/gl/gstglmemorypbo.h
new file mode 100644
index 000000000..335354a49
--- /dev/null
+++ b/gst-libs/gst/gl/gstglmemorypbo.h
@@ -0,0 +1,139 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
+ * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _GST_GL_MEMORY_PBO_H_
+#define _GST_GL_MEMORY_PBO_H_
+
+#include <gst/gst.h>
+#include <gst/gstallocator.h>
+#include <gst/gstmemory.h>
+#include <gst/video/video.h>
+
+#include <gst/gl/gstglmemory.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_GL_MEMORY_PBO_ALLOCATOR (gst_gl_memory_pbo_allocator_get_type())
+GType gst_gl_memory_pbo_allocator_get_type(void);
+
+#define GST_IS_GL_MEMORY_PBO_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_MEMORY_PBO_ALLOCATOR))
+#define GST_IS_GL_MEMORY_PBO_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GL_MEMORY_PBO_ALLOCATOR))
+#define GST_GL_MEMORY_PBO_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GL_MEMORY_PBO_ALLOCATOR, GstGLMemoryPBOAllocatorClass))
+#define GST_GL_MEMORY_PBO_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_MEMORY_PBO_ALLOCATOR, GstGLMemoryPBOAllocator))
+#define GST_GL_MEMORY_PBO_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GL_MEMORY_PBO_ALLOCATOR, GstGLAllocatorClass))
+#define GST_GL_MEMORY_PBO_ALLOCATOR_CAST(obj) ((GstGLMemoryPBOAllocator *)(obj))
+
+/**
+ * GstGLMemoryPBO:
+ *
+ * Private instance
+ */
+struct _GstGLMemoryPBO
+{
+ GstGLMemory mem;
+
+ /* <private> */
+ GstGLBuffer *pbo;
+};
+
+/**
+ * GST_GL_MEMORY_PBO_ALLOCATOR:
+ *
+ * The name of the GL Memory PBO allocator
+ */
+#define GST_GL_MEMORY_PBO_ALLOCATOR_NAME "GLMemoryPBO"
+
+void gst_gl_memory_pbo_init_once (void);
+gboolean gst_is_gl_memory_pbo (GstMemory * mem);
+
+GstMemory * gst_gl_memory_pbo_alloc (GstGLContext * context,
+ GstGLTextureTarget target,
+ GstAllocationParams *params,
+ GstVideoInfo * info,
+ guint plane,
+ GstVideoAlignment *valign);
+GstGLMemoryPBO * gst_gl_memory_pbo_wrapped (GstGLContext * context,
+ GstGLTextureTarget target,
+ GstVideoInfo * info,
+ guint plane,
+ GstVideoAlignment *valign,
+ gpointer data,
+ gpointer user_data,
+ GDestroyNotify notify);
+GstGLMemoryPBO * gst_gl_memory_pbo_wrapped_texture (GstGLContext * context,
+ guint texture_id,
+ GstGLTextureTarget target,
+ GstVideoInfo * info,
+ guint plane,
+ GstVideoAlignment *valign,
+ gpointer user_data,
+ GDestroyNotify notify);
+
+void gst_gl_memory_pbo_download_transfer (GstGLMemoryPBO * gl_mem);
+void gst_gl_memory_pbo_upload_transfer (GstGLMemoryPBO * gl_mem);
+
+gboolean gst_gl_memory_pbo_copy_into_texture (GstGLMemoryPBO *gl_mem,
+ guint tex_id,
+ GstGLTextureTarget target,
+ GstVideoGLTextureType tex_type,
+ gint width,
+ gint height,
+ gint stride,
+ gboolean respecify);
+
+gboolean gst_gl_memory_pbo_setup_buffer (GstGLContext * context,
+ GstGLTextureTarget target,
+ GstAllocationParams * params,
+ GstVideoInfo * info,
+ GstVideoAlignment *valign,
+ GstBuffer * buffer);
+gboolean gst_gl_memory_pbo_setup_wrapped (GstGLContext * context,
+ GstGLTextureTarget target,
+ GstVideoInfo * info,
+ GstVideoAlignment *valign,
+ gpointer data[GST_VIDEO_MAX_PLANES],
+ GstGLMemoryPBO *textures[GST_VIDEO_MAX_PLANES],
+ gpointer user_data,
+ GDestroyNotify notify);
+
+/**
+ * GstGLAllocator
+ *
+ * Opaque #GstGLAllocator struct
+ */
+struct _GstGLMemoryPBOAllocator
+{
+ GstGLMemoryAllocator parent;
+};
+
+/**
+ * GstGLAllocatorClass:
+ *
+ * The #GstGLAllocatorClass only contains private data
+ */
+struct _GstGLMemoryPBOAllocatorClass
+{
+ GstGLMemoryAllocatorClass parent_class;
+};
+
+G_END_DECLS
+
+#endif /* _GST_GL_MEMORY_PBO_H_ */
diff --git a/gst-libs/gst/gl/gstgloverlaycompositor.c b/gst-libs/gst/gl/gstgloverlaycompositor.c
index a3f906d1f..b62e396ef 100644
--- a/gst-libs/gst/gl/gstgloverlaycompositor.c
+++ b/gst-libs/gst/gl/gstgloverlaycompositor.c
@@ -347,9 +347,9 @@ gst_gl_composition_overlay_upload (GstGLCompositionOverlay * overlay,
gst_gl_composition_overlay_add_transformation (overlay, buf);
comp_gl_memory =
- gst_gl_memory_wrapped (overlay->context, GST_GL_TEXTURE_TARGET_2D,
- &comp_frame->info, 0, NULL, comp_frame->data[0], comp_frame,
- _video_frame_unmap_and_free);
+ (GstGLMemory *) gst_gl_memory_pbo_wrapped (overlay->context,
+ GST_GL_TEXTURE_TARGET_2D, &comp_frame->info, 0, NULL,
+ comp_frame->data[0], comp_frame, _video_frame_unmap_and_free);
overlay_buffer = gst_buffer_new ();
gst_buffer_append_memory (overlay_buffer, (GstMemory *) comp_gl_memory);
diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c
index ed5c09178..51ac1ba79 100644
--- a/gst-libs/gst/gl/gstglupload.c
+++ b/gst-libs/gst/gl/gstglupload.c
@@ -223,7 +223,7 @@ _gl_memory_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
GstAllocationParams params;
gst_allocation_params_init (&params);
- allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
+ allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR_NAME);
gst_query_add_allocation_param (query, allocator, &params);
gst_object_unref (allocator);
}
@@ -308,7 +308,8 @@ _gl_memory_upload_perform (gpointer impl, GstBuffer * buffer,
gl_mem->mem.context))
return GST_GL_UPLOAD_UNSHARED_GL_CONTEXT;
- gst_gl_memory_upload_transfer (gl_mem);
+ if (gst_is_gl_memory_pbo (mem))
+ gst_gl_memory_pbo_upload_transfer ((GstGLMemoryPBO *) mem);
}
*outbuf = gst_buffer_ref (buffer);
@@ -460,8 +461,9 @@ _egl_image_upload_perform_gl_thread (GstGLContext * context,
/* FIXME: buffer pool */
*image->outbuf = gst_buffer_new ();
- gst_gl_memory_setup_buffer (image->upload->context, GST_GL_TEXTURE_TARGET_2D,
- NULL, &image->upload->priv->out_info, NULL, *image->outbuf);
+ gst_gl_memory_pbo_setup_buffer (image->upload->context,
+ GST_GL_TEXTURE_TARGET_2D, NULL, &image->upload->priv->out_info, NULL,
+ *image->outbuf);
n = gst_buffer_n_memory (image->buffer);
for (i = 0; i < n; i++) {
@@ -479,8 +481,8 @@ _egl_image_upload_perform_gl_thread (GstGLContext * context,
}
if (GST_IS_GL_BUFFER_POOL (image->buffer->pool))
- gst_gl_buffer_pool_replace_last_buffer (GST_GL_BUFFER_POOL (image->buffer->
- pool), image->buffer);
+ gst_gl_buffer_pool_replace_last_buffer (GST_GL_BUFFER_POOL (image->
+ buffer->pool), image->buffer);
}
static GstGLUploadReturn
@@ -621,11 +623,11 @@ _upload_meta_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
gpointer handle;
gl_apis =
- gst_gl_api_to_string (gst_gl_context_get_gl_api (upload->
- upload->context));
+ gst_gl_api_to_string (gst_gl_context_get_gl_api (upload->upload->
+ context));
platform =
- gst_gl_platform_to_string (gst_gl_context_get_gl_platform
- (upload->upload->context));
+ gst_gl_platform_to_string (gst_gl_context_get_gl_platform (upload->
+ upload->context));
handle = (gpointer) gst_gl_context_get_gl_context (upload->upload->context);
gl_context =
@@ -677,8 +679,9 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer,
/* FIXME: buffer pool */
*outbuf = gst_buffer_new ();
- gst_gl_memory_setup_buffer (upload->upload->context, GST_GL_TEXTURE_TARGET_2D,
- NULL, &upload->upload->priv->in_info, NULL, *outbuf);
+ gst_gl_memory_pbo_setup_buffer (upload->upload->context,
+ GST_GL_TEXTURE_TARGET_2D, NULL, &upload->upload->priv->in_info, NULL,
+ *outbuf);
for (i = 0; i < GST_GL_UPLOAD_MAX_PLANES; i++) {
guint tex_id = 0;
@@ -872,9 +875,10 @@ _raw_data_upload_perform (gpointer impl, GstBuffer * buffer,
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
max_planes *= GST_VIDEO_INFO_VIEWS (in_info);
- gst_gl_memory_setup_wrapped (raw->upload->context, GST_GL_TEXTURE_TARGET_2D,
- &raw->upload->priv->in_info, NULL, raw->in_frame->frame.data, in_tex,
- raw->in_frame, (GDestroyNotify) _raw_upload_frame_unref);
+ gst_gl_memory_pbo_setup_wrapped (raw->upload->context,
+ GST_GL_TEXTURE_TARGET_2D, &raw->upload->priv->in_info, NULL,
+ raw->in_frame->frame.data, (GstGLMemoryPBO **) in_tex, raw->in_frame,
+ (GDestroyNotify) _raw_upload_frame_unref);
/* FIXME Use a buffer pool to cache the generated textures */
*outbuf = gst_buffer_new ();
diff --git a/gst-libs/gst/gl/gstglviewconvert.c b/gst-libs/gst/gl/gstglviewconvert.c
index 322ffd656..3f36b408c 100644
--- a/gst-libs/gst/gl/gstglviewconvert.c
+++ b/gst-libs/gst/gl/gstglviewconvert.c
@@ -1892,7 +1892,7 @@ static gboolean
_gen_buffer (GstGLViewConvert * viewconvert, GstBuffer ** target)
{
*target = gst_buffer_new ();
- if (!gst_gl_memory_setup_buffer (viewconvert->context,
+ if (!gst_gl_memory_pbo_setup_buffer (viewconvert->context,
viewconvert->to_texture_target, NULL, &viewconvert->out_info, NULL,
*target)) {
return FALSE;
@@ -2017,7 +2017,7 @@ _do_view_convert (GstGLContext * context, GstGLViewConvert * viewconvert)
* the attachments i.e. the smallest attachment size */
if (!priv->out_tex[j])
priv->out_tex[j] =
- (GstGLMemory *) gst_gl_memory_alloc (context,
+ (GstGLMemory *) gst_gl_memory_pbo_alloc (context,
viewconvert->to_texture_target, NULL, &temp_info, 0, NULL);
} else {
priv->out_tex[j] = out_tex;
@@ -2069,10 +2069,8 @@ out:
res = FALSE;
continue;
}
- gst_gl_memory_copy_into_texture (priv->out_tex[j],
- out_tex->tex_id, viewconvert->to_texture_target, out_tex->tex_type,
- width, height,
- GST_VIDEO_INFO_PLANE_STRIDE (&out_tex->info, out_tex->plane), FALSE);
+ gst_gl_memory_copy_into (priv->out_tex[j], out_tex->tex_id,
+ viewconvert->to_texture_target, out_tex->tex_type, width, height);
gst_memory_unmap ((GstMemory *) out_tex, &to_info);
}
diff --git a/tests/check/libs/gstglmemory.c b/tests/check/libs/gstglmemory.c
index 68ea7bc17..11903fa37 100644
--- a/tests/check/libs/gstglmemory.c
+++ b/tests/check/libs/gstglmemory.c
@@ -39,7 +39,7 @@ setup (void)
display = gst_gl_display_new ();
context = gst_gl_context_new (display);
gst_gl_context_create (context, 0, NULL);
- gst_gl_memory_init ();
+ gst_gl_memory_init_once ();
}
static void
@@ -60,7 +60,7 @@ GST_START_TEST (test_basic)
GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_I420
};
- gl_allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
+ gl_allocator = gst_allocator_find (GST_GL_MEMORY_PBO_ALLOCATOR_NAME);
fail_if (gl_allocator == NULL);
/* test allocator creation */
@@ -74,8 +74,8 @@ GST_START_TEST (test_basic)
for (j = 0; j < GST_VIDEO_INFO_N_PLANES (&v_info); j++) {
mem =
- gst_gl_memory_alloc (context, GST_GL_TEXTURE_TARGET_2D, NULL, &v_info,
- j, NULL);
+ gst_gl_memory_pbo_alloc (context, GST_GL_TEXTURE_TARGET_2D, NULL,
+ &v_info, j, NULL);
fail_if (mem == NULL);
gl_mem = (GstGLMemory *) mem;
@@ -120,47 +120,47 @@ GST_START_TEST (test_transfer)
GstMemory *mem, *mem2, *mem3;
GstMapInfo map_info;
- gl_allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
+ gl_allocator = gst_allocator_find (GST_GL_MEMORY_PBO_ALLOCATOR_NAME);
fail_if (gl_allocator == NULL);
gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 1, 1);
/* texture creation */
mem =
- (GstMemory *) gst_gl_memory_alloc (context, GST_GL_TEXTURE_TARGET_2D,
+ (GstMemory *) gst_gl_memory_pbo_alloc (context, GST_GL_TEXTURE_TARGET_2D,
NULL, &v_info, 0, NULL);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
/* test wrapping raw data */
mem2 =
- (GstMemory *) gst_gl_memory_wrapped (context, GST_GL_TEXTURE_TARGET_2D,
- &v_info, 0, NULL, rgba_pixel, NULL, NULL);
+ (GstMemory *) gst_gl_memory_pbo_wrapped (context,
+ GST_GL_TEXTURE_TARGET_2D, &v_info, 0, NULL, rgba_pixel, NULL, NULL);
fail_if (mem == NULL);
fail_unless (GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
/* wrapped texture creation */
- mem3 = (GstMemory *) gst_gl_memory_wrapped_texture (context,
+ mem3 = (GstMemory *) gst_gl_memory_pbo_wrapped_texture (context,
((GstGLMemory *) mem)->tex_id, GST_GL_TEXTURE_TARGET_2D, &v_info, 0, NULL,
NULL, NULL);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem3,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem3,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
/* check data/flags are correct */
fail_unless (gst_memory_map (mem2, &map_info, GST_MAP_READ));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (((gchar *) map_info.data)[0] == rgba_pixel[0]);
fail_unless (((gchar *) map_info.data)[1] == rgba_pixel[1]);
@@ -170,32 +170,31 @@ GST_START_TEST (test_transfer)
gst_memory_unmap (mem2, &map_info);
fail_unless (GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (gst_memory_map (mem2, &map_info, GST_MAP_READ | GST_MAP_GL));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
/* test texture copy */
- fail_unless (gst_gl_memory_copy_into_texture ((GstGLMemory *) mem2,
+ fail_unless (gst_gl_memory_copy_into ((GstGLMemory *) mem2,
((GstGLMemory *) mem)->tex_id, GST_GL_TEXTURE_TARGET_2D,
- GST_VIDEO_GL_TEXTURE_TYPE_RGBA, 1, 1, 4, FALSE));
- GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD);
- GST_GL_MEMORY_ADD_TRANSFER (mem, GST_GL_MEMORY_TRANSFER_NEED_DOWNLOAD);
+ GST_VIDEO_GL_TEXTURE_TYPE_RGBA, 1, 1));
+ GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
gst_memory_unmap (mem2, &map_info);
@@ -213,9 +212,9 @@ GST_START_TEST (test_transfer)
fail_unless (gst_memory_map (mem3, &map_info, GST_MAP_READ));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (((gchar *) map_info.data)[0] == rgba_pixel[0]);
fail_unless (((gchar *) map_info.data)[1] == rgba_pixel[1]);
@@ -229,18 +228,18 @@ GST_START_TEST (test_transfer)
gst_memory_unmap (mem3, &map_info);
fail_unless (GST_MEMORY_FLAG_IS_SET (mem3,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem3,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
/* test download flag */
fail_unless (gst_memory_map (mem3, &map_info, GST_MAP_WRITE | GST_MAP_GL));
gst_memory_unmap (mem3, &map_info);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem3,
- GST_GL_BASE_BUFFER_FLAG_NEED_UPLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem3,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
if (gst_gl_context_get_error ())
printf ("%s\n", gst_gl_context_get_error ());
@@ -261,22 +260,22 @@ GST_START_TEST (test_separate_transfer)
GstMemory *mem;
GstMapInfo info;
- gl_allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
+ gl_allocator = gst_allocator_find (GST_GL_MEMORY_PBO_ALLOCATOR_NAME);
fail_if (gl_allocator == NULL);
gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 1, 1);
mem =
- (GstMemory *) gst_gl_memory_wrapped (context, GST_GL_TEXTURE_TARGET_2D,
- &v_info, 0, NULL, rgba_pixel, NULL, NULL);
+ (GstMemory *) gst_gl_memory_pbo_wrapped (context,
+ GST_GL_TEXTURE_TARGET_2D, &v_info, 0, NULL, rgba_pixel, NULL, NULL);
fail_if (mem == NULL);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
- gst_gl_memory_upload_transfer ((GstGLMemory *) mem);
+ gst_gl_memory_pbo_upload_transfer ((GstGLMemoryPBO *) mem);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
- GST_GL_BASE_BUFFER_FLAG_NEED_DOWNLOAD));
+ GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));