aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/iphone/iphone_video.m
diff options
context:
space:
mode:
Diffstat (limited to 'backends/platform/iphone/iphone_video.m')
-rw-r--r--backends/platform/iphone/iphone_video.m245
1 files changed, 163 insertions, 82 deletions
diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m
index 016e9d4088..1e02dd104d 100644
--- a/backends/platform/iphone/iphone_video.m
+++ b/backends/platform/iphone/iphone_video.m
@@ -33,38 +33,38 @@
static iPhoneView *sharedInstance = nil;
static int _width = 0;
static int _height = 0;
-static bool _landscape;
static CGRect _screenRect;
+static char* _textureBuffer = 0;
+static int _textureWidth = 0;
+static int _textureHeight = 0;
+NSLock* _lock = nil;
+static int _needsScreenUpdate = 0;
// static long lastTick = 0;
// static int frames = 0;
-unsigned short* iPhone_getSurface() {
- return CoreSurfaceBufferGetBaseAddress([sharedInstance getSurface]);
-}
-
void iPhone_updateScreen() {
- [sharedInstance performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone: NO];
+ if (!_needsScreenUpdate) {
+ _needsScreenUpdate = 1;
+ [sharedInstance performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO];
+ }
}
-void iPhone_updateScreenRect(int x1, int y1, int x2, int y2) {
- //CGRect rect = CGRectMake(x1, y1, x2, y2);
- //[sharedInstance performSelectorOnMainThread:@selector(updateScreenRect:) withObject: [NSValue valueWithRect:rect] waitUntilDone: NO];
-}
+void iPhone_updateScreenRect(unsigned short* screen, int x1, int y1, int x2, int y2) {
+ [_lock lock];
+
+ int y;
+ for (y = y1; y < y2; ++y) {
+ memcpy(&_textureBuffer[(y * _textureWidth + x1 )* 2], &screen[y * _width + x1], (x2 - x1) * 2);
+ }
-void iPhone_lockSurface() {
- CoreSurfaceBufferLock([sharedInstance getSurface], 3);
+ [_lock unlock];
}
-void iPhone_unlockSurface() {
- CoreSurfaceBufferUnlock([sharedInstance getSurface]);
-}
-void iPhone_initSurface(int width, int height, bool landscape) {
+void iPhone_initSurface(int width, int height) {
_width = width;
_height = height;
- _landscape = landscape;
-
[sharedInstance performSelectorOnMainThread:@selector(initSurface) withObject:nil waitUntilDone: YES];
}
@@ -105,8 +105,26 @@ bool getLocalMouseCoords(CGPoint *point) {
return true;
}
+uint getSizeNextPOT(uint size) {
+ if ((size & (size - 1)) || !size) {
+ int log = 0;
+
+ while (size >>= 1)
+ ++log;
+
+ size = (2 << log);
+ }
+
+ return size;
+}
+
@implementation iPhoneView
++ (Class) layerClass
+{
+ return [CAEAGLLayer class];
+}
+
- (id)initWithFrame:(struct CGRect)frame {
[super initWithFrame: frame];
@@ -115,8 +133,11 @@ bool getLocalMouseCoords(CGPoint *point) {
_screenLayer = nil;
sharedInstance = self;
+
+ _lock = [NSLock new];
_keyboardView = nil;
- //[super setTapDelegate: self];
+ _context = nil;
+ _screenTexture = 0;
return self;
}
@@ -127,6 +148,9 @@ bool getLocalMouseCoords(CGPoint *point) {
if (_keyboardView != nil) {
[_keyboardView dealloc];
}
+
+ if (_screenTexture)
+ free(_textureBuffer);
}
- (void *)getSurface {
@@ -146,44 +170,132 @@ bool getLocalMouseCoords(CGPoint *point) {
// }
}
-- (void)updateScreenRect:(id)rect {
- // NSRect nsRect = [rect rectValue];
- // CGRect cgRect = CGRectMake(nsRect.origin.x, nsRect.origin.y, nsRect.size.width, nsRect.size.height);
- // [sharedInstance setNeedsDisplayInRect: cgRect];
+- (void)updateSurface {
+ if (!_needsScreenUpdate) {
+ return;
+ }
+ _needsScreenUpdate = 0;
+
+ GLfloat vertices[] = {
+ 0.0f + _heightOffset, 0.0f + _widthOffset,
+ _visibleWidth - _heightOffset, 0.0f + _widthOffset,
+ 0.0f + _heightOffset, _visibleHeight - _widthOffset,
+ _visibleWidth - _heightOffset, _visibleHeight - _widthOffset
+ };
+
+ float texWidth = _width / (float)_textureWidth;;
+ float texHeight = _height / (float)_textureHeight;
+
+ const GLfloat texCoords[] = {
+ texWidth, 0.0f,
+ 0.0f, 0.0f,
+ texWidth, texHeight,
+ 0.0f, texHeight
+ };
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+
+ [_lock lock];
+ // 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.
+ // In the future we could use several tiled textures instead.
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureWidth, _textureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _textureBuffer);
+ [_lock unlock];
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
+ [_context presentRenderbuffer:GL_RENDERBUFFER_OES];
+
}
- (void)initSurface {
- //printf("Window: (%d, %d), Surface: (%d, %d)\n", _fullWidth, _fullHeight, _width, _height);
-
- int pitch = _width * 2;
- int allocSize = 2 * _width * _height;
- char *pixelFormat = "565L";
-
- NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:
- kCFBooleanTrue, kCoreSurfaceBufferGlobal,
- @"PurpleGFXMem", kCoreSurfaceBufferMemoryRegion,
- [NSNumber numberWithInt: pitch], kCoreSurfaceBufferPitch,
- [NSNumber numberWithInt: _width], kCoreSurfaceBufferWidth,
- [NSNumber numberWithInt: _height], kCoreSurfaceBufferHeight,
- [NSNumber numberWithInt: *(int*)pixelFormat], kCoreSurfaceBufferPixelFormat,
- [NSNumber numberWithInt: allocSize], kCoreSurfaceBufferAllocSize,
- nil
- ];
+ _textureWidth = getSizeNextPOT(_width);
+ _textureHeight = getSizeNextPOT(_height);
+
+ UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
- //("Allocating surface: %d\n", allocSize);
- _screenSurface = CoreSurfaceBufferCreate((CFDictionaryRef)dict);
- //printf("Surface created.\n");
- CoreSurfaceBufferLock(_screenSurface, 3);
+ //printf("Window: (%d, %d), Surface: (%d, %d), Texture(%d, %d)\n", _fullWidth, _fullHeight, _width, _height, _textureWidth, _textureHeight);
+
+ if (_context == nil) {
+ orientation = UIDeviceOrientationLandscapeRight;
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer;
+
+ eaglLayer.opaque = YES;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil];
+
+ _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+ if (!_context || [EAGLContext setCurrentContext:_context]) {
+ glGenFramebuffersOES(1, &_viewFramebuffer);
+ glGenRenderbuffersOES(1, &_viewRenderbuffer);
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
+ [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer);
+
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth);
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight);
+
+ 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, _backingWidth, _backingHeight);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+ glEnable(GL_TEXTURE_2D);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ }
+ }
- CALayer* screenLayer = [[CALayer layer] retain];
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ if (orientation == UIDeviceOrientationLandscapeRight) {
+ glRotatef(-90, 0, 0, 1);
+ } else if (orientation == UIDeviceOrientationLandscapeLeft) {
+ glRotatef(90, 0, 0, 1);
+ } else {
+ glRotatef(180, 0, 0, 1);
+ }
+
+ glOrthof(0, _backingWidth, 0, _backingHeight, 0, 1);
+
+ if (_screenTexture > 0)
+ glDeleteTextures(1, &_screenTexture);
+ glGenTextures(1, &_screenTexture);
+ glBindTexture(GL_TEXTURE_2D, _screenTexture);
+ glEnable(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ if (_textureBuffer)
+ free(_textureBuffer);
+
+ int textureSize = _textureWidth * _textureHeight * 2;
+ _textureBuffer = (char*)malloc(textureSize);
+ memset(_textureBuffer, 0, textureSize);
+
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer);
+ [_context presentRenderbuffer:GL_RENDERBUFFER_OES];
+
if (_keyboardView != nil) {
[_keyboardView removeFromSuperview];
[[_keyboardView inputView] removeFromSuperview];
}
- if (_landscape) {
- float ratioDifference = ((float)_width / (float)_height) / ((float)_fullWidth / (float)_fullHeight);
+ if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {
+ _visibleHeight = _backingHeight;
+ _visibleWidth = _backingWidth;
+
+ float ratioDifference = ((float)_height / (float)_width) / ((float)_fullWidth / (float)_fullHeight);
int rectWidth, rectHeight;
if (ratioDifference < 1.0f) {
rectWidth = _fullWidth * ratioDifference;
@@ -199,15 +311,17 @@ bool getLocalMouseCoords(CGPoint *point) {
//printf("Rect: %i, %i, %i, %i\n", _widthOffset, _heightOffset, rectWidth, rectHeight);
_screenRect = CGRectMake(_widthOffset, _heightOffset, rectWidth, rectHeight);
- [screenLayer setFrame: _screenRect];
} else {
float ratio = (float)_height / (float)_width;
int height = _fullWidth * ratio;
//printf("Making rect (%u, %u)\n", _fullWidth, height);
_screenRect = CGRectMake(0, 0, _fullWidth - 1, height - 1);
- [screenLayer setFrame: _screenRect];
- //CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
+ _visibleHeight = height;
+ _visibleWidth = _backingWidth;
+ _heightOffset = 0.0f;
+ _widthOffset = 0.0f;
+
CGRect keyFrame = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
if (_keyboardView == nil) {
_keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
@@ -218,28 +332,6 @@ bool getLocalMouseCoords(CGPoint *point) {
[self addSubview: _keyboardView];
[[_keyboardView inputView] becomeFirstResponder];
}
-
- [screenLayer setContents: _screenSurface];
- [screenLayer setOpaque: YES];
-
- if (_screenLayer != nil) {
- [[sharedInstance layer] replaceSublayer: _screenLayer with: screenLayer];
- } else {
- [[sharedInstance layer] addSublayer: screenLayer];
- }
- _screenLayer = screenLayer;
-
- CoreSurfaceBufferUnlock(_screenSurface);
- [dict release];
-}
-
-
-- (void)lock {
- [_lock lock];
-}
-
-- (void)unlock {
- [_lock unlock];
}
- (id)getEvent {
@@ -247,25 +339,20 @@ bool getLocalMouseCoords(CGPoint *point) {
return nil;
}
- [self lock];
id event = [_events objectAtIndex: 0];
[_events removeObjectAtIndex: 0];
- [self unlock];
return event;
}
- (void)addEvent:(NSDictionary*)event {
- [self lock];
if(_events == nil)
_events = [[NSMutableArray alloc] init];
[_events addObject: event];
-
- [self unlock];
}
- (void)deviceOrientationChanged:(int)orientation {
@@ -289,7 +376,6 @@ bool getLocalMouseCoords(CGPoint *point) {
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:self];
- //point = [self convertPoint:point fromView:nil];
if (!getLocalMouseCoords(&point))
return;
@@ -307,7 +393,6 @@ bool getLocalMouseCoords(CGPoint *point) {
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:1];
CGPoint point = [touch locationInView:self];
- //point = [self convertPoint:point fromView:nil];
if (!getLocalMouseCoords(&point))
return;
@@ -333,7 +418,6 @@ bool getLocalMouseCoords(CGPoint *point) {
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:self];
- //point = [self convertPoint:point fromView:nil];
if (!getLocalMouseCoords(&point))
return;
@@ -351,7 +435,6 @@ bool getLocalMouseCoords(CGPoint *point) {
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:1];
CGPoint point = [touch locationInView:self];
- //point = [self convertPoint:point fromView:nil];
if (!getLocalMouseCoords(&point))
return;
@@ -377,7 +460,6 @@ bool getLocalMouseCoords(CGPoint *point) {
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:self];
- //point = [self convertPoint:point fromView:nil];
if (!getLocalMouseCoords(&point))
return;
@@ -395,7 +477,6 @@ bool getLocalMouseCoords(CGPoint *point) {
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:1];
CGPoint point = [touch locationInView:self];
- //point = [self convertPoint:point fromView:nil];
if (!getLocalMouseCoords(&point))
return;