glframebuffer: rewrite for a more consistent API
authorMatthew Waters <matthew@centricular.com>
Tue, 12 Jul 2016 02:59:57 +0000 (12:59 +1000)
committerMatthew Waters <matthew@centricular.com>
Tue, 26 Jul 2016 04:07:24 +0000 (14:07 +1000)
Facilities are given to create fbo's and attach GL memory (renderbuffers
or textures).  It also keeps track of the renderable size for use with
effective use with glViewport().

24 files changed:
ext/gl/gstglfilterapp.c
ext/gl/gstglfilterapp.h
ext/gl/gstglfiltercube.c
ext/gl/gstglfilterglass.c
ext/gl/gstglmixer.c
ext/gl/gstglmixer.h
ext/gl/gstglmosaic.c
ext/gl/gstgltestsrc.c
ext/gl/gstgltestsrc.h
ext/gl/gstgltransformation.c
ext/gl/gstglvideomixer.c
ext/gl/gstglvideomixer.h
gst-libs/gst/gl/gstgl_fwd.h
gst-libs/gst/gl/gstglcolorconvert.c
gst-libs/gst/gl/gstglcolorconvert.h
gst-libs/gst/gl/gstglfilter.c
gst-libs/gst/gl/gstglfilter.h
gst-libs/gst/gl/gstglframebuffer.c
gst-libs/gst/gl/gstglframebuffer.h
gst-libs/gst/gl/gstglutils.c
gst-libs/gst/gl/gstglutils.h
gst-libs/gst/gl/gstglviewconvert.c
gst-libs/gst/gl/gstglviewconvert.h
tests/check/libs/gstglcontext.c

index 07e1e5597e78a47235b039c77019e9ff7cd148d6..adcf006bb9107fab64d55dfc66b476bd265e327b 100644 (file)
@@ -184,35 +184,24 @@ gst_gl_filter_app_set_caps (GstGLFilter * filter, GstCaps * incaps,
   return TRUE;
 }
 
-static void
-_emit_draw_signal (guint tex, gint width, gint height, gpointer data)
-{
-  GstGLFilterApp *app_filter = GST_GL_FILTER_APP (data);
-  gboolean drawn;
-
-  g_signal_emit (app_filter, gst_gl_filter_app_signals[CLIENT_DRAW_SIGNAL], 0,
-      tex, width, height, &drawn);
-
-  app_filter->default_draw = !drawn;
-}
-
 struct glcb2
 {
-  GLCB func;
-  gpointer data;
+  GstGLFilterApp *app;
   GstGLMemory *in_tex;
   GstGLMemory *out_tex;
 };
 
-/* convenience functions to simplify filter development */
-static void
-_glcb2 (gpointer data)
+static gboolean
+_emit_draw_signal (gpointer data)
 {
   struct glcb2 *cb = data;
+  gboolean drawn;
+
+  g_signal_emit (cb->app, gst_gl_filter_app_signals[CLIENT_DRAW_SIGNAL], 0,
+      cb->in_tex->tex_id, gst_gl_memory_get_texture_width (cb->out_tex),
+      gst_gl_memory_get_texture_height (cb->out_tex), &drawn);
 
-  cb->func (gst_gl_memory_get_texture_width (cb->in_tex),
-      gst_gl_memory_get_texture_height (cb->in_tex), cb->in_tex->tex_id,
-      cb->data);
+  return !drawn;
 }
 
 static gboolean
@@ -220,20 +209,18 @@ gst_gl_filter_app_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
     GstGLMemory * out_tex)
 {
   GstGLFilterApp *app_filter = GST_GL_FILTER_APP (filter);
+  gboolean default_draw;
   struct glcb2 cb;
 
-  cb.func = (GLCB) _emit_draw_signal;
-  cb.data = filter;
+  cb.app = app_filter;
   cb.in_tex = in_tex;
   cb.out_tex = out_tex;
 
-  //blocking call, use a FBO
-  gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
-      GST_VIDEO_INFO_WIDTH (&filter->out_info),
-      GST_VIDEO_INFO_HEIGHT (&filter->out_info),
-      filter->fbo, filter->depthbuffer, out_tex->tex_id, _glcb2, &cb);
+  default_draw =
+      gst_gl_framebuffer_draw_to_texture (filter->fbo,
+      out_tex, _emit_draw_signal, &cb);
 
-  if (app_filter->default_draw) {
+  if (default_draw) {
     gst_gl_filter_render_to_target_with_shader (filter, TRUE, in_tex, out_tex,
         filter->default_shader);
   }
index a8978c519a0f50bd4d6a704cca3093a8f16e7f47..d7e9a6f2ab7de9f59cf0c96466260090bbbb820d 100644 (file)
@@ -37,8 +37,6 @@ typedef struct _GstGLFilterAppClass GstGLFilterAppClass;
 struct _GstGLFilterApp
 {
     GstGLFilter filter;
-
-    gboolean default_draw;
 };
 
 struct _GstGLFilterAppClass
index ba8d5243e07c08e0a445d789cfeb59bdb5754842..717eba693837cbf5d676ca53d1447683f9c98077 100644 (file)
@@ -79,7 +79,7 @@ static gboolean gst_gl_filter_cube_set_caps (GstGLFilter * filter,
     GstCaps * incaps, GstCaps * outcaps);
 static void gst_gl_filter_cube_reset_gl (GstGLFilter * filter);
 static gboolean gst_gl_filter_cube_init_shader (GstGLFilter * filter);
-static void _callback (gpointer stuff);
+static gboolean _callback (gpointer stuff);
 static gboolean gst_gl_filter_cube_filter_texture (GstGLFilter * filter,
     GstGLMemory * in_tex, GstGLMemory * out_tex);
 
@@ -342,13 +342,8 @@ gst_gl_filter_cube_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
 
   cube_filter->in_tex = in_tex;
 
-  /* blocking call, use a FBO */
-  gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
-      GST_VIDEO_INFO_WIDTH (&filter->out_info),
-      GST_VIDEO_INFO_HEIGHT (&filter->out_info), filter->fbo,
-      filter->depthbuffer, out_tex->tex_id, _callback, (gpointer) cube_filter);
-
-  return TRUE;
+  return gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex, _callback,
+      cube_filter);
 }
 
 /* *INDENT-OFF* */
@@ -440,7 +435,7 @@ _unbind_buffer (GstGLFilterCube * cube_filter)
   gl->DisableVertexAttribArray (cube_filter->attr_texture);
 }
 
-static void
+static gboolean
 _callback (gpointer stuff)
 {
   GstGLFilter *filter = GST_GL_FILTER (stuff);
@@ -516,4 +511,6 @@ _callback (gpointer stuff)
   xrot += 0.3f;
   yrot += 0.2f;
   zrot += 0.4f;
+
+  return TRUE;
 }
index a0639d2d02014bbec6d9dba2e53aed900899ef0c..28bc48585ef2c9322f2d5b5d3661c128f4380489 100644 (file)
@@ -73,7 +73,7 @@ static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
     gint width, gint height, guint texture, gfloat center_x, gfloat center_y,
     gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation);
 
-static void gst_gl_filter_glass_callback (gpointer stuff);
+static gboolean gst_gl_filter_glass_callback (gpointer stuff);
 
 /* *INDENT-OFF* */
 static const gchar *glass_fragment_source =
@@ -245,12 +245,8 @@ gst_gl_filter_glass_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
 
   glass_filter->in_tex = in_tex;
 
-  //blocking call, use a FBO
-  gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
-      GST_VIDEO_INFO_WIDTH (&filter->out_info),
-      GST_VIDEO_INFO_HEIGHT (&filter->out_info),
-      filter->fbo, filter->depthbuffer, out_tex->tex_id,
-      gst_gl_filter_glass_callback, (gpointer) glass_filter);
+  gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex,
+      gst_gl_filter_glass_callback, glass_filter);
 
   return TRUE;
 }
@@ -353,8 +349,7 @@ gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
   gl->DisableClientState (GL_COLOR_ARRAY);
 }
 
-//opengl scene, params: input texture (not the output filter->texture)
-static void
+static gboolean
 gst_gl_filter_glass_callback (gpointer stuff)
 {
   static gint64 start_time = 0;
@@ -376,7 +371,7 @@ gst_gl_filter_glass_callback (gpointer stuff)
     time_left -= 1000000 / 25;
     if (time_left > 2000) {
       GST_LOG ("escape");
-      return;
+      return FALSE;
     }
   }
 
@@ -408,4 +403,6 @@ gst_gl_filter_glass_callback (gpointer stuff)
   gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context);
 
   gl->Disable (GL_BLEND);
+
+  return TRUE;
 }
