app: remove OS X display link timer
The CGL display link is a timer keyed on screen refresh rate. It made sense to use it when the app package controlled the screen paint cycle. Now that the paint cycle control has moved to the user, and given that we have always made the equivalent of Publish block until vsync, it is just complicating matters. The user can come up with their own timer, and safely dedicate a goroutine to event handling that paints as fast as it likes without running over the vsync time. A version of this for iOS will follow (giving up on the timer provided by GLKViewController) when I get my iOS setup working again. (Note there is also a bug in the way drawgl works presently. This CL doesn't fix the bug, but is a first step in untangling the draw loop so I can fix it.) Change-Id: I464d5b15f018527d98b792026fb3899681f24e4b Reviewed-on: https://go-review.googlesource.com/15470 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Родитель
cc7d486c7d
Коммит
0d45604e75
|
@ -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 <Carbon/Carbon.h> // for HIToolbox/Events.h
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <pthread.h>
|
||||
|
@ -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
|
||||
|
|
|
@ -11,14 +11,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenGL/gl3.h>
|
||||
#import <QuartzCore/CVReturn.h>
|
||||
#import <QuartzCore/CVBase.h>
|
||||
|
||||
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<NSApplicationDelegate, NSWindowDelegate>
|
||||
{
|
||||
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];
|
||||
|
|
Загрузка…
Ссылка в новой задаче