[714/906] Add GstGLFramebuffer to replace _display_gen_fbo and friends
authorMatthew Waters <ystreet00@gmail.com>
Sun, 16 Jun 2013 10:44:47 +0000 (20:44 +1000)
committerMatthew Waters <ystreet00@gmail.com>
Sat, 15 Mar 2014 17:36:56 +0000 (18:36 +0100)
This version is simply API compatible with _display_gen_fbo.
The next version will likely revamp the API

gst-libs/gst/gl/Makefile.am
gst-libs/gst/gl/gstglframebuffer.c [new file with mode: 0644]
gst-libs/gst/gl/gstglframebuffer.h [new file with mode: 0644]
gst-libs/gst/gl/gstglutils.c
gst-libs/gst/gl/gstglutils.h

index 4de26fe..1f8d211 100644 (file)
@@ -16,7 +16,8 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \
         gstglwindow.c \
         gstglapi.c \
         gstglfeature.c \
-        gstglutils.c
+        gstglutils.c \
+        gstglframebuffer.c
 
 libgstgl_@GST_API_VERSION@_la_LIBADD = \
        $(GST_PLUGINS_BASE_LIBS) \
@@ -61,7 +62,8 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \
        gstglupload.h \
        gstglapi.h \
        gstglfeature.h \
-       gstglutils.h
+       gstglutils.h \
+       gstglframebuffer.h
 
 libgstgl_@GST_API_VERSION@_la_CFLAGS = \
        $(GL_CFLAGS) \
