gstgl: Add a new window type for WinRT

This is needed for using GstGL with ANGLE as the GLES implementation
in Universal Windows Platform apps that use the Windows Runtime
(WinRT) instead of Win32, which is deprecated and not allowed in
Windows Store apps.

This has been tested with Servo on the Microsoft HoloLens 2, and seems
to work quite well.
This commit is contained in:
Nirbheek Chauhan 2019-05-21 11:44:39 +05:30
parent 97426fd52e
commit 564ab3031b
8 changed files with 271 additions and 9 deletions

View file

@ -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) {

View file

@ -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)

View file

@ -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

View file

@ -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 */

View file

@ -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 <windows.h>
#include <GL/gl.h>''',
@ -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')

View file

@ -0,0 +1,108 @@
/*
* GStreamer
* Copyright (C) 2019 Nirbheek Chauhan <nirbheek@centricular.com>
*
* 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 <gst/gl/gstglcontext.h>
#include <gst/gl/egl/gstglcontext_egl.h>
#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;
}

View file

@ -0,0 +1,64 @@
/*
* GStreamer
* Copyright (C) 2019 Nirbheek Chauhan <nirbheek@centricular.com>
*
* 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 <gst/gl/gl.h>
#include <gst/gl/egl/gstegl.h>
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__ */

View file

@ -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 : '',