WinRT: expanded OpenGL ES 2 support to enable recent updates to ANGLE/WinRT ANGLE for WinRT has at least two versions: - an older version, which supports Windows 8.0 and 8.1. This is currently the "winrt" branch in MSOpenTech's ANGLE repository (at https://github.com/msopentech/angle) - a newer version, which drops support for Windows 8.0, but is under more active development (via MSOpenTech's "future-dev" branch), and which was recently merged into the ANGLE project's official "master" branch (at https://chromium.googlesource.com/angle/angle) Both versions are setup using slightly different APIs. SDL/WinRT will now attempt to detect which version is being used, and configure it appropriately.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp
index 4a84174..e3a955b 100644
--- a/src/video/winrt/SDL_winrtopengles.cpp
+++ b/src/video/winrt/SDL_winrtopengles.cpp
@@ -36,7 +36,10 @@ using namespace Windows::UI::Core;
/* ANGLE/WinRT constants */
static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
-
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
/*
* SDL/EGL top-level implementation
@@ -52,32 +55,56 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path)
}
/* Load ANGLE/WinRT-specific functions */
- CreateWinrtEglWindow_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Function) SDL_LoadFunction(_this->egl_data->egl_dll_handle, "CreateWinrtEglWindow");
- if (!CreateWinrtEglWindow) {
- return SDL_SetError("Could not retrieve ANGLE/WinRT function CreateWinrtEglWindow");
+ CreateWinrtEglWindow_Old_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Old_Function) SDL_LoadFunction(_this->egl_data->egl_dll_handle, "CreateWinrtEglWindow");
+ if (CreateWinrtEglWindow) {
+ /* 'CreateWinrtEglWindow' was found, which means that an an older
+ * version of ANGLE/WinRT is being used. Continue setting up EGL,
+ * as appropriate to this version of ANGLE.
+ */
+
+ /* Create an ANGLE/WinRT EGL-window */
+ /* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */
+ CoreWindow ^ native_win = CoreWindow::GetForCurrentThread();
+ Microsoft::WRL::ComPtr<IUnknown> cpp_win = reinterpret_cast<IUnknown *>(native_win);
+ HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow));
+ if (FAILED(result)) {
+ return -1;
+ }
+
+ /* Call eglGetDisplay and eglInitialize as appropriate. On other
+ * platforms, this would probably get done by SDL_EGL_LoadLibrary,
+ * however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of
+ * eglGetDisplay requires that a C++ object be passed into it, so the
+ * call will be made in this file, a C++ file, instead.
+ */
+ Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
+ _this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display);
+ if (!_this->egl_data->egl_display) {
+ return SDL_SetError("Could not get EGL display");
+ }
+ } else {
+ const EGLint displayAttributes[] = {
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_NONE,
+ };
+
+ /* 'CreateWinrtEglWindow' was NOT found, which either means that a
+ * newer version of ANGLE/WinRT is being used, or that we don't have
+ * a valid copy of ANGLE.
+ *
+ * Try loading ANGLE as if it were the newer version.
+ */
+ eglGetPlatformDisplayEXT_Function eglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_Function)_this->egl_data->eglGetProcAddress("eglGetPlatformDisplayEXT");
+ if (!eglGetPlatformDisplayEXT) {
+ return SDL_SetError("Could not retrieve ANGLE/WinRT display function(s)");
+ }
+
+ _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes);
+ if (!_this->egl_data->egl_display) {
+ return SDL_SetError("Could not get EGL display");
+ }
}
- /* Create an ANGLE/WinRT EGL-window */
- /* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */
- CoreWindow ^ native_win = CoreWindow::GetForCurrentThread();
- Microsoft::WRL::ComPtr<IUnknown> cpp_win = reinterpret_cast<IUnknown *>(native_win);
- HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow));
- if (FAILED(result)) {
- return -1;
- }
-
- /* Call eglGetDisplay and eglInitialize as appropriate. On other
- * platforms, this would probably get done by SDL_EGL_LoadLibrary,
- * however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of
- * eglGetDisplay requires that a C++ object be passed into it, so the
- * call will be made in this file, a C++ file, instead.
- */
- Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
- _this->egl_data->egl_display = ((eglGetDisplay_Function)_this->egl_data->eglGetDisplay)(cpp_display);
- if (!_this->egl_data->egl_display) {
- return SDL_SetError("Could not get EGL display");
- }
-
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
return SDL_SetError("Could not initialize EGL");
}
diff --git a/src/video/winrt/SDL_winrtopengles.h b/src/video/winrt/SDL_winrtopengles.h
index ae17391..f090f9b 100644
--- a/src/video/winrt/SDL_winrtopengles.h
+++ b/src/video/winrt/SDL_winrtopengles.h
@@ -47,18 +47,22 @@ extern int WINRT_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext cont
/* Typedefs for ANGLE/WinRT's C++-based native-display and native-window types,
* which are used when calling eglGetDisplay and eglCreateWindowSurface.
*/
-typedef Microsoft::WRL::ComPtr<IUnknown> WINRT_EGLNativeWindowType;
-typedef WINRT_EGLNativeWindowType WINRT_EGLNativeDisplayType;
+typedef Microsoft::WRL::ComPtr<IUnknown> WINRT_EGLNativeWindowType_Old;
-/* Function pointer typedefs for ANGLE/WinRT's functions that require
- * parameter customization [by passing in C++ objects].
+/* Function pointer typedefs for 'old' ANGLE/WinRT's functions, which may
+ * require that C++ objects be passed in:
*/
-typedef EGLDisplay (EGLAPIENTRY *eglGetDisplay_Function)(WINRT_EGLNativeWindowType);
-typedef EGLSurface (EGLAPIENTRY *eglCreateWindowSurface_Function)(EGLDisplay, EGLConfig, WINRT_EGLNativeWindowType, const EGLint *);
-typedef HRESULT (EGLAPIENTRY *CreateWinrtEglWindow_Function)(Microsoft::WRL::ComPtr<IUnknown>, int, IUnknown ** result);
+typedef EGLDisplay (EGLAPIENTRY *eglGetDisplay_Old_Function)(WINRT_EGLNativeWindowType_Old);
+typedef EGLSurface (EGLAPIENTRY *eglCreateWindowSurface_Old_Function)(EGLDisplay, EGLConfig, WINRT_EGLNativeWindowType_Old, const EGLint *);
+typedef HRESULT (EGLAPIENTRY *CreateWinrtEglWindow_Old_Function)(Microsoft::WRL::ComPtr<IUnknown>, int, IUnknown ** result);
#endif /* __cplusplus */
+/* Function pointer typedefs for 'new' ANGLE/WinRT functions, which, unlike
+ * the old functions, do not require C++ support and work with plain C.
+ */
+typedef EGLDisplay (EGLAPIENTRY *eglGetPlatformDisplayEXT_Function)(EGLenum, void *, const EGLint *);
+
#endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */
#endif /* _SDL_winrtopengles_h */
diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp
index 6ec0160..b58c9e2 100644
--- a/src/video/winrt/SDL_winrtvideo.cpp
+++ b/src/video/winrt/SDL_winrtvideo.cpp
@@ -328,13 +328,33 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
return SDL_SetError(buf);
}
- Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->winrtEglWindow;
- data->egl_surface = ((eglCreateWindowSurface_Function)_this->egl_data->eglCreateWindowSurface)(
- _this->egl_data->egl_display,
- _this->egl_data->egl_config,
- cpp_winrtEglWindow, NULL);
- if (data->egl_surface == NULL) {
- return SDL_SetError("eglCreateWindowSurface failed");
+ if (video_data->winrtEglWindow) { /* ... is the 'old' version of ANGLE/WinRT being used? */
+ /* Attempt to create a window surface using older versions of
+ * ANGLE/WinRT:
+ */
+ Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->winrtEglWindow;
+ data->egl_surface = ((eglCreateWindowSurface_Old_Function)_this->egl_data->eglCreateWindowSurface)(
+ _this->egl_data->egl_display,
+ _this->egl_data->egl_config,
+ cpp_winrtEglWindow, NULL);
+ if (data->egl_surface == NULL) {
+ return SDL_SetError("eglCreateWindowSurface failed");
+ }
+ } else if (data->coreWindow.Get() != nullptr) {
+ /* Attempt to create a window surface using newer versions of
+ * ANGLE/WinRT:
+ */
+ IInspectable * coreWindowAsIInspectable = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
+ data->egl_surface = _this->egl_data->eglCreateWindowSurface(
+ _this->egl_data->egl_display,
+ _this->egl_data->egl_config,
+ coreWindowAsIInspectable,
+ NULL);
+ if (data->egl_surface == NULL) {
+ return SDL_SetError("eglCreateWindowSurface failed");
+ }
+ } else {
+ return SDL_SetError("No supported means to create an EGL window surface are available");
}
}
#endif