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