--- /dev/null
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/video/video.h>
+
+#include "gstglmemory.h"
+
+/*GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
+#define GST_CAT_DEFUALT GST_CAT_GL_MEMORY
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_MEMORY);*/
+
+static GstAllocator *_gl_allocator;
+
+typedef struct
+{
+ GstGLMemory *src;
+ GLuint tex_id;
+} GstGLMemoryCopyParams;
+
+static void
+_gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
+ GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height)
+{
+ gst_memory_init (GST_MEMORY_CAST (mem), GST_MEMORY_FLAG_NO_SHARE,
+ allocator, parent, 0, 0, 0, 0);
+
+ mem->display = g_object_ref (display);
+ mem->gl_format = GL_RGBA;
+ mem->v_format = v_format;
+ mem->width = width;
+ mem->height = height;
+
+ GST_DEBUG ("new GL memory");
+}
+
+static GstGLMemory *
+_gl_mem_new (GstAllocator * allocator, GstMemory * parent,
+ GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height)
+{
+ GstGLMemory *mem;
+ GLuint tex_id;
+
+ gst_gl_display_gen_texture (display, &tex_id, v_format, width, height);
+ if (!tex_id) {
+ GST_WARNING ("Could not create GL texture with display:%p", display);
+ }
+
+ GST_TRACE ("created texture %u", tex_id);
+
+ mem = g_slice_alloc (sizeof (GstGLMemory));
+ _gl_mem_init (mem, allocator, parent, display, v_format, width, height);
+
+ mem->tex_id = tex_id;
+
+ return mem;
+}
+
+GstMemory *
+_gl_allocator_alloc_func (GstAllocator * allocator, gsize size,
+ GstAllocationParams * params, gpointer user_data)
+{
+ g_warning ("use gst_gl_memory_alloc () to allocate from this "
+ "GstGLMemory allocator");
+
+ return NULL;
+}
+
+gpointer
+_gl_mem_map_func (GstGLMemory * gl_mem, gsize maxsize, GstMapFlags flags)
+{
+ /* should we perform a {up,down}load? */
+ return NULL;
+}
+
+void
+_gl_mem_unmap_func (GstGLMemory * gl_mem)
+{
+}
+
+void
+_gl_mem_free_func (GstGLMemory * gl_mem)
+{
+ gst_gl_display_del_texture (gl_mem->display, &gl_mem->tex_id);
+
+ g_object_unref (gl_mem->display);
+
+ g_slice_free (GstGLMemory, gl_mem);
+}
+
+void
+_gl_mem_copy_thread (GstGLDisplay * display, gpointer data)
+{
+ GstGLMemoryCopyParams *copy_params;
+ GstGLMemory *src;
+ GLuint tex_id;
+ GLuint rboId, fboId;
+ GLenum status;
+ gsize width, height;
+ GLuint gl_format;
+ GstVideoFormat v_format;
+
+ copy_params = (GstGLMemoryCopyParams *) data;
+ src = copy_params->src;
+ width = src->width;
+ height = src->height;
+ v_format = src->v_format;
+ gl_format = src->gl_format;
+
+ if (!GLEW_EXT_framebuffer_object) {
+ //turn off the pipeline because Frame buffer object is a not present
+ gst_gl_display_set_error (display,
+ "Context, EXT_framebuffer_object not supported");
+ return;
+ }
+
+ gst_gl_display_gen_texture_thread (src->display, &tex_id, v_format, width,
+ height);
+ if (!tex_id) {
+ GST_WARNING ("Could not create GL texture with display:%p", src->display);
+ }
+
+ GST_DEBUG ("created texture %i", tex_id);
+
+ /* create a framebuffer object */
+ glGenFramebuffersEXT (1, &fboId);
+ glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fboId);
+
+ /* create a renderbuffer object */
+ glGenRenderbuffersEXT (1, &rboId);
+ glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, rboId);
+
+#ifndef OPENGL_ES2
+ glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width,
+ height);
+ glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+ width, height);
+#else
+ glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
+ width, height);
+#endif
+ /* attach the renderbuffer to depth attachment point */
+ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, rboId);
+
+#ifndef OPENGL_ES2
+ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+ GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);
+#endif
+
+ glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_RECTANGLE_ARB, src->tex_id, 0);
+
+ /* check FBO status */
+ status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ switch (status) {
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ GST_ERROR ("GL_FRAMEBUFFER_UNSUPPORTED");
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+ GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+ break;
+
+ case GL_FRAMEBUFFER_UNDEFINED:
+ GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED");
+ break;
+
+ default:
+ GST_ERROR ("General FBO error");
+ }
+ goto fbo_error;
+ }
+
+ /* copy tex */
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex_id);
+ glCopyTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, 0, 0,
+ width, height, 0);
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
+
+ glBindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
+
+ glDeleteRenderbuffers (1, &rboId);
+ glDeleteFramebuffers (1, &fboId);
+
+ copy_params->tex_id = tex_id;
+
+fbo_error:
+ {
+ glDeleteRenderbuffers (1, &rboId);
+ glDeleteFramebuffers (1, &fboId);
+
+ copy_params->tex_id = 0;
+ }
+}
+
+GstMemory *
+_gl_mem_copy_func (GstGLMemory * src, gssize offset, gssize size)
+{
+ GstGLMemory *dest;
+ GstGLMemoryCopyParams copy_params;
+
+ copy_params = (GstGLMemoryCopyParams) {
+ src, 0,};
+
+ gst_gl_display_thread_add (src->display, _gl_mem_copy_thread, ©_params);
+
+ dest = g_slice_alloc (sizeof (GstGLMemory));
+ _gl_mem_init (dest, src->mem.allocator, NULL, src->display, src->v_format,
+ src->width, src->height);
+
+ if (!copy_params.tex_id)
+ GST_WARNING ("Could not copy GL Memory");
+
+ dest->tex_id = copy_params.tex_id;
+
+ return (GstMemory *) dest;
+}
+
+GstGLMemory *
+gst_gl_memory_copy (GstGLMemory * src)
+{
+ return (GstGLMemory *) _gl_mem_copy_func (src, 0, 0);
+}
+
+GstMemory *
+_gl_mem_share_func (GstGLMemory * mem, gssize offset, gssize size)
+{
+ return NULL;
+}
+
+gboolean
+_gl_mem_is_span_func (GstGLMemory * mem1, GstGLMemory * mem2, gsize * offset)
+{
+ return FALSE;
+}
+
+static void
+_gl_mem_destroy_notify (gpointer user_data)
+{
+ GST_LOG ("GLTexture memory allocator freed");
+}
+
+/**
+ * gst_gl_memory_alloc:
+ * @display:a #GstGLDisplay
+ * @format: the format for the texture
+ * @width: width of the texture
+ * @height: height of the texture
+ *
+ * Returns: a GstMemory object with a GL texture specified by @format, @width and @height
+ * from @display
+ */
+GstMemory *
+gst_gl_memory_alloc (GstGLDisplay * display, GstVideoFormat format,
+ gsize width, gsize height)
+{
+ return (GstMemory *) _gl_mem_new (_gl_allocator, NULL, display, format, width,
+ height);
+}
+
+/**
+ * gst_gl_memory_init:
+ *
+ * Initializes the GL Memory allocator. It is safe to call this function multiple times
+ *
+ * Returns: a #GstAllocator
+ */
+void
+gst_gl_memory_init (void)
+{
+ static volatile gsize _init = 0;
+ static const GstMemoryInfo mem_info = {
+ GST_GL_MEMORY_ALLOCATOR,
+ (GstAllocatorAllocFunction) _gl_allocator_alloc_func,
+ (GstMemoryMapFunction) _gl_mem_map_func,
+ (GstMemoryUnmapFunction) _gl_mem_unmap_func,
+ (GstMemoryFreeFunction) _gl_mem_free_func,
+ (GstMemoryCopyFunction) _gl_mem_copy_func,
+ (GstMemoryShareFunction) _gl_mem_share_func,
+ (GstMemoryIsSpanFunction) _gl_mem_is_span_func,
+ };
+
+ if (g_once_init_enter (&_init)) {
+ _gl_allocator = gst_allocator_new (&mem_info, NULL, _gl_mem_destroy_notify);
+ gst_allocator_register (GST_GL_MEMORY_ALLOCATOR,
+ gst_allocator_ref (_gl_allocator));
+ g_once_init_leave (&_init, 1);
+ }
+}
--- /dev/null
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GST_GL_MEMORY_H_
+#define _GST_GL_MEMORY_H_
+
+#include <gst/gst.h>
+#include <gst/gstmemory.h>
+
+#include "gstgldisplay.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_GL_MEMORY (gst_gl_memory_get_type())
+GType gst_gl_memory_get_type(void);
+
+typedef struct _GstGLMemoryInitParams GstGLMemoryInitParams;
+typedef struct _GstGLMemory GstGLMemory;
+
+/**
+ * GstGLMemory:
+ * @mem: the parent object
+ * @display: the #GstGLDisplay to use
+ * @tex_id: the texture id
+ * @gl_format: the format of the texture
+ * @width: width of the texture
+ * @height: height of the texture
+ *
+ * Represents information about a GL texture
+ */
+struct _GstGLMemory
+{
+ GstMemory mem;
+
+ GstGLDisplay *display;
+ GLuint tex_id;
+ GstVideoFormat v_format;
+ GLenum gl_format;
+ GLuint width;
+ GLuint height;
+};
+
+#define GST_GL_MEMORY_ALLOCATOR "GLMemory"
+
+void gst_gl_memory_init (void);
+
+GstMemory * gst_gl_memory_alloc (GstGLDisplay * display, GstVideoFormat format,
+ gsize width, gsize height);
+
+G_END_DECLS
+
+#endif /* _GST_GL_MEMORY_H_ */
--- /dev/null
+/* GStreamer
+ *
+ * unit test for state changes on all elements
+ *
+ * Copyright (C) <2012> Matthew Waters <ystreet00@gmail.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gst/check/gstcheck.h>
+
+#include <gst/gl/gstglmemory.h>
+
+#include <stdio.h>
+
+static GstGLDisplay *display;
+
+void
+setup (void)
+{
+ display = gst_gl_display_new ();
+ gst_gl_display_create_context (display, 0);
+ gst_gl_memory_init ();
+}
+
+void
+teardown (void)
+{
+ g_object_unref (display);
+}
+
+GST_START_TEST (test_basic)
+{
+ GstMemory *mem, *mem2;
+ GstGLMemory *gl_mem, *gl_mem2;
+ GstAllocator *gl_allocator;
+ GstVideoInfo vinfo;
+ gint i;
+ static GstVideoFormat formats[15] = {
+ GST_VIDEO_FORMAT_RGBx, GST_VIDEO_FORMAT_BGRx, GST_VIDEO_FORMAT_xRGB,
+ GST_VIDEO_FORMAT_xBGR, GST_VIDEO_FORMAT_RGBA, GST_VIDEO_FORMAT_BGRA,
+ GST_VIDEO_FORMAT_ARGB, GST_VIDEO_FORMAT_ABGR, GST_VIDEO_FORMAT_RGB,
+ GST_VIDEO_FORMAT_BGR, GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_UYVY,
+ GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_AYUV,
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (formats); i++) {
+ gsize width = 320, height = 240;
+
+ gst_video_info_set_format (&vinfo, formats[i], width, height);
+ gl_allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
+ fail_if (gl_allocator == NULL);
+
+ /* test allocator creation */
+ ASSERT_WARNING (mem = gst_allocator_alloc (gl_allocator, 0, NULL););
+ mem = gst_gl_memory_alloc (display, formats[i], width, height);
+ fail_if (mem == NULL);
+ gl_mem = (GstGLMemory *) mem;
+
+ /* test init params */
+ fail_if (gl_mem->width != width);
+ fail_if (gl_mem->height != height);
+ fail_if (gl_mem->v_format != formats[i]);
+ fail_if (gl_mem->display != display);
+ fail_if (gl_mem->tex_id == 0);
+
+ /* copy the memory */
+ mem2 = gst_memory_copy (mem, 0, -1);
+ fail_if (mem == NULL);
+ gl_mem2 = (GstGLMemory *) mem2;
+
+ /* test params */
+ fail_if (gl_mem->tex_id == gl_mem2->tex_id);
+ fail_if (gl_mem->width != gl_mem->width);
+ fail_if (gl_mem->height != gl_mem->height);
+ fail_if (gl_mem->v_format != gl_mem->v_format);
+ fail_if (gl_mem->gl_format != gl_mem->gl_format);
+ fail_if (gl_mem->display != gl_mem->display);
+ fail_if (gl_mem->tex_id == 0);
+
+ if (display->error_message)
+ printf ("%s\n", display->error_message);
+ fail_if (display->error_message != NULL);
+
+ gst_memory_unref (mem);
+ gst_memory_unref (mem2);
+
+ gst_allocator_unref (gl_allocator);
+ }
+}
+
+GST_END_TEST;
+
+
+Suite *
+gst_gl_memory_suite (void)
+{
+ Suite *s = suite_create ("GstGLMemory");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_checked_fixture (tc_chain, setup, teardown);
+ tcase_add_test (tc_chain, test_basic);
+
+ return s;
+}
+
+GST_CHECK_MAIN (gst_gl_memory);