gl: Don't restore the viewport on function exit
authorMatthew Waters <matthew@centricular.com>
Tue, 5 Mar 2019 05:13:15 +0000 (16:13 +1100)
committerMatthew Waters <matthew@centricular.com>
Fri, 8 Mar 2019 06:49:05 +0000 (17:49 +1100)
Doing so involves retrieving the current viewport from OpenGL which as
with any glGet operation, is expensive.

This means that the various sinks need to reset the viewport on draw.

In the process, fix resizing on cocoa.

ext/gl/gstglimagesink.c
gst-libs/gst/gl/cocoa/gstglcaopengllayer.m
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
gst-libs/gst/gl/gstglcolorconvert.c
gst-libs/gst/gl/gstglframebuffer.c
gst-libs/gst/gl/gstglviewconvert.c
gst-libs/gst/gl/gstglwindow.c
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.h

index 38883c5aa5394297a264e33a5d4a49161a8ced99..15074f83ab2ec40f3fc2aa29576637d865a89db9 100644 (file)
@@ -2187,6 +2187,16 @@ gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, gint height)
     GST_DEBUG_OBJECT (gl_sink, "GL output area now %u,%u %ux%u",
         gl_sink->display_rect.x, gl_sink->display_rect.y,
         gl_sink->display_rect.w, gl_sink->display_rect.h);
+  } else {
+    gint viewport_dims[4];
+
+    /* save the viewport for use later */
+    gl->GetIntegerv (GL_VIEWPORT, viewport_dims);
+
+    gl_sink->display_rect.x = viewport_dims[0];
+    gl_sink->display_rect.y = viewport_dims[1];
+    gl_sink->display_rect.w = viewport_dims[2];
+    gl_sink->display_rect.h = viewport_dims[3];
   }
   GST_GLIMAGE_SINK_UNLOCK (gl_sink);
 }
@@ -2234,6 +2244,10 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
   gst_gl_context_clear_shader (gl_sink->context);
   gl->BindTexture (gl_target, 0);
 
