src/video/uikit/SDL_uikitopenglview.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Oct 2011 05:56:58 -0400
changeset 6044 35448a5ea044
parent 6022 e0327dd7d0c0
child 6085 fcffe5fdf54b
permissions -rw-r--r--
Lots of fixes importing SDL source wholesale into a new iOS project
slouken@2765
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@5535
     3
  Copyright (C) 1997-2011 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
*/
slouken@6044
    21
#include "SDL_config.h"
slouken@6044
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_UIKIT
slouken@2765
    24
slouken@2765
    25
#import <QuartzCore/QuartzCore.h>
slouken@2765
    26
#import <OpenGLES/EAGLDrawable.h>
slouken@2765
    27
#import "SDL_uikitopenglview.h"
slouken@2765
    28
slouken@2765
    29
slouken@2765
    30
@implementation SDL_uikitopenglview
slouken@2765
    31
slouken@2765
    32
@synthesize context;
slouken@2765
    33
kees@6003
    34
+ (Class)layerClass
kees@6003
    35
{
slouken@5129
    36
    return [CAEAGLLayer class];
slouken@2765
    37
}
slouken@2765
    38
kees@6003
    39
- (id)initWithFrame:(CGRect)frame
kees@6003
    40
      retainBacking:(BOOL)retained
kees@6003
    41
      rBits:(int)rBits
kees@6003
    42
      gBits:(int)gBits
kees@6003
    43
      bBits:(int)bBits
kees@6003
    44
      aBits:(int)aBits
kees@6003
    45
      depthBits:(int)depthBits
icculus@6021
    46
      stencilBits:(int)stencilBits
kees@6003
    47
      majorVersion:(int)majorVersion
slouken@2765
    48
{
icculus@5527
    49
    depthBufferFormat = 0;
icculus@5527
    50
icculus@6022
    51
    if ((self = [super initWithFrame:frame])) {
icculus@6022
    52
        const BOOL useStencilBuffer = (stencilBits != 0);
icculus@6022
    53
        const BOOL useDepthBuffer = (depthBits != 0);
icculus@6022
    54
        NSString *colorFormat = nil;
icculus@6022
    55
icculus@6022
    56
        if (rBits == 8 && gBits == 8 && bBits == 8) {
icculus@6022
    57
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
icculus@6022
    58
            colorFormat = kEAGLColorFormatRGBA8;
icculus@6022
    59
        } else {
icculus@6022
    60
            /* default case (faster) */
icculus@6022
    61
            colorFormat = kEAGLColorFormatRGB565;
icculus@6021
    62
        }
kees@6001
    63
icculus@6022
    64
        /* Get the layer */
slouken@5129
    65
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
kees@6001
    66
slouken@5129
    67
        eaglLayer.opaque = YES;
slouken@5129
    68
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
slouken@5129
    69
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
kees@6001
    70
slouken@5209
    71
        if (majorVersion > 1) {
slouken@5209
    72
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
slouken@5209
    73
        } else {
slouken@5209
    74
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
slouken@5209
    75
        }
slouken@5129
    76
        if (!context || ![EAGLContext setCurrentContext:context]) {
slouken@5129
    77
            [self release];
slouken@5129
    78
            return nil;
slouken@5129
    79
        }
kees@6001
    80
slouken@5129
    81
        /* create the buffers */
slouken@5129
    82
        glGenFramebuffersOES(1, &viewFramebuffer);
slouken@5129
    83
        glGenRenderbuffersOES(1, &viewRenderbuffer);
kees@6001
    84
slouken@5129
    85
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
slouken@5129
    86
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
slouken@5129
    87
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
slouken@5129
    88
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
kees@6001
    89
slouken@5129
    90
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
slouken@5129
    91
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
icculus@5527
    92
icculus@6021
    93
        if ((useDepthBuffer) || (useStencilBuffer)) {
icculus@6021
    94
            if (useStencilBuffer) {
icculus@6022
    95
                /* Apparently you need to pack stencil and depth into one buffer. */
icculus@6021
    96
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
icculus@6022
    97
            } else if (useDepthBuffer) {
icculus@6022
    98
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
icculus@6022
    99
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
icculus@6021
   100
            }
icculus@6022
   101
slouken@5129
   102
            glGenRenderbuffersOES(1, &depthRenderbuffer);
slouken@5129
   103
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
slouken@5129
   104
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
icculus@6021
   105
            if (useDepthBuffer) {
icculus@6021
   106
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
icculus@6021
   107
            }
icculus@6021
   108
            if (useStencilBuffer) {
icculus@6021
   109
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
icculus@6021
   110
            }
slouken@5129
   111
        }
kees@6001
   112
kees@6003
   113
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
slouken@5129
   114
            return NO;
slouken@5129
   115
        }
slouken@5129
   116
        /* end create buffers */
slouken@5130
   117
icculus@5520
   118
        // !!! FIXME: use the screen this is on!
slouken@5130
   119
        /* Use the main screen scale (for retina display support) */
slouken@5130
   120
        if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
slouken@5130
   121
            self.contentScaleFactor = [UIScreen mainScreen].scale;
icculus@5520
   122
icculus@5527
   123
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
slouken@5129
   124
    }
