src/video/uikit/SDL_uikitopengles.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 09 Dec 2016 01:47:43 -0800
changeset 10690 23a825f341e6
parent 10143 14719cd1bde2
child 10721 88943d97bf00
permissions -rw-r--r--
Fixed bug 3513 - SDL_GL_SwapWindow does not return error status

Return an error code from SDL_GL_SwapWindow(), like the other SDL APIs.
slouken@2765
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
slouken@5262
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@5262
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@5262
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@5262
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@6044
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_UIKIT
slouken@2765
    24
slouken@2765
    25
#include "SDL_uikitopengles.h"
slime73@9532
    26
#import "SDL_uikitopenglview.h"
slouken@6518
    27
#include "SDL_uikitmodes.h"
slouken@2765
    28
#include "SDL_uikitwindow.h"
slime73@9532
    29
#include "SDL_uikitevents.h"
slouken@6321
    30
#include "../SDL_sysvideo.h"
slouken@4490
    31
#include "../../events/SDL_keyboard_c.h"
slouken@4490
    32
#include "../../events/SDL_mouse_c.h"
slouken@6044
    33
#include "../../power/uikit/SDL_syspower.h"
slouken@2765
    34
#include "SDL_loadso.h"
slouken@2765
    35
#include <dlfcn.h>
slouken@2765
    36
slime73@9727
    37
@interface SDLEAGLContext : EAGLContext
slime73@9727
    38
slime73@9727
    39
/* The OpenGL ES context owns a view / drawable. */
slime73@9727
    40
@property (nonatomic, strong) SDL_uikitopenglview *sdlView;
slime73@9727
    41
slime73@9727
    42
@end
slime73@9727
    43
slime73@9727
    44
@implementation SDLEAGLContext
slime73@9727
    45
slime73@9727
    46
- (void)dealloc
slime73@9727
    47
{
slime73@9727
    48
    /* When the context is deallocated, its view should be removed from any
slime73@9727
    49
     * SDL window that it's attached to. */
slime73@9727
    50
    [self.sdlView setSDLWindow:NULL];
slime73@9727
    51
}
slime73@9727
    52
slime73@9727
    53
@end
slime73@9727
    54
slouken@2765
    55
void *
slouken@2765
    56
UIKit_GL_GetProcAddress(_THIS, const char *proc)
kees@6001
    57
{
slouken@5131
    58
    /* Look through all SO's for the proc symbol.  Here's why:
slime73@9532
    59
     * -Looking for the path to the OpenGL Library seems not to work in the iOS Simulator.
slime73@9532
    60
     * -We don't know that the path won't change in the future. */
slouken@5363
    61
    return dlsym(RTLD_DEFAULT, proc);
slouken@2765
    62
}
slouken@2765
    63
slouken@2765
    64
/*
slime73@9532
    65
  note that SDL_GL_DeleteContext makes it current without passing the window
slouken@2765
    66
*/
slime73@9488
    67
int
slime73@9488
    68
UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@2765
    69
{
slime73@9506
    70
    @autoreleasepool {
slime73@9532
    71
        SDLEAGLContext *eaglcontext = (__bridge SDLEAGLContext *) context;
slime73@9532
    72
slime73@9532
    73
        if (![EAGLContext setCurrentContext:eaglcontext]) {
slime73@9532
    74
            return SDL_SetError("Could not make EAGL context current");
slime73@9532
    75
        }
slime73@9532
    76
slime73@9532
    77
        if (eaglcontext) {
slime73@9532
    78
            [eaglcontext.sdlView setSDLWindow:window];
slime73@9532
    79
        }
slouken@8583
    80
    }
slime73@9532
    81
slouken@2765
    82
    return 0;
slouken@2765
    83
}
slouken@2765
    84
slime73@9529
    85
void
slime73@9529
    86
UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
slime73@9488
    87
{
slime73@9510
    88
    @autoreleasepool {
slime73@9510
    89
        SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
slime73@9532
    90
        UIView *view = data.viewcontroller.view;
slime73@9532
    91
        if ([view isKindOfClass:[SDL_uikitopenglview class]]) {
slime73@9532
    92
            SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view;
slime73@9532
    93
            if (w) {
slime73@9532
    94
                *w = glview.backingWidth;
slime73@9532
    95
            }
slime73@9532
    96
            if (h) {
slime73@9532
    97
                *h = glview.backingHeight;
slime73@9532
    98
            }
slime73@9506
    99
        }
slime73@9488
   100
    }
slime73@9488
   101
}
slime73@9488
   102
