src/video/winrt/SDL_winrtopengles.cpp
author Ryan C. Gordon <icculus@icculus.org>
Thu, 09 Apr 2015 22:28:37 -0400
changeset 9541 cf8fab52e33b
parent 9386 65e802af5d0e
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Merged Alex Szpakowski's iOS-improvement branch to default.

Fixes Bugzilla #2798.
Fixes Bugzilla #2212.
Fixes Bugzilla #2826.
Fixes Bugzilla #2661.
Fixes Bugzilla #1885.
Fixes Bugzilla #1578.
Fixes Bugzilla #2751.

(whew!)

Notable changes, from Alex's notes:

- The SDL_WINDOW_ALLOW_HIGHDPI flag is now needed (along with SDL_GL_GetDrawableSize or SDL_GetRendererOutputSize) to use Retina / high DPI resolutions, bringing SDL’s Retina-related behavior on iOS in line with Mac OS X. Window dimensions and display modes are now in the “points” (non-high DPI) coordinate system rather than pixels, whereas SDL_GL_GetDrawableSize is in pixels.

- Reworked the custom extended launch screen code:
- It now hides after the first SDL_PumpEvents call rather than SDL_CreateWindow, and it fades out in a similar manner to the system launch screen behavior.
- It now mirrors the system launch screen behavior when deciding which image to display: it falls back to using the Launch Images dictionary in Info.plist if the iOS 8+ launch screen nib isn’t available, and if the Launch Images dictionary doesn’t exist it uses the old standard launch image names.
- The extended launch screen can now be disabled via the SDL_IPHONE_LAUNCHSCREEN define in SDL_config_iphoneos.h.

- Added support for SDL_HINT_ACCELEROMETER_AS_JOYSTICK.

- Added access to a window view's renderbuffer and framebuffer to syswm.

- Added OpenGL ES debug labels for the Renderbuffer and Framebuffer Objects created with SDL_GL_CreateContext.

- Added support for sRGB OpenGL ES contexts on iOS 7+.

- Updated OpenGL ES contexts to support native-resolution rendering (when SDL_WINDOW_ALLOW_HIGHDPI is enabled) on the iPhone 6 Plus, i.e. 1080x1920 rather than 1242x2208.

- Updated SDL_GL_CreateContext, SDL_GL_SwapWindow, SDL_GL_MakeCurrent, and SDL_GL_DeleteContext to be more robust.

- Updated SDL windows to display a UIView at all times, even when an OpenGL context is not active. This allows rotation, touch events, and other windowing-related events to work properly without an active OpenGL context. It also makes it easier to use SDL_GetWindowWMInfo after creating a SDL window.

- Updated the iOS-specific Objective-C code to use cleaner and more modern language features and APIs, including ARC instead of manual reference counting.

- Updated SDL_HINT_ORIENTATIONS to allow disabling custom orientations if the hint is set with no valid orientation names.

- Fixed several rotation and orientation bugs with windows and display modes, especially in iOS 8+.

- Fixed SDL_SetWindowFullscreen failing to update the status bar visibility on iOS 7+.

- Fixed the orientation of the offset applied to the window’s view when the onscreen keyboard is shown in iOS 8+.

- Fixed SDL_IsScreenKeyboardShown (patch by Phil Hassey.)

- Fixed several major memory leaks caused by missing autorelease pool blocks in the iOS-specific Objective-C code.

- Removed several dead code paths.

- The iOS 7 SDK (Xcode 5) or newer is now required to build SDL for iOS.
slouken@8582
     1
/*
slouken@8582
     2
  Simple DirectMedia Layer
slouken@8615
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@8582
     4
slouken@8582
     5
  This software is provided 'as-is', without any express or implied
slouken@8582
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@8582
     7
  arising from the use of this software.
slouken@8582
     8
slouken@8582
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@8582
    10
  including commercial applications, and to alter it and redistribute it
slouken@8582
    11
  freely, subject to the following restrictions:
slouken@8582
    12
slouken@8582
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@8582
    14
     claim that you wrote the original software. If you use this software
slouken@8582
    15
     in a product, an acknowledgment in the product documentation would be
slouken@8582
    16
     appreciated but is not required.
slouken@8582
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@8582
    18
     misrepresented as being the original software.
slouken@8582
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@8582
    20
*/
slouken@8609
    21
#include "../../SDL_internal.h"
slouken@8582
    22
slouken@8582
    23
#if SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL
slouken@8582
    24
slouken@8582
    25
/* EGL implementation of SDL OpenGL support */
slouken@8582
    26
slouken@8582
    27
#include "SDL_winrtvideo_cpp.h"
slouken@8582
    28
extern "C" {
slouken@8582
    29
#include "SDL_winrtopengles.h"
dludwig@8663
    30
#include "SDL_loadso.h"
slouken@8582
    31
}
slouken@8582
    32
