libgstgl: fix rendering on iOS
authorAlessandro Decina <alessandro.d@gmail.com>
Thu, 2 Apr 2015 07:05:55 +0000 (18:05 +1100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:58 +0000 (19:31 +0000)
Stop assuming that the handle has been set by the time ->create_context is
called. After bc7a7259f357b0065dd94e0668b5a895d83fa53a set_window_handle always
happens after ->create_context in fact.

See also https://bugzilla.gnome.org/show_bug.cgi?id=745090

gst-libs/gst/gl/eagl/gstglcontext_eagl.h
gst-libs/gst/gl/eagl/gstglcontext_eagl.m
gst-libs/gst/gl/eagl/gstglwindow_eagl.m

index b621b35..c8997ff 100644 (file)
@@ -59,6 +59,7 @@ GType gst_gl_context_eagl_get_type (void);
 
 GstGLContextEagl * gst_gl_context_eagl_new (void);
 
+void gst_gl_context_eagl_update_layer (GstGLContext * context);
 void gst_gl_context_eagl_resize (GstGLContextEagl * eagl_context);
 void gst_gl_context_eagl_prepare_draw (GstGLContextEagl * context);
 void gst_gl_context_eagl_finish_draw (GstGLContextEagl * context);
index e01fa62..9fb29e6 100644 (file)
@@ -115,14 +115,114 @@ gst_gl_context_eagl_resize (GstGLContextEagl * eagl_context)
       height);
 }
 
+static void
+gst_gl_context_eagl_release_layer (GstGLContext * context)
+{
+  GstGLContextEagl *context_eagl;
+
+  context_eagl = GST_GL_CONTEXT_EAGL (context);
+
+  if (context_eagl->priv->eagl_layer) {
+    gst_gl_context_eagl_activate (context, TRUE);
+
+    [context_eagl->priv->eagl_context renderbufferStorage: GL_RENDERBUFFER fromDrawable:nil];
+
+    glDeleteFramebuffers (1, &context_eagl->priv->framebuffer);
+    context_eagl->priv->framebuffer = 0;
+
+    glDeleteRenderbuffers (1, &context_eagl->priv->depth_renderbuffer);
+    context_eagl->priv->depth_renderbuffer = 0;
+    glDeleteRenderbuffers (1, &context_eagl->priv->color_renderbuffer);
+    context_eagl->priv->color_renderbuffer = 0;
+
+    context_eagl->priv->eagl_layer = nil;
+    gst_gl_context_eagl_activate (context, FALSE);
+  }
+}
+
+void
+gst_gl_context_eagl_update_layer (GstGLContext * context)
+{
+  __block GLuint framebuffer;
+  __block GLuint color_renderbuffer;
+  __block GLuint depth_renderbuffer;
+  __block GLint width;
+  __block GLint height;
+  __block CAEAGLLayer *eagl_layer;
+  GLenum status;
+  GstGLContextEagl *context_eagl = GST_GL_CONTEXT_EAGL (context);
+  GstGLContextEaglPrivate *priv = context_eagl->priv;
+  UIView *window_handle = nil;
+  GstGLWindow *window = gst_gl_context_get_window (context);
+  if (window)
+    window_handle = (UIView *) gst_gl_window_get_window_handle (window);
+
+  if (!window_handle) {
+    GST_INFO_OBJECT (context, "window handle not set yet, not updating layer");
+    goto out;
+  }
+
+  GST_INFO_OBJECT (context, "updating layer, frame %fx%f",
+      window_handle.frame.size.width, window_handle.frame.size.height);
+
+  if (priv->eagl_layer)
+    gst_gl_context_eagl_release_layer (context);
+
+  dispatch_sync (dispatch_get_main_queue (), ^{
+      eagl_layer = (CAEAGLLayer *)[window_handle layer];
+      [EAGLContext setCurrentContext:priv->eagl_context];
+
+      /* Allocate framebuffer */
+      glGenFramebuffers (1, &framebuffer);
+      glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
+      /* Allocate color render buffer */
+      glGenRenderbuffers (1, &color_renderbuffer);
+      glBindRenderbuffer (GL_RENDERBUFFER, color_renderbuffer);
+      [priv->eagl_context renderbufferStorage: GL_RENDERBUFFER fromDrawable:eagl_layer];
+      glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+          GL_RENDERBUFFER, color_renderbuffer);
+      /* Get renderbuffer width/height */
+      glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,
+          &width);
+      glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT,
+          &height);
+      /* allocate depth render buffer */
+      glGenRenderbuffers (1, &depth_renderbuffer);
+      glBindRenderbuffer (GL_RENDERBUFFER, depth_renderbuffer);
+      glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width,
+          height);
+      glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+          GL_RENDERBUFFER, depth_renderbuffer);
+      [EAGLContext setCurrentContext:nil];
+  });
+
+  [EAGLContext setCurrentContext:priv->eagl_context];
+
+  glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
+  /* check creation status */
+  status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
+  if (status != GL_FRAMEBUFFER_COMPLETE) {
+    GST_ERROR ("Failed to make complete framebuffer object %x", status);
+    goto out;
+  }
+  glBindFramebuffer (GL_FRAMEBUFFER, 0);
+
+  priv->eagl_layer = eagl_layer;
+  priv->framebuffer = framebuffer;
+  priv->color_renderbuffer = color_renderbuffer;
+  priv->depth_renderbuffer = depth_renderbuffer;
+
+out:
+  if (window)
+    gst_object_unref (window);
+}
+
 static gboolean
 gst_gl_context_eagl_create_context (GstGLContext * context, GstGLAPI gl_api,
     GstGLContext * other_context, GError ** error)
 {
   GstGLContextEagl *context_eagl = GST_GL_CONTEXT_EAGL (context);
   GstGLContextEaglPrivate *priv = context_eagl->priv;
-  GstGLWindow *window = gst_gl_context_get_window (context);
-  UIView *window_handle = nil;
 
   dispatch_sync (dispatch_get_main_queue (), ^{
     if (other_context) {
@@ -136,73 +236,14 @@ gst_gl_context_eagl_create_context (GstGLContext * context, GstGLAPI gl_api,
       priv->eagl_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
     }
   });
+  
+  priv->eagl_layer = NULL;
+  priv->framebuffer = 0;
+  priv->color_renderbuffer = 0;
+  priv->depth_renderbuffer = 0;
 
-  if (window)
-    window_handle = (UIView *) gst_gl_window_get_window_handle (window);
-
-  if (window_handle) {
-    __block GLuint framebuffer;
-    __block GLuint color_renderbuffer;
-    __block GLuint depth_renderbuffer;
-    __block GLint width;
-    __block GLint height;
-    __block CAEAGLLayer *eagl_layer;
-    GLenum status;
-
-    dispatch_sync (dispatch_get_main_queue (), ^{
-          eagl_layer = (CAEAGLLayer *)[window_handle layer];
-          [EAGLContext setCurrentContext:priv->eagl_context];
-
-          /* Allocate framebuffer */
-          glGenFramebuffers (1, &framebuffer);
-          glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
-          /* Allocate color render buffer */
-          glGenRenderbuffers (1, &color_renderbuffer);
-          glBindRenderbuffer (GL_RENDERBUFFER, color_renderbuffer);
-          [priv->eagl_context renderbufferStorage: GL_RENDERBUFFER fromDrawable:eagl_layer];
-          glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-              GL_RENDERBUFFER, color_renderbuffer);
-          /* Get renderbuffer width/height */
-          glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,
-              &width);
-          glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT,
-              &height);
-          /* allocate depth render buffer */
-          glGenRenderbuffers (1, &depth_renderbuffer);
-          glBindRenderbuffer (GL_RENDERBUFFER, depth_renderbuffer);
-          glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width,
-              height);
-          glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-              GL_RENDERBUFFER, depth_renderbuffer);
-          [EAGLContext setCurrentContext:nil];
-    });
-
-    [EAGLContext setCurrentContext:priv->eagl_context];
-
-    glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
-    /* check creation status */
-    status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
-    if (status != GL_FRAMEBUFFER_COMPLETE) {
-      GST_ERROR ("Failed to make complete framebuffer object %x", status);
-      if (window)
-        gst_object_unref (window);
-      return FALSE;
-    }
-    glBindFramebuffer (GL_FRAMEBUFFER, 0);
-
-    priv->eagl_layer = eagl_layer;
-    priv->framebuffer = framebuffer;
-    priv->color_renderbuffer = color_renderbuffer;
-    priv->depth_renderbuffer = depth_renderbuffer;
-  } else {
-    priv->eagl_layer = NULL;
-    priv->framebuffer = 0;
-    priv->color_renderbuffer = 0;
-    priv->depth_renderbuffer = 0;
-  }
-
-  if (window)
-    gst_object_unref (window);
+  GST_INFO_OBJECT (context, "context created, updating layer");
+  gst_gl_context_eagl_update_layer (context);
 
   return TRUE;
 }