index f9c22a1d2e3d47a7e987cd1ec114e59c3cd4fcc5..3fc5aa6f505e04d78f0fa5ffc71650bcd1163d99 100644 (file)
@@ -410,8 +410,6 @@ static void
 gst_gl_mixer_init (GstGLMixer * mix)
 {
   mix->priv = GST_GL_MIXER_GET_PRIVATE (mix);
-  mix->fbo = 0;
-  mix->depthbuffer = 0;
 
   mix->priv->gl_resource_ready = FALSE;
   g_mutex_init (&mix->priv->gl_resource_lock);
@@ -512,33 +510,38 @@ gst_gl_mixer_get_output_buffer (GstVideoAggregator * videoaggregator,
   return ret;
 }
 
+static void
+_mixer_create_fbo (GstGLContext * context, GstGLMixer * mix)
+{
+  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
+  guint out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
+  guint out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info);
+
+  mix->fbo =
+      gst_gl_framebuffer_new_with_default_depth (context, out_width,
+      out_height);
+}
+
 static gboolean
 gst_gl_mixer_decide_allocation (GstGLBaseMixer * base_mix, GstQuery * query)
 {
   GstGLMixer *mix = GST_GL_MIXER (base_mix);
   GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
-  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
   GstGLContext *context = base_mix->context;
   GstBufferPool *pool = NULL;
   GstStructure *config;
   GstCaps *caps;
   guint min, max, size;
   gboolean update_pool;
-  guint out_width, out_height;
-
-  out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
-  out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info);
 
   g_mutex_lock (&mix->priv->gl_resource_lock);
   mix->priv->gl_resource_ready = FALSE;
-  if (mix->fbo) {
-    gst_gl_context_del_fbo (context, mix->fbo, mix->depthbuffer);
-    mix->fbo = 0;
-    mix->depthbuffer = 0;
-  }
+  if (mix->fbo)
+    gst_object_unref (mix->fbo);
 
-  if (!gst_gl_context_gen_fbo (context, out_width, out_height,
-          &mix->fbo, &mix->depthbuffer)) {
+  gst_gl_context_thread_add (context,
+      (GstGLContextThreadFunc) _mixer_create_fbo, mix);
+  if (!mix->fbo) {
     g_cond_signal (&mix->priv->gl_resource_cond);
     g_mutex_unlock (&mix->priv->gl_resource_lock);
     goto context_error;
@@ -735,14 +738,13 @@ gst_gl_mixer_stop (GstAggregator * agg)
 {
   GstGLMixer *mix = GST_GL_MIXER (agg);
   GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
-  GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
 
   if (mixer_class->reset)
     mixer_class->reset (mix);
+
   if (mix->fbo) {
-    gst_gl_context_del_fbo (context, mix->fbo, mix->depthbuffer);
-    mix->fbo = 0;
-    mix->depthbuffer = 0;
+    gst_object_unref (mix->fbo);
+    mix->fbo = NULL;
   }
 
   gst_gl_mixer_reset (mix);
index de5a3dc4efbdc20121fd3a3918b486dc9c871fb1..309f6bbf0c1fb399088928d2e808de0af4881e8e 100644 (file)
@@ -84,8 +84,7 @@ struct _GstGLMixer
 {
   GstGLBaseMixer vaggregator;
 
-  GLuint fbo;
-  GLuint depthbuffer;
+  GstGLFramebuffer *fbo;
 
   GstCaps *out_caps;
 
index 701435f8048cd2cdcbb1e546e2846b43e5981ae0..41441b06494373f9de6a9e45d6d993d2944880f2 100644 (file)
@@ -71,7 +71,7 @@ static gboolean gst_gl_mosaic_init_shader (GstGLMixer * mixer,
 
 static gboolean gst_gl_mosaic_process_textures (GstGLMixer * mixer,
     GstGLMemory * out_tex);
-static void gst_gl_mosaic_callback (gpointer stuff);
+static gboolean gst_gl_mosaic_callback (gpointer stuff);
 
 //vertex source
 static const gchar *mosaic_v_src =
@@ -193,23 +193,31 @@ gst_gl_mosaic_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
       mosaic_v_src, mosaic_f_src, &mosaic->shader);
 }
 
+static void
+_mosaic_render (GstGLContext * context, GstGLMosaic * mosaic)
+{
+  GstGLMixer *mixer = GST_GL_MIXER (mosaic);
+
+  gst_gl_framebuffer_draw_to_texture (mixer->fbo, mosaic->out_tex,
+      gst_gl_mosaic_callback, mosaic);
+}
+
 static gboolean
 gst_gl_mosaic_process_textures (GstGLMixer * mix, GstGLMemory * out_tex)
 {
   GstGLMosaic *mosaic = GST_GL_MOSAIC (mix);
+  GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
 
-  //blocking call, use a FBO
-  gst_gl_context_use_fbo_v2 (GST_GL_BASE_MIXER (mix)->context,
-      GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR (mix)->info),
-      GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR (mix)->info), mix->fbo,
-      mix->depthbuffer, out_tex->tex_id, gst_gl_mosaic_callback,
-      (gpointer) mosaic);
+  mosaic->out_tex = out_tex;
+
+  gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _mosaic_render,
+      mosaic);
 
   return TRUE;
 }
 
 /* opengl scene, params: input texture (not the output mixer->texture) */
-static void
+static gboolean
 gst_gl_mosaic_callback (gpointer stuff)
 {
   GstGLMosaic *mosaic = GST_GL_MOSAIC (stuff);
@@ -345,4 +353,6 @@ gst_gl_mosaic_callback (gpointer stuff)
   xrot += 0.6f;
   yrot += 0.4f;
   zrot += 0.8f;
+
+  return TRUE;
 }
index 69c8b33b63adc6516a80d8e33b2a26a770a4f53b..62d231ff8f476c2cfc5df121d165e70f479dca32 100644 (file)
@@ -107,7 +107,7 @@ static gboolean gst_gl_test_src_stop (GstBaseSrc * basesrc);
 static gboolean gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc,
     GstQuery * query);
 
-static void gst_gl_test_src_callback (gpointer stuff);
+static gboolean gst_gl_test_src_callback (gpointer stuff);
 
 static gboolean gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc);
 
@@ -454,22 +454,24 @@ gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc)
   return TRUE;
 }
 
+static void
+_fill_gl (GstGLContext * context, GstGLTestSrc * src)
+{
+  src->gl_result = gst_gl_framebuffer_draw_to_texture (src->fbo, src->out_tex,
+      gst_gl_test_src_callback, src);
+}
+
 static GstFlowReturn
 gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
 {
   GstGLTestSrc *src = GST_GL_TEST_SRC (psrc);
   GstClockTime next_time;
-  gint width, height;
   GstVideoFrame out_frame;
   GstGLSyncMeta *sync_meta;
-  guint out_tex;
 
   if (G_UNLIKELY (!src->negotiated || !src->context))
     goto not_negotiated;
 
-  width = GST_VIDEO_INFO_WIDTH (&src->out_info);
-  height = GST_VIDEO_INFO_HEIGHT (&src->out_info);
-
   /* 0 framerate and we are at the second frame, eos */
   if (G_UNLIKELY (GST_VIDEO_INFO_FPS_N (&src->out_info) == 0
           && src->n_frames == 1))
@@ -480,11 +482,11 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
     return GST_FLOW_NOT_NEGOTIATED;
   }
 
-  out_tex = *(guint *) out_frame.data[0];
+  src->out_tex = (GstGLMemory *) out_frame.map[0].memory;
 
-  if (!gst_gl_context_use_fbo_v2 (src->context, width, height, src->fbo,
-          src->depthbuffer, out_tex, gst_gl_test_src_callback,
-          (gpointer) src)) {
+  gst_gl_context_thread_add (src->context, (GstGLContextThreadFunc) _fill_gl,
+      src);
+  if (!src->gl_result) {
     gst_video_frame_unmap (&out_frame);
     goto gl_error;
   }
@@ -562,8 +564,11 @@ gst_gl_test_src_stop (GstBaseSrc * basesrc)
       gst_object_unref (src->shader);
       src->shader = NULL;
     }
-    //blocking call, delete the FBO
-    gst_gl_context_del_fbo (src->context, src->fbo, src->depthbuffer);
+
+    if (src->fbo)
+      gst_object_unref (src->fbo);
+    src->fbo = NULL;
+
     gst_object_unref (src->context);
     src->context = NULL;
   }
@@ -615,6 +620,14 @@ _find_local_gl_context (GstGLTestSrc * src)
   return FALSE;
 }
 
+static void
+_src_generate_fbo_gl (GstGLContext * context, GstGLTestSrc * src)
+{
+  src->fbo = gst_gl_framebuffer_new_with_default_depth (src->context,
+      GST_VIDEO_INFO_WIDTH (&src->out_info),
+      GST_VIDEO_INFO_HEIGHT (&src->out_info));
+}
+
 static gboolean
 gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
 {
@@ -625,7 +638,6 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
   guint min, max, size;
   gboolean update_pool;
   GError *error = NULL;
-  guint out_width, out_height;
 
   if (!gst_gl_ensure_element_data (src, &src->display, &src->other_context))
     return FALSE;
@@ -658,11 +670,9 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
   if ((gst_gl_context_get_gl_api (src->context) & SUPPORTED_GL_APIS) == 0)
     goto unsupported_gl_api;
 
-  out_width = GST_VIDEO_INFO_WIDTH (&src->out_info);
-  out_height = GST_VIDEO_INFO_HEIGHT (&src->out_info);
-
-  if (!gst_gl_context_gen_fbo (src->context, out_width, out_height,
-          &src->fbo, &src->depthbuffer))
+  gst_gl_context_thread_add (src->context,
+      (GstGLContextThreadFunc) _src_generate_fbo_gl, src);
+  if (!src->fbo)
     goto context_error;
 
   gst_query_parse_allocation (query, &caps, NULL);
@@ -735,8 +745,7 @@ context_error:
   }
 }
 
