glwindow: add API to request a resize event on the next draw
authorMatthew Waters <matthew@centricular.com>
Thu, 17 Sep 2015 07:06:37 +0000 (17:06 +1000)
committerMatthew Waters <matthew@centricular.com>
Thu, 17 Sep 2015 10:26:23 +0000 (20:26 +1000)
- glimagesink needs to be able to resize the viewport on aspect ratio
  changes resulting from either caps changes or 3d output mode changes.
- Performing a glViewport outside the GstGLWindow::resize callback
  will not have the winsys' stack of viewports required to correctly
  place the output frame.

Provide a function to request a resize on the next draw event from the
winsys.

Also track size changes inside the base GstGLWindow class rather
than in each subclass.

https://bugzilla.gnome.org/show_bug.cgi?id=755111

12 files changed:
gst-libs/gst/gl/android/gstglwindow_android_egl.c
gst-libs/gst/gl/cocoa/gstglcaopengllayer.h
gst-libs/gst/gl/cocoa/gstglcaopengllayer.m
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c
gst-libs/gst/gl/eagl/gstglwindow_eagl.m
gst-libs/gst/gl/gstglwindow.c
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
gst-libs/gst/gl/win32/gstglwindow_win32.c
gst-libs/gst/gl/x11/gstglwindow_x11.c
gst-libs/gst/gl/x11/gstglwindow_x11.h

index 4e57f4c..9837756 100644 (file)
@@ -108,18 +108,17 @@ draw_cb (gpointer data)
 
   if (context_egl->egl_surface) {
     gint width, height;
-
-    if (eglQuerySurface (context_egl->egl_display,
-            context_egl->egl_surface, EGL_WIDTH, &width) &&
-        eglQuerySurface (context_egl->egl_display,
-            context_egl->egl_surface, EGL_HEIGHT, &height)
-        && (width != window_egl->window_width
+    gint window_width, window_height;
+
+    gst_gl_window_get_surface_dimensions (window, &window_width,
+        &window_height);
+    if (eglQuerySurface (context_egl->egl_display, context_egl->egl_surface,
+            EGL_WIDTH, &width)
+        && eglQuerySurface (context_egl->egl_display, context_egl->egl_surface,
+            EGL_HEIGHT, &height)
+        && (window->queue_resize || width != window_egl->window_width
             || height != window_egl->window_height)) {
-      window_egl->window_width = width;
-      window_egl->window_height = height;
-
-      if (window->resize)
-        window->resize (window->resize_data, width, height);
+      gst_gl_window_resize (window, width, height);
     }
   }
 
index e3958f8..2ed87b7 100644 (file)
@@ -48,9 +48,11 @@ G_BEGIN_DECLS
   GDestroyNotify resize_notify;
 
   gint can_draw;
+  gboolean queue_resize;
 }
 - (void) setDrawCallback:(GstGLWindowCB)cb data:(gpointer)a notify:(GDestroyNotify)notify;
 - (void) setResizeCallback:(GstGLWindowResizeCB)cb data:(gpointer)a notify:(GDestroyNotify)notify;
+- (void) queueResize;
 - (id) initWithGstGLContext: (GstGLContextCocoa *)context;
 @end
 
index 9362bca..a48709f 100644 (file)
@@ -184,7 +184,7 @@ _context_ready (gpointer data)
   gl->GetIntegerv (GL_VIEWPORT, ca_viewport);
 
   gst_gl_context_activate (self->draw_context, TRUE);
-  if (self->last_bounds.size.width != self.bounds.size.width
+  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.bounds.size.width,
@@ -200,6 +200,7 @@ _context_ready (gpointer data)
     }
 
     self->last_bounds = self.bounds;
+    self->queue_resize = FALSE;
   }
 
   src.x = self->expected_dims[0];
index 975fe5a..9c37e6c 100644 (file)
@@ -76,6 +76,7 @@ static void gst_gl_window_cocoa_draw (GstGLWindow * window);
 static void gst_gl_window_cocoa_set_preferred_size (GstGLWindow * window,
     gint width, gint height);
 static void gst_gl_window_cocoa_show (GstGLWindow * window);
+static void gst_gl_window_cocoa_queue_resize (GstGLWindow * window);
 
 struct _GstGLWindowCocoaPrivate
 {
@@ -110,6 +111,7 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
   window_class->set_preferred_size =
       GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_preferred_size);
   window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_show);
+  window_class->queue_resize = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_queue_resize);
 
   gobject_class->finalize = gst_gl_window_cocoa_finalize;
 }
@@ -267,6 +269,20 @@ gst_gl_window_cocoa_show (GstGLWindow * window)
 }
 
 static void