diff --git a/gst-libs/gst/gl/gstglframebuffer.c b/gst-libs/gst/gl/gstglframebuffer.c
new file mode 100644 (file)
index 0000000..79ee374
--- /dev/null
@@ -0,0 +1,335 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#include "gstglframebuffer.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_gl_framebuffer_debug);
+#define GST_CAT_DEFAULT gst_gl_framebuffer_debug
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_gl_framebuffer_debug, "glframebuffer", 0, "GL Framebuffer");
+
+G_DEFINE_TYPE_WITH_CODE (GstGLFramebuffer, gst_gl_framebuffer, G_TYPE_OBJECT,
+    DEBUG_INIT);
+
+#define GST_GL_FRAMEBUFFER_GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_TYPE_GL_FRAMEBUFFER, GstGLFramebufferPrivate))
+
+static void gst_gl_framebuffer_finalize (GObject * object);
+
+struct _GstGLFramebufferPrivate
+{
+  gint width;
+  gint height;
+
+  guint fbo;
+  guint depth;
+};
+
+static void
+gst_gl_framebuffer_class_init (GstGLFramebufferClass * klass)
+{
+  g_type_class_add_private (klass, sizeof (GstGLFramebufferPrivate));
+
+  G_OBJECT_CLASS (klass)->finalize = gst_gl_framebuffer_finalize;
+}
+
+static void
+gst_gl_framebuffer_init (GstGLFramebuffer * fbo)
+{
+  fbo->priv = GST_GL_FRAMEBUFFER_GET_PRIVATE (fbo);
+}
+
+static void
+gst_gl_framebuffer_finalize (GObject * object)
+{
+  GstGLFramebuffer *fbo = GST_GL_FRAMEBUFFER (object);
+
+  if (fbo->display) {
+    gst_object_unref (fbo->display);
+    fbo->display = NULL;
+  }
+
+  G_OBJECT_CLASS (gst_gl_framebuffer_parent_class)->finalize (object);
+}
+
+GstGLFramebuffer *
+gst_gl_framebuffer_new (GstGLDisplay * display)
+{
+  GstGLFramebuffer *fbo = g_object_new (GST_TYPE_GL_FRAMEBUFFER, NULL);
+
+  fbo->display = gst_object_ref (display);
+
+  return fbo;
+}
+
+gboolean
+gst_gl_framebuffer_generate (GstGLFramebuffer * frame, gint width, gint height,
+    guint * fbo, guint * depth)
+{
+  GLuint fake_texture = 0;
+  const GstGLFuncs *gl;
+
+  g_return_val_if_fail (GST_IS_GL_FRAMEBUFFER (frame), FALSE);
+  g_return_val_if_fail (fbo != NULL && depth != NULL, FALSE);
+  g_return_val_if_fail (width > 0 && height > 0, FALSE);
+
+  gl = gst_gl_display_get_gl_vtable (frame->display);
+
+  GST_TRACE ("creating FBO dimensions:%ux%u", width, height);
+
+  if (!gl->GenFramebuffers) {
+    gst_gl_display_set_error (frame->display,
+        "Context, EXT_framebuffer_object not supported");
+    return FALSE;
+  }
+  /* setup FBO */
+  gl->GenFramebuffers (1, fbo);
+  gl->BindFramebuffer (GL_FRAMEBUFFER, *fbo);
+
+  /* setup the render buffer for depth */
+  gl->GenRenderbuffers (1, depth);
+  gl->BindRenderbuffer (GL_RENDERBUFFER, *depth);
+
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_OPENGL) {
+    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
+        width, height);
+    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+        width, height);
+  }
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_GLES2) {
+    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
+        width, height);
+  }
+
+  /* setup a texture to render to */
+  gl->GenTextures (1, &fake_texture);
+  gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
+  gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+      width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+      GL_LINEAR);
+  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+      GL_LINEAR);
+  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+      GL_CLAMP_TO_EDGE);
+  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+      GL_CLAMP_TO_EDGE);
+
+  /* attach the texture to the FBO to renderer to */
+  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+      GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
+
+  /* attach the depth render buffer to the FBO */
+  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+      GL_RENDERBUFFER, *depth);
+
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_OPENGL) {
+    gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+        GL_RENDERBUFFER, *depth);
+  }
+
+  if (gl->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+    gst_gl_display_set_error (frame->display,
+        "GL framebuffer status incomplete");
+    return FALSE;
+  }
+
+  /* unbind the FBO */
+  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+
+  gl->DeleteTextures (1, &fake_texture);
+
+  return TRUE;
+}
+
+gboolean
+gst_gl_framebuffer_use (GstGLFramebuffer * frame, gint texture_fbo_width,
+    gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
+    GLuint texture_fbo, GLCB cb, gint input_tex_width,
+    gint input_tex_height, GLuint input_tex, gdouble proj_param1,
+    gdouble proj_param2, gdouble proj_param3, gdouble proj_param4,
+    GstGLDisplayProjection projection, gpointer stuff)
+{
+  const GstGLFuncs *gl;
+#if GST_GL_HAVE_GLES2
+  GLint viewport_dim[4];
+#endif
+
+  g_return_val_if_fail (GST_IS_GL_FRAMEBUFFER (frame), FALSE);
+  g_return_val_if_fail (input_tex_width > 0 && input_tex_height > 0, FALSE);
+  g_return_val_if_fail (texture_fbo_width > 0 && texture_fbo_height > 0, FALSE);
+  g_return_val_if_fail (input_tex != 0, FALSE);
+  g_return_val_if_fail (fbo != 0, FALSE);
+  g_return_val_if_fail (texture_fbo != 0, FALSE);
+  g_return_val_if_fail (cb != NULL, FALSE);
+
+  gl = frame->display->gl_vtable;
+
+  GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u "
+      "dimensions:%ux%u", fbo, texture_fbo_width,
+      texture_fbo_height, texture_fbo, input_tex_width, input_tex_height);
+
+  gl->BindFramebuffer (GL_FRAMEBUFFER, fbo);
+
+  /*setup a texture to render to */
+  gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_fbo);
+
+  /* attach the texture to the FBO to renderer to */
+  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+      GL_TEXTURE_RECTANGLE_ARB, texture_fbo, 0);
+
+  gst_gl_display_clear_shader (frame->display);
+
+#if GST_GL_HAVE_OPENGL
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_OPENGL) {
+    gl->PushAttrib (GL_VIEWPORT_BIT);
+    gl->MatrixMode (GL_PROJECTION);
+    gl->PushMatrix ();
+    gl->LoadIdentity ();
+
+    switch (projection) {
+      case GST_GL_DISPLAY_PROJECTION_ORTHO2D:
+        gluOrtho2D (proj_param1, proj_param2, proj_param3, proj_param4);
+        break;
+      case GST_GL_DISPLAY_PROJECTION_PERSPECTIVE:
+        gluPerspective (proj_param1, proj_param2, proj_param3, proj_param4);
+        break;
+      default:
+        gst_gl_display_set_error (frame->display, "Unknow fbo projection %d",
+            projection);
+    }
+
+    gl->MatrixMode (GL_MODELVIEW);
+    gl->PushMatrix ();
+    gl->LoadIdentity ();
+  }
+#endif
+#if GST_GL_HAVE_GLES2
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_GLES2)
+    gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
+#endif
+
+  gl->Viewport (0, 0, texture_fbo_width, texture_fbo_height);
+
+#if GST_GL_HAVE_OPENGL
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_OPENGL) {
+    const GLenum rt[] = { GL_COLOR_ATTACHMENT0 };
+    gl->DrawBuffers (1, rt);
+  }
+#endif
+
+  gl->ClearColor (0.0, 0.0, 0.0, 0.0);
+  gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  cb (input_tex_width, input_tex_height, input_tex, stuff);
+
+#if GST_GL_HAVE_OPENGL
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_OPENGL) {
+    const GLenum rt[] = { GL_NONE };
+    gl->DrawBuffers (1, rt);
+    gl->MatrixMode (GL_PROJECTION);
+    gl->PopMatrix ();
+    gl->MatrixMode (GL_MODELVIEW);
+    gl->PopMatrix ();
+    gl->PopAttrib ();
+  }
+#endif
+#if GST_GL_HAVE_GLES2
+  if (gst_gl_display_get_gl_api (frame->display) & GST_GL_API_GLES2) {
+    gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
+        viewport_dim[3]);
+  }
+#endif
+
+  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+
+  return TRUE;
+}
+
+gboolean
+gst_gl_framebuffer_use_v2 (GstGLFramebuffer * frame, gint texture_fbo_width,
+    gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
+    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff)
+{
+  const GstGLFuncs *gl;
+  GLint viewport_dim[4];
+
+  g_return_val_if_fail (GST_IS_GL_FRAMEBUFFER (frame), FALSE);
+  g_return_val_if_fail (texture_fbo_width > 0 && texture_fbo_height > 0, FALSE);
+  g_return_val_if_fail (fbo != 0, FALSE);
+  g_return_val_if_fail (texture_fbo != 0, FALSE);
+  g_return_val_if_fail (cb != NULL, FALSE);
+
+  gl = frame->display->gl_vtable;
+
+  GST_TRACE ("Binding v2 FBO %u dimensions:%ux%u with texture:%u ",
+      fbo, texture_fbo_width, texture_fbo_height, texture_fbo);
+
+  gl->BindFramebuffer (GL_FRAMEBUFFER, fbo);
+
+  /* setup a texture to render to */
+  gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_fbo);
+
+  /* attach the texture to the FBO to renderer to */
+  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+      GL_TEXTURE_RECTANGLE_ARB, texture_fbo, 0);
+
+  gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
+
+  gl->Viewport (0, 0, texture_fbo_width, texture_fbo_height);
+
+  gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
+
+  gl->ClearColor (0.0, 0.0, 0.0, 0.0);
+  gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  /* the opengl scene */
+  cb (stuff);
+
+  gl->DrawBuffer (GL_NONE);
+
+  gl->Viewport (viewport_dim[0], viewport_dim[1],
+      viewport_dim[2], viewport_dim[3]);
+
+  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+
+  return TRUE;
+}
+
+void
+gst_gl_framebuffer_delete (GstGLFramebuffer * frame, guint fbo, guint depth)
+{
+  const GstGLFuncs *gl;
+
+  g_return_if_fail (GST_IS_GL_FRAMEBUFFER (frame));
+
+  gl = frame->display->gl_vtable;
+
+  GST_TRACE ("Deleting FBO %u", fbo);
+
+  if (fbo) {
+    gl->DeleteFramebuffers (1, &fbo);
+  }
+  if (depth) {
+    gl->DeleteRenderbuffers (1, &depth);
+  }
+}
diff --git a/gst-libs/gst/gl/gstglframebuffer.h b/gst-libs/gst/gl/gstglframebuffer.h
new file mode 100644 (file)
index 0000000..48250db
--- /dev/null
@@ -0,0 +1,76 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_GL_FRAMEBUFFER_H__
+#define __GST_GL_FRAMEBUFFER_H__
+
+#include "gstgldisplay.h"
+
+G_BEGIN_DECLS
+
+GType gst_gl_framebuffer_get_type (void);
+
+#define GST_TYPE_GL_FRAMEBUFFER             (gst_gl_framebuffer_get_type())
+#define GST_GL_FRAMEBUFFER(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FRAMEBUFFER,GstGLFramebuffer))
+#define GST_GL_FRAMEBUFFER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GL_FRAMEBUFFER,GstGLFramebufferClass))
+#define GST_IS_GL_FRAMEBUFFER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FRAMEBUFFER))
+#define GST_IS_GL_FRAMEBUFFER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GL_FRAMEBUFFER))
+#define GST_GL_FRAMEBUFFER_CAST(obj)        ((GstGLFramebuffer*)(obj))
+
+typedef struct _GstGLFramebuffer GstGLFramebuffer;
+typedef struct _GstGLFramebufferClass GstGLFramebufferClass;
+typedef struct _GstGLFramebufferPrivate GstGLFramebufferPrivate;
+
+struct _GstGLFramebuffer
+{
+  GObject             object;
+
+  /* <private> */
+  GstGLDisplay *display;
+
+  GstGLFramebufferPrivate  *priv;
+};
+
+struct _GstGLFramebufferClass
+{
+  GObjectClass object_class;
+};
+
+GstGLFramebuffer *gst_gl_framebuffer_new (GstGLDisplay *display);
+
+gboolean gst_gl_framebuffer_generate (GstGLFramebuffer *frame, gint width, gint height,
+    guint * fbo, guint * depthbuffer);
+
+gboolean gst_gl_framebuffer_use (GstGLFramebuffer * frame, gint texture_fbo_width,
+    gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
+    GLuint texture_fbo, GLCB cb, gint input_tex_width,
+    gint input_tex_height, GLuint input_tex, gdouble proj_param1,
+    gdouble proj_param2, gdouble proj_param3, gdouble proj_param4,
+    GstGLDisplayProjection projection, gpointer stuff);
+
+gboolean gst_gl_framebuffer_use_v2 (GstGLFramebuffer * frame, gint texture_fbo_width,
+    gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
+    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff);
+
+void gst_gl_framebuffer_delete (GstGLFramebuffer *frame, guint fbo, guint depth);
+
+G_END_DECLS
+
+#endif
index 4e8cc42..d36b525 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "gstglutils.h"
 #include "gstglfeature.h"