dludwig@8663
    33
/* Windows includes */
dludwig@8663
    34
#include <wrl/client.h>
dludwig@8663
    35
using namespace Windows::UI::Core;
dludwig@8663
    36
dludwig@8663
    37
/* ANGLE/WinRT constants */
dludwig@8663
    38
static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
dludwig@9386
    39
#define EGL_PLATFORM_ANGLE_ANGLE                        0x3202
dludwig@9386
    40
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE                   0x3203
dludwig@9386
    41
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE      0x3204
dludwig@9386
    42
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE      0x3205
dludwig@9386
    43
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE             0x3208
dludwig@9386
    44
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE            0x3209
dludwig@9386
    45
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE       0x320B
dludwig@9386
    46
#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE  0x320F
dludwig@9386
    47
dludwig@9350
    48
#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER   0x320B
dludwig@9350
    49
dludwig@8663
    50
dludwig@8663
    51
/*
dludwig@8663
    52
 * SDL/EGL top-level implementation
dludwig@8663
    53
 */
slouken@8582
    54
slouken@8582
    55
extern "C" int
dludwig@8663
    56
WINRT_GLES_LoadLibrary(_THIS, const char *path)
dludwig@8663
    57
{
dludwig@8663
    58
    SDL_VideoData *video_data = (SDL_VideoData *)_this->driverdata;
dludwig@8663
    59
dludwig@8663
    60
    if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY) != 0) {
dludwig@8663
    61
        return -1;
dludwig@8663
    62
    }
dludwig@8663
    63
dludwig@8663
    64
    /* Load ANGLE/WinRT-specific functions */
dludwig@9211
    65
    CreateWinrtEglWindow_Old_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Old_Function) SDL_LoadFunction(_this->egl_data->egl_dll_handle, "CreateWinrtEglWindow");
dludwig@9211
    66
    if (CreateWinrtEglWindow) {
dludwig@9211
    67
        /* 'CreateWinrtEglWindow' was found, which means that an an older
dludwig@9211
    68
         * version of ANGLE/WinRT is being used.  Continue setting up EGL,
dludwig@9211
    69
         * as appropriate to this version of ANGLE.
dludwig@9211
    70
         */
dludwig@9211
    71
dludwig@9211
    72
        /* Create an ANGLE/WinRT EGL-window */
dludwig@9211
    73
        /* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */
dludwig@9211
    74
        CoreWindow ^ native_win = CoreWindow::GetForCurrentThread();
dludwig@9211
    75
        Microsoft::WRL::ComPtr<IUnknown> cpp_win = reinterpret_cast<IUnknown *>(native_win);
dludwig@9211
    76
        HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow));
dludwig@9211
    77
        if (FAILED(result)) {
dludwig@9211
    78
            return -1;
dludwig@9211
    79
        }
dludwig@9211
    80
dludwig@9211
    81
        /* Call eglGetDisplay and eglInitialize as appropriate.  On other
dludwig@9211
    82
         * platforms, this would probably get done by SDL_EGL_LoadLibrary,
dludwig@9211
    83
         * however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of
dludwig@9211
    84
         * eglGetDisplay requires that a C++ object be passed into it, so the
dludwig@9211
    85
         * call will be made in this file, a C++ file, instead.
dludwig@9211
    86
         */
dludwig@9211
    87
        Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
dludwig@9211
    88
        _this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display);
dludwig@9211
    89
        if (!_this->egl_data->egl_display) {
dludwig@9384
    90
            return SDL_SetError("Could not get Windows 8.0 EGL display");
dludwig@9211
    91
        }
dludwig@9350
    92
dludwig@9350
    93
        if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
dludwig@9384
    94
            return SDL_SetError("Could not initialize Windows 8.0 EGL");
dludwig@9350
    95
        }
dludwig@9211
    96
    } else {
dludwig@9350
    97
        /* Declare some ANGLE/EGL initialization property-sets, as suggested by
dludwig@9350
    98
         * MSOpenTech's ANGLE-for-WinRT template apps:
dludwig@9350
    99
         */
dludwig@9350
   100
        const EGLint defaultDisplayAttributes[] =
dludwig@9350
   101
        {
dludwig@9211
   102
            EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
dludwig@9386
   103
            EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
dludwig@9386
   104
            EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
dludwig@9350
   105
            EGL_NONE,
dludwig@9350
   106
        };
dludwig@9350
   107
dludwig@9350
   108
        const EGLint fl9_3DisplayAttributes[] =
dludwig@9350
   109
        {
dludwig@9350
   110
            EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
dludwig@9350
   111
            EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
dludwig@9350
   112
            EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
dludwig@9386
   113
            EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
dludwig@9386
   114
            EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
dludwig@9350
   115
            EGL_NONE,
dludwig@9350
   116
        };
dludwig@9350
   117
dludwig@9350
   118
        const EGLint warpDisplayAttributes[] =
dludwig@9350
   119
        {
dludwig@9350
   120
            EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
dludwig@9386
   121
            EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
dludwig@9386
   122
            EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
dludwig@9386
   123
            EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
dludwig@9211
   124
            EGL_NONE,
dludwig@9211
   125
        };
dludwig@9211
   126
dludwig@9211
   127
        /* 'CreateWinrtEglWindow' was NOT found, which either means that a
dludwig@9211
   128
         * newer version of ANGLE/WinRT is being used, or that we don't have
dludwig@9211
   129
         * a valid copy of ANGLE.
dludwig@9211
   130
         *
dludwig@9211
   131
         * Try loading ANGLE as if it were the newer version.
dludwig@9211
   132
         */
dludwig@9211
   133
        eglGetPlatformDisplayEXT_Function eglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_Function)_this->egl_data->eglGetProcAddress("eglGetPlatformDisplayEXT");
