diff --git a/app/darwin_amd64.go b/app/darwin_amd64.go index dcee145..6935769 100644 --- a/app/darwin_amd64.go +++ b/app/darwin_amd64.go @@ -12,7 +12,7 @@ package app /* #cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Cocoa -framework OpenGL -framework QuartzCore +#cgo LDFLAGS: -framework Cocoa -framework OpenGL #import // for HIToolbox/Events.h #import #include @@ -70,45 +70,52 @@ func main(f func(App)) { // events in runApp, it starts loop on another goroutine. It is locked // to an OS thread for its OpenGL context. // -// Two Cocoa threads deliver draw signals to loop. The primary source of -// draw events is the CVDisplayLink timer, which is tied to the display -// vsync. Secondary draw events come from [NSView drawRect:] when the -// window is resized. +// The loop processes GL calls until a publish event appears. +// Then it runs any remaining GL calls and flushes the screen. +// +// As NSOpenGLCPSwapInterval is set to 1, the call to CGLFlushDrawable +// blocks until the screen refresh. func (a *app) loop(ctx C.GLintptr) { runtime.LockOSThread() C.makeCurrentContext(ctx) workAvailable := a.worker.WorkAvailable() + for { select { case <-workAvailable: a.worker.DoWork() - case <-draw: + case <-theApp.publish: loop1: for { select { case <-workAvailable: a.worker.DoWork() - case <-theApp.publish: - C.CGLFlushDrawable(C.CGLGetCurrentContext()) - theApp.publishResult <- PublishResult{} + default: break loop1 } } - drawDone <- struct{}{} + C.CGLFlushDrawable(C.CGLGetCurrentContext()) + theApp.publishResult <- PublishResult{} + select { + case drawDone <- struct{}{}: + default: + } } } } -var ( - draw = make(chan struct{}) - drawDone = make(chan struct{}) -) +var drawDone = make(chan struct{}) +// drawgl is used by Cocoa to occasionally request screen updates. +// //export drawgl func drawgl() { - draw <- struct{}{} - <-drawDone + switch theApp.lifecycleStage { + case lifecycle.StageFocused, lifecycle.StageVisible: + theApp.Send(paint.Event{}) + <-drawDone + } } //export startloop diff --git a/app/darwin_amd64.m b/app/darwin_amd64.m index 49ef8e2..c7c5fcd 100644 --- a/app/darwin_amd64.m +++ b/app/darwin_amd64.m @@ -11,14 +11,6 @@ #import #import #import -#import -#import - -static CVReturn displayLinkDraw(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) -{ - drawgl(); - return kCVReturnSuccess; -} void makeCurrentContext(GLintptr context) { NSOpenGLContext* ctx = (NSOpenGLContext*)context; @@ -33,10 +25,8 @@ uint64 threadID() { return id; } - @interface MobileGLView : NSOpenGLView { - CVDisplayLinkRef displayLink; } @end @@ -46,13 +36,6 @@ uint64 threadID() { GLint swapInt = 1; [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; - CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); - CVDisplayLinkSetOutputCallback(displayLink, &displayLinkDraw, self); - - CGLContextObj cglContext = [[self openGLContext] CGLContextObj]; - CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj]; - CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat); - // Using attribute arrays in OpenGL 3.3 requires the use of a VBA. // But VBAs don't exist in ES 2. So we bind a default one. GLuint vba; @@ -96,11 +79,8 @@ uint64 threadID() { } - (void)drawRect:(NSRect)theRect { - // Called during resize. Do an extra draw if we are visible. - // This gets rid of flicker when resizing. - if (CVDisplayLinkIsRunning(displayLink)) { - drawgl(); - } + // Called during resize. This gets rid of flicker when resizing. + drawgl(); } - (void)mouseDown:(NSEvent *)theEvent { @@ -136,7 +116,6 @@ uint64 threadID() { [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)]; [self.window makeKeyAndOrderFront:self]; lifecycleVisible(); - CVDisplayLinkStart(displayLink); } - (void)applicationWillTerminate:(NSNotification *)aNotification { @@ -144,17 +123,14 @@ uint64 threadID() { } - (void)applicationDidHide:(NSNotification *)aNotification { - CVDisplayLinkStop(displayLink); lifecycleAlive(); } - (void)applicationWillUnhide:(NSNotification *)notification { lifecycleVisible(); - CVDisplayLinkStart(displayLink); } - (void)windowWillClose:(NSNotification *)notification { - CVDisplayLinkStop(displayLink); lifecycleAlive(); } @end @@ -204,7 +180,6 @@ uint64 threadID() { } @end - void runApp(void) { [NSAutoreleasePool new];