summaryrefslogtreecommitdiff
path: root/gst-libs/gst/gl/win32
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2015-05-20 15:29:50 -0400
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2015-05-21 14:33:52 -0400
commite24bc348bd5e78688c9c0da4f81c58e76a5920e6 (patch)
tree6238ae8b850ffb0f0526fcb7bfc848f299043615 /gst-libs/gst/gl/win32
parentc9372ae33fc558b158800ba87c6d350bf584942f (diff)
downloadgstreamer-plugins-bad-e24bc348bd5e78688c9c0da4f81c58e76a5920e6.tar.gz
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
Diffstat (limited to 'gst-libs/gst/gl/win32')
-rw-r--r--gst-libs/gst/gl/win32/Makefile.am6
-rw-r--r--gst-libs/gst/gl/win32/gstglwindow_win32.c124
-rw-r--r--gst-libs/gst/gl/win32/gstglwindow_win32.h4
-rw-r--r--gst-libs/gst/gl/win32/win32_message_source.c83
-rw-r--r--gst-libs/gst/gl/win32/win32_message_source.h34
5 files changed, 197 insertions, 54 deletions
diff --git a/gst-libs/gst/gl/win32/Makefile.am b/gst-libs/gst/gl/win32/Makefile.am
index aaea0d7b3..80da958a5 100644
--- a/gst-libs/gst/gl/win32/Makefile.am
+++ b/gst-libs/gst/gl/win32/Makefile.am
@@ -3,10 +3,12 @@
noinst_LTLIBRARIES = libgstgl-win32.la
libgstgl_win32_la_SOURCES = \
- gstglwindow_win32.c
+ gstglwindow_win32.c \
+ win32_message_source.c
noinst_HEADERS = \
- gstglwindow_win32.h
+ gstglwindow_win32.h \
+ win32_message_source.h
if USE_WGL
libgstgl_win32_la_SOURCES += gstglcontext_wgl.c
diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.c b/gst-libs/gst/gl/win32/gstglwindow_win32.c
index 4191b0766..6ee70d04c 100644
--- a/gst-libs/gst/gl/win32/gstglwindow_win32.c
+++ b/gst-libs/gst/gl/win32/gstglwindow_win32.c
@@ -24,9 +24,9 @@
#endif
#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+2)
+#define WM_GST_GL_WINDOW_QUIT (WM_APP+1)
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
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_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
+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
gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
{
+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
g_type_class_add_private (klass, sizeof (GstGLWindowWin32Private));
+ obj_class->finalize = gst_gl_window_win32_finalize;
+
window_class->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);
@@ -90,6 +112,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
window_class->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->open = GST_DEBUG_FUNCPTR (gst_gl_window_win32_open);
+ window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_win32_close);
}
static void
@@ -97,6 +121,9 @@ gst_gl_window_win32_init (GstGLWindowWin32 * window)
{
window->priv = GST_GL_WINDOW_WIN32_GET_PRIVATE (window);
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 */
@@ -108,6 +135,37 @@ gst_gl_window_win32_new (void)
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
gst_gl_window_win32_create_window (GstGLWindowWin32 * window_win32,
GError ** error)
@@ -316,29 +374,8 @@ static void
gst_gl_window_win32_run (GstGLWindow * window)
{
GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window);
- gint bRet;
- MSG msg;
-
- GST_INFO ("begin message 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");
+ g_main_loop_run (window_win32->loop);
}
/* Thread safe */
@@ -389,29 +426,14 @@ gst_gl_window_win32_send_message_async (GstGLWindow * window,
GstGLMessage *message;
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);
- if (window_win32) {
- LRESULT res;
-
- message->callback = callback;
- message->data = data;
- message->destroy = destroy;
+ message->callback = callback;
+ message->data = data;
+ 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));
- }
+ g_main_context_invoke (window_win32->main_context, (GSourceFunc) _run_message,
+ message);
}
/* PRIVATE */
@@ -506,6 +528,12 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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");
@@ -513,14 +541,6 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
window->draw (window->draw_data);
break;
}
- case WM_GST_GL_WINDOW_CUSTOM:
- {
- if (!window_win32->is_closed) {
- GstGLMessage *message = (GstGLMessage *) wParam;
- _run_message (message);
- }
- break;
- }
case WM_ERASEBKGND:
return TRUE;
default:
diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.h b/gst-libs/gst/gl/win32/gstglwindow_win32.h
index c4416e197..76e1d9370 100644
--- a/gst-libs/gst/gl/win32/gstglwindow_win32.h
+++ b/gst-libs/gst/gl/win32/gstglwindow_win32.h
@@ -50,6 +50,10 @@ struct _GstGLWindowWin32 {
gboolean is_closed;
gboolean visible;
+ GSource *msg_source;
+ GMainContext *main_context;
+ GMainLoop *loop;
+
/*< private >*/
GstGLWindowWin32Private *priv;
diff --git a/gst-libs/gst/gl/win32/win32_message_source.c b/gst-libs/gst/gl/win32/win32_message_source.c
new file mode 100644
index 000000000..fd785f827
--- /dev/null
+++ b/gst-libs/gst/gl/win32/win32_message_source.c
@@ -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;
+}
diff --git a/gst-libs/gst/gl/win32/win32_message_source.h b/gst-libs/gst/gl/win32/win32_message_source.h
new file mode 100644
index 000000000..eef3eac4d
--- /dev/null
+++ b/gst-libs/gst/gl/win32/win32_message_source.h
@@ -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__ */