-//opengl scene
-static void
+static gboolean
 gst_gl_test_src_callback (gpointer stuff)
 {
   GstGLTestSrc *src = GST_GL_TEST_SRC (stuff);
@@ -752,21 +761,18 @@ gst_gl_test_src_callback (gpointer stuff)
     if (funcs == NULL) {
       GST_ERROR_OBJECT (src, "Could not find an implementation of the "
           "requested pattern");
-      src->gl_result = FALSE;
-      return;
+      return FALSE;
     }
     src->src_impl = funcs->new (src);
     if (!(src->gl_result =
             funcs->init (src->src_impl, src->context, &src->out_info))) {
       GST_ERROR_OBJECT (src, "Failed to initialize pattern");
-      return;
+      return FALSE;
     }
     src->active_pattern = src->set_pattern;
   }
 
-  src->gl_result = funcs->fill_bound_fbo (src->src_impl);
-  if (!src->gl_result)
-    GST_ERROR_OBJECT (src, "Failed to render the pattern");
+  return funcs->fill_bound_fbo (src->src_impl);
 }
 
 static GstStateChangeReturn
index 1b566ad0602c94b6d4ca6220a4cf28ea445cd23c..df4abb74a0d01d043e7269d2888030be92202c28 100644 (file)
@@ -62,8 +62,8 @@ struct _GstGLTestSrc {
     /* video state */
     GstVideoInfo out_info;
 
-    GLuint fbo;
-    GLuint depthbuffer;
+    GstGLFramebuffer *fbo;
+    GstGLMemory *out_tex;
 
     GstGLShader *shader;
 
index 1a8ddf28cb3fe485c360ebbc291e7ee2bb32e7d3..1e805901e36dbe87d6fef146b0885a82b823c4a0 100644 (file)
@@ -97,7 +97,7 @@ static gboolean gst_gl_transformation_decide_allocation (GstBaseTransform *
 static void gst_gl_transformation_reset_gl (GstGLFilter * filter);
 static gboolean gst_gl_transformation_stop (GstBaseTransform * trans);
 static gboolean gst_gl_transformation_init_shader (GstGLFilter * filter);
-static void gst_gl_transformation_callback (gpointer stuff);
+static gboolean gst_gl_transformation_callback (gpointer stuff);
 static void gst_gl_transformation_build_mvp (GstGLTransformation *
     transformation);
 
@@ -789,13 +789,8 @@ gst_gl_transformation_filter_texture (GstGLFilter * filter,
 
   transformation->in_tex = in_tex;
 
-  /* blocking call, use a FBO */
-  gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
-      GST_VIDEO_INFO_WIDTH (&filter->out_info),
-      GST_VIDEO_INFO_HEIGHT (&filter->out_info),
-      filter->fbo, filter->depthbuffer,
-      out_tex->tex_id, gst_gl_transformation_callback,
-      (gpointer) transformation);
+  gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex,
+      (GstGLFramebufferFunc) gst_gl_transformation_callback, transformation);
 
   return TRUE;
 }
@@ -857,7 +852,7 @@ _unbind_buffer (GstGLTransformation * transformation)
   gl->DisableVertexAttribArray (transformation->attr_texture);
 }
 
-static void
+static gboolean
 gst_gl_transformation_callback (gpointer stuff)
 {
   GstGLFilter *filter = GST_GL_FILTER (stuff);
@@ -925,4 +920,6 @@ gst_gl_transformation_callback (gpointer stuff)
 
   gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context);
   transformation->caps_change = FALSE;
+
+  return TRUE;
 }
index 176d27e547f7b776b395adf6c70c69f61b677f55..4491823d134e5c0127a81147ee5b71484ee13b96 100644 (file)
@@ -475,7 +475,7 @@ static gboolean gst_gl_video_mixer_init_shader (GstGLMixer * mixer,
 
 static gboolean gst_gl_video_mixer_process_textures (GstGLMixer * mixer,
     GstGLMemory * out_tex);
-static void gst_gl_video_mixer_callback (gpointer stuff);
+static gboolean gst_gl_video_mixer_callback (gpointer stuff);
 
 /* *INDENT-OFF* */
 
@@ -1155,16 +1155,25 @@ gst_gl_video_mixer_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
       video_mixer_f_src, &video_mixer->shader);
 }
 
+static void
+_video_mixer_process_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
+{
+  GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
+
+  gst_gl_framebuffer_draw_to_texture (mixer->fbo, video_mixer->out_tex,
+      gst_gl_video_mixer_callback, video_mixer);
+}
+
 static gboolean
 gst_gl_video_mixer_process_textures (GstGLMixer * mix, GstGLMemory * out_tex)
 {
   GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mix);
+  GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
+
+  video_mixer->out_tex = out_tex;
 
-  gst_gl_context_use_fbo_v2 (GST_GL_BASE_MIXER (mix)->context,
-      GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR (mix)->info),
-      GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR (mix)->info),
-      mix->fbo, mix->depthbuffer,
-      out_tex->tex_id, gst_gl_video_mixer_callback, (gpointer) video_mixer);
+  gst_gl_context_thread_add (context,
+      (GstGLContextThreadFunc) _video_mixer_process_gl, video_mixer);
 
   return TRUE;
 }
@@ -1383,7 +1392,7 @@ _set_blend_state (GstGLVideoMixer * video_mixer, GstGLVideoMixerPad * mix_pad)
 }
 
 /* opengl scene, params: input texture (not the output mixer->texture) */
-static void
+static gboolean
 gst_gl_video_mixer_callback (gpointer stuff)
 {
   GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (stuff);
@@ -1411,7 +1420,7 @@ gst_gl_video_mixer_callback (gpointer stuff)
   }
 
   if (!_draw_background (video_mixer))
-    return;
+    return FALSE;
 
   gst_gl_shader_use (video_mixer->shader);
 
@@ -1546,4 +1555,6 @@ gst_gl_video_mixer_callback (gpointer stuff)
   gl->Disable (GL_BLEND);
 
   gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context);
+
+  return TRUE;
 }
index a0776fd9fc1689e5b47013b24fda64475eb49a97..f3526465eb331ab7938e5ed374d8d48cc8b092e2 100644 (file)
@@ -125,6 +125,7 @@ struct _GstGLVideoMixer
     GLuint vao;
     GLuint vbo_indices;
     GLuint checker_vbo;
+    GstGLMemory *out_tex;
 };
 
 struct _GstGLVideoMixerClass
index 86fff2f5738c7218c6ea0f5d50ac6cad36db8516..465e2845378c58e77299ef6780ecd8d6cc4759c5 100644 (file)
@@ -63,6 +63,10 @@ typedef struct _GstGLRenderbuffer GstGLRenderbuffer;
 typedef struct _GstGLRenderbufferAllocator GstGLRenderbufferAllocator;
 typedef struct _GstGLRenderbufferAllocatorClass GstGLRenderbufferAllocatorClass;
 
+typedef struct _GstGLFramebuffer GstGLFramebuffer;
+typedef struct _GstGLFramebufferAllocator GstGLFramebufferAllocator;
+typedef struct _GstGLFramebufferAllocatorClass GstGLFramebufferAllocatorClass;
+
 typedef struct _GstGLSLStage        GstGLSLStage;
 typedef struct _GstGLSLStagePrivate GstGLSLStagePrivate;
 typedef struct _GstGLSLStageClass   GstGLSLStageClass;