+gst_gl_window_cocoa_queue_resize (GstGLWindow * window)
+{
+  GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
+  GstGLNSView *view;
+
+  if (!g_atomic_int_get (&window_cocoa->priv->view_ready))
+    return;
+
+  view = (GstGLNSView *)[window_cocoa->priv->internal_win_id contentView];
+
+  [view->layer queueResize];
+}
+
+static void
 gst_gl_window_cocoa_draw (GstGLWindow * window)
 {
   GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
@@ -343,10 +359,8 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
                       visibleRect.origin.x, visibleRect.origin.y,
                       visibleRect.size.width, visibleRect.size.height);
 
-    if (window->resize) {
-      window->resize (window->resize_data, width, height);
-      gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
-    }
+    gst_gl_window_resize (window, width, height);
+    gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
 
     gl->Viewport (viewport_dim[0] - visibleRect.origin.x,
                   viewport_dim[1] - visibleRect.origin.y,
index 99fd741..26e6df7 100644 (file)
@@ -185,6 +185,8 @@ static void
 window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height,
     gboolean visible)
 {
+  GstGLWindow *window = GST_GL_WINDOW (window_egl);
+
   GST_DEBUG ("resizing %s window from %ux%u to %ux%u",
       visible ? "visible" : "invisible", window_egl->native.width,
       window_egl->native.height, width, height);
@@ -234,9 +236,8 @@ window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height,
 
     vc_dispmanx_update_submit_sync (dispman_update);
 
-    if (GST_GL_WINDOW (window_egl)->resize)
-      GST_GL_WINDOW (window_egl)->
-          resize (GST_GL_WINDOW (window_egl)->resize_data, width, height);
+    if (window->resize)
+      window->resize (window->resize_data, width, height);
   }
 
   window_egl->native.width = width;
index 9d37b14..dfd889f 100644 (file)
@@ -143,7 +143,7 @@ draw_cb (gpointer data)
     eagl_layer = (CAEAGLLayer *)[window_eagl->priv->view layer];
     size = eagl_layer.frame.size;
 
-    if (window_eagl->priv->window_width != size.width ||
+    if (window->queue_resize || window_eagl->priv->window_width != size.width ||
         window_eagl->priv->window_height != size.height) {
 
       window_eagl->priv->window_width = size.width;
@@ -151,8 +151,7 @@ draw_cb (gpointer data)
 
       gst_gl_context_eagl_resize (eagl_context);
 
-      if (window->resize)
-        window->resize (window->resize_data, window_eagl->priv->window_width,
+      gst_gl_window_resize (window, window_eagl->priv->window_width,
             window_eagl->priv->window_height);
     }
   }
index a69b10d..05d0697 100644 (file)
@@ -96,6 +96,9 @@ struct _GstGLWindowPrivate
   GMainLoop *loop;
   GThread *navigation_thread;
 
+  guint surface_width;
+  guint surface_height;
+
   gboolean alive;
 };
 
@@ -437,6 +440,13 @@ draw_cb (gpointer data)
   GstGLContext *context = gst_gl_window_get_context (window);
   GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
 
+  if (window->queue_resize) {
+    guint width, height;
+
+    gst_gl_window_get_surface_dimensions (window, &width, &height);
+    gst_gl_window_resize (window, width, height);
+  }
+
   if (window->draw)
     window->draw (window->draw_data);
 
@@ -471,6 +481,8 @@ gst_gl_window_draw_unlocked (GstGLWindow * window)
   g_return_if_fail (window_class->draw_unlocked != NULL);
 
   window_class->draw_unlocked (window);