+#include "gstglframebuffer.h"
 
 #ifndef GL_FRAMEBUFFER_UNDEFINED
 #define GL_FRAMEBUFFER_UNDEFINED          0x8219
@@ -54,44 +55,12 @@ static GstVideoFormat gen_texture_video_format;
 
 static GLuint *del_texture;
 
-/* filter gen fbo */
-static GLuint gen_fbo_width;
-static GLuint gen_fbo_height;
-static GLuint generated_fbo;
-static GLuint generated_depth_buffer;
-
-/* filter use fbo */
-static GLuint use_fbo;
-static GLuint use_depth_buffer;
-static GLuint use_fbo_texture;
-static GLuint use_fbo_width;
-static GLuint use_fbo_height;
-static GLCB use_fbo_scene_cb;
-static GLCB_V2 use_fbo_scene_cb_v2;
-static gdouble use_fbo_proj_param1;
-static gdouble use_fbo_proj_param2;
-static gdouble use_fbo_proj_param3;
-static gdouble use_fbo_proj_param4;
-static GstGLDisplayProjection use_fbo_projection;
-static gpointer *use_fbo_stuff;
-static GLuint input_texture_width;
-static GLuint input_texture_height;
-static GLuint input_texture;
-
-/* filter del fbo */
-static GLuint del_fbo;
-static GLuint del_depth_buffer;
-
 /* action gen and del shader */
 static const gchar *gen_shader_fragment_source;
 static const gchar *gen_shader_vertex_source;
 static GstGLShader *gen_shader;
 static GstGLShader *del_shader;
 