index ebddb2d2bafb1793ead62880e08298056083e7ff..34a581897580d381d418dbc752949d2107bfff2d 100644 (file)
@@ -549,11 +549,9 @@ gst_gl_color_convert_reset (GstGLColorConvert * convert)
 {
   guint i;
 
-  if (convert->fbo || convert->depth_buffer) {
-    gst_gl_context_del_fbo (convert->context, convert->fbo,
-        convert->depth_buffer);
-    convert->fbo = 0;
-    convert->depth_buffer = 0;
+  if (convert->fbo) {
+    gst_object_unref (convert->fbo);
+    convert->fbo = NULL;
   }
 
   for (i = 0; i < convert->priv->convert_info.out_n_textures; i++) {
@@ -2027,7 +2025,7 @@ _init_convert (GstGLColorConvert * convert)
 
   gst_gl_context_clear_shader (convert->context);
 
-  if (convert->fbo == 0 && !_init_convert_fbo (convert)) {
+  if (convert->fbo == NULL && !_init_convert_fbo (convert)) {
     goto error;
   }
 
@@ -2088,82 +2086,16 @@ incompatible_api:
 static gboolean
 _init_convert_fbo (GstGLColorConvert * convert)
 {
-  GstGLFuncs *gl;
   guint out_width, out_height;
-  GLuint fake_texture = 0;      /* a FBO must hava texture to init */
-  GLenum internal_format;
-
-  gl = convert->context->gl_vtable;
 
   out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
   out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
 
-  if (!gl->GenFramebuffers) {
-    /* turn off the pipeline because Frame buffer object is a not present */
-    gst_gl_context_set_error (convert->context,
-        "Context, EXT_framebuffer_object supported: no");
-    return FALSE;
-  }
-
-  GST_INFO ("Context, EXT_framebuffer_object supported: yes");
-
-  /* setup FBO */
-  gl->GenFramebuffers (1, &convert->fbo);
-  gl->BindFramebuffer (GL_FRAMEBUFFER, convert->fbo);
+  convert->fbo =
+      gst_gl_framebuffer_new_with_default_depth (convert->context, out_width,
+      out_height);
 
-  /* setup the render buffer for depth */
-  gl->GenRenderbuffers (1, &convert->depth_buffer);
-  gl->BindRenderbuffer (GL_RENDERBUFFER, convert->depth_buffer);
-  if (USING_OPENGL (convert->context) || USING_OPENGL3 (convert->context)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
-        out_width, out_height);
-  }
-  if (USING_GLES2 (convert->context)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
-        out_width, out_height);
-  }
-
-  /* a fake texture is attached to the convert FBO (cannot init without it) */
-  gl->GenTextures (1, &fake_texture);
-  gl->BindTexture (GL_TEXTURE_2D, fake_texture);
-  internal_format =
-      gst_gl_sized_gl_format_from_gl_format_type (convert->context, GL_RGBA,
-      GL_UNSIGNED_BYTE);
-  gl->TexImage2D (GL_TEXTURE_2D, 0, internal_format, out_width, out_height, 0,
-      GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  gl->TexParameteri (GL_TEXTURE_2D, 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_2D, fake_texture, 0);
-
-  /* attach the depth render buffer to the FBO */
-  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-      GL_RENDERBUFFER, convert->depth_buffer);
-
-  if (USING_OPENGL (convert->context)) {
-    gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-        GL_RENDERBUFFER, convert->depth_buffer);
-  }
-
-  if (!gst_gl_context_check_framebuffer_status (convert->context)) {
-    gst_gl_context_set_error (convert->context,
-        "GL framebuffer status incomplete");
-
-    gl->DeleteTextures (1, &fake_texture);
-
-    return FALSE;
-  }
-
-  /* unbind the FBO */
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
-
-  gl->DeleteTextures (1, &fake_texture);
-
-  return TRUE;
+  return convert->fbo != NULL;
 }
 
 static gboolean
@@ -2487,21 +2419,13 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
 
   gl = context->gl_vtable;
 
-  out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
-  out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
-
-  gl->BindFramebuffer (GL_FRAMEBUFFER, convert->fbo);
+  gst_gl_framebuffer_bind (convert->fbo);
 
   /* attach the texture to the FBO to renderer to */
   for (i = 0; i < c_info->out_n_textures; i++) {
-    guint gl_target =
-        gst_gl_texture_target_to_gl (convert->priv->to_texture_target);
-
-    /* needed? */
-    gl->BindTexture (gl_target, convert->priv->out_tex[i]->tex_id);
+    GstGLBaseMemory *tex = (GstGLBaseMemory *) convert->priv->out_tex[i];
 
-    gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
-        gl_target, convert->priv->out_tex[i]->tex_id, 0);
+    gst_gl_framebuffer_attach (convert->fbo, GL_COLOR_ATTACHMENT0 + i, tex);
   }
 
   if (gl->DrawBuffers)
@@ -2511,6 +2435,8 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
 
   gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
 
+  gst_gl_framebuffer_get_effective_dimensions (convert->fbo, &out_width,
+      &out_height);
   gl->Viewport (0, 0, out_width, out_height);
 
   gst_gl_shader_use (convert->shader);
@@ -2556,7 +2482,7 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
 
   gst_gl_context_check_framebuffer_status (context);
 
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+  gst_gl_context_clear_framebuffer (context);
 
   return TRUE;
 }
index 5980cfa182adc7afe5371afd6e9cfed3733e1ee1..fbbbf3b0d77cd9be27f137e11d56e6ce172b7207 100644 (file)
@@ -59,8 +59,7 @@ struct _GstGLColorConvert
   GstBuffer *    outbuf;
 
   /* used for the conversion */
-  GLuint           fbo;
-  GLuint           depth_buffer;
+  GstGLFramebuffer *fbo;
   GstGLShader     *shader;
 
   /* <private> */
index 3f805886232faa72ea694dbceea74d722138c91b..f6fd4392c0e143272ee2cb23b6b0d3fb5eac0d36 100644 (file)
@@ -228,12 +228,11 @@ gst_gl_filter_gl_stop (GstGLBaseFilter * base_filter)
     filter->vbo_indices = 0;
   }
 