slouken@2765
   103
int
slouken@2765
   104
UIKit_GL_LoadLibrary(_THIS, const char *path)
slouken@2765
   105
{
slime73@9532
   106
    /* We shouldn't pass a path to this function, since we've already loaded the
slime73@9532
   107
     * library. */
slouken@2765
   108
    if (path != NULL) {
slime73@9532
   109
        return SDL_SetError("iOS GL Load Library just here for compatibility");
slouken@2765
   110
    }
slouken@2765
   111
    return 0;
slouken@2765
   112
}
slouken@2765
   113
slouken@10690
   114
int UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@2765
   115
{
slime73@9506
   116
    @autoreleasepool {
slime73@9532
   117
        SDLEAGLContext *context = (__bridge SDLEAGLContext *) SDL_GL_GetCurrentContext();
slime73@9510
   118
icculus@6088
   119
#if SDL_POWER_UIKIT
slime73@9506
   120
        /* Check once a frame to see if we should turn off the battery monitor. */
slime73@9506
   121
        SDL_UIKit_UpdateBatteryMonitoring();
kees@6003
   122
#endif
slouken@2765
   123
slime73@9532
   124
        [context.sdlView swapBuffers];
kees@6001
   125
slime73@9506
   126
        /* You need to pump events in order for the OS to make changes visible.
slime73@9532
   127
         * We don't pump events here because we don't want iOS application events
slime73@9532
   128
         * (low memory, terminate, etc.) to happen inside low level rendering. */
slouken@5131
   129
    }
slouken@10690
   130
    return 0;
slouken@2765
   131
}
slouken@2765
   132
slime73@9488
   133
SDL_GLContext
slime73@9488
   134
UIKit_GL_CreateContext(_THIS, SDL_Window * window)
slouken@2765
   135
{
slime73@9506
   136
    @autoreleasepool {
slime73@9727
   137
        SDLEAGLContext *context = nil;
slime73@9506
   138
        SDL_uikitopenglview *view;
slime73@9510
   139
        SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
slime73@9532
   140
        CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
slime73@9532
   141
        EAGLSharegroup *sharegroup = nil;
slime73@9506
   142
        CGFloat scale = 1.0;
slime73@9810
   143
        int samples = 0;
slime73@10143
   144
        int major = _this->gl_config.major_version;
slime73@10143
   145
        int minor = _this->gl_config.minor_version;
icculus@7423
   146
slime73@9727
   147
        /* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
slime73@9727
   148
         * versions. */
slime73@10143
   149
        EAGLRenderingAPI api = major;
slime73@10143
   150
slime73@10143
   151
        /* iOS currently doesn't support GLES >3.0. iOS 6 also only supports up
slime73@10143
   152
         * to GLES 2.0. */
slime73@10143
   153
        if (major > 3 || (major == 3 && (minor > 0 || !UIKit_IsSystemVersionAtLeast(7.0)))) {
slime73@10143
   154
            SDL_SetError("OpenGL ES %d.%d context could not be created", major, minor);
slime73@10143
   155
            return NULL;
slime73@10143
   156
        }
slime73@9727
   157
slime73@9810
   158
        if (_this->gl_config.multisamplebuffers > 0) {
slime73@9810
   159
            samples = _this->gl_config.multisamplesamples;
slime73@9810
   160
        }
slime73@9810
   161
slime73@9532
   162
        if (_this->gl_config.share_with_current_context) {
slime73@9532
   163
            EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
slime73@9532
   164
            sharegroup = context.sharegroup;
slime73@9532
   165
        }
slime73@9532
   166
slime73@9506
   167
        if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
slime73@9517
   168
            /* Set the scale to the natural scale factor of the screen - the
slime73@9532
   169
             * backing dimensions of the OpenGL view will match the pixel
slime73@9532
   170
             * dimensions of the screen rather than the dimensions in points. */
slime73@9517
   171
#ifdef __IPHONE_8_0
slime73@9532
   172
            if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
slime73@9532
   173
                scale = data.uiwindow.screen.nativeScale;
slime73@9517
   174
            } else
slime73@9517
   175
#endif
slime73@9517
   176
            {
slime73@9532
   177
                scale = data.uiwindow.screen.scale;
slime73@9517
   178
            }
slime73@9506
   179
        }