-static void _gen_fbo (GstGLDisplay * display);
-static void _use_fbo (GstGLDisplay * display);
-static void _use_fbo_v2 (GstGLDisplay * display);
-static void _del_fbo (GstGLDisplay * display);
 static void _gen_shader (GstGLDisplay * display);
 static void _del_shader (GstGLDisplay * display);
 
@@ -298,32 +267,65 @@ gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture)
   gst_gl_display_unlock (display);
 }
 
+typedef struct _GenFBO
+{
+  GstGLFramebuffer *frame;
+  gint width, height;
+  GLuint *fbo, *depth;
+} GenFBO;
+
+static void
+_gen_fbo (GstGLDisplay * display, GenFBO * data)
+{
+  gst_gl_framebuffer_generate (data->frame, data->width, data->height,
+      data->fbo, data->depth);
+}
+
 gboolean
 gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height,
     GLuint * fbo, GLuint * depthbuffer)
 {
-  gboolean alive = FALSE;
-  GstGLWindow *window;
+  GstGLFramebuffer *frame = gst_gl_framebuffer_new (display);
 
-  gst_gl_display_lock (display);
+  GenFBO data = { frame, width, height, fbo, depthbuffer };
 
-  window = gst_gl_display_get_window_unlocked (display);
+  gst_gl_display_thread_add (display, (GstGLDisplayThreadFunc) _gen_fbo, &data);
 
-  if (gst_gl_window_is_running (window)) {
-    gen_fbo_width = width;
-    gen_fbo_height = height;
-    gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_gen_fbo), display);
-    *fbo = generated_fbo;
-    *depthbuffer = generated_depth_buffer;
-  }
-  alive = gst_gl_window_is_running (window);
+  gst_object_unref (frame);
 