-  if (filter->fbo != 0) {
-    gst_gl_context_del_fbo (context, filter->fbo, filter->depthbuffer);
+  if (filter->fbo != NULL) {
+    gst_object_unref (filter->fbo);
+    filter->fbo = NULL;
   }
 
-  filter->fbo = 0;
-  filter->depthbuffer = 0;
   filter->default_shader = NULL;
   filter->draw_attr_position_loc = -1;
   filter->draw_attr_texture_loc = -1;
@@ -691,14 +690,12 @@ gst_gl_filter_gl_set_caps (GstGLBaseFilter * bt, GstCaps * incaps,
   out_width = GST_VIDEO_INFO_WIDTH (&filter->out_info);
   out_height = GST_VIDEO_INFO_HEIGHT (&filter->out_info);
 
-  if (filter->fbo) {
-    gst_gl_context_del_fbo (context, filter->fbo, filter->depthbuffer);
-    filter->fbo = 0;
-    filter->depthbuffer = 0;
-  }
-  //blocking call, generate a FBO
-  if (!gst_gl_context_gen_fbo (context, out_width, out_height,
-          &filter->fbo, &filter->depthbuffer))
+  if (filter->fbo)
+    gst_object_unref (filter->fbo);
+
+  if (!(filter->fbo =
+          gst_gl_framebuffer_new_with_default_depth (context, out_width,
+              out_height)))
     goto context_error;
 
   if (filter_class->init_fbo) {
@@ -1009,12 +1006,14 @@ struct glcb2
 };
 
 /* convenience functions to simplify filter development */
-static void
+static gboolean
 _glcb2 (gpointer data)
 {
   struct glcb2 *cb = data;
 
   cb->func (cb->width, cb->height, cb->texture, cb->data);
+
+  return TRUE;
 }
 
 /**
@@ -1034,7 +1033,6 @@ void
 gst_gl_filter_render_to_target (GstGLFilter * filter, gboolean resize,
     GstGLMemory * input, GstGLMemory * output, GLCB func, gpointer data)
 {
-  GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   guint in_width, in_height, out_width, out_height;
   struct glcb2 cb;
 
@@ -1057,8 +1055,7 @@ gst_gl_filter_render_to_target (GstGLFilter * filter, gboolean resize,
   cb.width = in_width;
   cb.height = in_height;
 
-  gst_gl_context_use_fbo_v2 (context, out_width, out_height,
-      filter->fbo, filter->depthbuffer, output->tex_id, _glcb2, &cb);
+  gst_gl_framebuffer_draw_to_texture (filter->fbo, output, _glcb2, &cb);
 }
 
 static void
index 71ff0467db994f19ab08eef2f823eec9bc6e3676..795f6fffce9ac2cb3cb756cd9d4306e240b6fdee 100644 (file)
@@ -63,9 +63,10 @@ struct _GstGLFilter
 
   GstCaps           *out_caps;
 
+  /* <protected> */
+  GstGLFramebuffer  *fbo;
+
   /* <private> */
-  GLuint             fbo;
-  GLuint             depthbuffer;
   gboolean           gl_result;
   GstBuffer         *inbuf;
   GstBuffer         *outbuf;
index fb706f50dbda9f2ba45fef859079fd960fa1166a..054c1049607d4500e004b6dddfe7620eb01a4af6 100644 (file)
 #include "gl.h"
 #include "gstglframebuffer.h"
 
+#ifndef GL_FRAMEBUFFER_UNDEFINED
+#define GL_FRAMEBUFFER_UNDEFINED          0x8219
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#endif
+#ifndef GL_FRAMEBUFFER_UNSUPPORTED
+#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#endif
+
 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,
+G_DEFINE_TYPE_WITH_CODE (GstGLFramebuffer, gst_gl_framebuffer, GST_TYPE_OBJECT,
     DEBUG_INIT);
 
 #define GST_GL_FRAMEBUFFER_GET_PRIVATE(o) \
@@ -40,13 +56,35 @@ static void gst_gl_framebuffer_finalize (GObject * object);
 
 struct _GstGLFramebufferPrivate
 {
-  gint width;
-  gint height;
+  guint effective_width;
+  guint effective_height;
+};
 
-  guint fbo;
-  guint depth;
+struct fbo_attachment
+{
+  guint attachment_point;
+  GstGLBaseMemory *mem;
 };
 
+static void
+_fbo_attachment_init (struct fbo_attachment *attach, guint point,
+    GstGLBaseMemory * mem)
+{
+  attach->attachment_point = point;
+  attach->mem = (GstGLBaseMemory *) gst_memory_ref (GST_MEMORY_CAST (mem));
+}
+
+static void
+_fbo_attachment_unset (struct fbo_attachment *attach)
+{
+  if (!attach)
+    return;
+
+  if (attach->mem)
+    gst_memory_unref (GST_MEMORY_CAST (attach->mem));
+  attach->mem = NULL;
+}
+
 static void
 gst_gl_framebuffer_class_init (GstGLFramebufferClass * klass)
 {
@@ -56,183 +94,355 @@ gst_gl_framebuffer_class_init (GstGLFramebufferClass * klass)
 }
 
 static void
-gst_gl_framebuffer_init (GstGLFramebuffer * fbo)
+gst_gl_framebuffer_init (GstGLFramebuffer * fb)
 {
-  fbo->priv = GST_GL_FRAMEBUFFER_GET_PRIVATE (fbo);
+  fb->priv = GST_GL_FRAMEBUFFER_GET_PRIVATE (fb);
+
+  fb->attachments =
+      g_array_new (FALSE, FALSE, (sizeof (struct fbo_attachment)));
+  g_array_set_clear_func (fb->attachments,
+      (GDestroyNotify) _fbo_attachment_unset);
+}
+
+static void
+_delete_fbo_gl (GstGLContext * context, GstGLFramebuffer * fb)
+{
+  const GstGLFuncs *gl = context->gl_vtable;
+
+  if (fb->fbo_id)
+    gl->DeleteFramebuffers (1, &fb->fbo_id);
+  fb->fbo_id = 0;
 }
 
 static void
 gst_gl_framebuffer_finalize (GObject * object)
 {
-  GstGLFramebuffer *fbo = GST_GL_FRAMEBUFFER (object);
+  GstGLFramebuffer *fb = GST_GL_FRAMEBUFFER (object);
+
+  if (fb->context) {
+    if (fb->fbo_id)
+      gst_gl_context_thread_add (fb->context,
+          (GstGLContextThreadFunc) _delete_fbo_gl, fb);
 
-  if (fbo->context) {
-    gst_object_unref (fbo->context);
-    fbo->context = NULL;
+    gst_object_unref (fb->context);
+    fb->context = NULL;
   }
 
+  if (fb->attachments)
+    g_array_free (fb->attachments, TRUE);
+  fb->attachments = NULL;
+
   G_OBJECT_CLASS (gst_gl_framebuffer_parent_class)->finalize (object);
 }
 
 GstGLFramebuffer *
 gst_gl_framebuffer_new (GstGLContext * context)
 {
-  GstGLFramebuffer *fbo = g_object_new (GST_TYPE_GL_FRAMEBUFFER, NULL);
+  GstGLFramebuffer *fb;
+  const GstGLFuncs *gl;
+
+  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
+  g_return_val_if_fail (gst_gl_context_get_current () == context, NULL);
+
+  gl = context->gl_vtable;
+
+  if (!gl->GenFramebuffers) {
+    GST_ERROR_OBJECT (context, "Framebuffers are not supported!");
+    return NULL;
+  }
+
+  fb = g_object_new (GST_TYPE_GL_FRAMEBUFFER, NULL);
+  fb->context = gst_object_ref (context);
+  gl->GenFramebuffers (1, &fb->fbo_id);
+
+  return fb;
+}
+
+GstGLFramebuffer *
+gst_gl_framebuffer_new_with_default_depth (GstGLContext * context, guint width,
+    guint height)
+{
+  GstGLFramebuffer *fb = gst_gl_framebuffer_new (context);
+  GstGLBaseMemoryAllocator *render_alloc;
+  GstGLAllocationParams *params;
+  GstGLBaseMemory *renderbuffer;
+  guint attach_point, attach_type;
+
+  if (!fb)
+    return NULL;
+
+  if (gst_gl_context_get_gl_api (fb->context) & (GST_GL_API_OPENGL |
+          GST_GL_API_OPENGL3)) {
+    attach_point = GL_DEPTH_STENCIL_ATTACHMENT;
+    attach_type = GST_GL_DEPTH24_STENCIL8;
+  } else if (gst_gl_context_get_gl_api (fb->context) & GST_GL_API_GLES2) {
+    attach_point = GL_DEPTH_ATTACHMENT;
+    attach_type = GST_GL_DEPTH_COMPONENT16;
+  } else {
+    g_assert_not_reached ();
+    return NULL;
+  }
 
-  fbo->context = gst_object_ref (context);
+  render_alloc = (GstGLBaseMemoryAllocator *)
+      gst_allocator_find (GST_GL_RENDERBUFFER_ALLOCATOR_NAME);
+  params = (GstGLAllocationParams *)
+      gst_gl_renderbuffer_allocation_params_new (context, NULL, attach_type,
+      width, height);
 
-  return fbo;
+  renderbuffer = gst_gl_base_memory_alloc (render_alloc, params);
+  gst_gl_allocation_params_free (params);
+  gst_object_unref (render_alloc);
+
+  gst_gl_framebuffer_bind (fb);
+  gst_gl_framebuffer_attach (fb, attach_point, renderbuffer);
+  gst_gl_context_clear_framebuffer (fb->context);
+  gst_memory_unref (GST_MEMORY_CAST (renderbuffer));
+
+  return fb;
 }
 
 gboolean
-gst_gl_framebuffer_generate (GstGLFramebuffer * frame, gint width, gint height,
-    guint * fbo, guint * depth)
+gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
+    GstGLFramebufferFunc func, gpointer user_data)
 {
-  GLuint fake_texture = 0;
+  GLint viewport_dim[4] = { 0 };
   const GstGLFuncs *gl;
-  GLenum internal_format;
+  gboolean ret;
 
-  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);
+  g_return_val_if_fail (GST_IS_GL_FRAMEBUFFER (fb), FALSE);
+  g_return_val_if_fail (gst_is_gl_memory (GST_MEMORY_CAST (mem)), FALSE);
 
-  gl = frame->context->gl_vtable;
+  gl = fb->context->gl_vtable;
 
-  GST_TRACE ("creating FBO dimensions:%ux%u", width, height);
+  GST_TRACE_OBJECT (fb, "drawing to texture %u, dimensions %ix%i", mem->tex_id,
+      gst_gl_memory_get_texture_width (mem),
+      gst_gl_memory_get_texture_height (mem));
 
-  if (!gl->GenFramebuffers) {
-    gst_gl_context_set_error (frame->context,
-        "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);
+  gst_gl_framebuffer_bind (fb);
+  gst_gl_framebuffer_attach (fb, GL_COLOR_ATTACHMENT0, (GstGLBaseMemory *) mem);
 
-  if (gst_gl_context_get_gl_api (frame->context) & (GST_GL_API_OPENGL |
-          GST_GL_API_OPENGL3)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width,
-        height);
-  }
-  if (gst_gl_context_get_gl_api (frame->context) & GST_GL_API_GLES2) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
-        width, height);
-  }
+  gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
+  gl->Viewport (0, 0, fb->priv->effective_width, fb->priv->effective_height);
+  if (gst_gl_context_get_gl_api (fb->context) & (GST_GL_API_OPENGL |
+          GST_GL_API_OPENGL3))
+    gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
 
-  /* setup a texture to render to */
-  gl->GenTextures (1, &fake_texture);
-  gl->BindTexture (GL_TEXTURE_2D, fake_texture);
-  internal_format =
-      gst_gl_sized_gl_format_from_gl_format_type (frame->context, GL_RGBA,
-      GL_UNSIGNED_BYTE);
-  gl->TexImage2D (GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_RGBA,
-      GL_UNSIGNED_BYTE, NULL);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  gl->TexParameteri (GL_TEXTURE_2D, 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_2D, fake_texture, 0);
-
-  /* attach the depth render buffer to the FBO */
-  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-      GL_RENDERBUFFER, *depth);
-
-  if (gst_gl_context_get_gl_api (frame->context) & (GST_GL_API_OPENGL |
-          GST_GL_API_OPENGL3)) {
-    gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-        GL_RENDERBUFFER, *depth);
-  }
+  ret = func (user_data);
 
-  if (gl->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
-    gst_gl_context_set_error (frame->context,
-        "GL framebuffer status incomplete");
+  if (gst_gl_context_get_gl_api (fb->context) & (GST_GL_API_OPENGL |
+          GST_GL_API_OPENGL3))
+    gl->DrawBuffer (GL_NONE);
+  gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
+      viewport_dim[3]);
+  gst_gl_context_clear_framebuffer (fb->context);
 
-    gl->DeleteTextures (1, &fake_texture);
+  return ret;
+}
 
