app: remove iOS system draw loop
Much like the recent change for OS X, this puts the Go paint loop in control of drawing onto the screen. Change-Id: I37321e4bb58869d4c7cafc51951ea64e540d536b Reviewed-on: https://go-review.googlesource.com/15611 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
parent
ab6091a309
commit
b4e66eeef7
|
@ -14,11 +14,13 @@ package app
|
|||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <UIKit/UIDevice.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
extern struct utsname sysInfo;
|
||||
|
||||
void runApp(void);
|
||||
void setContext(void* context);
|
||||
void makeCurrentContext(GLintptr ctx);
|
||||
void swapBuffers(GLintptr ctx);
|
||||
uint64_t threadID();
|
||||
*/
|
||||
import "C"
|
||||
|
@ -27,7 +29,6 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/mobile/event/lifecycle"
|
||||
"golang.org/x/mobile/event/paint"
|
||||
|
@ -116,6 +117,7 @@ func updateConfig(width, height, orientation int32) {
|
|||
PixelsPerPt: pixelsPerPt,
|
||||
Orientation: o,
|
||||
}
|
||||
theApp.eventsIn <- paint.Event{External: true}
|
||||
}
|
||||
|
||||
// touchIDs is the current active touches. The position in the array
|
||||
|
@ -165,28 +167,50 @@ func sendTouch(cTouch, cTouchType uintptr, x, y float32) {
|
|||
}
|
||||
}
|
||||
|
||||
var workAvailable <-chan struct{}
|
||||
//export lifecycleDead
|
||||
func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) }
|
||||
|
||||
//export drawgl
|
||||
func drawgl(ctx uintptr) {
|
||||
if workAvailable == nil {
|
||||
C.setContext(unsafe.Pointer(ctx))
|
||||
workAvailable = theApp.worker.WorkAvailable()
|
||||
// TODO(crawshaw): not just on process start.
|
||||
theApp.sendLifecycle(lifecycle.StageFocused)
|
||||
}
|
||||
//export lifecycleAlive
|
||||
func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) }
|
||||
|
||||
// TODO(crawshaw): don't send a paint.Event unconditionally. Only send one
|
||||
// if the window actually needs redrawing.
|
||||
theApp.eventsIn <- paint.Event{}
|
||||
//export lifecycleVisible
|
||||
func lifecycleVisible() { theApp.sendLifecycle(lifecycle.StageVisible) }
|
||||
|
||||
//export lifecycleFocused
|
||||
func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) }
|
||||
|
||||
//export startloop
|
||||
func startloop(ctx C.GLintptr) {
|
||||
go theApp.loop(ctx)
|
||||
}
|
||||
|
||||
// loop is the primary drawing loop.
|
||||
//
|
||||
// After UIKit has captured the initial OS thread for processing UIKit
|
||||
// events in runApp, it starts loop on another goroutine. It is locked
|
||||
// to an OS thread for its OpenGL context.
|
||||
func (a *app) loop(ctx C.GLintptr) {
|
||||
runtime.LockOSThread()
|
||||
C.makeCurrentContext(ctx)
|
||||
|
||||
workAvailable := a.worker.WorkAvailable()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-workAvailable:
|
||||
theApp.worker.DoWork()
|
||||
a.worker.DoWork()
|
||||
case <-theApp.publish:
|
||||
loop1:
|
||||
for {
|
||||
select {
|
||||
case <-workAvailable:
|
||||
a.worker.DoWork()
|
||||
default:
|
||||
break loop1
|
||||
}
|
||||
}
|
||||
C.swapBuffers(ctx)
|
||||
theApp.publishResult <- PublishResult{}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
struct utsname sysInfo;
|
||||
|
||||
@interface GoAppAppController : GLKViewController<UIContentContainer>
|
||||
@interface GoAppAppController : GLKViewController<UIContentContainer, GLKViewDelegate>
|
||||
@end
|
||||
|
||||
@interface GoAppAppDelegate : UIResponder<UIApplicationDelegate>
|
||||
|
@ -25,27 +25,58 @@ struct utsname sysInfo;
|
|||
|
||||
@implementation GoAppAppDelegate
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
lifecycleAlive();
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.controller = [[GoAppAppController alloc] initWithNibName:nil bundle:nil];
|
||||
self.window.rootViewController = self.controller;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication * )application {
|
||||
lifecycleFocused();
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
lifecycleVisible();
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
lifecycleAlive();
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
lifecycleDead();
|
||||
}
|
||||
@end
|
||||
|
||||
@interface GoAppAppController ()
|
||||
@property (strong, nonatomic) EAGLContext *context;
|
||||
@property (strong, nonatomic) GLKView *glview;
|
||||
@end
|
||||
|
||||
@implementation GoAppAppController
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
// TODO: replace by swapping out GLKViewController for a UIVIewController.
|
||||
[super viewWillAppear:animated];
|
||||
self.paused = YES;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.preferredFramesPerSecond = 60;
|
||||
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
GLKView *view = (GLKView *)self.view;
|
||||
view.context = self.context;
|
||||
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
view.multipleTouchEnabled = true; // TODO expose setting to user.
|
||||
self.glview = (GLKView*)self.view;
|
||||
self.glview.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
self.glview.multipleTouchEnabled = true; // TODO expose setting to user.
|
||||
self.glview.context = self.context;
|
||||
self.glview.userInteractionEnabled = YES;
|
||||
self.glview.enableSetNeedsDisplay = YES; // only invoked once
|
||||
|
||||
// Do not use the GLKViewController draw loop.
|
||||
self.paused = YES;
|
||||
self.resumeOnDidBecomeActive = NO;
|
||||
self.preferredFramesPerSecond = 0;
|
||||
|
||||
int scale = 1;
|
||||
if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)]) {
|
||||
|
@ -67,8 +98,11 @@ struct utsname sysInfo;
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
drawgl((GoUintptr)self.context);
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
|
||||
// Now that we have been asked to do the first draw, disable any
|
||||
// future draw and hand control over to the Go paint.Event cycle.
|
||||
self.glview.enableSetNeedsDisplay = NO;
|
||||
startloop((GLintptr)self.context);
|
||||
}
|
||||
|
||||
#define TOUCH_TYPE_BEGIN 0 // touch.TypeBegin
|
||||
|
@ -106,7 +140,7 @@ void runApp(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void setContext(void* context) {
|
||||
void makeCurrentContext(GLintptr context) {
|
||||
EAGLContext* ctx = (EAGLContext*)context;
|
||||
if (![EAGLContext setCurrentContext:ctx]) {
|
||||
// TODO(crawshaw): determine how terrible this is. Exit?
|
||||
|
@ -114,6 +148,14 @@ void setContext(void* context) {
|
|||
}
|
||||
}
|
||||
|
||||
void swapBuffers(GLintptr context) {
|
||||
__block EAGLContext* ctx = (EAGLContext*)context;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[EAGLContext setCurrentContext:ctx];
|
||||
[ctx presentRenderbuffer:GL_RENDERBUFFER];
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t threadID() {
|
||||
uint64_t id;
|
||||
if (pthread_threadid_np(pthread_self(), &id)) {
|
||||
|
|
Loading…
Reference in New Issue