-  gst_object_unref (window);
-  gst_gl_display_unlock (display);
-
-  return alive;
+  return TRUE;
 }
 
+typedef struct _UseFBO
+{
+  GstGLFramebuffer *frame;
+  gint texture_fbo_width;
+  gint texture_fbo_height;
+  GLuint fbo;
+  GLuint depth_buffer;
+  GLuint texture_fbo;
+  GLCB cb;
+  gint input_tex_width;
+  gint input_tex_height;
+  GLuint input_tex;
+  gdouble proj_param1;
+  gdouble proj_param2;
+  gdouble proj_param3;
+  gdouble proj_param4;
+  GstGLDisplayProjection projection;
+  gpointer stuff;
+} UseFBO;
+
+static void
+_use_fbo (GstGLDisplay * display, UseFBO * data)
+{
+  gst_gl_framebuffer_use (data->frame, data->texture_fbo_width,
+      data->texture_fbo_height, data->fbo, data->depth_buffer,
+      data->texture_fbo, data->cb, data->input_tex_width,
+      data->input_tex_height, data->input_tex, data->proj_param1,
+      data->proj_param2, data->proj_param3, data->proj_param4, data->projection,
+      data->stuff);
+}
 
 /* Called by glfilter */
 /* this function really has to be simplified...  do we really need to
@@ -339,87 +341,88 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width,
     GLuint texture_fbo, GLCB cb, gint input_tex_width,
     gint input_tex_height, GLuint input_tex, gdouble proj_param1,
     gdouble proj_param2, gdouble proj_param3, gdouble proj_param4,
-    GstGLDisplayProjection projection, gpointer stuff)
+    GstGLDisplayProjection projection, gpointer stuff)
 {
-  gboolean alive;
-  GstGLWindow *window;
+  GstGLFramebuffer *frame = gst_gl_framebuffer_new (display);
 
-  gst_gl_display_lock (display);
+  UseFBO data =
+      { frame, texture_fbo_width, texture_fbo_height, fbo, depth_buffer,
+    texture_fbo, cb, input_tex_width, input_tex_height, input_tex,
+    proj_param1, proj_param2, proj_param3, proj_param4, projection, stuff
+  };
 
-  window = gst_gl_display_get_window_unlocked (display);
-  if (gst_gl_window_is_running (window)) {
-    use_fbo = fbo;
-    use_depth_buffer = depth_buffer;
-    use_fbo_texture = texture_fbo;
-    use_fbo_width = texture_fbo_width;
-    use_fbo_height = texture_fbo_height;
-    use_fbo_scene_cb = cb;
-    use_fbo_proj_param1 = proj_param1;
-    use_fbo_proj_param2 = proj_param2;
-    use_fbo_proj_param3 = proj_param3;
-    use_fbo_proj_param4 = proj_param4;
-    use_fbo_projection = projection;
-    use_fbo_stuff = stuff;
-    input_texture_width = input_tex_width;
-    input_texture_height = input_tex_height;
-    input_texture = input_tex;
-    gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_use_fbo), display);
-  }
-  alive = gst_gl_window_is_running (window);
+  gst_gl_display_thread_add (display, (GstGLDisplayThreadFunc) _use_fbo, &data);
 
-  gst_object_unref (window);
-  gst_gl_display_unlock (display);
+  gst_object_unref (frame);
 
-  return alive;
+  return TRUE;
+}
+
+typedef struct _UseFBO2
+{
+  GstGLFramebuffer *frame;
+  gint texture_fbo_width;
+  gint texture_fbo_height;
+  GLuint fbo;
+  GLuint depth_buffer;
+  GLuint texture_fbo;
+  GLCB_V2 cb;
+  gpointer stuff;
+} UseFBO2;
+
+static void
+_use_fbo_v2 (GstGLDisplay * display, UseFBO2 * data)
+{
+  gst_gl_framebuffer_use_v2 (data->frame, data->texture_fbo_width,
+      data->texture_fbo_height, data->fbo, data->depth_buffer,
+      data->texture_fbo, data->cb, data->stuff);
 }
 
 gboolean
 gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width,
     gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
-    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff)
+    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff)
 {
-  gboolean alive;
-  GstGLWindow *window;
+  GstGLFramebuffer *frame = gst_gl_framebuffer_new (display);
 
-  gst_gl_display_lock (display);
+  UseFBO2 data =
+      { frame, texture_fbo_width, texture_fbo_height, fbo, depth_buffer,
+    texture_fbo, cb, stuff
+  };
 
-  window = gst_gl_display_get_window_unlocked (display);
-  if (gst_gl_window_is_running (window)) {
-    use_fbo = fbo;
-    use_depth_buffer = depth_buffer;
-    use_fbo_texture = texture_fbo;
-    use_fbo_width = texture_fbo_width;
-    use_fbo_height = texture_fbo_height;
-    use_fbo_scene_cb_v2 = cb;
-    use_fbo_stuff = stuff;
-    gst_gl_window_send_message (window,
-        GST_GL_WINDOW_CB (_use_fbo_v2), display);
-  }
-  alive = gst_gl_window_is_running (window);
+  gst_gl_display_thread_add (display, (GstGLDisplayThreadFunc) _use_fbo_v2,
+      &data);
 
-  gst_object_unref (window);
-  gst_gl_display_unlock (display);
+  gst_object_unref (frame);
 
-  return alive;
+  return TRUE;
+}
+
+typedef struct _DelFBO
+{
+  GstGLFramebuffer *frame;
+  GLuint fbo;
+  GLuint depth;
+} DelFBO;
+
+/* Called in the gl thread */
+static void
+_del_fbo (GstGLDisplay * display, DelFBO * data)
+{
+  gst_gl_framebuffer_delete (data->frame, data->fbo, data->depth);
 }
 
 /* Called by gltestsrc and glfilter */
 void
 gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, GLuint depth_buffer)
 {
-  GstGLWindow *window;
+  GstGLFramebuffer *frame = gst_gl_framebuffer_new (display);
 
-  gst_gl_display_lock (display);
+  DelFBO data = { frame, fbo, depth_buffer };
 
-  window = gst_gl_display_get_window_unlocked (display);
-  if (gst_gl_window_is_running (window)) {
-    del_fbo = fbo;
-    del_depth_buffer = depth_buffer;
-    gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_del_fbo), display);
-  }
+  gst_gl_display_thread_add (display, (GstGLDisplayThreadFunc) _del_fbo, &data);
 