@@ -217,22 +258,7 @@ gst_gl_context_eagl_destroy_context (GstGLContext * context)
   if (!context_eagl->priv->eagl_context)
     return;
 
-  if (context_eagl->priv->eagl_layer) {
-    gst_gl_context_eagl_activate (context, TRUE);
-
-    [context_eagl->priv->eagl_context renderbufferStorage: GL_RENDERBUFFER fromDrawable:nil];
-
-    glDeleteFramebuffers (1, &context_eagl->priv->framebuffer);
-    context_eagl->priv->framebuffer = 0;
-
-    glDeleteRenderbuffers (1, &context_eagl->priv->depth_renderbuffer);
-    context_eagl->priv->depth_renderbuffer = 0;
-    glDeleteRenderbuffers (1, &context_eagl->priv->color_renderbuffer);
-    context_eagl->priv->color_renderbuffer = 0;
-
-    context_eagl->priv->eagl_layer = nil;
-    gst_gl_context_eagl_activate (context, FALSE);
-  }
+  gst_gl_context_eagl_release_layer (context);
 
   [context_eagl->priv->eagl_context release];
   context_eagl->priv->eagl_context = nil;
index f1fc8b8..e1d06fd 100644 (file)
@@ -139,10 +139,14 @@ static void
 gst_gl_window_eagl_set_window_handle (GstGLWindow * window, guintptr handle)
 {
   GstGLWindowEagl *window_eagl;
+  GstGLContext *context;
 
   window_eagl = GST_GL_WINDOW_EAGL (window);
+  context = gst_gl_window_get_context (window);
 
   window_eagl->priv->view = (UIView *) handle;
+  GST_INFO_OBJECT (context, "handle set, updating layer");
+  gst_gl_context_eagl_update_layer (context);
 }
 
 static gboolean