• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer
3  * Copyright (C) 2019 Nirbheek Chauhan <nirbheek@centricular.com>
4  * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <gst/gl/gstglcontext.h>
26 #include <gst/gl/egl/gstglcontext_egl.h>
27 
28 #include "gstglwindow_winrt_egl.h"
29 #include "../gstglwindow_private.h"
30 
31 /* workaround for GetCurrentTime collision */
32 #ifdef GetCurrentTime
33 #undef GetCurrentTime
34 #endif
35 #include <windows.ui.xaml.h>
36 #include <windows.ui.xaml.media.dxinterop.h>
37 #include <windows.applicationmodel.core.h>
38 #include <windows.graphics.display.h>
39 #include <wrl.h>
40 #include <wrl/wrappers/corewrappers.h>
41 
42 using namespace Microsoft::WRL;
43 using namespace Microsoft::WRL::Wrappers;
44 using namespace ABI::Windows::UI;
45 using namespace ABI::Windows::Foundation;
46 using namespace ABI::Windows::Foundation::Collections;
47 using namespace ABI::Windows::Graphics;
48 
49 #define GST_CAT_DEFAULT gst_gl_window_debug
50 
51 /* timeout to wait busy UI thread, 15 seconds */
52 /* XXX: If UI is not responsible in this amount of time, that means
53  * there were something wrong situation at the application side.
54  * Note that ANGLE uses 10 seconds timeout value, so even if a timeout happens
55  * on our side, it would be a timeout condition of ANGLE as well.
56  */
57 #define DEFAULT_ASYNC_TIMEOUT (15 * 1000)
58 
59 static void gst_gl_window_winrt_egl_on_resize (GstGLWindow * window,
60     guint width, guint height);
61 
62 typedef enum
63 {
64   GST_GL_WINDOW_WINRT_NATIVE_TYPE_NONE = 0,
65   GST_GL_WINDOW_WINRT_NATIVE_TYPE_CORE_WINDOW,
66   GST_GL_WINDOW_WINRT_NATIVE_TYPE_SWAP_CHAIN_PANEL,
67 } GstGLWindowWinRTNativeType;
68 
69 template <typename CB>
70 static HRESULT
run_async(const ComPtr<Core::ICoreDispatcher> & dispatcher,DWORD timeout,CB && cb)71 run_async (const ComPtr<Core::ICoreDispatcher> &dispatcher, DWORD timeout,
72     CB &&cb)
73 {
74   ComPtr<IAsyncAction> async_action;
75   HRESULT hr;
76   HRESULT async_hr;
77   boolean can_now;
78   DWORD wait_ret;
79 
80   hr = dispatcher->get_HasThreadAccess (&can_now);
81 
82   if (FAILED (hr))
83     return hr;
84 
85   if (can_now)
86     return cb ();
87 
88   Event event (CreateEventEx (NULL, NULL, CREATE_EVENT_MANUAL_RESET,
89       EVENT_ALL_ACCESS));
90 
91   if (!event.IsValid())
92     return E_FAIL;
93 
94   auto handler =
95       Callback<Implements<RuntimeClassFlags<ClassicCom>,
96           Core::IDispatchedHandler, FtmBase>>([&async_hr, &cb, &event] {
97         async_hr = cb ();
98         SetEvent (event.Get ());
99         return S_OK;
100       });
101 
102   hr = dispatcher->RunAsync (Core::CoreDispatcherPriority_Normal,
103       handler.Get (), &async_action);
104 
105   if (FAILED (hr))
106     return hr;
107 
108   wait_ret = WaitForSingleObjectEx (event.Get (), timeout, true);
109   if (wait_ret != WAIT_OBJECT_0)
110     return E_FAIL;
111 
112   return async_hr;
113 }
114 
115 /* ICoreWindow resize event handler */
116 typedef ABI::Windows::Foundation::
117     __FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t
118         IWindowSizeChangedEventHandler;
119 
120 static float
get_logical_dpi(void)121 get_logical_dpi (void)
122 {
123   ComPtr<Display::IDisplayPropertiesStatics> properties;
124   HRESULT hr;
125   HStringReference str_ref =
126       HStringReference (RuntimeClass_Windows_Graphics_Display_DisplayProperties);
127 
128   hr = GetActivationFactory (str_ref.Get(), properties.GetAddressOf());
129 
130   if (SUCCEEDED (hr)) {
131     float dpi = 96.0f;
132 
133     hr = properties->get_LogicalDpi (&dpi);
134     if (SUCCEEDED (hr))
135       return dpi;
136   }
137 
138   return 96.0f;
139 }
140 
dip_to_pixel(float dip,float logical_dpi)141 static inline float dip_to_pixel (float dip, float logical_dpi)
142 {
143   /* https://docs.microsoft.com/en-us/windows/win32/learnwin32/dpi-and-device-independent-pixels */
144   return dip * logical_dpi / 96.0f;
145 }
146 
147 class CoreResizeHandler
148     : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
149                           IWindowSizeChangedEventHandler>
150 {
151 public:
CoreResizeHandler()152   CoreResizeHandler () {}
RuntimeClassInitialize(GstGLWindow * window)153   HRESULT RuntimeClassInitialize (GstGLWindow * window)
154   {
155     if (!window)
156       return E_INVALIDARG;
157 
158     listener_ = window;
159     return S_OK;
160   }
161 
IFACEMETHOD(Invoke)162   IFACEMETHOD(Invoke)
163   (Core::ICoreWindow * sender, Core::IWindowSizeChangedEventArgs * args)
164   {
165     Size new_size;
166     HRESULT hr;
167 
168     if (!listener_)
169       return S_OK;
170 
171     hr = args->get_Size(&new_size);
172     if (SUCCEEDED (hr)) {
173       gint width, height;
174       float dpi;
175 
176       dpi = get_logical_dpi ();
177 
178       width = (guint) dip_to_pixel (new_size.Width, dpi);
179       height = (guint) dip_to_pixel (new_size.Height, dpi);
180 
181       gst_gl_window_winrt_egl_on_resize (listener_, width, height);
182     }
183 
184     return S_OK;
185   }
186 
187 private:
188   GstGLWindow * listener_;
189 };
190 
191 class PanelResizeHandler
192     : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
193         Xaml::ISizeChangedEventHandler>
194 {
195 public:
PanelResizeHandler()196   PanelResizeHandler () {}
RuntimeClassInitialize(GstGLWindow * window)197   HRESULT RuntimeClassInitialize (GstGLWindow * window)
198   {
199     if (!window)
200       return E_INVALIDARG;
201 
202     listener_ = window;
203     return S_OK;
204   }
205 
IFACEMETHOD(Invoke)206   IFACEMETHOD(Invoke)
207   (IInspectable * sender, Xaml::ISizeChangedEventArgs * args)
208   {
209     Size new_size;
210     HRESULT hr;
211 
212     if (!listener_)
213       return S_OK;
214 
215     hr = args->get_NewSize(&new_size);
216     if (SUCCEEDED(hr)) {
217       gst_gl_window_winrt_egl_on_resize (listener_,
218           (guint) new_size.Width, (guint) new_size.Height);
219     }
220 
221     return S_OK;
222   }
223 
224 private:
225   GstGLWindow * listener_;
226 };
227 
228 class GstGLWindowWinRTEGLResizeHandler
229 {
230 public:
GstGLWindowWinRTEGLResizeHandler(IInspectable * native_handle,GstGLWindow * listener)231   GstGLWindowWinRTEGLResizeHandler(IInspectable * native_handle,
232       GstGLWindow * listener)
233     : native_type_ (GST_GL_WINDOW_WINRT_NATIVE_TYPE_NONE)
234     , isValid_ (false)
235   {
236     ComPtr<IInspectable> window;
237     HRESULT hr = E_FAIL;
238 
239     if (!native_handle) {
240       GST_WARNING ("Null handler");
241       return;
242     }
243 
244     window = native_handle;
245     if (SUCCEEDED (window.As (&core_window_))) {
246       GST_INFO ("Valid ICoreWindow");
247       native_type_ = GST_GL_WINDOW_WINRT_NATIVE_TYPE_CORE_WINDOW;
248       core_window_->get_Dispatcher (&dispatcher_);
249     } else if (SUCCEEDED (window.As (&panel_))) {
250       ComPtr<Xaml::IDependencyObject> dependency_obj;
251 
252       GST_INFO ("Valid ISwapChainPanel");
253       native_type_ = GST_GL_WINDOW_WINRT_NATIVE_TYPE_SWAP_CHAIN_PANEL;
254       hr = panel_.As (&dependency_obj);
255       if (FAILED (hr)) {
256         GST_WARNING ("Couldn't get IDependencyObject interface");
257         return;
258       }
259 
260       dependency_obj->get_Dispatcher (&dispatcher_);
261     } else {
262       GST_ERROR ("Invalid window handle");
263       return;
264     }
265 
266     if (!dispatcher_) {
267       GST_WARNING ("ICoreDispatcher is unavailable");
268       return;
269     }
270 
271     switch (native_type_) {
272       case GST_GL_WINDOW_WINRT_NATIVE_TYPE_CORE_WINDOW:
273         if (!registerSizeChangedHandlerForCoreWindow (listener)) {
274           GST_WARNING
275               ("Couldn't install size changed event handler for corewindow");
276           return;
277         }
278         break;
279       case GST_GL_WINDOW_WINRT_NATIVE_TYPE_SWAP_CHAIN_PANEL:
280         if (!registerSizeChangedHandlerForSwapChainPanel (listener)) {
281           GST_WARNING
282               ("Couldn't install size changed event handler for swapchainpanel");
283           return;
284         }
285         break;
286       default:
287         g_assert_not_reached ();
288         return;
289     }
290 
291     isValid_ = true;
292   }
293 
~GstGLWindowWinRTEGLResizeHandler()294   ~GstGLWindowWinRTEGLResizeHandler()
295   {
296     if (!isValid_ || !dispatcher_)
297       return;
298 
299     switch (native_type_) {
300       case GST_GL_WINDOW_WINRT_NATIVE_TYPE_CORE_WINDOW:
301         unregisterSizeChangedHandlerForCoreWindow ();
302         break;
303       case GST_GL_WINDOW_WINRT_NATIVE_TYPE_SWAP_CHAIN_PANEL:
304         unregisterSizeChangedHandlerForSwapChainPanel ();
305         break;
306       default:
307         g_assert_not_reached ();
308         return;
309     }
310   }
311 
312   bool
IsValid(void)313   IsValid (void)
314   {
315     return isValid_;
316   }
317 
318   bool
GetWindowSize(guint * width,guint * height)319   GetWindowSize (guint * width, guint * height)
320   {
321     bool ret = true;
322 
323     if (!isValid_)
324       return false;
325 
326     switch (native_type_) {
327       case GST_GL_WINDOW_WINRT_NATIVE_TYPE_CORE_WINDOW:
328         return getWindowSizeForCoreWindow (width, height);
329       case GST_GL_WINDOW_WINRT_NATIVE_TYPE_SWAP_CHAIN_PANEL:
330         return getWindowSizeForSwapChainPanel (width, height);
331       default:
332         g_assert_not_reached ();
333         break;
334     }
335 
336     return false;
337   }
338 
339   HRESULT
GetHasThreadAccess(bool & has_access)340   GetHasThreadAccess (bool &has_access)
341   {
342     HRESULT hr;
343     boolean val;
344 
345     if (!isValid_ || !dispatcher_)
346       return E_FAIL;
347 
348     hr = dispatcher_->get_HasThreadAccess (&val);
349     if (FAILED (hr))
350       return hr;
351 
352     if (val)
353       has_access = true;
354     else
355       has_access = false;
356 
357     return hr;
358   }
359 
360 private:
361   bool
registerSizeChangedHandlerForCoreWindow(GstGLWindow * window)362   registerSizeChangedHandlerForCoreWindow (GstGLWindow * window)
363   {
364     ComPtr<IWindowSizeChangedEventHandler> resize_handler;
365     HRESULT hr;
366 
367     hr = MakeAndInitialize<CoreResizeHandler>(&resize_handler, window);
368     if (FAILED (hr)) {
369       GST_WARNING ("Couldn't creat resize handler object");
370       return false;
371     }
372 
373     hr = run_async (dispatcher_, DEFAULT_ASYNC_TIMEOUT,
374         [this, resize_handler] {
375           return core_window_->add_SizeChanged (resize_handler.Get(),
376               &event_token_);
377         });
378 
379     if (FAILED (hr)) {
380       GST_WARNING ("Couldn't install resize handler");
381       return false;
382     }
383 
384     return true;
385   }
386 
387   bool
registerSizeChangedHandlerForSwapChainPanel(GstGLWindow * window)388   registerSizeChangedHandlerForSwapChainPanel (GstGLWindow * window)
389   {
390     ComPtr<Xaml::ISizeChangedEventHandler> resize_handler;
391     ComPtr<Xaml::IFrameworkElement> framework;
392     HRESULT hr;
393 
394     hr = MakeAndInitialize<PanelResizeHandler>(&resize_handler, window);
395     if (FAILED (hr)) {
396       GST_WARNING ("Couldn't creat resize handler object");
397       return false;
398     }
399 
400     hr = panel_.As (&framework);
401     if (FAILED (hr)) {
402       GST_WARNING ("Couldn't get IFrameworkElement interface");
403       return false;
404     }
405 
406     hr = run_async (dispatcher_, DEFAULT_ASYNC_TIMEOUT,
407       [this, framework, resize_handler] {
408         return framework->add_SizeChanged (resize_handler.Get(),
409             &event_token_);
410       });
411 
412     if (FAILED (hr)) {
413       GST_WARNING ("Couldn't install resize handler");
414       return false;
415     }
416 
417     return true;
418   }
419 
420   void
unregisterSizeChangedHandlerForCoreWindow(void)421   unregisterSizeChangedHandlerForCoreWindow (void)
422   {
423     run_async (dispatcher_, DEFAULT_ASYNC_TIMEOUT,
424         [this] {
425           core_window_->remove_SizeChanged(event_token_);
426           return S_OK;
427         });
428   }
429 
430   void
unregisterSizeChangedHandlerForSwapChainPanel(void)431   unregisterSizeChangedHandlerForSwapChainPanel (void)
432   {
433     ComPtr<Xaml::IFrameworkElement> framework;
434     HRESULT hr;
435 
436     hr = panel_.As (&framework);
437     if (SUCCEEDED (hr)) {
438       run_async (dispatcher_, DEFAULT_ASYNC_TIMEOUT,
439           [this, framework] {
440             return framework->remove_SizeChanged (event_token_);
441           });
442     }
443   }
444 
445   bool
getWindowSizeForCoreWindow(guint * width,guint * height)446   getWindowSizeForCoreWindow (guint * width, guint * height)
447   {
448     HRESULT hr;
449 
450     hr = run_async (dispatcher_, DEFAULT_ASYNC_TIMEOUT,
451       [this, width, height] {
452         HRESULT async_hr;
453         Rect bounds;
454 
455         async_hr = core_window_->get_Bounds (&bounds);
456         if (SUCCEEDED (async_hr)) {
457           float dpi;
458 
459           dpi = get_logical_dpi ();
460 
461           *width = (guint) dip_to_pixel (bounds.Width, dpi);
462           *height = (guint) dip_to_pixel (bounds.Height, dpi);
463         }
464 
465         return async_hr;
466       });
467 
468     return SUCCEEDED (hr);
469   }
470 
471   bool
getWindowSizeForSwapChainPanel(guint * width,guint * height)472   getWindowSizeForSwapChainPanel (guint * width, guint * height)
473   {
474     HRESULT hr;
475     ComPtr<Xaml::IUIElement> ui;
476 
477     hr = panel_.As (&ui);
478     if (FAILED (hr))
479       return false;
480 
481     hr = run_async (dispatcher_, DEFAULT_ASYNC_TIMEOUT,
482         [ui, width, height] {
483           Size size;
484           HRESULT async_hr;
485 
486           async_hr = ui->get_RenderSize (&size);
487           if (SUCCEEDED (async_hr)) {
488             *width = (guint) size.Width;
489             *height = (guint) size.Height;
490           }
491 
492           return async_hr;
493         });
494 
495     return SUCCEEDED (hr);
496   }
497 
498 private:
499   GstGLWindowWinRTNativeType native_type_;
500   ComPtr<Core::ICoreDispatcher> dispatcher_;
501 
502   ComPtr<Core::ICoreWindow> core_window_;
503   ComPtr<Xaml::Controls::ISwapChainPanel> panel_;
504 
505   EventRegistrationToken event_token_;
506   bool isValid_;
507 };
508 
509 struct _GstGLWindowWinRTEGLPrivate
510 {
511   GstGLWindowWinRTEGLResizeHandler *resize_handler;
512   guint surface_width;
513   guint surface_height;
514   GMutex event_lock;
515 };
516 
517 #define gst_gl_window_winrt_egl_parent_class parent_class
518 G_DEFINE_TYPE_WITH_PRIVATE (GstGLWindowWinRTEGL, gst_gl_window_winrt_egl,
519     GST_TYPE_GL_WINDOW);
520 
521 static void gst_gl_window_winrt_egl_dispose (GObject * object);
522 static void gst_gl_window_winrt_egl_finalize (GObject * object);
523 static guintptr gst_gl_window_winrt_egl_get_display (GstGLWindow * window);
524 static guintptr gst_gl_window_winrt_egl_get_window_handle (GstGLWindow *
525     window);
526 static void gst_gl_window_winrt_egl_set_window_handle (GstGLWindow * window,
527     guintptr handle);
528 static void gst_gl_window_winrt_egl_show (GstGLWindow * window);
529 static void gst_gl_window_winrt_egl_quit (GstGLWindow * window);
530 
531 static void
gst_gl_window_winrt_egl_class_init(GstGLWindowWinRTEGLClass * klass)532 gst_gl_window_winrt_egl_class_init (GstGLWindowWinRTEGLClass * klass)
533 {
534   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
535   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
536 
537   gobject_class->dispose = gst_gl_window_winrt_egl_dispose;
538   gobject_class->finalize = gst_gl_window_winrt_egl_finalize;
539 
540   window_class->get_display =
541       GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_get_display);
542   window_class->get_window_handle =
543       GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_get_window_handle);
544   window_class->set_window_handle =
545       GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_set_window_handle);
546   window_class->show =
547       GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_show);
548   window_class->quit =
549       GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_quit);
550 }
551 
552 static void
gst_gl_window_winrt_egl_init(GstGLWindowWinRTEGL * window_winrt)553 gst_gl_window_winrt_egl_init (GstGLWindowWinRTEGL * window_winrt)
554 {
555   window_winrt->priv = (GstGLWindowWinRTEGLPrivate *)
556       gst_gl_window_winrt_egl_get_instance_private (window_winrt);
557 
558   g_mutex_init (&window_winrt->priv->event_lock);
559 }
560 
561 static void
gst_gl_window_winrt_egl_dispose(GObject * object)562 gst_gl_window_winrt_egl_dispose (GObject * object)
563 {
564   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (object);
565   GstGLWindowWinRTEGLPrivate *priv = window_egl->priv;
566 
567   if (priv->resize_handler) {
568     delete priv->resize_handler;
569     priv->resize_handler = nullptr;
570   }
571 
572   G_OBJECT_CLASS (parent_class)->dispose (object);
573 }
574 
575 static void
gst_gl_window_winrt_egl_finalize(GObject * object)576 gst_gl_window_winrt_egl_finalize (GObject * object)
577 {
578   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (object);
579   GstGLWindowWinRTEGLPrivate *priv = window_egl->priv;
580 
581   g_mutex_clear (&priv->event_lock);
582 
583   G_OBJECT_CLASS (parent_class)->finalize (object);
584 }
585 
586 static void
gst_gl_window_winrt_egl_set_window_handle(GstGLWindow * window,guintptr handle)587 gst_gl_window_winrt_egl_set_window_handle (GstGLWindow * window,
588     guintptr handle)
589 {
590   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window);
591   GstGLWindowWinRTEGLPrivate *priv = window_egl->priv;
592 
593   GST_INFO_OBJECT (window, "Setting WinRT EGL window handle: %p", handle);
594 
595   window_egl->window = (EGLNativeWindowType) handle;
596 
597   if (priv->resize_handler)
598     delete priv->resize_handler;
599   priv->resize_handler = nullptr;
600 
601   if (!handle) {
602     GST_WARNING_OBJECT (window, "NULL window handle");
603     return;
604   }
605 
606   priv->resize_handler =
607       new GstGLWindowWinRTEGLResizeHandler
608       (reinterpret_cast<IInspectable*> (handle), window);
609 
610   if (!priv->resize_handler->IsValid ()) {
611     GST_WARNING_OBJECT (window,
612         "Invalid window handle %" G_GUINTPTR_FORMAT, handle);
613     delete priv->resize_handler;
614     priv->resize_handler = nullptr;
615   }
616 }
617 
618 static guintptr
gst_gl_window_winrt_egl_get_window_handle(GstGLWindow * window)619 gst_gl_window_winrt_egl_get_window_handle (GstGLWindow * window)
620 {
621   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window);
622 
623   GST_INFO_OBJECT (window, "Getting WinRT EGL window handle");
624 
625   return (guintptr) window_egl->window;
626 }
627 
628 /* Must be called in the gl thread */
629 GstGLWindowWinRTEGL *
gst_gl_window_winrt_egl_new(GstGLDisplay * display)630 gst_gl_window_winrt_egl_new (GstGLDisplay * display)
631 {
632   GstGLWindowWinRTEGL *window_egl;
633 
634   GST_INFO_OBJECT (display, "Trying to create WinRT EGL window");
635 
636   if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_EGL) == 0)
637     /* we require an EGL display to create windows */
638     return NULL;
639 
640   GST_INFO_OBJECT (display, "Creating WinRT EGL window");
641 
642   window_egl = (GstGLWindowWinRTEGL *)
643       g_object_new (GST_TYPE_GL_WINDOW_WINRT_EGL, NULL);
644 
645   return window_egl;
646 }
647 
648 static guintptr
gst_gl_window_winrt_egl_get_display(GstGLWindow * window)649 gst_gl_window_winrt_egl_get_display (GstGLWindow * window)
650 {
651   /* EGL_DEFAULT_DISPLAY */
652   return 0;
653 }
654 
655 static void
gst_gl_window_winrt_egl_show(GstGLWindow * window)656 gst_gl_window_winrt_egl_show (GstGLWindow * window)
657 {
658   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window);
659   GstGLWindowWinRTEGLPrivate *priv = window_egl->priv;
660   guint width, height;
661   gboolean resize = FALSE;
662 
663   if (!priv->resize_handler)
664     return;
665 
666   g_mutex_lock (&priv->event_lock);
667   if (!priv->surface_width || !priv->surface_height) {
668     if (priv->resize_handler->GetWindowSize (&width, &height)) {
669       GST_INFO_OBJECT (window, "Client window size %dx%d", width, height);
670       priv->surface_width = width;
671       priv->surface_height = height;
672       resize = TRUE;
673     }
674   }
675   g_mutex_unlock (&priv->event_lock);
676 
677   if (resize)
678     gst_gl_window_resize (window, width, height);
679 }
680 
681 static void
gst_gl_window_winrt_egl_on_resize(GstGLWindow * window,guint width,guint height)682 gst_gl_window_winrt_egl_on_resize (GstGLWindow * window,
683     guint width, guint height)
684 {
685   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window);
686   GstGLWindowWinRTEGLPrivate *priv = window_egl->priv;
687 
688   GST_DEBUG_OBJECT (window, "New client window size %dx%d", width, height);
689 
690   g_mutex_lock (&priv->event_lock);
691   priv->surface_width = width;
692   priv->surface_height = height;
693   g_mutex_unlock (&priv->event_lock);
694 
695   gst_gl_window_resize (window, width, height);
696 }
697 
698 static void
gst_gl_window_winrt_egl_quit(GstGLWindow * window)699 gst_gl_window_winrt_egl_quit (GstGLWindow * window)
700 {
701   GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window);
702   GstGLWindowWinRTEGLPrivate *priv = window_egl->priv;
703 
704   if (priv->resize_handler) {
705     HRESULT hr;
706     bool is_dispatcher_thread = false;
707 
708     hr = priv->resize_handler->GetHasThreadAccess (is_dispatcher_thread);
709     if (SUCCEEDED (hr) && is_dispatcher_thread) {
710       /* In GstGLContext::destroy_context() -> eglDestroySurface(),
711        * ANGLE will wait a UI thread for its own operations to be called
712        * from the thread. Note that gst_gl_context_egl_destroy_context() will be
713        * called from GstGLContext's internal GL thread.
714        *
715        * A problem is that if GstGLWindow is being closed from the UI thread,
716        * ANGLE cannot access the UI thread as current thread is the thread.
717        */
718       GST_ERROR_OBJECT (window,
719           "Closing from a UI thread might cause a deadlock or crash");
720 
721       g_warning ("GstGLWindowWinRTEGL should be closed from non-UI thread");
722     }
723   }
724 
725   GST_GL_WINDOW_CLASS (parent_class)->quit (window);
726 }
727