From 3addb6bbf4bffe20c41fd2599153a6ee846a4845 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 17 Sep 2015 17:06:37 +1000 Subject: [PATCH] glwindow: add API to request a resize event on the next draw - 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 --- .../gst/gl/android/gstglwindow_android_egl.c | 19 +++---- gst-libs/gst/gl/cocoa/gstglcaopengllayer.h | 2 + gst-libs/gst/gl/cocoa/gstglcaopengllayer.m | 3 +- gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 22 ++++++-- .../gl/dispmanx/gstglwindow_dispmanx_egl.c | 7 ++- gst-libs/gst/gl/eagl/gstglwindow_eagl.m | 5 +- gst-libs/gst/gl/gstglwindow.c | 56 ++++++++++++++----- gst-libs/gst/gl/gstglwindow.h | 8 ++- .../gst/gl/wayland/gstglwindow_wayland_egl.c | 12 +++- gst-libs/gst/gl/win32/gstglwindow_win32.c | 19 +++++-- gst-libs/gst/gl/x11/gstglwindow_x11.c | 33 +++-------- gst-libs/gst/gl/x11/gstglwindow_x11.h | 2 - 12 files changed, 119 insertions(+), 69 deletions(-) diff --git a/gst-libs/gst/gl/android/gstglwindow_android_egl.c b/gst-libs/gst/gl/android/gstglwindow_android_egl.c index 4e57f4c90e..983775613d 100644 --- a/gst-libs/gst/gl/android/gstglwindow_android_egl.c +++ b/gst-libs/gst/gl/android/gstglwindow_android_egl.c @@ -108,18 +108,17 @@ draw_cb (gpointer data) if (context_egl->egl_surface) { gint width, height; + gint 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) - && (width != window_egl->window_width + 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); } } diff --git a/gst-libs/gst/gl/cocoa/gstglcaopengllayer.h b/gst-libs/gst/gl/cocoa/gstglcaopengllayer.h index e3958f8efa..2ed87b7b44 100644 --- a/gst-libs/gst/gl/cocoa/gstglcaopengllayer.h +++ b/gst-libs/gst/gl/cocoa/gstglcaopengllayer.h @@ -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 diff --git a/gst-libs/gst/gl/cocoa/gstglcaopengllayer.m b/gst-libs/gst/gl/cocoa/gstglcaopengllayer.m index 9362bca740..a48709fbef 100644 --- a/gst-libs/gst/gl/cocoa/gstglcaopengllayer.m +++ b/gst-libs/gst/gl/cocoa/gstglcaopengllayer.m @@ -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]; diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 975fe5a902..9c37e6c538 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -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; } @@ -266,6 +268,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) { @@ -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, diff --git a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c index 99fd7414b9..26e6df7a94 100644 --- a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c +++ b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c @@ -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; diff --git a/gst-libs/gst/gl/eagl/gstglwindow_eagl.m b/gst-libs/gst/gl/eagl/gstglwindow_eagl.m index 9d37b14ad8..dfd889fa82 100644 --- a/gst-libs/gst/gl/eagl/gstglwindow_eagl.m +++ b/gst-libs/gst/gl/eagl/gstglwindow_eagl.m @@ -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); } } diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index a69b10d10b..05d0697753 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -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); @@ -1007,12 +1020,6 @@ gst_gl_dummy_window_get_display (GstGLWindow * window) return 0; } -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) { @@ -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; +} diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index b7c5a76202..e4781c7b99 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -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); diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index 592c03ca58..b34ad4239b 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -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); diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.c b/gst-libs/gst/gl/win32/gstglwindow_win32.c index 29d97f23e2..a2ed3e6772 100644 --- a/gst-libs/gst/gl/win32/gstglwindow_win32.c +++ b/gst-libs/gst/gl/win32/gstglwindow_win32.c @@ -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; diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.c b/gst-libs/gst/gl/x11/gstglwindow_x11.c index 20b327de50..29c2aead4d 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.c +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.c @@ -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; -} diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.h b/gst-libs/gst/gl/x11/gstglwindow_x11.h index db392b534c..c16a6375d2 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.h +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.h @@ -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;