diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index 49175300bf..c362f301f3 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -804,11 +804,22 @@ gst_gl_context_egl_create_context (GstGLContext * context, window_handle = gst_gl_window_get_window_handle (window); if (window_handle) { +#if GST_GL_HAVE_WINDOW_WINRT + const EGLint attrs[] = { + /* EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is an optimization that can + * have large performance benefits on mobile devices. */ + EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_NONE + }; +#else + const EGLint *attrs = NULL; +#endif + GST_DEBUG ("Creating EGLSurface from window_handle %p", (void *) window_handle); egl->egl_surface = eglCreateWindowSurface (egl->egl_display, egl->egl_config, - (EGLNativeWindowType) window_handle, NULL); + (EGLNativeWindowType) window_handle, attrs); /* Store window handle for later comparision */ egl->window_handle = window_handle; } else if (!gst_gl_check_extension ("EGL_KHR_surfaceless_context", @@ -906,6 +917,16 @@ gst_gl_context_egl_activate (GstGLContext * context, gboolean activate) gst_object_unref (window); } if (handle && handle != egl->window_handle) { +#if GST_GL_HAVE_WINDOW_WINRT + const EGLint attrs[] = { + /* EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is an optimization that can + * have large performance benefits on mobile devices. */ + EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_NONE + }; +#else + const EGLint *attrs = NULL; +#endif GST_DEBUG_OBJECT (context, "Handle changed (have:%p, now:%p), switching surface", (void *) egl->window_handle, (void *) handle); @@ -920,7 +941,7 @@ gst_gl_context_egl_activate (GstGLContext * context, gboolean activate) } egl->egl_surface = eglCreateWindowSurface (egl->egl_display, egl->egl_config, - (EGLNativeWindowType) handle, NULL); + (EGLNativeWindowType) handle, attrs); egl->window_handle = handle; if (egl->egl_surface == EGL_NO_SURFACE) { diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl.c b/gst-libs/gst/gl/egl/gstgldisplay_egl.c index 9961ca0ea6..31a097bf61 100644 --- a/gst-libs/gst/gl/egl/gstgldisplay_egl.c +++ b/gst-libs/gst/gl/egl/gstgldisplay_egl.c @@ -59,6 +59,9 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); #ifndef EGL_PLATFORM_DEVICE_EXT #define EGL_PLATFORM_DEVICE_EXT 0x313F #endif +#ifndef EGL_PLATFORM_ANGLE_ANGLE +#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 +#endif typedef EGLDisplay (*_gst_eglGetPlatformDisplay_type) (EGLenum platform, void *native_display, const EGLint * attrib_list); @@ -122,7 +125,7 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) { const gchar *egl_exts; EGLDisplay ret = EGL_NO_DISPLAY; - _gst_eglGetPlatformDisplay_type _gst_eglGetPlatformDisplay; + _gst_eglGetPlatformDisplay_type _gst_eglGetPlatformDisplay = NULL; g_return_val_if_fail (type != GST_GL_DISPLAY_TYPE_NONE, EGL_NO_DISPLAY); g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0) @@ -147,8 +150,11 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) if (!gst_gl_check_extension ("EGL_EXT_platform_base", egl_exts)) goto default_display; + /* we need EXT for WinRT to pass attributes */ +#if !GST_GL_HAVE_WINDOW_WINRT _gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type) eglGetProcAddress ("eglGetPlatformDisplay"); +#endif if (!_gst_eglGetPlatformDisplay) _gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type) eglGetProcAddress ("eglGetPlatformDisplayEXT"); @@ -179,6 +185,34 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_GBM_MESA, (gpointer) display, NULL); } +#endif +#if GST_GL_HAVE_WINDOW_WINRT + if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_EGL) && + (gst_gl_check_extension ("EGL_ANGLE_platform_angle", egl_exts) || + gst_gl_check_extension ("EGL_ANGLE_platform_angle", egl_exts))) { + const EGLint attrs[] = { + /* These are the default display attributes, used to request ANGLE's + * D3D11 renderer. eglInitialize will only succeed with these + * attributes if the hardware supports D3D11 Feature Level 10_0+. */ + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + + /* EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization + * that can have large performance benefits on mobile devices. Its + * syntax is subject to change, though. Please update your Visual + * Studio templates if you experience compilation issues with it. */ + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + + /* EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that + * enables ANGLE to automatically call the IDXGIDevice3::Trim method + * on behalf of the application when it gets suspended. Calling + * IDXGIDevice3::Trim when an application is suspended is a Windows + * Store application certification requirement. */ + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, + EGL_NONE, + }; + ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_ANGLE_ANGLE, + (gpointer) display, attrs); + } #endif if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_EGL_DEVICE) && (gst_gl_check_extension ("EGL_EXT_device_base", egl_exts) && @@ -187,7 +221,6 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) _gst_eglGetPlatformDisplay (EGL_PLATFORM_DEVICE_EXT, (gpointer) display, NULL); } - /* android only has one winsys/display connection */ if (ret != EGL_NO_DISPLAY) diff --git a/gst-libs/gst/gl/gstglconfig.h.meson b/gst-libs/gst/gl/gstglconfig.h.meson index 11795c16c9..aefd93aa8d 100644 --- a/gst-libs/gst/gl/gstglconfig.h.meson +++ b/gst-libs/gst/gl/gstglconfig.h.meson @@ -1,6 +1,4 @@ /* gstglconfig.h - * - * This is a generated file. Please modify `configure.ac' */ #ifndef __GST_GL_CONFIG_H__ @@ -19,6 +17,7 @@ G_BEGIN_DECLS #mesondefine GST_GL_HAVE_WINDOW_X11 #mesondefine GST_GL_HAVE_WINDOW_COCOA #mesondefine GST_GL_HAVE_WINDOW_WIN32 +#mesondefine GST_GL_HAVE_WINDOW_WINRT #mesondefine GST_GL_HAVE_WINDOW_WAYLAND #mesondefine GST_GL_HAVE_WINDOW_ANDROID #mesondefine GST_GL_HAVE_WINDOW_DISPMANX diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 720bb62b3d..cadc5bc49a 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -68,6 +68,9 @@ #if GST_GL_HAVE_WINDOW_DISPMANX #include "dispmanx/gstglwindow_dispmanx_egl.h" #endif +#if GST_GL_HAVE_WINDOW_WINRT +#include "winrt/gstglwindow_winrt_egl.h" +#endif #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) @@ -290,6 +293,10 @@ gst_gl_window_new (GstGLDisplay * display) if (!window && (!user_choice || g_strstr_len (user_choice, 3, "gbm"))) window = GST_GL_WINDOW (gst_gl_window_gbm_egl_new (display)); #endif +#if GST_GL_HAVE_WINDOW_WINRT + if (!window && (!user_choice || g_strstr_len (user_choice, 5, "winrt"))) + window = GST_GL_WINDOW (gst_gl_window_winrt_egl_new (display)); +#endif if (!window) { /* subclass returned a NULL window */ diff --git a/gst-libs/gst/gl/meson.build b/gst-libs/gst/gl/meson.build index a5034940f3..4f692da0ea 100644 --- a/gst-libs/gst/gl/meson.build +++ b/gst-libs/gst/gl/meson.build @@ -112,6 +112,7 @@ glconf_options = [ 'GST_GL_HAVE_WINDOW_X11', 'GST_GL_HAVE_WINDOW_COCOA', 'GST_GL_HAVE_WINDOW_WIN32', + 'GST_GL_HAVE_WINDOW_WINRT', 'GST_GL_HAVE_WINDOW_WAYLAND', 'GST_GL_HAVE_WINDOW_ANDROID', 'GST_GL_HAVE_WINDOW_DISPMANX', @@ -232,6 +233,7 @@ if gl_winsys.contains('auto') need_win_x11 = 'auto' need_win_wayland = 'auto' need_win_win32 = 'auto' + need_win_winrt = 'auto' need_win_cocoa = 'auto' need_win_eagl = 'auto' need_win_dispmanx = 'auto' @@ -242,6 +244,7 @@ else need_win_x11 = 'no' need_win_wayland = 'no' need_win_win32 = 'no' + need_win_winrt = 'no' need_win_cocoa = 'no' need_win_eagl = 'no' need_win_dispmanx = 'no' @@ -255,6 +258,8 @@ else need_win_wayland = 'yes' elif winsys == 'win32' need_win_win32 = 'yes' + elif winsys == 'winrt' + need_win_winrt = 'yes' elif winsys == 'cocoa' need_win_cocoa = 'yes' elif winsys == 'eagl' @@ -655,7 +660,6 @@ endif if need_platform_wgl != 'no' and need_win_win32 != 'no' gdi_dep = cc.find_library('gdi32', required : false) - # FIXME: Revert back to has_header once it gains prefix support wglext_h = cc.has_header('GL/wglext.h', prefix : '''#include #include ''', @@ -677,6 +681,32 @@ if need_platform_wgl != 'no' and need_win_win32 != 'no' endif endif +# WinRT ANGLE checks +if need_win_winrt != 'no' and host_system == 'windows' + if need_win_winrt == 'yes' and not enabled_gl_platforms.contains('egl') + error('Impossible situation requested: Cannot use WinRT ANGLE without EGL support') + endif + + if egl_dep.found() + windows_graphics_h = cc.has_header('windows.graphics.h') + windows_app_dep = cc.find_library('WindowsApp', required: false) + + if windows_graphics_h and windows_app_dep.found() + enabled_gl_winsys += 'winrt' + glconf.set10('GST_GL_HAVE_WINDOW_WINRT', 1) + gl_sources += [ + 'winrt/gstglwindow_winrt_egl.c' + ] + elif need_win_winrt == 'yes' + error('WinRT is enabled, but headers/libraries were not found') + endif + elif need_win_winrt == 'yes' + error('WinRT ANGLE is enabled, but EGL was not found') + else + message('WinRT ANGLE disabled because EGL was not found') + endif +endif + if ['darwin', 'ios'].contains(host_system) if not have_objc error('No ObjC compiler found') diff --git a/gst-libs/gst/gl/winrt/gstglwindow_winrt_egl.c b/gst-libs/gst/gl/winrt/gstglwindow_winrt_egl.c new file mode 100644 index 0000000000..9e8d386302 --- /dev/null +++ b/gst-libs/gst/gl/winrt/gstglwindow_winrt_egl.c @@ -0,0 +1,108 @@ +/* + * GStreamer + * Copyright (C) 2019 Nirbheek Chauhan + * + * 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 +#include + +#include "gstglwindow_winrt_egl.h" +#include "../gstglwindow_private.h" + +#define GST_CAT_DEFAULT gst_gl_window_debug + +#define GST_GL_WINDOW_WINRT_EGL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + GST_TYPE_GL_WINDOW_WINRT_EGL, GstGLWindowWinRTEGLPrivate)) + + +G_DEFINE_TYPE (GstGLWindowWinRTEGL, gst_gl_window_winrt_egl, + GST_TYPE_GL_WINDOW); + +static guintptr gst_gl_window_winrt_egl_get_display (GstGLWindow * window); +static guintptr gst_gl_window_winrt_egl_get_window_handle (GstGLWindow * + window); +static void gst_gl_window_winrt_egl_set_window_handle (GstGLWindow * window, + guintptr handle); + +static void +gst_gl_window_winrt_egl_class_init (GstGLWindowWinRTEGLClass * klass) +{ + GstGLWindowClass *window_class = (GstGLWindowClass *) klass; + + window_class->get_display = + GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_get_display); + window_class->get_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_get_window_handle); + window_class->set_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_winrt_egl_set_window_handle); +} + +static void +gst_gl_window_winrt_egl_init (GstGLWindowWinRTEGL * window_winrt) +{ +} + +static void +gst_gl_window_winrt_egl_set_window_handle (GstGLWindow * window, + guintptr handle) +{ + GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window); + + GST_INFO_OBJECT (window, "Setting WinRT EGL window handle: %p", handle); + + window_egl->window = (EGLNativeWindowType) handle; +} + +static guintptr +gst_gl_window_winrt_egl_get_window_handle (GstGLWindow * window) +{ + GstGLWindowWinRTEGL *window_egl = GST_GL_WINDOW_WINRT_EGL (window); + + GST_INFO_OBJECT (window, "Getting WinRT EGL window handle"); + + return (guintptr) window_egl->window; +} + +/* Must be called in the gl thread */ +GstGLWindowWinRTEGL * +gst_gl_window_winrt_egl_new (GstGLDisplay * display) +{ + GstGLWindowWinRTEGL *window_egl; + + GST_INFO_OBJECT (display, "Trying to create WinRT EGL window"); + + if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_EGL) == 0) + /* we require an EGL display to create windows */ + return NULL; + + GST_INFO_OBJECT (display, "Creating WinRT EGL window"); + + window_egl = g_object_new (GST_TYPE_GL_WINDOW_WINRT_EGL, NULL); + + return window_egl; +} + +static guintptr +gst_gl_window_winrt_egl_get_display (GstGLWindow * window) +{ + /* EGL_DEFAULT_DISPLAY */ + return 0; +} diff --git a/gst-libs/gst/gl/winrt/gstglwindow_winrt_egl.h b/gst-libs/gst/gl/winrt/gstglwindow_winrt_egl.h new file mode 100644 index 0000000000..08bff31ac3 --- /dev/null +++ b/gst-libs/gst/gl/winrt/gstglwindow_winrt_egl.h @@ -0,0 +1,64 @@ +/* + * GStreamer + * Copyright (C) 2019 Nirbheek Chauhan + * + * 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 __GST_GL_WINDOW_WINRT_EGL_H__ +#define __GST_GL_WINDOW_WINRT_EGL_H__ + +#include +#include + +G_BEGIN_DECLS + +GType gst_gl_window_winrt_egl_get_type (void); + +#define GST_TYPE_GL_WINDOW_WINRT_EGL (gst_gl_window_winrt_egl_get_type()) +#define GST_GL_WINDOW_WINRT_EGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_GL_WINDOW_WINRT_EGL, GstGLWindowWinRTEGL)) +#define GST_GL_WINDOW_WINRT_EGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_TYPE_GL_WINDOW_WINRT_EGL, GstGLWindowWinRTEGLClass)) +#define GST_IS_GL_WINDOW_WINRT_EGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_GL_WINDOW_WINRT_EGL)) +#define GST_IS_GL_WINDOW_WINRT_EGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_GL_WINDOW_WINRT_EGL)) +#define GST_GL_WINDOW_WINRT_EGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_GL_WINDOW_WINRT_EGL, GstGLWindowWinRTEGL_Class)) + +typedef struct _GstGLWindowWinRTEGL GstGLWindowWinRTEGL; +typedef struct _GstGLWindowWinRTEGLClass GstGLWindowWinRTEGLClass; + +struct _GstGLWindowWinRTEGL { + /*< private >*/ + GstGLWindow parent; + + /* This is actually an IInspectable type, which must be one of: + * ICoreWindow, ISwapChainPanel, IPropertySet */ + EGLNativeWindowType window; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstGLWindowWinRTEGLClass { + /*< private >*/ + GstGLWindowClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING_LARGE]; +}; + +GstGLWindowWinRTEGL * gst_gl_window_winrt_egl_new (GstGLDisplay * display); + +G_END_DECLS + +#endif /* __GST_GL_WINDOW_WINRT_EGL_H__ */ diff --git a/meson_options.txt b/meson_options.txt index 141bb3e514..73de93f0f1 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -12,8 +12,8 @@ option('gl_platform', type : 'array', choices : ['glx', 'egl', 'cgl', 'wgl', 'eagl', 'auto'], value : ['auto'], description : 'A comma separated list of opengl platforms to enable building against') option('gl_winsys', type : 'array', - choices : ['x11', 'wayland', 'win32', 'cocoa', 'dispmanx', 'viv-fb', 'gbm', 'android', 'auto'], value : ['auto'], - description : 'A comma separated list of opengl windows systems to enable building against. Supported values are x11, wayland, win32, cocoa, dispmanx, viv-fb, gbm and android') + choices : ['x11', 'wayland', 'win32', 'winrt', 'cocoa', 'dispmanx', 'viv-fb', 'gbm', 'android', 'auto'], value : ['auto'], + description : 'A comma separated list of opengl windows systems to enable building against. Supported values are x11, wayland, win32, winrt, cocoa, dispmanx, viv-fb, gbm, and android') option('egl_module_name', type : 'string', value : '', description : 'The file to pass to g_module_open to open the libEGL library (default: libEGL)') option('opengl_module_name', type : 'string', value : '',