slime73@9506
   180
slime73@9727
   181
        context = [[SDLEAGLContext alloc] initWithAPI:api sharegroup:sharegroup];
slime73@9727
   182
        if (!context) {
slime73@9727
   183
            SDL_SetError("OpenGL ES %d context could not be created", _this->gl_config.major_version);
slime73@9727
   184
            return NULL;
slime73@9727
   185
        }
slime73@9727
   186
slime73@9506
   187
        /* construct our view, passing in SDL's OpenGL configuration data */
slime73@9524
   188
        view = [[SDL_uikitopenglview alloc] initWithFrame:frame
slime73@9524
   189
                                                    scale:scale
slime73@9524
   190
                                            retainBacking:_this->gl_config.retained_backing
slime73@9524
   191
                                                    rBits:_this->gl_config.red_size
slime73@9524
   192
                                                    gBits:_this->gl_config.green_size
slime73@9524
   193
                                                    bBits:_this->gl_config.blue_size
slime73@9524
   194
                                                    aBits:_this->gl_config.alpha_size
slime73@9524
   195
                                                depthBits:_this->gl_config.depth_size
slime73@9524
   196
                                              stencilBits:_this->gl_config.stencil_size
slime73@9524
   197
                                                     sRGB:_this->gl_config.framebuffer_srgb_capable
slime73@9810
   198
                                             multisamples:samples
slime73@9727
   199
                                                  context:context];
slime73@9727
   200
slime73@9506
   201
        if (!view) {
slime73@9506
   202
            return NULL;
slime73@9506
   203
        }
slime73@9506
   204
slime73@9727
   205
        /* The context owns the view / drawable. */
slime73@9727
   206
        context.sdlView = view;
slime73@9727
   207
slime73@9512
   208
        if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
slime73@9512
   209
            UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
slime73@9506
   210
            return NULL;
slime73@9506
   211
        }
slime73@9506
   212
slime73@9532
   213
        /* We return a +1'd context. The window's driverdata owns the view (via
slime73@9532
   214
         * MakeCurrent.) */
slime73@9512
   215
        return (SDL_GLContext) CFBridgingRetain(context);
icculus@7423
   216
    }
slouken@2765
   217
}
slouken@2765
   218
slime73@9488
   219
void
slime73@9488
   220
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@2765
   221
{
slime73@9506
   222
    @autoreleasepool {
slime73@9727
   223
        /* The context was retained in SDL_GL_CreateContext, so we release it
slime73@9727
   224
         * here. The context's view will be detached from its window when the
slime73@9727
   225
         * context is deallocated. */
slime73@9727
   226
        CFRelease(context);
icculus@5520
   227
    }
slouken@2765
   228
}
slouken@2765
   229
slime73@10141
   230
void
slime73@10141
   231
UIKit_GL_RestoreCurrentContext()
slime73@10141
   232
{
slime73@10141
   233
    @autoreleasepool {
slime73@10141
   234
        /* Some iOS system functionality (such as Dictation on the on-screen
slime73@10141
   235
         keyboard) uses its own OpenGL ES context but doesn't restore the
slime73@10141
   236
         previous one when it's done. This is a workaround to make sure the
slime73@10141
   237
         expected SDL-created OpenGL ES context is active after the OS is
slime73@10141
   238
         finished running its own code for the frame. If this isn't done, the
slime73@10141
   239
         app may crash or have other nasty symptoms when Dictation is used.
slime73@10141
   240
         */
slime73@10141
   241
        EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
slime73@10141
   242
        if (context != NULL && [EAGLContext currentContext] != context) {
slime73@10141
   243
            [EAGLContext setCurrentContext:context];
slime73@10141
   244
        }
slime73@10141
   245
    }
slime73@10141
   246
}
slime73@10141
   247
slouken@6044
   248
#endif /* SDL_VIDEO_DRIVER_UIKIT */
slouken@6044
   249
slouken@5132
   250
/* vi: set ts=4 sw=4 expandtab: */