caopengllayersink: correctly use the sync meta across multiple contexts
authorMatthew Waters <matthew@centricular.com>
Tue, 19 May 2015 14:28:52 +0000 (00:28 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:32:01 +0000 (19:32 +0000)
1. Set the sync point after the (possible) upload has occured
2. Wait in the correct GL context (the draw context)

Note: We don't add the GL sync meta to the input buffer as it's not
writable and a copy would be expensive.

Similar to the change with the same name for glimagesink

ext/gl/caopengllayersink.h
ext/gl/caopengllayersink.m

index c0513c7..b28eb3f 100644 (file)
@@ -59,6 +59,7 @@ struct _GstCAOpenGLLayerSink
 
     guint      next_tex;
     GstBuffer *next_buffer;
+    GstBuffer *next_sync;
 
     GstGLCAOpenGLLayer *layer;
 
@@ -70,6 +71,7 @@ struct _GstCAOpenGLLayerSink
     /* avoid replacing the stored_buffer while drawing */
     GMutex drawing_lock;
     GstBuffer *stored_buffer;
+    GstBuffer *stored_sync;
     GLuint redisplay_texture;
 
     gboolean caps_change;
index 724de6f..a9ca2ca 100644 (file)
@@ -448,6 +448,7 @@ gst_ca_opengl_layer_sink_query (GstBaseSink * bsink, GstQuery * query)
         gst_buffer_unref (buf);
 
       gst_buffer_replace (&ca_sink->next_buffer, NULL);
+      gst_buffer_replace (&ca_sink->next_sync, NULL);
 
       res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
       break;
@@ -528,12 +529,16 @@ gst_ca_opengl_layer_sink_change_state (GstElement * element, GstStateChange tran
        */
       GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink);
       ca_sink->redisplay_texture = 0;
+
+      gst_buffer_replace (&ca_sink->stored_sync, NULL);
+
       if (ca_sink->stored_buffer) {
         gst_buffer_unref (ca_sink->stored_buffer);
         ca_sink->stored_buffer = NULL;
       }
-      GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink);
       gst_buffer_replace (&ca_sink->next_buffer, NULL);
+      gst_buffer_replace (&ca_sink->next_sync, NULL);
+      GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink);
 
       if (ca_sink->pool) {
         gst_buffer_pool_set_active (ca_sink->pool, FALSE);
@@ -662,7 +667,9 @@ static GstFlowReturn
 gst_ca_opengl_layer_sink_prepare (GstBaseSink * bsink, GstBuffer * buf)
 {
   GstCAOpenGLLayerSink *ca_sink;
+  GstBuffer *next_sync, *old_sync, *old_buffer;
   GstVideoFrame gl_frame;
+  GstGLSyncMeta *sync_meta;
 
   ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink);
 
@@ -683,7 +690,24 @@ gst_ca_opengl_layer_sink_prepare (GstBaseSink * bsink, GstBuffer * buf)
 
   ca_sink->next_tex = *(guint *) gl_frame.data[0];
 
-  gst_buffer_replace (&ca_sink->next_buffer, buf);
+  next_sync = gst_buffer_new ();
+  sync_meta = gst_buffer_add_gl_sync_meta (ca_sink->context, next_sync);
+  gst_gl_sync_meta_set_sync_point (sync_meta, ca_sink->context);
+
+  GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink);
+  ca_sink->next_tex = *(guint *) gl_frame.data[0];
+
+  old_buffer = ca_sink->next_buffer;
+  ca_sink->next_buffer = gst_buffer_ref (buf);
+
+  old_sync = ca_sink->next_sync;
+  ca_sink->next_sync = next_sync;
+  GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink);
+
+  if (old_buffer)
+    gst_buffer_unref (old_buffer);
+  if (old_sync)
+    gst_buffer_unref (old_sync);
 
   gst_video_frame_unmap (&gl_frame);
 
@@ -701,7 +725,7 @@ static GstFlowReturn
 gst_ca_opengl_layer_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 {
   GstCAOpenGLLayerSink *ca_sink;
-  GstBuffer *stored_buffer;
+  GstBuffer *stored_buffer, *old_sync;
 
   GST_TRACE ("rendering buffer:%p", buf);
 
@@ -716,8 +740,12 @@ gst_ca_opengl_layer_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
   /* Avoid to release the texture while drawing */
   GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink);
   ca_sink->redisplay_texture = ca_sink->next_tex;
+
   stored_buffer = ca_sink->stored_buffer;
   ca_sink->stored_buffer = gst_buffer_ref (ca_sink->next_buffer);
+
+  old_sync = ca_sink->stored_sync;
+  ca_sink->stored_sync = gst_buffer_ref (ca_sink->next_sync);
   GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink);
 
   /* The layer will automatically call the draw callback to draw the new
@@ -730,6 +758,8 @@ gst_ca_opengl_layer_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 
   if (stored_buffer)
     gst_buffer_unref (stored_buffer);
+  if (old_sync)
+    gst_buffer_unref (old_sync);
 
   if (g_atomic_int_get (&ca_sink->to_quit) != 0) {
     GST_ELEMENT_ERROR (ca_sink, RESOURCE, NOT_FOUND,
@@ -978,6 +1008,7 @@ gst_ca_opengl_layer_sink_on_draw (GstCAOpenGLLayerSink * ca_sink)
    */
 
   const GstGLFuncs *gl = NULL;
+  GstGLSyncMeta *sync_meta;
 
   g_return_if_fail (GST_IS_CA_OPENGL_LAYER_SINK (ca_sink));
 
@@ -1008,10 +1039,9 @@ gst_ca_opengl_layer_sink_on_draw (GstCAOpenGLLayerSink * ca_sink)
     ca_sink->caps_change = TRUE;
   }
 
-#if GST_GL_HAVE_OPENGL
-  if (USING_OPENGL (ca_sink->context))
-    gl->Disable (GL_TEXTURE_2D);
-#endif
+  sync_meta = gst_buffer_get_gl_sync_meta (ca_sink->stored_sync);
+  if (sync_meta)
+    gst_gl_sync_meta_wait (sync_meta, gst_gl_context_get_current ());
 
   gl->BindTexture (GL_TEXTURE_2D, 0);