+  if (!gst_gl_window_controls_viewport (window))
+    gl->Viewport (gl_sink->display_rect.x, gl_sink->display_rect.y,
+        gl_sink->display_rect.w, gl_sink->display_rect.h);
+
   sample = gst_sample_new (gl_sink->stored_buffer[0],
       gl_sink->out_caps, &GST_BASE_SINK (gl_sink)->segment, NULL);
   g_signal_emit (gl_sink, gst_glimage_sink_signals[CLIENT_DRAW_SIGNAL], 0,
index 065d596de71faab17f00f0602d72b64a302386db..254a3f21f4c3d0265c593c0f84c26025dafc1868 100644 (file)
@@ -206,15 +206,21 @@ _context_ready (gpointer data)
    * the CA viewport set up on entry to this function */
   gl->GetIntegerv (GL_VIEWPORT, ca_viewport);
 
+  GST_TRACE ("retrieved viewport from CA %u,%u %ux%u", self->expected_dims[0],
+      self->expected_dims[1], self->expected_dims[2], self->expected_dims[3]);
   gst_gl_context_activate (self->draw_context, TRUE);
   if (self->queue_resize || self->last_bounds.size.width != self.bounds.size.width
       || self->last_bounds.size.height != self.bounds.size.height) {
     if (self->resize_cb) {
-      self->resize_cb (self->resize_data, 
+      self->resize_cb (self->resize_data,
           self.bounds.size.width*self.contentsScale,
           self.bounds.size.height*self.contentsScale);
 
       gl->GetIntegerv (GL_VIEWPORT, self->expected_dims);
+
+      GST_LOG ("resize callback wants viewport %u,%u %ux%u",
+          self->expected_dims[0], self->expected_dims[1],
+          self->expected_dims[2], self->expected_dims[3]);
     } else {
       /* default to whatever ca gives us */
       self->expected_dims[0] = ca_viewport[0];
@@ -239,6 +245,8 @@ _context_ready (gpointer data)
 
   gst_video_sink_center_rect (src, dst, &result, TRUE);
 
+  GST_TRACE ("Using viewport %u,%u %ux%u", result.x, result.y, result.w,
+      result.h);
   gl->Viewport (result.x, result.y, result.w, result.h);
 
   if (self->draw_cb)
index 91c1187ef3cf72e6bc7f90b6a5b35ef901f1ff51..996c2ea46654413b5c2bfbc4373e0a03ccf413c8 100644 (file)
@@ -81,6 +81,8 @@ static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
     GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 static gboolean gst_gl_window_cocoa_set_render_rectangle (GstGLWindow * window,
     gint x, gint y, gint width, gint height);
+static gboolean gst_gl_window_cocoa_controls_viewport (GstGLWindow * window);
+
 
 struct _GstGLWindowCocoaPrivate
 {
@@ -125,6 +127,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
       GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async);
   window_class->set_render_rectangle =
       GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_render_rectangle);
+  window_class->controls_viewport =
+      GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_controls_viewport);
 
   gobject_class->finalize = gst_gl_window_cocoa_finalize;
 }
@@ -387,9 +391,11 @@ gst_gl_cocoa_draw_cb (GstGLWindowCocoa *window_cocoa)
   GstGLNSWindow *internal_win_id = (__bridge GstGLNSWindow *)priv->internal_win_id;
 
   if (internal_win_id && ![internal_win_id isClosed]) {
-   GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
+    GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
 
     /* draw opengl scene in the back buffer */
+    /* We do not need to change viewports like in other window implementations
+     * as the caopengllayer will take care of that for us. */
     if (window->draw)
       window->draw (window->draw_data);
   }
@@ -409,6 +415,7 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
     NSRect bounds = [view bounds];
     NSRect visibleRect = [view visibleRect];
     gint viewport_dim[4];
+    GstVideoRectangle viewport;
 
     gl = context->gl_vtable;
 
@@ -417,19 +424,30 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
     visibleRect = [view convertRectToBacking:visibleRect];
 #endif
 
+    /* don't use the default gst_gl_window_resize() as that will marshal through
+     * the GL thread.  We are being called from the main thread by the
+     * caopengllayer */
+    if (window->resize)
+      window->resize (window->resize_data, width, height);
+
+    gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
+
     GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf "
-                      "visibleRect %lf %lf %lf %lf",
+                      "visibleRect %lf %lf %lf %lf, "
+                      "viewport dimensions %i %i %i %i",
                       bounds.origin.x, bounds.origin.y,
                       bounds.size.width, bounds.size.height,
                       visibleRect.origin.x, visibleRect.origin.y,
-                      visibleRect.size.width, visibleRect.size.height);
+                      visibleRect.size.width, visibleRect.size.height,
+                      viewport_dim[0], viewport_dim[1], viewport_dim[2],
+                      viewport_dim[3]);
 
-    gst_gl_window_resize (window, width, height);
-    gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
+    viewport.x = viewport_dim[0] - visibleRect.origin.x;
+    viewport.x = viewport_dim[1] - visibleRect.origin.y;
+    viewport.w = viewport_dim[2];
+    viewport.h = viewport_dim[3];
 
-    gl->Viewport (viewport_dim[0] - visibleRect.origin.x,
-                  viewport_dim[1] - visibleRect.origin.y,
-                  viewport_dim[2], viewport_dim[3]);
+    gl->Viewport (viewport.x, viewport.y, viewport.w, viewport.h);
   }
 
   gst_object_unref (context);
@@ -532,6 +550,12 @@ gst_gl_window_cocoa_set_render_rectangle (GstGLWindow * window, gint x, gint y,
  return TRUE;
 }
 
+static gboolean
+gst_gl_window_cocoa_controls_viewport (GstGLWindow * window)
+{
+  return TRUE;
+}
+
 /* =============================================================*/
 /*                                                              */
 /*                    GstGLNSWindow implementation              */
