From 045137d34065f5969d5edad4724152ad7a569b3e Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 11 Mar 2019 16:59:36 +0530 Subject: [PATCH] glwindow/win32: Don't use condition variables for message synchronization Using a single condition variable for synchronization across all GL messages is very slow on Windows and uses up to 20% CPU usage in some workloads due to lock contention and false broadcasts. Using per-message event handles reduces the CPU usage to negligible amounts despite having to allocate a new event handle for each message. --- gst-libs/gst/gl/win32/gstglwindow_win32.c | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.c b/gst-libs/gst/gl/win32/gstglwindow_win32.c index 67fc0b6bf3..96280f92b9 100644 --- a/gst-libs/gst/gl/win32/gstglwindow_win32.c +++ b/gst-libs/gst/gl/win32/gstglwindow_win32.c @@ -61,6 +61,8 @@ static void gst_gl_window_win32_draw (GstGLWindow * window); 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_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data); static void gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) @@ -77,6 +79,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) 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); + window_class->send_message = + GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message); } static void @@ -500,3 +504,37 @@ sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return CallWindowProc (window_parent_proc, hWnd, uMsg, wParam, lParam); } + +typedef struct _GstGLWin32SyncMessage +{ + GstGLWindowCB callback; + gpointer data; + + HANDLE *event; +} GstGLWin32SyncMessage; + +static void +_run_message_sync (GstGLWin32SyncMessage * message) +{ + if (message->callback) + message->callback (message->data); + + SetEvent (message->event); +} + +void +gst_gl_window_win32_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data) +{ + GstGLWin32SyncMessage message; + + message.callback = callback; + message.data = data; + message.event = CreateEvent (NULL, FALSE, FALSE, NULL); + + gst_gl_window_send_message_async (window, (GstGLWindowCB) _run_message_sync, + &message, NULL); + + WaitForSingleObject (message.event, INFINITE); + CloseHandle (message.event); +}