SDL_uikitopenglview.m 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #if SDL_VIDEO_DRIVER_UIKIT
  20. #include <QuartzCore/QuartzCore.h>
  21. #include <OpenGLES/EAGLDrawable.h>
  22. #include "SDL_uikitopenglview.h"
  23. #include "SDL_uikitmessagebox.h"
  24. @implementation SDL_uikitopenglview
  25. @synthesize context;
  26. + (Class)layerClass
  27. {
  28. return [CAEAGLLayer class];
  29. }
  30. - (id)initWithFrame:(CGRect)frame
  31. scale:(CGFloat)scale
  32. retainBacking:(BOOL)retained
  33. rBits:(int)rBits
  34. gBits:(int)gBits
  35. bBits:(int)bBits
  36. aBits:(int)aBits
  37. depthBits:(int)depthBits
  38. stencilBits:(int)stencilBits
  39. majorVersion:(int)majorVersion
  40. shareGroup:(EAGLSharegroup*)shareGroup
  41. {
  42. depthBufferFormat = 0;
  43. if ((self = [super initWithFrame:frame])) {
  44. const BOOL useStencilBuffer = (stencilBits != 0);
  45. const BOOL useDepthBuffer = (depthBits != 0);
  46. NSString *colorFormat = nil;
  47. /* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
  48. versions, and this allows us to handle future OpenGL ES versions.
  49. */
  50. EAGLRenderingAPI api = majorVersion;
  51. if (rBits == 8 && gBits == 8 && bBits == 8) {
  52. /* if user specifically requests rbg888 or some color format higher than 16bpp */
  53. colorFormat = kEAGLColorFormatRGBA8;
  54. } else {
  55. /* default case (faster) */
  56. colorFormat = kEAGLColorFormatRGB565;
  57. }
  58. /* Get the layer */
  59. CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
  60. eaglLayer.opaque = YES;
  61. eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
  62. [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
  63. context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
  64. if (!context || ![EAGLContext setCurrentContext:context]) {
  65. [self release];
  66. SDL_SetError("OpenGL ES %d not supported", majorVersion);
  67. return nil;
  68. }
  69. /* Set the appropriate scale (for retina display support) */
  70. if ([self respondsToSelector:@selector(contentScaleFactor)])
  71. self.contentScaleFactor = scale;
  72. /* create the buffers */
  73. glGenFramebuffersOES(1, &viewFramebuffer);
  74. glGenRenderbuffersOES(1, &viewRenderbuffer);
  75. glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
  76. glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  77. [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
  78. glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
  79. glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
  80. glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
  81. if ((useDepthBuffer) || (useStencilBuffer)) {
  82. if (useStencilBuffer) {
  83. /* Apparently you need to pack stencil and depth into one buffer. */
  84. depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
  85. } else if (useDepthBuffer) {
  86. /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
  87. depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
  88. }
  89. glGenRenderbuffersOES(1, &depthRenderbuffer);
  90. glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
  91. glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
  92. if (useDepthBuffer) {
  93. glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
  94. }
  95. if (useStencilBuffer) {
  96. glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
  97. }
  98. }
  99. if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
  100. return NO;
  101. }
  102. glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  103. /* end create buffers */
  104. self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
  105. self.autoresizesSubviews = YES;
  106. }
  107. return self;
  108. }
  109. - (void)updateFrame
  110. {
  111. glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
  112. glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
  113. glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, 0);
  114. glDeleteRenderbuffersOES(1, &viewRenderbuffer);
  115. glGenRenderbuffersOES(1, &viewRenderbuffer);
  116. glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  117. [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
  118. glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
  119. glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
  120. glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
  121. if (depthRenderbuffer != 0) {
  122. glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
  123. glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
  124. }
  125. glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  126. }
  127. - (void)setAnimationCallback:(int)interval
  128. callback:(void (*)(void*))callback
  129. callbackParam:(void*)callbackParam
  130. {
  131. [self stopAnimation];
  132. animationInterval = interval;
  133. animationCallback = callback;
  134. animationCallbackParam = callbackParam;
  135. if (animationCallback)
  136. [self startAnimation];
  137. }
  138. - (void)startAnimation
  139. {
  140. /* CADisplayLink is API new to iPhone SDK 3.1.
  141. * Compiling against earlier versions will result in a warning, but can be dismissed
  142. * if the system version runtime check for CADisplayLink exists in -initWithCoder:.
  143. */
  144. displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
  145. [displayLink setFrameInterval:animationInterval];
  146. [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  147. }
  148. - (void)stopAnimation
  149. {
  150. [displayLink invalidate];
  151. displayLink = nil;
  152. }
  153. - (void)doLoop:(id)sender
  154. {
  155. /* Don't run the game loop while a messagebox is up */
  156. if (!UIKit_ShowingMessageBox()) {
  157. animationCallback(animationCallbackParam);
  158. }
  159. }
  160. - (void)setCurrentContext
  161. {
  162. [EAGLContext setCurrentContext:context];
  163. }
  164. - (void)swapBuffers
  165. {
  166. /* viewRenderbuffer should always be bound here. Code that binds something
  167. else is responsible for rebinding viewRenderbuffer, to reduce
  168. duplicate state changes. */
  169. [context presentRenderbuffer:GL_RENDERBUFFER_OES];
  170. }
  171. - (void)layoutSubviews
  172. {
  173. [EAGLContext setCurrentContext:context];
  174. [self updateFrame];
  175. }
  176. - (void)destroyFramebuffer
  177. {
  178. glDeleteFramebuffersOES(1, &viewFramebuffer);
  179. viewFramebuffer = 0;
  180. glDeleteRenderbuffersOES(1, &viewRenderbuffer);
  181. viewRenderbuffer = 0;
  182. if (depthRenderbuffer) {
  183. glDeleteRenderbuffersOES(1, &depthRenderbuffer);
  184. depthRenderbuffer = 0;
  185. }
  186. }
  187. - (void)dealloc
  188. {
  189. [self destroyFramebuffer];
  190. if ([EAGLContext currentContext] == context) {
  191. [EAGLContext setCurrentContext:nil];
  192. }
  193. [context release];
  194. [super dealloc];
  195. }
  196. @end
  197. #endif /* SDL_VIDEO_DRIVER_UIKIT */
  198. /* vi: set ts=4 sw=4 expandtab: */