+
+  window->queue_resize = FALSE;
 }
 
 /**
@@ -496,6 +508,8 @@ gst_gl_window_draw (GstGLWindow * window)
   }
 
   window_class->draw (window);
+
+  window->queue_resize = FALSE;
 }
 
 /**
@@ -926,11 +940,10 @@ void
 gst_gl_window_get_surface_dimensions (GstGLWindow * window, guint * width,
     guint * height)
 {
-  GstGLWindowClass *window_class;
-  g_return_if_fail (GST_GL_IS_WINDOW (window));
-  window_class = GST_GL_WINDOW_GET_CLASS (window);
-  g_return_if_fail (window_class->get_surface_dimensions != NULL);
-  window_class->get_surface_dimensions (window, width, height);
+  if (width)
+    *width = window->priv->surface_width;
+  if (height)
+    *height = window->priv->surface_height;
 }
 
 GType gst_gl_dummy_window_get_type (void);
@@ -1008,12 +1021,6 @@ gst_gl_dummy_window_get_display (GstGLWindow * window)
 }
 
 static void
-gst_gl_dummy_window_get_surface_dimensions (GstGLWindow * window, guint * width,
-    guint * height)
-{
-}
-
-static void
 gst_gl_dummy_window_class_init (GstGLDummyWindowClass * klass)
 {
   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
@@ -1024,8 +1031,6 @@ gst_gl_dummy_window_class_init (GstGLDummyWindowClass * klass)
       GST_DEBUG_FUNCPTR (gst_gl_dummy_window_get_window_handle);
   window_class->set_window_handle =
       GST_DEBUG_FUNCPTR (gst_gl_dummy_window_set_window_handle);
-  window_class->get_surface_dimensions =
-      GST_DEBUG_FUNCPTR (gst_gl_dummy_window_get_surface_dimensions);
 }
 
 static void
@@ -1138,3 +1143,28 @@ gst_gl_window_set_render_rectangle (GstGLWindow * window, gint x, gint y,
 
   return ret;
 }
+
+void
+gst_gl_window_queue_resize (GstGLWindow * window)
+{
+  GstGLWindowClass *window_class;
+
+  g_return_val_if_fail (GST_GL_IS_WINDOW (window), FALSE);
+  window_class = GST_GL_WINDOW_GET_CLASS (window);
+
+  window->queue_resize = TRUE;
+  if (window_class->queue_resize)
+    window_class->queue_resize (window);
+}
+
+void
+gst_gl_window_resize (GstGLWindow * window, guint width, guint height)
+{
+  g_return_if_fail (GST_GL_IS_WINDOW (window));
+
+  if (window->resize)
+    window->resize (window->resize_data, width, height);
+
+  window->priv->surface_width = width;
+  window->priv->surface_height = height;
+}
index b7c5a76..e4781c7 100644 (file)
@@ -90,6 +90,8 @@ struct _GstGLWindow {
   gpointer              resize_data;
   GDestroyNotify        resize_notify;
 
+  gboolean              queue_resize;
+
   /*< private >*/
   GMainContext *navigation_context;
   GMainLoop *navigation_loop;
