diff --git a/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj b/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj
index 9649279ad..d19b9d0ec 100644
--- a/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj
+++ b/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj
@@ -324,7 +324,7 @@
-
+
diff --git a/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj.filters b/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj.filters
index 7cdc81daf..b5050af5f 100644
--- a/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj.filters
+++ b/VisualC-WinRT/SDL/SDL-WinRT_VS2012.vcxproj.filters
@@ -633,9 +633,6 @@
Source Files
-
- Source Files
-
Header Files
@@ -666,6 +663,9 @@
Source Files
+
+ Source Files
+
diff --git a/include/SDL_egl.h b/include/SDL_egl.h
index d312f0425..a345818ae 100644
--- a/include/SDL_egl.h
+++ b/include/SDL_egl.h
@@ -394,8 +394,8 @@ typedef enum {
#if __WINRT__
#include
typedef IUnknown * EGLNativeWindowType;
-typedef int EGLNativeDisplayType;
-typedef HBITMAP EGLNativePixmapType;
+typedef IUnknown * EGLNativePixmapType;
+typedef IUnknown * EGLNativeDisplayType;
#else
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c
index cfba20071..e0efa64ef 100644
--- a/src/video/SDL_egl.c
+++ b/src/video/SDL_egl.c
@@ -216,6 +216,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
LOAD_FUNC(eglWaitGL);
LOAD_FUNC(eglBindAPI);
+#if !defined(__WINRT__)
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
if (!_this->egl_data->egl_display) {
return SDL_SetError("Could not get EGL display");
@@ -224,6 +225,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
return SDL_SetError("Could not initialize EGL");
}
+#endif
_this->egl_data->dll_handle = dll_handle;
_this->egl_data->egl_dll_handle = egl_dll_handle;
diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp
index 6f3ddcedf..4a84174d0 100644
--- a/src/video/winrt/SDL_winrtopengles.cpp
+++ b/src/video/winrt/SDL_winrtopengles.cpp
@@ -20,8 +20,6 @@
*/
#include "../../SDL_internal.h"
-// TODO: WinRT, make this file compile via C code
-
#if SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL
/* EGL implementation of SDL OpenGL support */
@@ -29,13 +27,77 @@
#include "SDL_winrtvideo_cpp.h"
extern "C" {
#include "SDL_winrtopengles.h"
+#include "SDL_loadso.h"
}
-#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((NativeDisplayType) -3)
+/* Windows includes */
+#include
+using namespace Windows::UI::Core;
+
+/* ANGLE/WinRT constants */
+static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
+
+
+/*
+ * SDL/EGL top-level implementation
+ */
extern "C" int
-WINRT_GLES_LoadLibrary(_THIS, const char *path) {
- return SDL_EGL_LoadLibrary(_this, path, EGL_D3D11_ONLY_DISPLAY_ANGLE);
+WINRT_GLES_LoadLibrary(_THIS, const char *path)
+{
+ SDL_VideoData *video_data = (SDL_VideoData *)_this->driverdata;
+
+ if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY) != 0) {
+ return -1;
+ }
+
+ /* 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");
+ }
+
+ /* 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 cpp_win = reinterpret_cast(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 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");
+ }
+
+ return 0;
+}
+
+extern "C" void
+WINRT_GLES_UnloadLibrary(_THIS)
+{
+ SDL_VideoData *video_data = (SDL_VideoData *)_this->driverdata;
+
+ /* Release SDL's own COM reference to the ANGLE/WinRT IWinrtEglWindow */
+ if (video_data->winrtEglWindow) {
+ video_data->winrtEglWindow->Release();
+ video_data->winrtEglWindow = nullptr;
+ }
+
+ /* Perform the bulk of the unloading */
+ SDL_EGL_UnloadLibrary(_this);
}
extern "C" {
diff --git a/src/video/winrt/SDL_winrtopengles.h b/src/video/winrt/SDL_winrtopengles.h
index f051132eb..ae1739171 100644
--- a/src/video/winrt/SDL_winrtopengles.h
+++ b/src/video/winrt/SDL_winrtopengles.h
@@ -31,16 +31,34 @@
/* OpenGLES functions */
#define WINRT_GLES_GetAttribute SDL_EGL_GetAttribute
#define WINRT_GLES_GetProcAddress SDL_EGL_GetProcAddress
-#define WINRT_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define WINRT_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
#define WINRT_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
#define WINRT_GLES_DeleteContext SDL_EGL_DeleteContext
extern int WINRT_GLES_LoadLibrary(_THIS, const char *path);
+extern void WINRT_GLES_UnloadLibrary(_THIS);
extern SDL_GLContext WINRT_GLES_CreateContext(_THIS, SDL_Window * window);
extern void WINRT_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int WINRT_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+
+#ifdef __cplusplus
+
+/* 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 WINRT_EGLNativeWindowType;
+typedef WINRT_EGLNativeWindowType WINRT_EGLNativeDisplayType;
+
+/* Function pointer typedefs for ANGLE/WinRT's functions that require
+ * parameter customization [by passing in C++ objects].
+ */
+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, int, IUnknown ** result);
+
+#endif /* __cplusplus */
+
#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 4a5301f22..f54e9855b 100644
--- a/src/video/winrt/SDL_winrtvideo.cpp
+++ b/src/video/winrt/SDL_winrtvideo.cpp
@@ -30,6 +30,7 @@
/* Windows includes */
#include
+#include
using namespace Windows::UI::Core;
@@ -86,6 +87,15 @@ WINRT_DeleteDevice(SDL_VideoDevice * device)
if (device == WINRT_GlobalSDLVideoDevice) {
WINRT_GlobalSDLVideoDevice = NULL;
}
+
+ if (device->driverdata) {
+ SDL_VideoData * video_data = (SDL_VideoData *)device->driverdata;
+ if (video_data->winrtEglWindow) {
+ video_data->winrtEglWindow->Release();
+ }
+ SDL_free(video_data);
+ }
+
SDL_free(device);
}
@@ -93,6 +103,7 @@ static SDL_VideoDevice *
WINRT_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
+ SDL_VideoData *data;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
@@ -104,6 +115,14 @@ WINRT_CreateDevice(int devindex)
return (0);
}
+ data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+ if (!data) {
+ SDL_OutOfMemory();
+ return (0);
+ }
+ SDL_zerop(data);
+ device->driverdata = data;
+
/* Set the function pointers */
device->VideoInit = WINRT_VideoInit;
device->VideoQuit = WINRT_VideoQuit;
@@ -301,29 +320,25 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
data->egl_surface = EGL_NO_SURFACE;
} else {
/* OpenGL ES 2 was reuqested. Set up an EGL surface. */
+ SDL_VideoData * video_data = (SDL_VideoData *)_this->driverdata;
- /* HACK: ANGLE/WinRT currently uses non-pointer, C++ objects to represent
- native windows. The object only contains a single pointer to a COM
- interface pointer, which on x86 appears to be castable to the object
- without apparant problems. On other platforms, notable ARM and x64,
- doing so will cause a crash. To avoid this crash, we'll bypass
- SDL's normal call to eglCreateWindowSurface, which is invoked from C
- code, and call it here, where an appropriate C++ object may be
- passed in.
+ /* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly,
+ * rather than via SDL_EGL_CreateSurface, as ANGLE/WinRT requires
+ * a C++ object, ComPtr, to be passed into
+ * eglCreateWindowSurface.
*/
- typedef EGLSurface (*eglCreateWindowSurfaceFunction)(EGLDisplay dpy, EGLConfig config,
- Microsoft::WRL::ComPtr win,
- const EGLint *attrib_list);
- eglCreateWindowSurfaceFunction WINRT_eglCreateWindowSurface =
- (eglCreateWindowSurfaceFunction) _this->egl_data->eglCreateWindowSurface;
+ if (SDL_EGL_ChooseConfig(_this) != 0) {
+ char buf[512];
+ SDL_snprintf(buf, sizeof(buf), "SDL_EGL_ChooseConfig failed: %s", SDL_GetError());
+ return SDL_SetError(buf);
+ }
- Microsoft::WRL::ComPtr nativeWindow = reinterpret_cast(data->coreWindow.Get());
- data->egl_surface = WINRT_eglCreateWindowSurface(
+ Microsoft::WRL::ComPtr cpp_winrtEglWindow = video_data->winrtEglWindow;
+ data->egl_surface = ((eglCreateWindowSurface_Function)_this->egl_data->eglCreateWindowSurface)(
_this->egl_data->egl_display,
_this->egl_data->egl_config,
- nativeWindow, NULL);
+ cpp_winrtEglWindow, NULL);
if (data->egl_surface == NULL) {
- // TODO, WinRT: see if eglCreateWindowSurface, or its callee(s), sets an error message. If so, attach it to the SDL error.
return SDL_SetError("eglCreateWindowSurface failed");
}
}
diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h
index b5f44510d..119f5b8f2 100644
--- a/src/video/winrt/SDL_winrtvideo_cpp.h
+++ b/src/video/winrt/SDL_winrtvideo_cpp.h
@@ -34,6 +34,13 @@ extern "C" {
#include "../SDL_egl_c.h"
}
+/* Private display data */
+typedef struct SDL_VideoData {
+ /* An object created by ANGLE/WinRT (OpenGL ES 2 for WinRT) that gets
+ * passed to eglGetDisplay and eglCreateWindowSurface:
+ */
+ IUnknown *winrtEglWindow;
+} SDL_VideoData;
/* The global, WinRT, SDL Window.
For now, SDL/WinRT only supports one window (due to platform limitations of