mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
gl: win32: use a GMainContext to dispatch win32 messages
gst_gl_window_win32_send_message_async() could be called before the internal window is created so we cannot use PostMessage there. x11 and wayland backends both create a custom GSource for this, so there is no reason to not do that for win32. https://bugzilla.gnome.org/show_bug.cgi?id=749601
This commit is contained in:
parent
95b08b75ba
commit
886ea15c52
5 changed files with 197 additions and 54 deletions
|
@ -3,10 +3,12 @@
|
||||||
noinst_LTLIBRARIES = libgstgl-win32.la
|
noinst_LTLIBRARIES = libgstgl-win32.la
|
||||||
|
|
||||||
libgstgl_win32_la_SOURCES = \
|
libgstgl_win32_la_SOURCES = \
|
||||||
gstglwindow_win32.c
|
gstglwindow_win32.c \
|
||||||
|
win32_message_source.c
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
gstglwindow_win32.h
|
gstglwindow_win32.h \
|
||||||
|
win32_message_source.h
|
||||||
|
|
||||||
if USE_WGL
|
if USE_WGL
|
||||||
libgstgl_win32_la_SOURCES += gstglcontext_wgl.c
|
libgstgl_win32_la_SOURCES += gstglcontext_wgl.c
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "gstglwindow_win32.h"
|
#include "gstglwindow_win32.h"
|
||||||
|
#include "win32_message_source.h"
|
||||||
|
|
||||||
#define WM_GST_GL_WINDOW_CUSTOM (WM_APP+1)
|
#define WM_GST_GL_WINDOW_QUIT (WM_APP+1)
|
||||||
#define WM_GST_GL_WINDOW_QUIT (WM_APP+2)
|
|
||||||
|
|
||||||
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
|
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||||
LPARAM lParam);
|
LPARAM lParam);
|
||||||
|
@ -69,14 +69,36 @@ static void gst_gl_window_win32_run (GstGLWindow * window);
|
||||||
static void gst_gl_window_win32_quit (GstGLWindow * window);
|
static void gst_gl_window_win32_quit (GstGLWindow * window);
|
||||||
static void gst_gl_window_win32_send_message_async (GstGLWindow * window,
|
static void gst_gl_window_win32_send_message_async (GstGLWindow * window,
|
||||||
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
|
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
|
||||||
|
gst_gl_window_win32_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (object);
|
||||||
|
|
||||||
|
if (window_win32->loop) {
|
||||||
|
g_main_loop_unref (window_win32->loop);
|
||||||
|
window_win32->loop = NULL;
|
||||||
|
}
|
||||||
|
if (window_win32->main_context) {
|
||||||
|
g_main_context_unref (window_win32->main_context);
|
||||||
|
window_win32->main_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
|
gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *obj_class = G_OBJECT_CLASS (klass);
|
||||||
GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
|
GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GstGLWindowWin32Private));
|
g_type_class_add_private (klass, sizeof (GstGLWindowWin32Private));
|
||||||
|
|
||||||
|
obj_class->finalize = gst_gl_window_win32_finalize;
|
||||||
|
|
||||||
window_class->set_window_handle =
|
window_class->set_window_handle =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_window_win32_set_window_handle);
|
GST_DEBUG_FUNCPTR (gst_gl_window_win32_set_window_handle);
|
||||||
window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_window_win32_draw);
|
window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_window_win32_draw);
|
||||||
|
@ -90,6 +112,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
|
||||||
window_class->set_preferred_size =
|
window_class->set_preferred_size =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_window_win32_set_preferred_size);
|
GST_DEBUG_FUNCPTR (gst_gl_window_win32_set_preferred_size);
|
||||||
window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_win32_show);
|
window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_win32_show);
|
||||||
|
window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_win32_open);
|
||||||
|
window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_win32_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -97,6 +121,9 @@ gst_gl_window_win32_init (GstGLWindowWin32 * window)
|
||||||
{
|
{
|
||||||
window->priv = GST_GL_WINDOW_WIN32_GET_PRIVATE (window);
|
window->priv = GST_GL_WINDOW_WIN32_GET_PRIVATE (window);
|
||||||
window->priv->thread = NULL;
|
window->priv->thread = NULL;
|
||||||
|
|
||||||
|
window->main_context = g_main_context_new ();
|
||||||
|
window->loop = g_main_loop_new (window->main_context, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called in the gl thread */
|
/* Must be called in the gl thread */
|
||||||
|
@ -108,6 +135,37 @@ gst_gl_window_win32_new (void)
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
msg_cb (GstGLWindowWin32 * window_win32, MSG * msg, gpointer user_data)
|
||||||
|
{
|
||||||
|
GST_TRACE ("handle message");
|
||||||
|
TranslateMessage (msg);
|
||||||
|
DispatchMessage (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_gl_window_win32_open (GstGLWindow * window, GError ** error)
|
||||||
|
{
|
||||||
|
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||||
|
|
||||||
|
window_win32->msg_source = win32_message_source_new (window_win32);
|
||||||
|
g_source_set_callback (window_win32->msg_source, (GSourceFunc) msg_cb,
|
||||||
|
NULL, NULL);
|
||||||
|
g_source_attach (window_win32->msg_source, window_win32->main_context);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_gl_window_win32_close (GstGLWindow * window)
|
||||||
|
{
|
||||||
|
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||||
|
|
||||||
|
g_source_destroy (window_win32->msg_source);
|
||||||
|
g_source_unref (window_win32->msg_source);
|
||||||
|
window_win32->msg_source = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_gl_window_win32_create_window (GstGLWindowWin32 * window_win32,
|
gst_gl_window_win32_create_window (GstGLWindowWin32 * window_win32,
|
||||||
GError ** error)
|
GError ** error)
|
||||||
|
@ -316,29 +374,8 @@ static void
|
||||||
gst_gl_window_win32_run (GstGLWindow * window)
|
gst_gl_window_win32_run (GstGLWindow * window)
|
||||||
{
|
{
|
||||||
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
|
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||||
gint bRet;
|
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
GST_INFO ("begin message loop");
|
g_main_loop_run (window_win32->loop);
|
||||||
|
|
||||||
window_win32->priv->thread = g_thread_self ();
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
bRet = GetMessage (&msg, NULL, 0, 0);
|
|
||||||
if (bRet == 0)
|
|
||||||
break;
|
|
||||||
else if (bRet == -1) {
|
|
||||||
GST_WARNING ("Failed to get message 0x%x",
|
|
||||||
(unsigned int) GetLastError ());
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
GST_TRACE ("handle message");
|
|
||||||
TranslateMessage (&msg);
|
|
||||||
DispatchMessage (&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_INFO ("end message loop");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thread safe */
|
/* Thread safe */
|
||||||
|
@ -389,29 +426,14 @@ gst_gl_window_win32_send_message_async (GstGLWindow * window,
|
||||||
GstGLMessage *message;
|
GstGLMessage *message;
|
||||||
|
|
||||||
window_win32 = GST_GL_WINDOW_WIN32 (window);
|
window_win32 = GST_GL_WINDOW_WIN32 (window);
|
||||||
|
|
||||||
if (window_win32->priv->thread == g_thread_self ()) {
|
|
||||||
/* re-entracy... */
|
|
||||||
if (callback)
|
|
||||||
callback (data);
|
|
||||||
if (destroy)
|
|
||||||
destroy (data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
message = g_slice_new (GstGLMessage);
|
message = g_slice_new (GstGLMessage);
|
||||||
|
|
||||||
if (window_win32) {
|
message->callback = callback;
|
||||||
LRESULT res;
|
message->data = data;
|
||||||
|
message->destroy = destroy;
|
||||||
|
|
||||||
message->callback = callback;
|
g_main_context_invoke (window_win32->main_context, (GSourceFunc) _run_message,
|
||||||
message->data = data;
|
message);
|
||||||
message->destroy = destroy;
|
|
||||||
|
|
||||||
res = PostMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM,
|
|
||||||
(WPARAM) message, (LPARAM) NULL);
|
|
||||||
g_return_if_fail (SUCCEEDED (res));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PRIVATE */
|
/* PRIVATE */
|
||||||
|
@ -506,6 +528,12 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
PostQuitMessage (0);
|
PostQuitMessage (0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WM_QUIT:
|
||||||
|
{
|
||||||
|
if (window_win32->loop)
|
||||||
|
g_main_loop_quit (window_win32->loop);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case WM_CAPTURECHANGED:
|
case WM_CAPTURECHANGED:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("WM_CAPTURECHANGED");
|
GST_DEBUG ("WM_CAPTURECHANGED");
|
||||||
|
@ -513,14 +541,6 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
window->draw (window->draw_data);
|
window->draw (window->draw_data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_GST_GL_WINDOW_CUSTOM:
|
|
||||||
{
|
|
||||||
if (!window_win32->is_closed) {
|
|
||||||
GstGLMessage *message = (GstGLMessage *) wParam;
|
|
||||||
_run_message (message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WM_ERASEBKGND:
|
case WM_ERASEBKGND:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -50,6 +50,10 @@ struct _GstGLWindowWin32 {
|
||||||
gboolean is_closed;
|
gboolean is_closed;
|
||||||
gboolean visible;
|
gboolean visible;
|
||||||
|
|
||||||
|
GSource *msg_source;
|
||||||
|
GMainContext *main_context;
|
||||||
|
GMainLoop *loop;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
GstGLWindowWin32Private *priv;
|
GstGLWindowWin32Private *priv;
|
||||||
|
|
||||||
|
|
83
gst-libs/gst/gl/win32/win32_message_source.c
Normal file
83
gst-libs/gst/gl/win32/win32_message_source.c
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
|
||||||
|
* Copyright (C) 2015 Collabora ltd.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "win32_message_source.h"
|
||||||
|
|
||||||
|
typedef struct _Win32MessageSource
|
||||||
|
{
|
||||||
|
GSource source;
|
||||||
|
GPollFD pfd;
|
||||||
|
GstGLWindowWin32 *window;
|
||||||
|
} Win32MessageSource;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
win32_message_source_check (GSource * base)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
return PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
win32_message_source_dispatch (GSource * base, GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
Win32MessageSource *source = (Win32MessageSource *) base;
|
||||||
|
Win32MessageSourceFunc func = (Win32MessageSourceFunc) callback;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
if (!PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
|
if (func)
|
||||||
|
func (source->window, &msg, user_data);
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs win32_message_source_funcs = {
|
||||||
|
NULL,
|
||||||
|
win32_message_source_check,
|
||||||
|
win32_message_source_dispatch,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
GSource *
|
||||||
|
win32_message_source_new (GstGLWindowWin32 * window_win32)
|
||||||
|
{
|
||||||
|
Win32MessageSource *source;
|
||||||
|
|
||||||
|
source = (Win32MessageSource *)
|
||||||
|
g_source_new (&win32_message_source_funcs, sizeof (Win32MessageSource));
|
||||||
|
source->window = window_win32;
|
||||||
|
source->pfd.fd = G_WIN32_MSG_HANDLE;
|
||||||
|
source->pfd.events = G_IO_IN;
|
||||||
|
g_source_add_poll (&source->source, &source->pfd);
|
||||||
|
|
||||||
|
return &source->source;
|
||||||
|
}
|
34
gst-libs/gst/gl/win32/win32_message_source.h
Normal file
34
gst-libs/gst/gl/win32/win32_message_source.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
|
||||||
|
* Copyright (C) 2015 Collabora ltd.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WIN32_MESSAGE_SOURCE_H__
|
||||||
|
#define __WIN32_MESSAGE_SOURCE_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gstglwindow_win32.h"
|
||||||
|
|
||||||
|
typedef void (*Win32MessageSourceFunc) (GstGLWindowWin32 *window_win32,
|
||||||
|
MSG *msg, gpointer user_data);
|
||||||
|
|
||||||
|
GSource *
|
||||||
|
win32_message_source_new (GstGLWindowWin32 *window_win32);
|
||||||
|
|
||||||
|
#endif /* __WIN32_MESSAGE_SOURCE_H__ */
|
Loading…
Reference in a new issue