index 9fa123a42d4ca60c1291b0f0a99681cb92eb9824..351d8598af242b9965c364a632f713dfb09cbd9a 100644 (file)
@@ -2531,8 +2531,6 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
   gint i;
   gboolean ret = TRUE;
 
-  GLint viewport_dim[4] = { 0 };
-
   GLenum multipleRT[] = {
     GL_COLOR_ATTACHMENT0,
     GL_COLOR_ATTACHMENT1,
@@ -2555,8 +2553,6 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
   else if (gl->DrawBuffer)
     gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
 
-  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);
@@ -2598,9 +2594,6 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
   /* we are done with the shader */
   gst_gl_context_clear_shader (context);
 
-  gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
-      viewport_dim[3]);
-
   if (!gst_gl_context_check_framebuffer_status (context, GL_FRAMEBUFFER))
     ret = FALSE;
 
index 98eee348f471c95686fa36025b6e0de77b269f3f..19307ca0bdf2bb1bd237cdd7b225bbde010627d2 100644 (file)
@@ -269,7 +269,6 @@ gboolean
 gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
     GstGLFramebufferFunc func, gpointer user_data)
 {
-  GLint viewport_dim[4] = { 0 };
   const GstGLFuncs *gl;
   gboolean ret;
 
@@ -285,7 +284,6 @@ gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
   gst_gl_framebuffer_bind (fb);
   gst_gl_framebuffer_attach (fb, GL_COLOR_ATTACHMENT0, (GstGLBaseMemory *) mem);
 
-  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))
@@ -296,8 +294,6 @@ gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
   if (gst_gl_context_get_gl_api (fb->context) & (GST_GL_API_OPENGL |
           GST_GL_API_OPENGL3))
     gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
-  gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
-      viewport_dim[3]);
   gst_gl_context_clear_framebuffer (fb->context);
 
   return ret;
index 20a94d03b3cd483280cc4d9ba980df86b4b4a0c9..89f2e50e6bb1dec528a945d4215704ef9a3e9c36 100644 (file)
@@ -1850,7 +1850,6 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
   GstGLFuncs *gl;
   guint out_width, out_height;
   gint out_views, i;
-  GLint viewport_dim[4] = { 0 };
   GLenum multipleRT[] = {
     GL_COLOR_ATTACHMENT0,
     GL_COLOR_ATTACHMENT1,
@@ -1886,7 +1885,6 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
 
   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);
 
   gst_gl_shader_use (viewconvert->shader);
@@ -1934,8 +1932,6 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
     gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
   /* we are done with the shader */
   gst_gl_context_clear_shader (context);
-  gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
-      viewport_dim[3]);
   gst_gl_context_clear_framebuffer (context);
 
   return TRUE;
index 17ad5edccebcdd63e237d5f9729b72a9eaa3cd1d..1044b9858054817e033c5e3da21d09bfa3b21985 100644 (file)
@@ -975,6 +975,20 @@ gst_gl_window_resize (GstGLWindow * window, guint width, guint height)
   window->queue_resize = FALSE;
 }
 
+gboolean
+gst_gl_window_controls_viewport (GstGLWindow * window)
+{
+  GstGLWindowClass *window_class;
+
+  g_return_val_if_fail (GST_IS_GL_WINDOW (window), FALSE);
+  window_class = GST_GL_WINDOW_GET_CLASS (window);
+
+  if (!window_class->controls_viewport)
+    return FALSE;
+
+  return window_class->controls_viewport (window);
+}
+
 static GType gst_gl_dummy_window_get_type (void);
 
 G_DEFINE_TYPE (GstGLDummyWindow, gst_gl_dummy_window, GST_TYPE_GL_WINDOW);