-  gst_object_unref (window);
-  gst_gl_display_unlock (display);
+  gst_object_unref (frame);
 }
 
 
@@ -494,227 +497,6 @@ gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader)
   gst_gl_display_unlock (display);
 }
 
-void
-_gen_fbo (GstGLDisplay * display)
-{
-  /* a texture must be attached to the FBO */
-  const GstGLFuncs *gl = display->gl_vtable;
-  GLuint fake_texture = 0;
-
-  GST_TRACE ("creating FBO dimensions:%ux%u", gen_fbo_width, gen_fbo_height);
-
-  /* -- generate frame buffer object */
-
-  if (!gl->GenFramebuffers) {
-    gst_gl_display_set_error (display,
-        "Context, EXT_framebuffer_object not supported");
-    return;
-  }
-  /* setup FBO */
-  gl->GenFramebuffers (1, &generated_fbo);
-  gl->BindFramebuffer (GL_FRAMEBUFFER, generated_fbo);
-
-  /* setup the render buffer for depth */
-  gl->GenRenderbuffers (1, &generated_depth_buffer);
-  gl->BindRenderbuffer (GL_RENDERBUFFER, generated_depth_buffer);
-
-  if (USING_OPENGL (display)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
-        gen_fbo_width, gen_fbo_height);
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
-        gen_fbo_width, gen_fbo_height);
-  }
-  if (USING_GLES2 (display)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
-        gen_fbo_width, gen_fbo_height);
-  }
-
-  /* setup a texture to render to */
-  gl->GenTextures (1, &fake_texture);
-  gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
-  gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-      gen_fbo_width, gen_fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-      GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-      GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-      GL_CLAMP_TO_EDGE);
-  gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-      GL_CLAMP_TO_EDGE);
-
-  /* attach the texture to the FBO to renderer to */
-  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-      GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
-
-  /* attach the depth render buffer to the FBO */
-  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-      GL_RENDERBUFFER, generated_depth_buffer);
-
-  if (USING_OPENGL (display)) {
-    gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-        GL_RENDERBUFFER, generated_depth_buffer);
-  }
-
-  if (gl->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-    gst_gl_display_set_error (display, "GL framebuffer status incomplete");
-
-  /* unbind the FBO */
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
-
-  gl->DeleteTextures (1, &fake_texture);
-}
-
-static void
-_use_fbo (GstGLDisplay * display)
-{
-  const GstGLFuncs *gl = display->gl_vtable;
-#if GST_GL_HAVE_GLES2
-  GLint viewport_dim[4];
-#endif
-
-  GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u "
-      "dimensions:%ux%u", use_fbo, use_fbo_width,
-      use_fbo_height, use_fbo_texture,
-      input_texture_width, input_texture_height);
-
-  gl->BindFramebuffer (GL_FRAMEBUFFER, use_fbo);
-
-  /*setup a texture to render to */
-  gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture);
-
-  /* attach the texture to the FBO to renderer to */
-  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-      GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture, 0);
-
-  gst_gl_display_clear_shader (display);
-
-
-#if GST_GL_HAVE_OPENGL
-  if (USING_OPENGL (display)) {
-    gl->PushAttrib (GL_VIEWPORT_BIT);
-    gl->MatrixMode (GL_PROJECTION);
-    gl->PushMatrix ();
-    gl->LoadIdentity ();
-
-    switch (use_fbo_projection) {
-      case GST_GL_DISPLAY_PROJECTION_ORTHO2D:
-        gluOrtho2D (use_fbo_proj_param1,
-            use_fbo_proj_param2, use_fbo_proj_param3, use_fbo_proj_param4);
-        break;
-      case GST_GL_DISPLAY_PROJECTION_PERSPECTIVE:
-        gluPerspective (use_fbo_proj_param1,
-            use_fbo_proj_param2, use_fbo_proj_param3, use_fbo_proj_param4);
-        break;
-      default:
-        gst_gl_display_set_error (display, "Unknow fbo projection %d",
-            use_fbo_projection);
-    }
-
-    gl->MatrixMode (GL_MODELVIEW);
-    gl->PushMatrix ();
-    gl->LoadIdentity ();
-  }
-#endif
-#if GST_GL_HAVE_GLES2
-  if (USING_GLES2 (display))
-    gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
-#endif
-
-  gl->Viewport (0, 0, use_fbo_width, use_fbo_height);
-
-#if GST_GL_HAVE_OPENGL
-  if (USING_OPENGL (display)) {
-    const GLenum rt[] = { GL_COLOR_ATTACHMENT0 };
-    gl->DrawBuffers (1, rt);
-  }
-#endif
-
-  gl->ClearColor (0.0, 0.0, 0.0, 0.0);
-  gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-  use_fbo_scene_cb (input_texture_width,
-      input_texture_height, input_texture, use_fbo_stuff);
-
-#if GST_GL_HAVE_OPENGL
-  if (USING_OPENGL (display)) {
-    const GLenum rt[] = { GL_NONE };
-    gl->DrawBuffers (1, rt);
-    gl->MatrixMode (GL_PROJECTION);
-    gl->PopMatrix ();
-    gl->MatrixMode (GL_MODELVIEW);
-    gl->PopMatrix ();
-    gl->PopAttrib ();
-  }
-#endif
-#if GST_GL_HAVE_GLES2
-  if (USING_GLES2 (display)) {
-    gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
-        viewport_dim[3]);
-  }
-#endif
-
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
-}
-
-/* Called in a gl thread
- * Need full shader support */
-static void
-_use_fbo_v2 (GstGLDisplay * display)
-{
-  const GstGLFuncs *gl = display->gl_vtable;
-  GLint viewport_dim[4];
-
-  GST_TRACE ("Binding v2 FBO %u dimensions:%ux%u with texture:%u ",
-      use_fbo, use_fbo_width, use_fbo_height, use_fbo_texture);
-
-  gl->BindFramebuffer (GL_FRAMEBUFFER, use_fbo);
-
-  /* setup a texture to render to */
-  gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture);
-
-  /* attach the texture to the FBO to renderer to */
-  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-      GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture, 0);
-
-  gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
-
-  gl->Viewport (0, 0, use_fbo_width, use_fbo_height);
-
-  gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
-
-  gl->ClearColor (0.0, 0.0, 0.0, 0.0);
-  gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-  /* the opengl scene */
-  use_fbo_scene_cb_v2 (use_fbo_stuff);
-
-  gl->DrawBuffer (GL_NONE);
-
-  gl->Viewport (viewport_dim[0], viewport_dim[1],
-      viewport_dim[2], viewport_dim[3]);
-
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
-}
-
-/* Called in the gl thread */
-static void
-_del_fbo (GstGLDisplay * display)
-{
-  const GstGLFuncs *gl = display->gl_vtable;
-
-  GST_TRACE ("Deleting FBO %u", del_fbo);
-
-  if (del_fbo) {
-    gl->DeleteFramebuffers (1, &del_fbo);
-    del_fbo = 0;
-  }
-  if (del_depth_buffer) {
-    gl->DeleteRenderbuffers (1, &del_depth_buffer);
-    del_depth_buffer = 0;
-  }
-}
-
 /* Called in the gl thread */
 static void
 _gen_shader (GstGLDisplay * display)
index 569a8f0..2761a02 100644 (file)
@@ -91,10 +91,10 @@ gboolean gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width,
     GLuint texture_fbo, GLCB cb, gint input_texture_width,
     gint input_texture_height, GLuint input_texture, gdouble proj_param1,
     gdouble proj_param2, gdouble proj_param3, gdouble proj_param4,
-    GstGLDisplayProjection projection, gpointer stuff);
+    GstGLDisplayProjection projection, gpointer stuff);
 gboolean gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width,
     gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
-    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff);
+    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff);
 void gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo,
     GLuint depth_buffer);