slouken@5129
   125
    return self;
slouken@2765
   126
}
slouken@2765
   127
kees@6003
   128
- (void)updateFrame
kees@6003
   129
{
icculus@5527
   130
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
icculus@5527
   131
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
icculus@5527
   132
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, 0);
icculus@5527
   133
    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
icculus@5527
   134
icculus@5527
   135
    glGenRenderbuffersOES(1, &viewRenderbuffer);
icculus@5527
   136
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
icculus@5527
   137
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
kees@6001
   138
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
icculus@5527
   139
icculus@5527
   140
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
icculus@5527
   141
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
icculus@5527
   142
icculus@5527
   143
    if (depthRenderbuffer != 0) {
icculus@5527
   144
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
icculus@5527
   145
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
icculus@5527
   146
    }
kees@6001
   147
icculus@5527
   148
    // !!! FIXME: use the screen this is on!
icculus@5527
   149
    /* Use the main screen scale (for retina display support) */
icculus@5527
   150
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
icculus@5527
   151
        self.contentScaleFactor = [UIScreen mainScreen].scale;
icculus@5527
   152
}
icculus@5527
   153
kees@6003
   154
- (void)setCurrentContext
kees@6003
   155
{
slouken@5129
   156
    [EAGLContext setCurrentContext:context];
slouken@2765
   157
}
slouken@2765
   158
slouken@2765
   159
kees@6003
   160
- (void)swapBuffers
kees@6003
   161
{
slouken@5129
   162
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
slouken@5129
   163
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
slouken@2765
   164
}
slouken@2765
   165
slouken@2765
   166
kees@6003
   167
- (void)layoutSubviews
kees@6003
   168
{
slouken@5129
   169
    [EAGLContext setCurrentContext:context];
slouken@2765
   170
}
slouken@2765
   171
kees@6003
   172
- (void)destroyFramebuffer
kees@6003
   173
{
slouken@5129
   174
    glDeleteFramebuffersOES(1, &viewFramebuffer);
slouken@5129
   175
    viewFramebuffer = 0;
slouken@5129
   176
    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
slouken@5129
   177
    viewRenderbuffer = 0;
kees@6001
   178
slouken@5129
   179
    if (depthRenderbuffer) {
slouken@5129
   180
        glDeleteRenderbuffersOES(1, &depthRenderbuffer);
slouken@5129
   181
        depthRenderbuffer = 0;
slouken@5129
   182
    }
slouken@2765
   183
}
slouken@2765
   184
slouken@2765
   185
kees@6003
   186
- (void)dealloc
kees@6003
   187
{
slouken@5129
   188
    [self destroyFramebuffer];
slouken@5129
   189
    if ([EAGLContext currentContext] == context) {
slouken@5129
   190
        [EAGLContext setCurrentContext:nil];
slouken@5129
   191
    }
kees@6001
   192
    [context release];
slouken@5129
   193
    [super dealloc];
slouken@2765
   194
}
slouken@2765
   195
slouken@2859
   196
@end
slouken@5132
   197
slouken@6044
   198
#endif /* SDL_VIDEO_DRIVER_UIKIT */
slouken@6044
   199
slouken@5132
   200
/* vi: set ts=4 sw=4 expandtab: */