-    return FALSE;
-  }
+void
+gst_gl_framebuffer_bind (GstGLFramebuffer * fb)
+{
+  const GstGLFuncs *gl;
 
-  /* unbind the FBO */
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+  g_return_if_fail (GST_IS_GL_FRAMEBUFFER (fb));
+  g_return_if_fail (gst_gl_context_get_current () == fb->context);
+  g_return_if_fail (fb->fbo_id != 0);
 
-  gl->DeleteTextures (1, &fake_texture);
+  gl = fb->context->gl_vtable;
 
-  return TRUE;
+  gl->BindFramebuffer (GL_FRAMEBUFFER, fb->fbo_id);
 }
 
-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_context_clear_framebuffer (GstGLContext * context)
 {
   const GstGLFuncs *gl;
-  GLint viewport_dim[4] = { 0 };
 
-  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);
+  g_return_if_fail (GST_IS_GL_CONTEXT (context));
 
-  gl = frame->context->gl_vtable;
+  gl = context->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, 0);
+}
 
-  gl->BindFramebuffer (GL_FRAMEBUFFER, fbo);
+static void
+_update_effective_dimensions (GstGLFramebuffer * fb)
+{
+  int i;
+  guint min_width = -1, min_height = -1;
+
+  /* remove the previous attachment */
+  for (i = 0; i < fb->attachments->len; i++) {
+    struct fbo_attachment *attach;
+    int width, height;
+
+    attach = &g_array_index (fb->attachments, struct fbo_attachment, i);
+
+    if (gst_is_gl_memory (GST_MEMORY_CAST (attach->mem))) {
+      GstGLMemory *mem = (GstGLMemory *) attach->mem;
+
+      width = gst_gl_memory_get_texture_width (mem);
+      height = gst_gl_memory_get_texture_height (mem);
+    } else if (gst_is_gl_renderbuffer (GST_MEMORY_CAST (attach->mem))) {
+      GstGLRenderbuffer *mem = (GstGLRenderbuffer *) attach->mem;
+
+      width = mem->width;
+      height = mem->height;
+    } else {
+      g_assert_not_reached ();
+    }
+
+    if (width < min_width)
+      min_width = width;
+    if (height < min_height)
+      min_height = height;
+  }
 
-  /* setup a texture to render to */
-  gl->BindTexture (GL_TEXTURE_2D, texture_fbo);
+  fb->priv->effective_width = min_width;
+  fb->priv->effective_height = min_height;
+}
 
-  /* attach the texture to the FBO to renderer to */
-  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-      GL_TEXTURE_2D, texture_fbo, 0);
+static gboolean
+_is_valid_attachment_point (guint attachment_point)
+{
+  /* all 31 possible color attachments */
+  if (attachment_point >= 0x8CE0 && attachment_point <= 0x8CFF)
+    return TRUE;
 
-  gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
+  /* depth-stencil attachment */
+  if (attachment_point == 0x821A)
+    return TRUE;
 
-  gl->Viewport (0, 0, texture_fbo_width, texture_fbo_height);
+  /* depth attachment */
+  if (attachment_point == 0x8D00)
+    return TRUE;
 
-  if (gst_gl_context_get_gl_api (frame->context) & (GST_GL_API_OPENGL |
-          GST_GL_API_OPENGL3))
-    gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
+  /* stencil attachment */
+  if (attachment_point == 0x8D20)
+    return TRUE;
 
-  /* the opengl scene */
-  cb (stuff);
+  return FALSE;
+}
 
-  if (gst_gl_context_get_gl_api (frame->context) & (GST_GL_API_OPENGL |
-          GST_GL_API_OPENGL3))
-    gl->DrawBuffer (GL_NONE);
+static void
+_attach_gl_memory (GstGLFramebuffer * fb, guint attachment_point,
+    GstGLMemory * mem)
+{
+  struct fbo_attachment attach;
+  const GstGLFuncs *gl = fb->context->gl_vtable;
+  guint gl_target = gst_gl_texture_target_to_gl (mem->tex_target);
 
-  gl->Viewport (viewport_dim[0], viewport_dim[1],
-      viewport_dim[2], viewport_dim[3]);
+  gst_gl_framebuffer_bind (fb);
 
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+  gl->FramebufferTexture2D (GL_FRAMEBUFFER, attachment_point, gl_target,
+      mem->tex_id, 0);
+
+  _fbo_attachment_init (&attach, attachment_point, (GstGLBaseMemory *) mem);
+  fb->attachments = g_array_append_val (fb->attachments, attach);
+}
+
+static void
+_attach_renderbuffer (GstGLFramebuffer * fb, guint attachment_point,
+    GstGLRenderbuffer * rb)
+{
+  struct fbo_attachment attach;
+  const GstGLFuncs *gl = fb->context->gl_vtable;
+
+  gst_gl_framebuffer_bind (fb);
+  gl->BindRenderbuffer (GL_RENDERBUFFER, rb->renderbuffer_id);
 
-  return TRUE;
+  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, attachment_point,
+      GL_RENDERBUFFER, rb->renderbuffer_id);
+
+  _fbo_attachment_init (&attach, attachment_point, (GstGLBaseMemory *) rb);
+  fb->attachments = g_array_append_val (fb->attachments, attach);
 }
 
 void