dludwig@9211
   134
        if (!eglGetPlatformDisplayEXT) {
dludwig@9211
   135
            return SDL_SetError("Could not retrieve ANGLE/WinRT display function(s)");
dludwig@9211
   136
        }
dludwig@9211
   137
dludwig@9350
   138
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
dludwig@9350
   139
        /* Try initializing EGL at D3D11 Feature Level 10_0+ (which is not
dludwig@9350
   140
         * supported on WinPhone 8.x.
dludwig@9350
   141
         */
dludwig@9350
   142
        _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
dludwig@9211
   143
        if (!_this->egl_data->egl_display) {
dludwig@9385
   144
            return SDL_SetError("Could not get 10_0+ EGL display");
dludwig@9211
   145
        }
dludwig@8663
   146
dludwig@9350
   147
        if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE)
dludwig@9350
   148
#endif
dludwig@9350
   149
        {
dludwig@9350
   150
            /* Try initializing EGL at D3D11 Feature Level 9_3, in case the
dludwig@9350
   151
             * 10_0 init fails, or we're on Windows Phone (which only supports
dludwig@9350
   152
             * 9_3).
dludwig@9350
   153
             */
dludwig@9350
   154
            _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
dludwig@9350
   155
            if (!_this->egl_data->egl_display) {
dludwig@9350
   156
                return SDL_SetError("Could not get 9_3 EGL display");
dludwig@9350
   157
            }
dludwig@9350
   158
dludwig@9350
   159
            if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
dludwig@9350
   160
                /* Try initializing EGL at D3D11 Feature Level 11_0 on WARP
dludwig@9350
   161
                 * (a Windows-provided, software rasterizer) if all else fails.
dludwig@9350
   162
                 */
dludwig@9350
   163
                _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
dludwig@9350
   164
                if (!_this->egl_data->egl_display) {
dludwig@9350
   165
                    return SDL_SetError("Could not get WARP EGL display");
dludwig@9350
   166
                }
dludwig@9350
   167
dludwig@9350
   168
                if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
dludwig@9384
   169
                    return SDL_SetError("Could not initialize WinRT 8.x+ EGL");
dludwig@9350
   170
                }
dludwig@9350
   171
            }
dludwig@9350
   172
        }
dludwig@8663
   173
    }
dludwig@8663
   174
dludwig@8663
   175
    return 0;
dludwig@8663
   176
}
dludwig@8663
   177
dludwig@8663
   178
extern "C" void
dludwig@8663
   179
WINRT_GLES_UnloadLibrary(_THIS)
dludwig@8663
   180
{
dludwig@8663
   181
    SDL_VideoData *video_data = (SDL_VideoData *)_this->driverdata;
dludwig@8663
   182
dludwig@8663
   183
    /* Release SDL's own COM reference to the ANGLE/WinRT IWinrtEglWindow */
dludwig@8663
   184
    if (video_data->winrtEglWindow) {
dludwig@8663
   185
        video_data->winrtEglWindow->Release();
dludwig@8663
   186
        video_data->winrtEglWindow = nullptr;
dludwig@8663
   187
    }
dludwig@8663
   188
dludwig@8663
   189
    /* Perform the bulk of the unloading */
dludwig@8663
   190
    SDL_EGL_UnloadLibrary(_this);
slouken@8582
   191
}
slouken@8582
   192
slouken@8582
   193
extern "C" {
slouken@8582
   194
SDL_EGL_CreateContext_impl(WINRT)
slouken@8582
   195
SDL_EGL_SwapWindow_impl(WINRT)
slouken@8582
   196
SDL_EGL_MakeCurrent_impl(WINRT)
slouken@8582
   197
}
slouken@8582
   198
slouken@8582
   199
#endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */
slouken@8582
   200
slouken@8582
   201
/* vi: set ts=4 sw=4 expandtab: */
slouken@8582
   202