index ece8d315b06fba10aba7b60563a7a833a023f239..9d68a244c0cbcdc6b7b70784d4c9ad1a791565cc 100644 (file)
@@ -148,6 +148,8 @@ struct _GstGLWindow {
  * @show: request that the window be shown to the user
  * @set_render_rectangle: request a rectangle to render into.  See #GstVideoOverlay
  * @queue_resize: request a resize to occur when possible
+ * @controls_viewport: Whether the window takes care of glViewport setup.
+ *                     and the user does not need to deal with viewports
  */
 struct _GstGLWindowClass {
   GstObjectClass parent_class;
@@ -168,9 +170,10 @@ struct _GstGLWindowClass {
   void     (*show)               (GstGLWindow *window);
   gboolean (*set_render_rectangle)(GstGLWindow *window, gint x, gint y, gint width, gint height);
   void     (*queue_resize)       (GstGLWindow *window);
+  gboolean (*controls_viewport)  (GstGLWindow *window);
 
   /*< private >*/
-  gpointer _reserved[GST_PADDING];
+  gpointer _reserved[GST_PADDING-1];
 };
 
 GST_GL_API
@@ -250,6 +253,8 @@ gboolean gst_gl_window_set_render_rectangle   (GstGLWindow * window,
                                                gint y,
                                                gint width,
                                                gint height);
+GST_GL_API
+gboolean gst_gl_window_controls_viewport      (GstGLWindow * window);
 
 /* subclass usage only */
 GST_GL_API
index 8d6fceb80bfae80c698f19e57f4d7e843a6bd5ea..40b8c73a482f1543bb511f786384e6b1c9d49ec7 100644 (file)
@@ -46,6 +46,8 @@ static void gst_gl_window_viv_fb_egl_draw (GstGLWindow * window);
 static gboolean
 gst_gl_window_viv_fb_egl_set_render_rectangle (GstGLWindow * window,
     gint x, gint y, gint width, gint height);
+static gboolean gst_gl_window_viv_fb_egl_controls_viewport (GstGLWindow *
+    window);
 
 static void
 gst_gl_window_viv_fb_egl_class_init (GstGLWindowVivFBEGLClass * klass)
@@ -63,6 +65,8 @@ gst_gl_window_viv_fb_egl_class_init (GstGLWindowVivFBEGLClass * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_draw);
   window_class->set_render_rectangle =
       GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_set_render_rectangle);
+  window_class->controls_viewport =
+      GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_controls_viewport);
 }
 
 static void
@@ -179,12 +183,15 @@ draw_cb (gpointer data)
     gst_gl_window_resize (window, width, height);
 
     gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
-    viewport_dim[0] += window_egl->render_rectangle.x;
-    viewport_dim[1] += window_egl->render_rectangle.y;
-    gl->Viewport (viewport_dim[0],
-        viewport_dim[1], viewport_dim[2], viewport_dim[3]);
+    window_egl->viewport.x = viewport_dim[0] + window_egl->render_rectangle.x;
+    window_egl->viewport.y = viewport_dim[1] + window_egl->render_rectangle.y;
+    window_egl->viewport.w = viewport_dim[2];
+    window_egl->viewport.h = viewport_dim[2];
   }
 
+  gl->Viewport (window_egl->viewport.x, window_egl->viewport.y,
+      window_egl->viewport.w, window_egl->viewport.h);
+
   if (window->draw)
     window->draw (window->draw_data);
 
@@ -263,3 +270,9 @@ gst_gl_window_viv_fb_egl_set_render_rectangle (GstGLWindow * window,
 
   return TRUE;
 }
+
+static gboolean
+gst_gl_window_viv_fb_egl_controls_viewport (GstGLWindow * window)
+{
+  return TRUE;
+}
index 60205e0dcb7d3edfc67d415c0197201467fb1f97..244e66368fc7970cade196f11b81f9c247265250 100644 (file)
@@ -47,6 +47,7 @@ struct _GstGLWindowVivFBEGL {
   gint window_width, window_height;
 
   GstVideoRectangle render_rectangle;
+  GstVideoRectangle viewport;
 };
 
 struct _GstGLWindowVivFBEGLClass {