diff options
-rw-r--r-- | backends/platform/ios7/ios7_video.h | 31 | ||||
-rw-r--r-- | backends/platform/ios7/ios7_video.mm | 500 |
2 files changed, 314 insertions, 217 deletions
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h index 96a0984882..bed552c7cf 100644 --- a/backends/platform/ios7/ios7_video.h +++ b/backends/platform/ios7/ios7_video.h @@ -28,8 +28,8 @@ #include <QuartzCore/QuartzCore.h> #include <OpenGLES/EAGL.h> -#include <OpenGLES/ES1/gl.h> -#include <OpenGLES/ES1/glext.h> +#include <OpenGLES/ES2/gl.h> +#include <OpenGLES/ES2/glext.h> #include "ios7_keyboard.h" #include "ios7_common.h" @@ -37,6 +37,11 @@ #include "common/list.h" #import "graphics/scaler.h" +typedef struct { + GLfloat x, y; + GLfloat u,v; +} GLVertex; + @interface iPhoneView : UIView { VideoContext _videoContext; @@ -51,19 +56,29 @@ GLuint _overlayTexture; GLuint _mouseCursorTexture; + GLuint _vertexShader; + GLuint _fragmentShader; + + GLuint _vertexBuffer; + + GLuint _screenSizeSlot; + GLuint _textureSlot; + GLuint _shakeSlot; + + GLuint _positionSlot; + GLuint _textureCoordSlot; + GLint _renderBufferWidth; GLint _renderBufferHeight; - GLfloat _gameScreenVertCoords[4 * 2]; - GLfloat _gameScreenTexCoords[4 * 2]; + GLVertex _gameScreenCoords[4]; CGRect _gameScreenRect; - GLfloat _overlayVertCoords[4 * 2]; - GLfloat _overlayTexCoords[4 * 2]; + GLVertex _overlayCoords[4]; CGRect _overlayRect; - GLfloat _mouseVertCoords[4 * 2]; - GLfloat _mouseTexCoords[4 * 2]; + GLVertex _mouseCoords[4]; + GLint _mouseHotspotX, _mouseHotspotY; GLint _mouseWidth, _mouseHeight; GLfloat _mouseScaleX, _mouseScaleY; diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm index 10900b4d55..fe2285253c 100644 --- a/backends/platform/ios7/ios7_video.mm +++ b/backends/platform/ios7/ios7_video.mm @@ -102,7 +102,7 @@ uint getSizeNextPOT(uint size) { kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGB565 }; - _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; // In case creating the OpenGL ES context failed, we will error out here. if (_context == nil) { @@ -111,66 +111,226 @@ uint getSizeNextPOT(uint size) { } if ([EAGLContext setCurrentContext:_context]) { - glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError(); - glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError(); + // glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError(); + // glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError(); + [self setupOpenGL]; + } +} - glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError(); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); - [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer]; +- (void)setupOpenGL { + [self setupFramebuffer]; + [self createOverlaySurface]; + [self compileShaders]; + [self setupVBOs]; + [self setupTextures]; - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); + [self finishGLSetup]; +} - // Retrieve the render buffer size. This *should* match the frame size, - // i.e. g_fullWidth and g_fullHeight. - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_renderBufferWidth); printOpenGLError(); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_renderBufferHeight); printOpenGLError(); +- (void)finishGLSetup { + glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError(); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError(); - if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { - NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); - return; - } - uint overlayWidth = MAX(_renderBufferWidth, _renderBufferHeight); - uint overlayHeight = MIN(_renderBufferWidth, _renderBufferHeight); - - if (iOS7_isBigDevice()) { - // On really big displays, like the iPad Pro, we scale the interface down - // so that the controls are not too small.. - while (overlayHeight > 1024) { - overlayWidth /= 2; - overlayHeight /= 2; - } + glUniform2f(_screenSizeSlot, _renderBufferWidth, _renderBufferHeight); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +- (void)freeOpenGL { + [self deleteTextures]; + [self deleteVBOs]; + [self deleteShaders]; + [self deleteFramebuffer]; +} + +- (void)rebuildFrameBuffer { + [self deleteFramebuffer]; + [self setupFramebuffer]; + [self finishGLSetup]; +} + +- (void)setupFramebuffer { + glGenRenderbuffers(1, &_viewRenderbuffer); + printOpenGLError(); + glBindRenderbuffer(GL_RENDERBUFFER, _viewRenderbuffer); + printOpenGLError(); + [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id <EAGLDrawable>) self.layer]; + + glGenFramebuffers(1, &_viewFramebuffer); + printOpenGLError(); + glBindFramebuffer(GL_FRAMEBUFFER, _viewFramebuffer); + printOpenGLError(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _viewRenderbuffer); + printOpenGLError(); + + // Retrieve the render buffer size. This *should* match the frame size, + // i.e. g_fullWidth and g_fullHeight. + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_renderBufferWidth); + printOpenGLError(); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_renderBufferHeight); + printOpenGLError(); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + return; + } +} + +- (void)createOverlaySurface { + uint overlayWidth = (uint) MAX(_renderBufferWidth, _renderBufferHeight); + uint overlayHeight = (uint) MIN(_renderBufferWidth, _renderBufferHeight); + + if (iOS7_isBigDevice()) { + // On really big displays, like the iPad Pro, we scale the interface down + // so that the controls are not too small.. + while (overlayHeight > 1024) { + overlayWidth /= 2; + overlayHeight /= 2; } - else { - // On small devices, we force the user interface to use the small theme - while (overlayHeight > 480) { - overlayWidth /= 2; - overlayHeight /= 2; - } + } + else { + // On small devices, we force the user interface to use the small theme + while (overlayHeight > 480) { + overlayWidth /= 2; + overlayHeight /= 2; } + } + + _videoContext.overlayWidth = overlayWidth; + _videoContext.overlayHeight = overlayHeight; + + uint overlayTextureWidthPOT = getSizeNextPOT(overlayWidth); + uint overlayTextureHeightPOT = getSizeNextPOT(overlayHeight); + + // Since the overlay size won't change the whole run, we can + // precalculate the texture coordinates for the overlay texture here + // and just use it later on. + GLfloat u = _videoContext.overlayWidth / (GLfloat) overlayTextureWidthPOT; + GLfloat v = _videoContext.overlayHeight / (GLfloat) overlayTextureHeightPOT; + _overlayCoords[0].x = 0; _overlayCoords[0].y = 0; _overlayCoords[0].u = 0; _overlayCoords[0].v = 0; + _overlayCoords[1].x = 0; _overlayCoords[1].y = 0; _overlayCoords[1].u = u; _overlayCoords[1].v = 0; + _overlayCoords[2].x = 0; _overlayCoords[2].y = 0; _overlayCoords[2].u = 0; _overlayCoords[2].v = v; + _overlayCoords[3].x = 0; _overlayCoords[3].y = 0; _overlayCoords[3].u = u; _overlayCoords[3].v = v; + + _videoContext.overlayTexture.create((uint16) overlayTextureWidthPOT, (uint16) overlayTextureHeightPOT, Graphics::createPixelFormat<5551>()); +} + +- (void)deleteFramebuffer { + glDeleteRenderbuffers(1, &_viewRenderbuffer); + glDeleteFramebuffers(1, &_viewFramebuffer); +} + +- (void)setupVBOs { + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); +} + +- (void)deleteVBOs { + glDeleteBuffers(1, &_vertexBuffer); +} + +- (GLuint)compileShader:(const char*)shaderPrg withType:(GLenum)shaderType { + GLuint shaderHandle = glCreateShader(shaderType); + + int shaderPrgLength = strlen(shaderPrg); + glShaderSource(shaderHandle, 1, &shaderPrg, &shaderPrgLength); + + glCompileShader(shaderHandle); - _videoContext.overlayWidth = overlayWidth; - _videoContext.overlayHeight = overlayHeight; + GLint compileSuccess; + glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess); + if (compileSuccess == GL_FALSE) { + GLchar messages[256]; + glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]); + NSString *messageString = [NSString stringWithUTF8String:messages]; + NSLog(@"%@", messageString); + exit(1); + } + + return shaderHandle; +} + +- (void)compileShaders { + const char *vertexPrg = + "uniform vec2 ScreenSize;" + "uniform float Shake;" + "" + "attribute vec2 Position;" + "attribute vec2 TexCoord;" + "" + "varying vec4 DestColor;" + "varying vec2 o_TexCoord;" + "" + "void main(void) {" + " DestColor = vec4(Position.x, Position.y, 0, 1);" + " o_TexCoord = TexCoord;" + " gl_Position = vec4((Position.x / ScreenSize.x) * 2.0 - 1.0, (1.0 - (Position.y + Shake) / ScreenSize.y) * 2.0 - 1.0, 0, 1);" + "}"; + + const char *fragmentPrg = + "uniform sampler2D Texture;" + "" + "varying lowp vec4 DestColor;" + "varying lowp vec2 o_TexCoord;" + "" + "void main(void) {" + " gl_FragColor = texture2D(Texture, o_TexCoord);" + "}"; + + _vertexShader = [self compileShader:vertexPrg withType:GL_VERTEX_SHADER]; + _fragmentShader = [self compileShader:fragmentPrg withType:GL_FRAGMENT_SHADER]; + + GLuint programHandle = glCreateProgram(); + glAttachShader(programHandle, _vertexShader); + glAttachShader(programHandle, _fragmentShader); + glLinkProgram(programHandle); + + GLint linkSuccess; + glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess); + if (linkSuccess == GL_FALSE) { + printOpenGLError(); + exit(1); + } + + glUseProgram(programHandle); + + _screenSizeSlot = (GLuint) glGetUniformLocation(programHandle, "ScreenSize"); + _textureSlot = (GLuint) glGetUniformLocation(programHandle, "Texture"); + _shakeSlot = (GLuint) glGetUniformLocation(programHandle, "Shake"); - uint overlayTextureWidthPOT = getSizeNextPOT(overlayWidth); - uint overlayTextureHeightPOT = getSizeNextPOT(overlayHeight); + _positionSlot = (GLuint) glGetAttribLocation(programHandle, "Position"); + _textureCoordSlot = (GLuint) glGetAttribLocation(programHandle, "TexCoord"); - // Since the overlay size won't change the whole run, we can - // precalculate the texture coordinates for the overlay texture here - // and just use it later on. - _overlayTexCoords[2] = _overlayTexCoords[6] = _videoContext.overlayWidth / (GLfloat) overlayTextureWidthPOT; - _overlayTexCoords[5] = _overlayTexCoords[7] = _videoContext.overlayHeight / (GLfloat) overlayTextureHeightPOT; + glEnableVertexAttribArray(_positionSlot); + glEnableVertexAttribArray(_textureCoordSlot); +} - _videoContext.overlayTexture.create(overlayTextureWidthPOT, overlayTextureHeightPOT, Graphics::createPixelFormat<5551>()); +- (void)deleteShaders { + glDeleteShader(_vertexShader); + glDeleteShader(_fragmentShader); +} - glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError(); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError(); +- (void)setupTextures { + glGenTextures(1, &_screenTexture); printOpenGLError(); + glGenTextures(1, &_overlayTexture); printOpenGLError(); + glGenTextures(1, &_mouseCursorTexture); printOpenGLError(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + [self setGraphicsMode]; +} - glEnable(GL_TEXTURE_2D); printOpenGLError(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError(); - glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError(); +- (void)deleteTextures { + if (_screenTexture) { + glDeleteTextures(1, &_screenTexture); printOpenGLError(); + _screenTexture = 0; + } + if (_overlayTexture) { + glDeleteTextures(1, &_overlayTexture); printOpenGLError(); + _overlayTexture = 0; + } + if (_mouseCursorTexture) { + glDeleteTextures(1, &_mouseCursorTexture); printOpenGLError(); + _mouseCursorTexture = 0; } } @@ -242,35 +402,9 @@ uint getSizeNextPOT(uint size) { _eventLock = [[NSLock alloc] init]; - _gameScreenVertCoords[0] = _gameScreenVertCoords[1] = - _gameScreenVertCoords[2] = _gameScreenVertCoords[3] = - _gameScreenVertCoords[4] = _gameScreenVertCoords[5] = - _gameScreenVertCoords[6] = _gameScreenVertCoords[7] = 0; - - _gameScreenTexCoords[0] = _gameScreenTexCoords[1] = - _gameScreenTexCoords[2] = _gameScreenTexCoords[3] = - _gameScreenTexCoords[4] = _gameScreenTexCoords[5] = - _gameScreenTexCoords[6] = _gameScreenTexCoords[7] = 0; - - _overlayVertCoords[0] = _overlayVertCoords[1] = - _overlayVertCoords[2] = _overlayVertCoords[3] = - _overlayVertCoords[4] = _overlayVertCoords[5] = - _overlayVertCoords[6] = _overlayVertCoords[7] = 0; - - _overlayTexCoords[0] = _overlayTexCoords[1] = - _overlayTexCoords[2] = _overlayTexCoords[3] = - _overlayTexCoords[4] = _overlayTexCoords[5] = - _overlayTexCoords[6] = _overlayTexCoords[7] = 0; - - _mouseVertCoords[0] = _mouseVertCoords[1] = - _mouseVertCoords[2] = _mouseVertCoords[3] = - _mouseVertCoords[4] = _mouseVertCoords[5] = - _mouseVertCoords[6] = _mouseVertCoords[7] = 0; - - _mouseTexCoords[0] = _mouseTexCoords[1] = - _mouseTexCoords[2] = _mouseTexCoords[3] = - _mouseTexCoords[4] = _mouseTexCoords[5] = - _mouseTexCoords[6] = _mouseTexCoords[7] = 0; + memset(_gameScreenCoords, 0, sizeof(GLVertex) * 4); + memset(_overlayCoords, 0, sizeof(GLVertex) * 4); + memset(_mouseCoords, 0, sizeof(GLVertex) * 4); // Initialize the OpenGL ES context [self createContext]; @@ -292,106 +426,105 @@ uint getSizeNextPOT(uint size) { [super dealloc]; } -#if 0 -- (void)drawRect:(CGRect)frame { - if (g_lastTick == 0) { - g_lastTick = time(0); - } - - g_frames++; - if (time(0) > g_lastTick) { - g_lastTick = time(0); - printf("FPS: %i\n", g_frames); - g_frames = 0; - } -} -#endif - - (void)setFilterModeForTexture:(GLuint)tex { if (!tex) return; + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); printOpenGLError(); GLint filter = GL_LINEAR; + + switch (_videoContext.graphicsMode) { + case kGraphicsModeNone: + filter = GL_NEAREST; + break; + + case kGraphicsModeLinear: + case kGraphicsMode2xSaI: + case kGraphicsModeSuper2xSaI: + case kGraphicsModeSuperEagle: + case kGraphicsModeAdvMame2x: + case kGraphicsModeAdvMame3x: + case kGraphicsModeHQ2x: + case kGraphicsModeHQ3x: + case kGraphicsModeTV2x: + case kGraphicsModeDotMatrix: + filter = GL_LINEAR; + break; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); printOpenGLError(); + // We use GL_CLAMP_TO_EDGE here to avoid artifacts when linear filtering + // is used. If we would not use this for example the cursor in Loom would + // have a line/border artifact on the right side of the covered rect. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); printOpenGLError(); +} + +- (void)setScaler { ScalerProc *scaler = NULL; int scalerScale = 1; switch (_videoContext.graphicsMode) { case kGraphicsModeLinear: - filter = GL_LINEAR; break; case kGraphicsModeNone: - filter = GL_NEAREST; break; #ifdef USE_SCALERS case kGraphicsMode2xSaI: - filter = GL_LINEAR; scaler = _2xSaI; scalerScale = 2; break; case kGraphicsModeSuper2xSaI: - filter = GL_LINEAR; scaler = Super2xSaI; scalerScale = 2; break; case kGraphicsModeSuperEagle: - filter = GL_LINEAR; scaler = SuperEagle; scalerScale = 2; break; case kGraphicsModeAdvMame2x: - filter = GL_LINEAR; scaler = AdvMame2x; scalerScale = 2; break; case kGraphicsModeAdvMame3x: - filter = GL_LINEAR; scaler = AdvMame3x; scalerScale = 3; break; #ifdef USE_HQ_SCALERS case kGraphicsModeHQ2x: - filter = GL_LINEAR; scaler = HQ2x; scalerScale = 2; break; case kGraphicsModeHQ3x: - filter = GL_LINEAR; scaler = HQ3x; scalerScale = 3; break; #endif case kGraphicsModeTV2x: - filter = GL_LINEAR; scaler = TV2x; scalerScale = 2; break; case kGraphicsModeDotMatrix: - filter = GL_LINEAR; scaler = DotMatrix; scalerScale = 2; break; - #endif - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); printOpenGLError(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); printOpenGLError(); - // We use GL_CLAMP_TO_EDGE here to avoid artifacts when linear filtering - // is used. If we would not use this for example the cursor in Loom would - // have a line/border artifact on the right side of the covered rect. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); printOpenGLError(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); printOpenGLError(); + default: + break; + } _scaler = scaler; _scalerScale = scalerScale; @@ -401,6 +534,7 @@ uint getSizeNextPOT(uint size) { [self setFilterModeForTexture:_screenTexture]; [self setFilterModeForTexture:_overlayTexture]; [self setFilterModeForTexture:_mouseCursorTexture]; + [self setScaler]; } - (void)updateSurface { @@ -419,19 +553,18 @@ uint getSizeNextPOT(uint size) { if (_videoContext.mouseIsVisible) [self updateMouseSurface]; - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); - [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; - + [_context presentRenderbuffer:GL_RENDERBUFFER]; + glFinish(); } - (void)notifyMouseMove { const GLint mouseX = (GLint)(_videoContext.mouseX * _mouseScaleX) - _mouseHotspotX; const GLint mouseY = (GLint)(_videoContext.mouseY * _mouseScaleY) - _mouseHotspotY; - _mouseVertCoords[0] = _mouseVertCoords[4] = mouseX; - _mouseVertCoords[1] = _mouseVertCoords[3] = mouseY; - _mouseVertCoords[2] = _mouseVertCoords[6] = mouseX + _mouseWidth; - _mouseVertCoords[5] = _mouseVertCoords[7] = mouseY + _mouseHeight; + _mouseCoords[0].x = _mouseCoords[2].x = mouseX; + _mouseCoords[0].y = _mouseCoords[1].y = mouseY; + _mouseCoords[1].x = _mouseCoords[3].x = mouseX + _mouseWidth; + _mouseCoords[2].y = _mouseCoords[3].y = mouseY + _mouseHeight; } - (void)updateMouseCursorScaling { @@ -476,25 +609,23 @@ uint getSizeNextPOT(uint size) { } - (void)updateMouseCursor { - if (_mouseCursorTexture == 0) { - glGenTextures(1, &_mouseCursorTexture); printOpenGLError(); - [self setFilterModeForTexture:_mouseCursorTexture]; - } - [self updateMouseCursorScaling]; - _mouseTexCoords[2] = _mouseTexCoords[6] = _videoContext.mouseWidth / (GLfloat)_videoContext.mouseTexture.w; - _mouseTexCoords[5] = _mouseTexCoords[7] = _videoContext.mouseHeight / (GLfloat)_videoContext.mouseTexture.h; + _mouseCoords[1].u = _mouseCoords[3].u = _videoContext.mouseWidth / (GLfloat)_videoContext.mouseTexture.w; + _mouseCoords[2].v = _mouseCoords[3].v = _videoContext.mouseHeight / (GLfloat)_videoContext.mouseTexture.h; - glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); + [self setFilterModeForTexture:_mouseCursorTexture]; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.mouseTexture.w, _videoContext.mouseTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.mouseTexture.getPixels()); printOpenGLError(); + glUniform1i(_textureSlot, 0); printOpenGLError(); } - (void)updateMainSurface { - glVertexPointer(2, GL_FLOAT, 0, _gameScreenVertCoords); printOpenGLError(); - glTexCoordPointer(2, GL_FLOAT, 0, _gameScreenTexCoords); printOpenGLError(); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, _gameScreenCoords, GL_STATIC_DRAW); + glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0); + glVertexAttribPointer(_textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid *) (sizeof(GLfloat) * 2)); - glBindTexture(GL_TEXTURE_2D, _screenTexture); printOpenGLError(); + [self setFilterModeForTexture:_screenTexture]; + glUniform1i(_textureSlot, 0); printOpenGLError(); // Unfortunately we have to update the whole texture every frame, since glTexSubImage2D is actually slower in all cases // due to the iPhone internals having to convert the whole texture back from its internal format when used. @@ -512,16 +643,16 @@ uint getSizeNextPOT(uint size) { } // Clear two lines before - memset(_scalerMemorySrc, 0, _videoContext.screenTexture.pitch * 2); + memset(_scalerMemorySrc, 0, (size_t) (_videoContext.screenTexture.pitch * 2)); // Copy original buffer memcpy(_scalerMemorySrc + _videoContext.screenTexture.pitch * 2, _videoContext.screenTexture.getPixels(), _videoContext.screenTexture.pitch * _videoContext.screenTexture.h); // Clear two lines after - memset(_scalerMemorySrc + _videoContext.screenTexture.pitch * (2 + _videoContext.screenTexture.h), 0, _videoContext.screenTexture.pitch * 2); + memset(_scalerMemorySrc + _videoContext.screenTexture.pitch * (2 + _videoContext.screenTexture.h), 0, (size_t) (_videoContext.screenTexture.pitch * 2)); // Apply scaler _scaler(_scalerMemorySrc + _videoContext.screenTexture.pitch * 2, _videoContext.screenTexture.pitch, _scalerMemoryDst, - (uint32) (_videoContext.screenTexture.pitch * _scalerScale), + (uint32) (_videoContext.screenTexture.pitch * _scalerScale), _videoContext.screenTexture.w, _videoContext.screenTexture.h); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w * _scalerScale, _videoContext.screenTexture.h * _scalerScale, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _scalerMemoryDst); printOpenGLError(); @@ -529,23 +660,30 @@ uint getSizeNextPOT(uint size) { else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.getPixels()); printOpenGLError(); } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } - (void)updateOverlaySurface { - glVertexPointer(2, GL_FLOAT, 0, _overlayVertCoords); printOpenGLError(); - glTexCoordPointer(2, GL_FLOAT, 0, _overlayTexCoords); printOpenGLError(); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, _overlayCoords, GL_STATIC_DRAW); + glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0); + glVertexAttribPointer(_textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid *) (sizeof(GLfloat) * 2)); + + [self setFilterModeForTexture:_overlayTexture]; + glUniform1i(_textureSlot, 0); printOpenGLError(); - glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.overlayTexture.w, _videoContext.overlayTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.overlayTexture.getPixels()); printOpenGLError(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } - (void)updateMouseSurface { - glVertexPointer(2, GL_FLOAT, 0, _mouseVertCoords); printOpenGLError(); - glTexCoordPointer(2, GL_FLOAT, 0, _mouseTexCoords); printOpenGLError(); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, _mouseCoords, GL_STATIC_DRAW); + glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0); + glVertexAttribPointer(_textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid *) (sizeof(GLfloat) * 2)); glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); + glUniform1i(_textureSlot, 0); printOpenGLError(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } @@ -553,80 +691,33 @@ uint getSizeNextPOT(uint size) { const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth); const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight); - _gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth; - _gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight; + _gameScreenCoords[1].u = _gameScreenCoords[3].u = _videoContext.screenWidth / (GLfloat)screenTexWidth; + _gameScreenCoords[2].v = _gameScreenCoords[3].v = _videoContext.screenHeight / (GLfloat)screenTexHeight; - _videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>()); + _videoContext.screenTexture.create((uint16) screenTexWidth, (uint16) screenTexHeight, Graphics::createPixelFormat<565>()); } - (void)initSurface { if (_context) { - glDeleteTextures(1, &_screenTexture); printOpenGLError(); - glDeleteTextures(1, &_overlayTexture); printOpenGLError(); - - glDeleteRenderbuffersOES(1, &_viewRenderbuffer); - glDeleteFramebuffersOES(1, &_viewFramebuffer); - - glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError(); - glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError(); - - glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError(); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); - [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer]; - - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); - - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_renderBufferWidth); printOpenGLError(); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_renderBufferHeight); printOpenGLError(); - - if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { - NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); - return; - } - - glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError(); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError(); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glEnable(GL_TEXTURE_2D); printOpenGLError(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError(); - glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError(); + [self rebuildFrameBuffer]; } BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height); // UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]); -// glMatrixMode(GL_PROJECTION); -// glLoadIdentity(); - int screenWidth, screenHeight; if (isLandscape) { screenWidth = MAX(_renderBufferWidth, _renderBufferHeight); screenHeight = MIN(_renderBufferWidth, _renderBufferHeight); -// glOrthof(0, screenWidth, screenHeight, 0, 0, 1); printOpenGLError(); } else { screenWidth = MIN(_renderBufferWidth, _renderBufferHeight); screenHeight = MAX(_renderBufferWidth, _renderBufferHeight); -// glOrthof(0, screenHeight, screenWidth, 0, 0, 1); printOpenGLError(); } - glGenTextures(1, &_screenTexture); printOpenGLError(); - [self setFilterModeForTexture:_screenTexture]; - - glGenTextures(1, &_overlayTexture); printOpenGLError(); - [self setFilterModeForTexture:_overlayTexture]; - - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); + glBindRenderbuffer(GL_RENDERBUFFER, _viewRenderbuffer); printOpenGLError(); [self clearColorBuffer]; -// if (_keyboardView != nil) { -// [_keyboardView removeFromSuperview]; -// [[_keyboardView inputView] removeFromSuperview]; -// } - GLfloat adjustedWidth = _videoContext.screenWidth; GLfloat adjustedHeight = _videoContext.screenHeight; if (_videoContext.asprectRatioCorrection) { @@ -688,34 +779,24 @@ uint getSizeNextPOT(uint size) { } _overlayRect = CGRectMake(0, 0, screenWidth, screenHeight * overlayPortraitRatio); - _gameScreenVertCoords[0] = _gameScreenVertCoords[4] = CGRectGetMinX(_gameScreenRect); - _gameScreenVertCoords[1] = _gameScreenVertCoords[3] = CGRectGetMinY(_gameScreenRect); - _gameScreenVertCoords[2] = _gameScreenVertCoords[6] = CGRectGetMaxX(_gameScreenRect); - _gameScreenVertCoords[5] = _gameScreenVertCoords[7] = CGRectGetMaxY(_gameScreenRect); + _gameScreenCoords[0].x = _gameScreenCoords[2].x = CGRectGetMinX(_gameScreenRect); + _gameScreenCoords[0].y = _gameScreenCoords[1].y = CGRectGetMinY(_gameScreenRect); + _gameScreenCoords[1].x = _gameScreenCoords[3].x = CGRectGetMaxX(_gameScreenRect); + _gameScreenCoords[2].y = _gameScreenCoords[3].y = CGRectGetMaxY(_gameScreenRect); - _overlayVertCoords[2] = _overlayVertCoords[6] = CGRectGetMaxX(_overlayRect); - _overlayVertCoords[5] = _overlayVertCoords[7] = CGRectGetMaxY(_overlayRect); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, screenWidth, screenHeight, 0, 0, 1); + _overlayCoords[1].x = _overlayCoords[3].x = CGRectGetMaxX(_overlayRect); + _overlayCoords[2].y = _overlayCoords[3].y = CGRectGetMaxY(_overlayRect); [self setViewTransformation]; [self updateMouseCursorScaling]; } - (void)setViewTransformation { - // Set the modelview matrix. This matrix will be used for the shake offset - // support. - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - // Scale the shake offset according to the overlay size. We need this to // adjust the overlay mouse click coordinates when an offset is set. _scaledShakeOffsetY = (int)(_videoContext.shakeOffsetY / (GLfloat)_videoContext.screenHeight * CGRectGetHeight(_overlayRect)); - // Apply the shakeing to the output screen. - glTranslatef(0, -_scaledShakeOffsetY, 0); + glUniform1f(_shakeSlot, _scaledShakeOffsetY); } - (void)clearColorBuffer { @@ -723,7 +804,8 @@ uint getSizeNextPOT(uint size) { int clearCount = 5; while (clearCount-- > 0) { glClear(GL_COLOR_BUFFER_BIT); printOpenGLError(); - [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; + [_context presentRenderbuffer:GL_RENDERBUFFER]; + glFinish(); } } @@ -748,7 +830,7 @@ uint getSizeNextPOT(uint size) { - (bool)getMouseCoords:(CGPoint)point eventX:(int *)x eventY:(int *)y { // We scale the input according to our scale factor to get actual screen - // cooridnates. + // coordinates. point.x *= _contentScaleFactor; point.y *= _contentScaleFactor; |