-gst_gl_framebuffer_delete (GstGLFramebuffer * frame, guint fbo, guint depth)
+gst_gl_framebuffer_attach (GstGLFramebuffer * fb, guint attachment_point,
+    GstGLBaseMemory * mem)
 {
-  const GstGLFuncs *gl;
+  int i;
 
-  g_return_if_fail (GST_IS_GL_FRAMEBUFFER (frame));
+  g_return_if_fail (GST_IS_GL_FRAMEBUFFER (fb));
+  g_return_if_fail (gst_gl_context_get_current () == fb->context);
+  g_return_if_fail (_is_valid_attachment_point (attachment_point));
 
-  gl = frame->context->gl_vtable;
+  /* remove the previous attachment */
+  for (i = 0; i < fb->attachments->len; i++) {
+    struct fbo_attachment *attach;
 
-  GST_TRACE ("Deleting FBO %u", fbo);
+    attach = &g_array_index (fb->attachments, struct fbo_attachment, i);
 
-  if (fbo) {
-    gl->DeleteFramebuffers (1, &fbo);
+    if (attach->attachment_point == attachment_point) {
+      g_array_remove_index_fast (fb->attachments, i);
+      break;
+    }
   }
-  if (depth) {
-    gl->DeleteRenderbuffers (1, &depth);
+
+  if (gst_is_gl_memory (GST_MEMORY_CAST (mem))) {
+    _attach_gl_memory (fb, attachment_point, (GstGLMemory *) mem);
+  } else if (gst_is_gl_renderbuffer (GST_MEMORY_CAST (mem))) {
+    _attach_renderbuffer (fb, attachment_point, (GstGLRenderbuffer *) mem);
+  } else {
+    g_assert_not_reached ();
+    return;
   }
+
+  _update_effective_dimensions (fb);
+}
+
+void
+gst_gl_framebuffer_get_effective_dimensions (GstGLFramebuffer * fb,
+    guint * width, guint * height)
+{
+  g_return_if_fail (GST_IS_GL_FRAMEBUFFER (fb));
+
+  if (width)
+    *width = fb->priv->effective_width;
+  if (height)
+    *height = fb->priv->effective_height;
+}
+
+gboolean
+gst_gl_context_check_framebuffer_status (GstGLContext * context)
+{
+  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
+
+  switch (context->gl_vtable->CheckFramebufferStatus (GL_FRAMEBUFFER)) {
+    case GL_FRAMEBUFFER_COMPLETE:
+      return TRUE;
+      break;
+    case GL_FRAMEBUFFER_UNSUPPORTED:
+      GST_WARNING_OBJECT (context, "GL_FRAMEBUFFER_UNSUPPORTED");
+      break;
+    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+      GST_WARNING_OBJECT (context, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+      break;
+    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+      GST_WARNING_OBJECT (context,
+          "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
+      break;
+    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+      GST_WARNING_OBJECT (context, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+      break;
+#if GST_GL_HAVE_OPENGL
+    case GL_FRAMEBUFFER_UNDEFINED:
+      GST_WARNING_OBJECT (context, "GL_FRAMEBUFFER_UNDEFINED");
+      break;
+#endif
+    default:
+      GST_WARNING_OBJECT (context, "Unknown FBO error");
+      break;
+  }
+
+  return FALSE;
+}
+
+guint
+gst_gl_framebuffer_get_id (GstGLFramebuffer * fb)
+{
+  g_return_val_if_fail (GST_IS_GL_FRAMEBUFFER (fb), 0);
+
+  return fb->fbo_id;
 }
index 4768afb0cd3ec8f56787e274578a1ba106abc879..7e9e7012474bc30167dfa0c5920d14b7e532dd44 100644 (file)
@@ -38,31 +38,55 @@ typedef struct _GstGLFramebuffer GstGLFramebuffer;
 typedef struct _GstGLFramebufferClass GstGLFramebufferClass;
 typedef struct _GstGLFramebufferPrivate GstGLFramebufferPrivate;
 
+/**
+ * GstGLFramebufferFunc:
+ * @data: user data
+ *
+ * callback definition for operating through a Framebuffer object
+ */
+typedef gboolean (*GstGLFramebufferFunc) (gpointer stuff);
+
 struct _GstGLFramebuffer
 {
-  GObject             object;
+  GstObject             object;
 
   /* <private> */
   GstGLContext *context;
 
+  guint fbo_id;
+  GArray *attachments;
+
   GstGLFramebufferPrivate  *priv;
 };
 
 struct _GstGLFramebufferClass
 {
-  GObjectClass object_class;
+  GstObjectClass object_class;
 };
 
-GstGLFramebuffer *gst_gl_framebuffer_new (GstGLContext *context);
+GstGLFramebuffer *      gst_gl_framebuffer_new                      (GstGLContext *context);
+GstGLFramebuffer *      gst_gl_framebuffer_new_with_default_depth   (GstGLContext *context,
+                                                                     guint width,
+                                                                     guint height);
+
+guint                   gst_gl_framebuffer_get_id                   (GstGLFramebuffer * fb);
+
+void                    gst_gl_framebuffer_attach                   (GstGLFramebuffer * fb,
+                                                                     guint attachment_point,
+                                                                     GstGLBaseMemory * mem);
+void                    gst_gl_framebuffer_bind                     (GstGLFramebuffer * fb);
+void                    gst_gl_context_clear_framebuffer            (GstGLContext * context);
 
-gboolean gst_gl_framebuffer_generate (GstGLFramebuffer *frame, gint width, gint height,
-    guint * fbo, guint * depthbuffer);
+void                    gst_gl_framebuffer_get_effective_dimensions (GstGLFramebuffer * fb,
+                                                                     guint * width,
+                                                                     guint * height);
 
-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);
+gboolean                gst_gl_context_check_framebuffer_status     (GstGLContext * context);
 
-void gst_gl_framebuffer_delete (GstGLFramebuffer *frame, guint fbo, guint depth);
+gboolean                gst_gl_framebuffer_draw_to_texture          (GstGLFramebuffer * fb,
+                                                                     GstGLMemory * mem,
+                                                                     GstGLFramebufferFunc cb,
+                                                                     gpointer user_data);
 
 #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstGLFramebuffer, gst_object_unref)
index ade2f95620563c57049feae1d5e43ada92e4e991..e4cbd91e9179bde50392fe4fb00726cd982a2971 100644 (file)
 #include <gst/gl/wayland/gstgldisplay_wayland.h>
 #endif
 
-#ifndef GL_FRAMEBUFFER_UNDEFINED
-#define GL_FRAMEBUFFER_UNDEFINED          0x8219
-#endif
-#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
-#endif
-#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
-#endif
-#ifndef GL_FRAMEBUFFER_UNSUPPORTED
-#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
-#endif
-#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
-#endif
-
 #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))
 
 static gchar *error_message;
 
-/* called in the gl thread */
-gboolean
-gst_gl_context_check_framebuffer_status (GstGLContext * context)
-{
-  GLenum status = 0;
-  status = context->gl_vtable->CheckFramebufferStatus (GL_FRAMEBUFFER);
-
-  switch (status) {
-    case GL_FRAMEBUFFER_COMPLETE:
-      return TRUE;
-      break;
-
-    case GL_FRAMEBUFFER_UNSUPPORTED:
-      GST_ERROR ("GL_FRAMEBUFFER_UNSUPPORTED");
-      break;
-
-    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
-      GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
-      break;
-
-    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
-      GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
-      break;
-    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
-      GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
-      break;
-#if GST_GL_HAVE_OPENGL
-    case GL_FRAMEBUFFER_UNDEFINED:
-      GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED");
-      break;
-#endif
-    default:
-      GST_ERROR ("General FBO error");
-  }
-
-  return FALSE;
-}
-
-typedef struct _GenFBO
-{
-  GstGLFramebuffer *frame;
-  gint width, height;
-  GLuint *fbo, *depth;
-} GenFBO;
-
-static void
-_gen_fbo (GstGLContext * context, GenFBO * data)
-{
-  gst_gl_framebuffer_generate (data->frame, data->width, data->height,
-      data->fbo, data->depth);
-}
-
-gboolean
-gst_gl_context_gen_fbo (GstGLContext * context, gint width, gint height,
-    GLuint * fbo, GLuint * depthbuffer)
-{
-  GstGLFramebuffer *frame = gst_gl_framebuffer_new (context);
-
-  GenFBO data = { frame, width, height, fbo, depthbuffer };
-
-  gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _gen_fbo, &data);
-
-  gst_object_unref (frame);
-
-  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 (GstGLContext * context, 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_context_use_fbo_v2 (GstGLContext * context, gint texture_fbo_width,
-    gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
-    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff)
-{
-  GstGLFramebuffer *frame = gst_gl_framebuffer_new (context);
-
-  UseFBO2 data =
-      { frame, texture_fbo_width, texture_fbo_height, fbo, depth_buffer,
-    texture_fbo, cb, stuff
-  };
-
-  gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _use_fbo_v2,
-      &data);
-
-  gst_object_unref (frame);
-
-  return TRUE;
-}
-
-typedef struct _DelFBO
-{
-  GstGLFramebuffer *frame;
-  GLuint fbo;
-  GLuint depth;
-} DelFBO;
-
-/* Called in the gl thread */
-static void
-_del_fbo (GstGLContext * context, DelFBO * data)
-{
-  gst_gl_framebuffer_delete (data->frame, data->fbo, data->depth);
-}
-
-/* Called by gltestsrc and glfilter */
-void
-gst_gl_context_del_fbo (GstGLContext * context, GLuint fbo, GLuint depth_buffer)
-{
-  GstGLFramebuffer *frame = gst_gl_framebuffer_new (context);
-
-  DelFBO data = { frame, fbo, depth_buffer };
-
-  gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _del_fbo, &data);
-
-  gst_object_unref (frame);
-}
-
 struct _compile_shader
 {
   GstGLShader **shader;
index 4741dadc17fee7821519a8b05c64e627d27e5122..8914310fa5612a149c4bad23f7f3c732645d8a08 100644 (file)
@@ -60,29 +60,12 @@ typedef gboolean (*CDCB) (GLuint texture, GLuint width, GLuint height, gpointer
  * callback definition for operating on textures
  */
 typedef void (*GLCB) (gint, gint, guint, gpointer stuff);
-/**
- * GLCB_V2:
- * @stuff: user data
- *
- * callback definition for operating through a Framebuffer object
- */
-typedef void (*GLCB_V2) (gpointer stuff);
-
-gboolean gst_gl_context_gen_fbo (GstGLContext * context, gint width, gint height,
-    GLuint * fbo, GLuint * depthbuffer);
-gboolean gst_gl_context_use_fbo_v2 (GstGLContext * context, gint texture_fbo_width,
-    gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
-    GLuint texture_fbo, GLCB_V2 cb, gpointer stuff);
-void gst_gl_context_del_fbo (GstGLContext * context, GLuint fbo,
-    GLuint depth_buffer);
 
 gboolean gst_gl_context_gen_shader (GstGLContext * context,
     const gchar * shader_vertex_source,
     const gchar * shader_fragment_source, GstGLShader ** shader);
 void gst_gl_context_del_shader (GstGLContext * context, GstGLShader * shader);
 
-gboolean gst_gl_context_check_framebuffer_status (GstGLContext * context);
-
 void gst_gl_context_set_error (GstGLContext * context, const char * format, ...);
 gchar *gst_gl_context_get_error (void);
 
index 06978914c40c40ae4de22cd84520fcad9da32bd9..c50ca5213a960a06366fb4ee5d5ed102ddf93bdf 100644 (file)
@@ -1304,6 +1304,11 @@ gst_gl_view_convert_reset (GstGLViewConvert * viewconvert)
   if (viewconvert->shader)
     gst_gl_context_del_shader (viewconvert->context, viewconvert->shader);
   viewconvert->shader = NULL;
+
+  if (viewconvert->fbo)
+    gst_object_unref (viewconvert->fbo);
+  viewconvert->fbo = NULL;
+
   viewconvert->initted = FALSE;
   viewconvert->reconfigure = FALSE;
 }
@@ -1383,74 +1388,16 @@ gst_gl_view_convert_perform (GstGLViewConvert * viewconvert, GstBuffer * inbuf)
 static gboolean
 _init_view_convert_fbo (GstGLViewConvert * viewconvert)
 {
-  GstGLFuncs *gl;
   guint out_width, out_height;
-  GLuint fake_texture = 0;      /* a FBO must hava texture to init */
-  GLenum internal_format;
-  gboolean ret = TRUE;
 
-  gl = viewconvert->context->gl_vtable;
   out_width = GST_VIDEO_INFO_WIDTH (&viewconvert->out_info);
   out_height = GST_VIDEO_INFO_HEIGHT (&viewconvert->out_info);
-  if (!gl->GenFramebuffers) {
-    /* turn off the pipeline because Frame buffer object is a not present */
-    gst_gl_context_set_error (viewconvert->context,
-        "Frambuffer objects unsupported");
-    return FALSE;
-  }
 
-  /* setup FBO */
-  gl->GenFramebuffers (1, &viewconvert->fbo);
-  gl->BindFramebuffer (GL_FRAMEBUFFER, viewconvert->fbo);
-  /* setup the render buffer for depth */
-  gl->GenRenderbuffers (1, &viewconvert->depth_buffer);
-  gl->BindRenderbuffer (GL_RENDERBUFFER, viewconvert->depth_buffer);
-  if (USING_OPENGL (viewconvert->context)
-      || USING_OPENGL3 (viewconvert->context)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, out_width,
-        out_height);
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
-        out_width, out_height);
-  }
-  if (USING_GLES2 (viewconvert->context)) {
-    gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
-        out_width, out_height);
-  }
-
-  /* a fake texture is attached to the convert FBO (cannot init without it) */
-  gl->GenTextures (1, &fake_texture);
-  gl->BindTexture (GL_TEXTURE_2D, fake_texture);
-  internal_format =
-      gst_gl_sized_gl_format_from_gl_format_type (viewconvert->context, GL_RGBA,
-      GL_UNSIGNED_BYTE);
-  gl->TexImage2D (GL_TEXTURE_2D, 0, internal_format, out_width, out_height,
-      0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  gl->TexParameteri (GL_TEXTURE_2D, 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_2D, fake_texture, 0);
-  /* attach the depth render buffer to the FBO */
-  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-      GL_RENDERBUFFER, viewconvert->depth_buffer);
-  if (USING_OPENGL (viewconvert->context)) {
-    gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-        GL_RENDERBUFFER, viewconvert->depth_buffer);
-  }
-
-  if (!gst_gl_context_check_framebuffer_status (viewconvert->context)) {
-    gst_gl_context_set_error (viewconvert->context,
-        "GL framebuffer status incomplete");
-    ret = FALSE;
-  }
+  viewconvert->fbo =
+      gst_gl_framebuffer_new_with_default_depth (viewconvert->context,
+      out_width, out_height);
 
-  /* unbind the FBO */
-  gl->BindTexture (GL_TEXTURE_2D, 0);
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
-  gl->DeleteTextures (1, &fake_texture);
-  return ret;
+  return viewconvert->fbo != NULL;
 }
 
 /* free after use */