@@ -138,11 +140,11 @@ struct _GstGLWindowClass {
 
   gboolean (*open)               (GstGLWindow *window, GError **error);
   void     (*close)              (GstGLWindow *window);
-  void     (*get_surface_dimensions)  (GstGLWindow *window, guint *width, guint *height);
   void     (*handle_events)      (GstGLWindow *window, gboolean handle_events);
   void     (*set_preferred_size) (GstGLWindow *window, gint width, gint height);
   void     (*show)               (GstGLWindow *window);
   gboolean (*set_render_rectangle)(GstGLWindow *window, gint x, gint y, gint width, gint height);
+  void     (*queue_resize)       (GstGLWindow *window);
 
   /*< private >*/
   gpointer _reserved[GST_PADDING];
@@ -213,6 +215,7 @@ void     gst_gl_window_send_mouse_event     (GstGLWindow * window,
                                              double posy);
 
 /* surfaces/rendering */
+void     gst_gl_window_queue_resize         (GstGLWindow *window);
 void     gst_gl_window_draw_unlocked        (GstGLWindow *window);
 void     gst_gl_window_draw                 (GstGLWindow *window);
 void     gst_gl_window_show                 (GstGLWindow *window);
@@ -228,6 +231,9 @@ gboolean gst_gl_window_set_render_rectangle   (GstGLWindow * window,
                                                gint width,
                                                gint height);
 
+/* subclass usage only */
+void     gst_gl_window_resize               (GstGLWindow *window, guint width, guint height);
+
 GstGLContext * gst_gl_window_get_context    (GstGLWindow *window);
 guintptr       gst_gl_window_get_display    (GstGLWindow *window);
 
index 592c03c..b34ad42 100644 (file)
@@ -315,6 +315,8 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
   window_egl->window.window_height = height;
 
   if (!window_egl->window.native) {
+    gst_gl_window_resize (GST_GL_WINDOW (window_egl), width, height);
+
     window_egl->window.native =
         wl_egl_window_create (window_egl->window.surface, width, height);
     if (window_egl->window.queue)
@@ -469,8 +471,7 @@ window_resize (GstGLWindowWaylandEGL * window_egl, guint width, guint height)
     wl_egl_window_resize (window_egl->window.native, width, height, 0, 0);
   }
 
-  if (window->resize)
-    window->resize (window->resize_data, width, height);
+  gst_gl_window_resize (window, width, height);
 
   window_egl->window.window_width = width;
   window_egl->window.window_height = height;
@@ -489,6 +490,13 @@ draw_cb (gpointer data)
   if (window_egl->window.subsurface)
     wl_subsurface_set_desync (window_egl->window.subsurface);
 
+  if (window->queue_resize) {
+    guint width, height;
+
+    gst_gl_window_get_surface_dimensions (window, &width, &height);
+    gst_gl_window_resize (window, width, height);
+  }
+
   if (window->draw)
     window->draw (window->draw_data);
 
index 29d97f2..a2ed3e6 100644 (file)
@@ -409,15 +409,16 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
     switch (uMsg) {
       case WM_SIZE:
-      {
-        if (window->resize) {
-          window->resize (window->resize_data, LOWORD (lParam),
-              HIWORD (lParam));
-        }
+        gst_gl_window_resize (window, LOWORD (lParam), HIWORD (lParam));
         break;
-      }
       case WM_PAINT:
       {
+        if (window->queue_resize) {
+          guint width, height;
+
+          gst_gl_window_get_surface_dimensions (window, &width, &height);
+          gst_gl_window_resize (window, width, height);
+        }
         if (window->draw) {
           PAINTSTRUCT ps;
           BeginPaint (hWnd, &ps);
@@ -440,6 +441,12 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
       case WM_CAPTURECHANGED:
       {
         GST_DEBUG ("WM_CAPTURECHANGED");
+        if (window->queue_resize) {
+          guint width, height;
+
+          gst_gl_window_get_surface_dimensions (window, &width, &height);
+          gst_gl_window_resize (window, width, height);
+        }
         if (window->draw)
           window->draw (window->draw_data);
         break;
index 20b327d..29c2aea 100644 (file)
@@ -80,8 +80,6 @@ gboolean gst_gl_window_x11_create_context (GstGLWindow * window,
     GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
 gboolean gst_gl_window_x11_open (GstGLWindow * window, GError ** error);
 void gst_gl_window_x11_close (GstGLWindow * window);
-static void gst_gl_window_x11_get_surface_dimensions (GstGLWindow * window,
-    guint * width, guint * height);
 void gst_gl_window_x11_handle_events (GstGLWindow * window,
     gboolean handle_events);
 
@@ -111,8 +109,6 @@ gst_gl_window_x11_class_init (GstGLWindowX11Class * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_x11_draw);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_x11_open);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_x11_close);
-  window_class->get_surface_dimensions =
-      GST_DEBUG_FUNCPTR (gst_gl_window_x11_get_surface_dimensions);
   window_class->handle_events =
       GST_DEBUG_FUNCPTR (gst_gl_window_x11_handle_events);
   window_class->set_preferred_size =
@@ -399,6 +395,13 @@ gst_gl_window_x11_draw_unlocked (GstGLWindow * window)
 
   if (gst_gl_window_is_running (GST_GL_WINDOW (window_x11))
       && window_x11->allow_extra_expose_events) {
+    if (window->queue_resize) {
+      guint width, height;
+
+      gst_gl_window_get_surface_dimensions (window, &width, &height);
+      gst_gl_window_resize (window, width, height);
+    }
+
     if (window->draw) {
       GstGLContext *context = gst_gl_window_get_context (window);
       GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
@@ -566,12 +569,8 @@ gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11)
       case CreateNotify:
       case ConfigureNotify:
       {
-        if (window->resize)
-          window->resize (window->resize_data, event.xconfigure.width,
-              event.xconfigure.height);
-
-        window_x11->current_width = event.xconfigure.width;
-        window_x11->current_height = event.xconfigure.height;
+        gst_gl_window_resize (window, event.xconfigure.width,
+            event.xconfigure.height);
         break;
       }
 
@@ -597,9 +596,6 @@ gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11)
 
           gst_object_unref (context);
         }
-
-        window_x11->current_width = event.xexpose.width;
-        window_x11->current_height = event.xexpose.height;
         break;
 
       case VisibilityNotify:
@@ -699,14 +695,3 @@ gst_gl_window_x11_get_display (GstGLWindow * window)
 
   return (guintptr) window_x11->device;
 }
-
-static void
-gst_gl_window_x11_get_surface_dimensions (GstGLWindow * window, guint * width,
-    guint * height)
-{
-  GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window);
-  if (width != NULL)
-    *width = window_x11->current_width;
-  if (height != NULL)
-    *height = window_x11->current_height;
-}
index db392b5..c16a637 100644 (file)
@@ -64,8 +64,6 @@ struct _GstGLWindowX11
   gint          depth;
   gint          device_width;
   gint          device_height;
-  gint          current_width;
-  gint          current_height;
   gint          connection;
   XVisualInfo  *visual_info;
   Window        parent_win;