src/video/uikit/SDL_uikitopenglview.m
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 11:28:44 -0700
changeset 7776 d4a39491577f
parent 7423 dfe7ad02f008
child 7784 70b305e09b4e
permissions -rw-r--r--
Added the platform specific messagebox function to the video function list
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_UIKIT
    24 
    25 #include <QuartzCore/QuartzCore.h>
    26 #include <OpenGLES/EAGLDrawable.h>
    27 #include "SDL_uikitopenglview.h"
    28 #include "SDL_uikitmessagebox.h"
    29 
    30 
    31 @implementation SDL_uikitopenglview
    32 
    33 @synthesize context;
    34 
    35 + (Class)layerClass
    36 {
    37     return [CAEAGLLayer class];
    38 }
    39 
    40 - (id)initWithFrame:(CGRect)frame
    41       scale:(CGFloat)scale
    42       retainBacking:(BOOL)retained
    43       rBits:(int)rBits
    44       gBits:(int)gBits
    45       bBits:(int)bBits
    46       aBits:(int)aBits
    47       depthBits:(int)depthBits
    48       stencilBits:(int)stencilBits
    49       majorVersion:(int)majorVersion
    50       shareGroup:(EAGLSharegroup*)shareGroup
    51 {
    52     depthBufferFormat = 0;
    53 
    54     if ((self = [super initWithFrame:frame])) {
    55         const BOOL useStencilBuffer = (stencilBits != 0);
    56         const BOOL useDepthBuffer = (depthBits != 0);
    57         NSString *colorFormat = nil;
    58 
    59         if (rBits == 8 && gBits == 8 && bBits == 8) {
    60             /* if user specifically requests rbg888 or some color format higher than 16bpp */
    61             colorFormat = kEAGLColorFormatRGBA8;
    62         } else {
    63             /* default case (faster) */
    64             colorFormat = kEAGLColorFormatRGB565;
    65         }
    66 
    67         /* Get the layer */
    68         CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
    69 
    70         eaglLayer.opaque = YES;
    71         eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
    72                                         [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
    73 
    74         if (majorVersion > 1) {
    75             context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:shareGroup];
    76         } else {
    77             context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:shareGroup];
    78         }
    79         if (!context || ![EAGLContext setCurrentContext:context]) {
    80             [self release];
    81             SDL_SetError("OpenGL ES %d not supported", majorVersion);
    82             return nil;
    83         }
    84 
    85         /* Set the appropriate scale (for retina display support) */
    86         if ([self respondsToSelector:@selector(contentScaleFactor)])
    87             self.contentScaleFactor = scale;
    88 
    89         /* create the buffers */
    90         glGenFramebuffersOES(1, &viewFramebuffer);
    91         glGenRenderbuffersOES(1, &viewRenderbuffer);
    92 
    93         glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    94         glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    95         [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
    96         glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
    97 
    98         glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    99         glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
   100 
   101         if ((useDepthBuffer) || (useStencilBuffer)) {
   102             if (useStencilBuffer) {
   103                 /* Apparently you need to pack stencil and depth into one buffer. */
   104                 depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
   105             } else if (useDepthBuffer) {
   106                 /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
   107                 depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
   108             }
   109 
   110             glGenRenderbuffersOES(1, &depthRenderbuffer);
   111             glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
   112             glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
   113             if (useDepthBuffer) {
   114                 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
   115             }
   116             if (useStencilBuffer) {
   117                 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
   118             }
   119         }
   120 
   121         if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
   122             return NO;
   123         }
   124         /* end create buffers */
   125 
   126         self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
   127         self.autoresizesSubviews = YES;
   128     }
   129     return self;
   130 }
   131 
   132 - (void)updateFrame
   133 {
   134     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
   135     glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
   136     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, 0);
   137     glDeleteRenderbuffersOES(1, &viewRenderbuffer);
   138 
   139     glGenRenderbuffersOES(1, &viewRenderbuffer);
   140     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
   141     [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
   142     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
   143 
   144     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
   145     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
   146 
   147     if (depthRenderbuffer != 0) {
   148         glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
   149         glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
   150     }
   151 }
   152 
   153 - (void)setAnimationCallback:(int)interval
   154     callback:(void (*)(void*))callback
   155     callbackParam:(void*)callbackParam
   156 {
   157     [self stopAnimation];
   158 
   159     animationInterval = interval;
   160     animationCallback = callback;
   161     animationCallbackParam = callbackParam;
   162 
   163     if (animationCallback)
   164         [self startAnimation];
   165 }
   166 
   167 - (void)startAnimation
   168 {
   169     /* CADisplayLink is API new to iPhone SDK 3.1.
   170      * Compiling against earlier versions will result in a warning, but can be dismissed
   171      * if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   172      */
   173     displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
   174     [displayLink setFrameInterval:animationInterval];
   175     [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   176 }
   177 
   178 - (void)stopAnimation
   179 {
   180     [displayLink invalidate];
   181     displayLink = nil;
   182 }
   183 
   184 - (void)doLoop:(id)sender
   185 {
   186     /* Don't run the game loop while a messagebox is up */
   187     if (!UIKit_ShowingMessageBox()) {
   188         animationCallback(animationCallbackParam);
   189     }
   190 }
   191 
   192 - (void)setCurrentContext
   193 {
   194     [EAGLContext setCurrentContext:context];
   195 }
   196 
   197 
   198 - (void)swapBuffers
   199 {
   200     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
   201     [context presentRenderbuffer:GL_RENDERBUFFER_OES];
   202 }
   203 
   204 
   205 - (void)layoutSubviews
   206 {
   207     [EAGLContext setCurrentContext:context];
   208     [self updateFrame];
   209 }
   210 
   211 - (void)destroyFramebuffer
   212 {
   213     glDeleteFramebuffersOES(1, &viewFramebuffer);
   214     viewFramebuffer = 0;
   215     glDeleteRenderbuffersOES(1, &viewRenderbuffer);
   216     viewRenderbuffer = 0;
   217 
   218     if (depthRenderbuffer) {
   219         glDeleteRenderbuffersOES(1, &depthRenderbuffer);
   220         depthRenderbuffer = 0;
   221     }
   222 }
   223 
   224 
   225 - (void)dealloc
   226 {
   227     [self destroyFramebuffer];
   228     if ([EAGLContext currentContext] == context) {
   229         [EAGLContext setCurrentContext:nil];
   230     }
   231     [context release];
   232     [super dealloc];
   233 }
   234 
   235 @end
   236 
   237 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   238 
   239 /* vi: set ts=4 sw=4 expandtab: */