@@ -1865,9 +1812,9 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
       gst_gl_texture_target_to_gl (viewconvert->from_texture_target);
 
   gl = context->gl_vtable;
-  out_width = GST_VIDEO_INFO_WIDTH (&viewconvert->out_info);
-  out_height = GST_VIDEO_INFO_HEIGHT (&viewconvert->out_info);
-  gl->BindFramebuffer (GL_FRAMEBUFFER, viewconvert->fbo);
+
+  gst_gl_framebuffer_bind (viewconvert->fbo);
+
   if (out_mode == GST_VIDEO_MULTIVIEW_MODE_SEPARATED ||
       out_mode == GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME) {
     out_views = viewconvert->out_info.views;
@@ -1877,19 +1824,18 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
 
   /* attach the texture to the FBO to renderer to */
   for (i = 0; i < out_views; i++) {
-    guint gl_target =
-        gst_gl_texture_target_to_gl (viewconvert->to_texture_target);
+    GstGLBaseMemory *tex = (GstGLBaseMemory *) priv->out_tex[i];
 
-    /* needed? */
-    gl->BindTexture (gl_target, priv->out_tex[i]->tex_id);
-    gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
-        gl_target, priv->out_tex[i]->tex_id, 0);
+    gst_gl_framebuffer_attach (viewconvert->fbo, GL_COLOR_ATTACHMENT0 + i, tex);
   }
 
   if (gl->DrawBuffers)
     gl->DrawBuffers (out_views, multipleRT);
   else if (gl->DrawBuffer)
     gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
+
+  gst_gl_framebuffer_get_effective_dimensions (viewconvert->fbo, &out_width,
+      &out_height);
   gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
   gl->Viewport (0, 0, out_width, out_height);
 
@@ -1911,6 +1857,7 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
     gl->BindVertexArray (priv->vao);
   else
     _bind_buffer (viewconvert);
+
   if (in_mode == GST_VIDEO_MULTIVIEW_MODE_SEPARATED ||
       in_mode == GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME) {
     if (priv->in_tex[1] == NULL) {
@@ -1924,7 +1871,9 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
 
   gl->ActiveTexture (GL_TEXTURE0);
   gl->BindTexture (from_gl_target, priv->in_tex[0]->tex_id);
+
   gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL);
+
   if (gl->BindVertexArray)
     gl->BindVertexArray (0);
   else
@@ -1935,8 +1884,8 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
   gst_gl_context_clear_shader (context);
   gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
       viewport_dim[3]);
-  gst_gl_context_check_framebuffer_status (context);
-  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
+  gst_gl_context_clear_framebuffer (context);
+
   return TRUE;
 }
 
index 8cfa1b270040d4abdcb256ad79e064bb5c66368d..ee1166cc9064b3e55e2bb27c24c3e37d9e0d9f24 100644 (file)
@@ -68,8 +68,7 @@ struct _GstGLViewConvert
   gboolean initted;
   gboolean reconfigure;
 
-  GLuint fbo;
-  GLuint depth_buffer;
+  GstGLFramebuffer *fbo;
 
   GstGLViewConvertPrivate *priv;
 };
index 662e3a765a2a5063571800f37195d6d02086c547..25f3e00cf7e7717212146c80b2c027a63ea54200 100644 (file)
@@ -43,7 +43,7 @@ teardown (void)
 }
 
 static GstGLMemory *gl_tex;
-static GLuint vbo, vbo_indices, vao, fbo_id, rbo;
+static GLuint vbo, vbo_indices, vao;
 static GstGLFramebuffer *fbo;
 static GstGLShader *shader;
 static GLint shader_attr_position_loc;
@@ -75,10 +75,9 @@ init (gpointer data)
       GST_GL_TEXTURE_TARGET_2D, GST_VIDEO_GL_TEXTURE_TYPE_RGBA);
 
   /* has to be called in the thread that is going to use the framebuffer */
-  fbo = gst_gl_framebuffer_new (context);
+  fbo = gst_gl_framebuffer_new_with_default_depth (context, 320, 240);
 
-  gst_gl_framebuffer_generate (fbo, 320, 240, &fbo_id, &rbo);
-  fail_if (fbo == NULL || fbo_id == 0, "failed to create framebuffer object");
+  fail_if (fbo == NULL, "failed to create framebuffer object");
 
   gl_tex =
       (GstGLMemory *) gst_gl_base_memory_alloc ((GstGLBaseMemoryAllocator *)
@@ -109,7 +108,7 @@ deinit (gpointer data)
   gst_memory_unref (GST_MEMORY_CAST (gl_tex));
 }
 
-static void
+static gboolean
 clear_tex (gpointer data)
 {
   GstGLContext *context = data;
@@ -122,13 +121,15 @@ clear_tex (gpointer data)
   r = r > 1.0 ? 0.0 : r + 0.03;
   g = g > 1.0 ? 0.0 : g + 0.01;
   b = b > 1.0 ? 0.0 : b + 0.015;
+
+  return TRUE;
 }
 
 static void
 draw_tex (gpointer data)
 {
-  gst_gl_framebuffer_use_v2 (fbo, 320, 240, fbo_id, rbo,
-      gst_gl_memory_get_texture_id (gl_tex), (GLCB_V2) clear_tex, data);
+  gst_gl_framebuffer_draw_to_texture (fbo, gl_tex,
+      (GstGLFramebufferFunc) clear_tex, data);
 }
 
 static void
@@ -275,7 +276,8 @@ GST_START_TEST (test_share)
   gst_gl_window_set_preferred_size (window, 320, 240);
   gst_gl_window_draw (window);
 
-  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (init), context);
+  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (init),
+      other_context);
   gst_gl_window_send_message (window, GST_GL_WINDOW_CB (init_blit), context);
 
   while (i < 10) {
@@ -286,7 +288,8 @@ GST_START_TEST (test_share)
     i++;
   }
 
-  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (deinit), context);
+  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (deinit),
+      other_context);
   gst_gl_window_send_message (window, GST_GL_WINDOW_CB (deinit_blit), context);
 
   gst_object_unref (window);
@@ -380,7 +383,8 @@ GST_START_TEST (test_wrapped_context)
   gst_gl_window_set_preferred_size (window, 320, 240);
   gst_gl_window_draw (window);
 
-  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (init), context);
+  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (init),
+      other_context);
   gst_gl_window_send_message (window, GST_GL_WINDOW_CB (init_blit), context);
 
   while (i < 10) {
@@ -394,7 +398,8 @@ GST_START_TEST (test_wrapped_context)
   gst_gl_window_send_message (window, GST_GL_WINDOW_CB (check_wrapped),
       wrapped_context);
 
-  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (deinit), context);
+  gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (deinit),
+      other_context);
   gst_gl_window_send_message (window, GST_GL_WINDOW_CB (deinit_blit), context);
 
   gst_object_unref (other_context);