mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
gl: win32: fix crash when finalizing GstGLContext
gst_gl_context_finalize() is calling gst_gl_window_win32_quit() which was posting a message. But then window_proc takes window's context and get a NULL. Now that we've got a GMainLoop we can do like other backends and simply call g_main_loop_quit(). This also remove duplicated code to release the parent window and potential crash there because parent_proc could be NULL if we never created the internal window. That could happen for example if setting state to READY then setting a window_handle, and go back to NULL state. https://bugzilla.gnome.org/show_bug.cgi?id=749601
This commit is contained in:
parent
e1a827822e
commit
247697ce62
1 changed files with 39 additions and 65 deletions
|
@ -26,8 +26,6 @@
|
|||
#include "gstglwindow_win32.h"
|
||||
#include "win32_message_source.h"
|
||||
|
||||
#define WM_GST_GL_WINDOW_QUIT (WM_APP+1)
|
||||
|
||||
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||
|
@ -71,6 +69,7 @@ static void gst_gl_window_win32_send_message_async (GstGLWindow * window,
|
|||
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
|
||||
gboolean gst_gl_window_win32_open (GstGLWindow * window, GError ** error);
|
||||
void gst_gl_window_win32_close (GstGLWindow * window);
|
||||
static void release_parent_win_id (GstGLWindowWin32 * window_win32);
|
||||
|
||||
static void
|
||||
gst_gl_window_win32_finalize (GObject * object)
|
||||
|
@ -161,9 +160,21 @@ gst_gl_window_win32_close (GstGLWindow * window)
|
|||
{
|
||||
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||
|
||||
release_parent_win_id (window_win32);
|
||||
|
||||
if (window_win32->internal_win_id) {
|
||||
RemoveProp (window_win32->internal_win_id, "gl_window");
|
||||
if (!DestroyWindow (window_win32->internal_win_id))
|
||||
GST_WARNING ("failed to destroy window %" G_GUINTPTR_FORMAT
|
||||
", 0x%x", (guintptr) window_win32->internal_win_id,
|
||||
(unsigned int) GetLastError ());
|
||||
}
|
||||
|
||||
g_source_destroy (window_win32->msg_source);
|
||||
g_source_unref (window_win32->msg_source);
|
||||
window_win32->msg_source = NULL;
|
||||
|
||||
window_win32->is_closed = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -206,6 +217,28 @@ set_parent_win_id (GstGLWindowWin32 * window_win32)
|
|||
rect.bottom, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
release_parent_win_id (GstGLWindowWin32 * window_win32)
|
||||
{
|
||||
WNDPROC parent_proc;
|
||||
|
||||
if (!window_win32->parent_win_id)
|
||||
return;
|
||||
|
||||
parent_proc = GetProp (window_win32->parent_win_id, "gl_window_parent_proc");
|
||||
if (!parent_proc)
|
||||
return;
|
||||
|
||||
GST_DEBUG ("release parent %" G_GUINTPTR_FORMAT,
|
||||
(guintptr) window_win32->parent_win_id);
|
||||
|
||||
SetWindowLongPtr (window_win32->parent_win_id, GWLP_WNDPROC,
|
||||
(LONG_PTR) parent_proc);
|
||||
SetParent (window_win32->internal_win_id, NULL);
|
||||
|
||||
RemoveProp (window_win32->parent_win_id, "gl_window_parent_proc");
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_gl_window_win32_create_window (GstGLWindowWin32 * window_win32,
|
||||
GError ** error)
|
||||
|
@ -304,7 +337,6 @@ static void
|
|||
gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id)
|
||||
{
|
||||
GstGLWindowWin32 *window_win32;
|
||||
HWND parent_id;
|
||||
|
||||
window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||
|
||||
|
@ -313,27 +345,12 @@ gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id)
|
|||
return;
|
||||
}
|
||||
|
||||
/* retrieve parent if previously set */
|
||||
parent_id = window_win32->parent_win_id;
|
||||
|
||||
if (window_win32->visible) {
|
||||
ShowWindow (window_win32->internal_win_id, SW_HIDE);
|
||||
window_win32->visible = FALSE;
|
||||
}
|
||||
|
||||
if (parent_id) {
|
||||
WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
|
||||
|
||||
GST_DEBUG ("release parent %" G_GUINTPTR_FORMAT, (guintptr) parent_id);
|
||||
|
||||
g_return_if_fail (parent_proc);
|
||||
|
||||
SetWindowLongPtr (parent_id, GWLP_WNDPROC, (LONG_PTR) parent_proc);
|
||||
SetParent (window_win32->internal_win_id, NULL);
|
||||
|
||||
RemoveProp (parent_id, "gl_window_parent_proc");
|
||||
}
|
||||
|
||||
release_parent_win_id (window_win32);
|
||||
window_win32->parent_win_id = (HWND) id;
|
||||
set_parent_win_id (window_win32);
|
||||
}
|
||||
|
@ -398,18 +415,11 @@ gst_gl_window_win32_run (GstGLWindow * window)
|
|||
static void
|
||||
gst_gl_window_win32_quit (GstGLWindow * window)
|
||||
{
|
||||
GstGLWindowWin32 *window_win32;
|
||||
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||
|
||||
|
||||
window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||
window_win32->priv->thread = NULL;
|
||||
|
||||
if (window_win32 && window_win32->internal_win_id) {
|
||||
LRESULT res =
|
||||
PostMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_QUIT,
|
||||
(WPARAM) 0, (LPARAM) 0);
|
||||
GST_DEBUG ("end loop requested");
|
||||
g_return_if_fail (SUCCEEDED (res));
|
||||
}
|
||||
g_main_loop_quit (window_win32->loop);
|
||||
}
|
||||
|
||||
typedef struct _GstGLMessage
|
||||
|
@ -515,42 +525,6 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
window->close (window->close_data);
|
||||
break;
|
||||
}
|
||||
case WM_GST_GL_WINDOW_QUIT:
|
||||
{
|
||||
HWND parent_id = 0;
|
||||
|
||||
GST_TRACE ("WM_GST_GL_WINDOW_QUIT");
|
||||
|
||||
parent_id = window_win32->parent_win_id;
|
||||
if (parent_id) {
|
||||
WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
|
||||
|
||||
g_assert (parent_proc);
|
||||
|
||||
SetWindowLongPtr (parent_id, GWLP_WNDPROC, (LONG_PTR) parent_proc);
|
||||
SetParent (hWnd, NULL);
|
||||
|
||||
RemoveProp (parent_id, "gl_window_parent_proc");
|
||||
}
|
||||
|
||||
window_win32->is_closed = TRUE;
|
||||
RemoveProp (hWnd, "gl_window");
|
||||
|
||||
if (window_win32->internal_win_id) {
|
||||
if (!DestroyWindow (window_win32->internal_win_id))
|
||||
GST_WARNING ("failed to destroy window %" G_GUINTPTR_FORMAT
|
||||
", 0x%x", (guintptr) hWnd, (unsigned int) GetLastError ());
|
||||
}
|
||||
|
||||
PostQuitMessage (0);
|
||||
break;
|
||||
}
|
||||
case WM_QUIT:
|
||||
{
|
||||
if (window_win32->loop)
|
||||
g_main_loop_quit (window_win32->loop);
|
||||
break;
|
||||
}
|
||||
case WM_CAPTURECHANGED:
|
||||
{
|
||||
GST_DEBUG ("WM_CAPTURECHANGED");
|
||||
|
|
Loading…
Reference in a new issue