diff options
author | Sven Gothel <[email protected]> | 2011-11-09 00:14:01 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-11-09 00:14:01 +0100 |
commit | 1055ce051fd7bd3c88724888cf8f46c75535a249 (patch) | |
tree | c93785b2d2eff1363b8eba17398f57534c55c9a5 /src/jogl | |
parent | 835b88a4ec0a01edf23d2af2cc1d22a7550bdf9b (diff) |
OS X Layered View: Part2 Java/Native MacOSXCGLContext / MacOSXPbufferCGLContext
Undo 368cbf4462d7f3635c1ef4497424c360b5ccc203:
- "use SurfaceUpdateListener() to notify layer", simply use MacOSXCGLContext's swap impl.
MacOSXCGLContext:
- NSOpenGLImpl.create():
- issues createNSOpenGLLayer() using tex-size (maybe POT) as args
- attaches the NSOpenGLLayer to the JAWT layered surface host
- NSOpenGLImpl.setSwapInterval() propagates interval to our NSOpenGLLayer impl.
- NSOpenGLImpl.swapBuffer() (layer case):
- waits for v-sync if enabled (v-sync), or until native 'draw' is finished (tearing)
using our pthread/ NSOpenGLLayer synchronization.
The latter uses CADisplayLink or CVDisplayLinkRef for v-sync synchronization.
- flushes our local ctx
- triggers our NSOpenGLLayer to 'draw'
- MacOSXPbufferCGLContext create() sets the texture size independently of pbuffer size (POT/NPOT)
Diffstat (limited to 'src/jogl')
3 files changed, 326 insertions, 82 deletions
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index b942fb904..4ab81e5ff 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -45,9 +45,7 @@ import java.util.Map; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceUpdatedListener; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; @@ -67,7 +65,6 @@ import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; - public abstract class MacOSXCGLContext extends GLContextImpl { // Abstract interface for implementation of this context (either @@ -285,12 +282,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl if(!impl.setSwapInterval(interval)) { throw new GLException("Error set swap-interval: "+this); } - if ( isNSContext() ) { - CGL.setSwapInterval(contextHandle, interval); - } else { - int[] lval = new int[] { (int) interval } ; - CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); - } currentSwapInterval = interval ; } @@ -431,6 +422,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle())); + Thread.dumpStack(); } try { int[] viewNotReady = new int[1]; @@ -473,21 +465,24 @@ public abstract class MacOSXCGLContext extends GLContextImpl final MacOSXJAWTWindow lsh = MacOSXCGLDrawableFactory.getLayeredSurfaceHost(surface); nsOpenGLLayerPFmt = pixelFormat; pixelFormat = 0; - // final long nsView = drawable.getNSViewHandle(); - // nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, nsView, fixedCaps.isBackgroundOpaque()); - nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), - drawable.getWidth(), drawable.getHeight()); + /* + final long nsView = drawable.getNSViewHandle(); + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, nsView, fixedCaps.isBackgroundOpaque()); + */ + final int texWidth, texHeight; + if(drawable instanceof MacOSXPbufferCGLDrawable) { + final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable; + texWidth = osxPDrawable.getTextureWidth(); + texHeight = osxPDrawable.getTextureHeight(); + } else { + texWidth = drawable.getWidth(); + texHeight = drawable.getHeight(); + } + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight); if (DEBUG) { System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)); } lsh.attachSurfaceLayer(nsOpenGLLayer); - lsh.addSurfaceUpdatedListener(new SurfaceUpdatedListener() { - public void surfaceUpdated(Object updater, NativeSurface ns, long when) { - if(0 != nsOpenGLLayer) { - CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer); - } - } - }); } } finally { if(0!=pixelFormat) { @@ -527,11 +522,26 @@ public abstract class MacOSXCGLContext extends GLContextImpl } public boolean setSwapInterval(int interval) { - CGL.setSwapInterval(contextHandle, interval); + if(0 != nsOpenGLLayer) { + CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval); + } + CGL.setSwapInterval(contextHandle, interval); return true; } + public boolean swapBuffers() { - return CGL.flushBuffer(contextHandle); + if(0 != nsOpenGLLayer) { + // sync w/ CALayer renderer - wait until next frame is required (v-sync) + CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, 16); // timeout 16ms -> 60Hz + } + if(CGL.flushBuffer(contextHandle)) { + if(0 != nsOpenGLLayer) { + // trigger CALayer to update + CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer); + } + return true; + } + return false; } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java index c5743b923..f4b71d37d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java @@ -33,19 +33,14 @@ package jogamp.opengl.macosx.cgl; -import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.opengl.GL; -import javax.media.opengl.GL2; -import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLPbuffer; - public class MacOSXPbufferCGLContext extends MacOSXCGLContext { // State for render-to-texture and render-to-texture-rectangle support - private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV private int texture; // actual texture object public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable, @@ -55,7 +50,7 @@ public class MacOSXPbufferCGLContext extends MacOSXCGLContext { public void bindPbufferToTexture() { GL gl = getGL(); - gl.glBindTexture(textureTarget, texture); + gl.glBindTexture(((MacOSXPbufferCGLDrawable)drawable).getTextureTarget(), texture); // FIXME: not clear whether this is really necessary, but since // the API docs seem to imply it is and since it doesn't seem to // impact performance, leaving it in @@ -70,18 +65,10 @@ public class MacOSXPbufferCGLContext extends MacOSXCGLContext { if (newCreated) { // Initialize render-to-texture support if requested - DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - GL gl = getGL(); - boolean rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle(); - if (rect) { - if (!gl.isExtensionAvailable("GL_EXT_texture_rectangle")) { - System.err.println("MacOSXPbufferCGLContext: WARNING: GL_EXT_texture_rectangle extension not " + - "supported; skipping requested render_to_texture_rectangle support for pbuffer"); - rect = false; - } - } - textureTarget = (rect ? GL2.GL_TEXTURE_RECTANGLE : GL.GL_TEXTURE_2D); + final GL gl = getGL(); + final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable; + final int textureTarget = osxPDrawable.getTextureTarget(); + int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); texture = tmp[0]; @@ -90,7 +77,9 @@ public class MacOSXPbufferCGLContext extends MacOSXCGLContext { gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); - gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0); + gl.glTexImage2D(textureTarget, 0, GL.GL_RGB, osxPDrawable.getTextureWidth(), osxPDrawable.getTextureHeight(), + 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null); + gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, drawable.getWidth(), drawable.getHeight()); } } diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m index 16e5829ba..6e6e1e2c2 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m @@ -1,54 +1,175 @@ #import "MacOSXWindowSystemInterface.h" +#import <QuartzCore/QuartzCore.h> +#import <pthread.h> +#include "timespec.h" + +// +// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. +// Use CVDisplayLink otherwise. +// +// #define HAS_CADisplayLink 1 +// + +// lock/sync debug output +// +// #define DBG_SYNC 1 +// +#ifdef DBG_SYNC + // #define SYNC_PRINT(...) NSLog(@ ## __VA_ARGS__) + #define SYNC_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define SYNC_PRINT(...) +#endif + +// fps debug output +// +// #define DBG_PERF 1 @interface MyNSOpenGLLayer: NSOpenGLLayer { @protected NSOpenGLPixelBuffer* pbuffer; - int width; - int height; + int texWidth; + int texHeight; GLuint textureID; + GLint swapInterval; +#ifdef HAS_CADisplayLink + CADisplayLink* displayLink; +#else + CVDisplayLinkRef displayLink; +#endif + int tc; + struct timespec t0; @public - volatile BOOL shallDraw; + pthread_mutex_t renderLock; + pthread_cond_t renderSignal; + BOOL shallDraw; } - (id) initWithContext: (NSOpenGLContext*) ctx pixelFormat: (NSOpenGLPixelFormat*) pfmt pbuffer: (NSOpenGLPixelBuffer*) p opaque: (Bool) opaque - width: (int) width - height: (int) height; + texWidth: (int) texWidth + texHeight: (int) texHeight; + +- (int)getSwapInterval; +- (void)setSwapInterval:(int)interval; +- (void)tick; @end +#ifndef HAS_CADisplayLink + +static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*)displayLinkContext; + pthread_mutex_lock(&l->renderLock); + #ifdef DBG_PERF + [l tick]; + #endif + pthread_cond_signal(&l->renderSignal); + SYNC_PRINT("-*-"); + pthread_mutex_unlock(&l->renderLock); + [pool release]; + return kCVReturnSuccess; +} + +#endif + @implementation MyNSOpenGLLayer - (id) initWithContext: (NSOpenGLContext*) _ctx pixelFormat: (NSOpenGLPixelFormat*) _fmt pbuffer: (NSOpenGLPixelBuffer*) p opaque: (Bool) opaque - width: (int) _width - height: (int) _height; + texWidth: (int) _texWidth + texHeight: (int) _texHeight; { self = [super init]; + + pthread_mutex_init(&renderLock, NULL); // fast non-recursive + pthread_cond_init(&renderSignal, NULL); // no attribute + pbuffer = p; [pbuffer retain]; - [self setAsynchronous: NO]; - // [self setAsynchronous: YES]; // FIXME: JAU - [self setNeedsDisplayOnBoundsChange: NO]; + // instantiate a deactivated displayLink +#ifdef HAS_CADisplayLink + displayLink = [[CVDisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)] retain]; + [displayLink setPaused: YES]; +#else + CVReturn cvres; + { + int allDisplaysMask = 0; + int virtualScreen, accelerated, displayMask; + for (virtualScreen = 0; virtualScreen < [_fmt numberOfVirtualScreens]; virtualScreen++) { + [_fmt getValues:&displayMask forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:virtualScreen]; + [_fmt getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:virtualScreen]; + if (accelerated) { + allDisplaysMask |= displayMask; + } + } + cvres = CVDisplayLinkCreateWithOpenGLDisplayMask(allDisplaysMask, &displayLink); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkCreateWithOpenGLDisplayMask %X failed: %d\n", self, allDisplaysMask, cvres); + displayLink = NULL; + } + } + /** + if(NULL != displayLink) { + cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [_ctx CGLContextObj], [_fmt CGLPixelFormatObj]); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres); + displayLink = NULL; + } + } */ + if(NULL != displayLink) { + cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + CVDisplayLinkStop(displayLink); + } +#endif + [self setAsynchronous: YES]; + + [self setNeedsDisplayOnBoundsChange: YES]; // FIXME: learn how to recreate on size change! [self setOpaque: opaque ? YES : NO]; - width = _width; - height = _height; + texWidth = _texWidth; + texHeight = _texHeight; textureID = 0; + swapInterval = -1; shallDraw = NO; - DBG_PRINT("MyNSOpenGLLayer::init %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, %dx%d -> %dx%d\n", - self, _ctx, _fmt, pbuffer, opaque, width, height, [pbuffer pixelsWide], [pbuffer pixelsHigh]); + DBG_PRINT("MyNSOpenGLLayer::init %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d\n", + self, _ctx, _fmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight); return self; } - (void)dealloc { + [self setAsynchronous: NO]; +#ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + [displayLink release]; +#else + if(NULL!=displayLink) { + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); + } +#endif [pbuffer release]; + pthread_cond_destroy(&renderSignal); + pthread_mutex_destroy(&renderLock); DBG_PRINT("MyNSOpenGLLayer::dealloc %p\n", self); [super dealloc]; } @@ -56,31 +177,59 @@ - (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { - DBG_PRINT("MyNSOpenGLLayer::canDrawInOpenGLContext %p: %d\n", self, self->shallDraw); - return self->shallDraw; + // assume both methods 'canDrawInOpenGLContext' and 'drawInOpenGLContext' + // are called from the same thread subsequently + pthread_mutex_lock(&renderLock); + if(NO == shallDraw) { + SYNC_PRINT("<0>"); + pthread_mutex_unlock(&renderLock); + } else { + SYNC_PRINT("<"); + } + return shallDraw; } - (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { - self->shallDraw = NO; - [context makeCurrentContext]; + /** + * v-sync doesn't works w/ NSOpenGLLayer's context .. well :( + * Using CVDisplayLink .. see setSwapInterval() below. + * + if(0 <= swapInterval) { + GLint si; + [context getValues: &si forParameter: NSOpenGLCPSwapInterval]; + if(si != swapInterval) { + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p setSwapInterval: %d -> %d\n", self, si, swapInterval); + [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + } + } */ GLenum textureTarget = [pbuffer textureTarget]; - GLsizei pwidth = [pbuffer pixelsWide]; - GLsizei pheight = [pbuffer pixelsHigh]; - GLfloat tWidth = textureTarget == GL_TEXTURE_2D ? (GLfloat)width/(GLfloat)pwidth : pwidth; - GLfloat tHeight = textureTarget == GL_TEXTURE_2D ? (GLfloat)height/(GLfloat)pheight : pheight; + GLfloat tWidth, tHeight; + { + GLsizei pwidth = [pbuffer pixelsWide]; + GLsizei pheight = [pbuffer pixelsHigh]; + tWidth = textureTarget == GL_TEXTURE_2D ? (GLfloat)pwidth /(GLfloat)texWidth : pwidth; + tHeight = textureTarget == GL_TEXTURE_2D ? (GLfloat)pheight/(GLfloat)texHeight : pheight; + } + Bool texCreated = 0 == textureID; - DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p, ctx %p, pfmt %p %dx%d -> %fx%f 0x%X\n", - self, context, pixelFormat, width, height, tWidth, tHeight, textureTarget); - - if(0 == textureID) { + if(texCreated) { glGenTextures(1, &textureID); + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p, ctx %p, pfmt %p tex %dx%d -> %fx%f 0x%X: creating texID 0x%X\n", + self, context, pixelFormat, texWidth, texHeight, tWidth, tHeight, textureTarget, textureID); } + glBindTexture(textureTarget, textureID); + /** + if(texCreated) { + // proper tex size setup + glTexImage2D(textureTarget, 0, GL_RGB, texWidth, texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + } */ + [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -117,30 +266,126 @@ glDisable(textureTarget); [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; + shallDraw = NO; + if(0 >= swapInterval) { + pthread_cond_signal(&renderSignal); + SYNC_PRINT("*"); + } + SYNC_PRINT("1>"); + pthread_mutex_unlock(&renderLock); +} + +- (int)getSwapInterval +{ + return swapInterval; +} + +- (void)setSwapInterval:(int)interval +{ + DBG_PRINT("MyNSOpenGLLayer::setSwapInterval: %d\n", interval); + swapInterval = interval; + if(0 < swapInterval) { + tc = 0; + timespec_now(&t0); + + [self setAsynchronous: NO]; + #ifdef HAS_CADisplayLink + [displayLink setPaused: NO]; + [displayLink setFrameInterval: interval]; + #else + if(NULL!=displayLink) { + CVDisplayLinkStart(displayLink); + // FIXME: doesn't support interval .. + } + #endif + } else { + #ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + #else + if(NULL!=displayLink) { + CVDisplayLinkStop(displayLink); + } + #endif + [self setAsynchronous: YES]; + } +} + +-(void)tick +{ + tc++; + if(tc%60==0) { + struct timespec t1, td; + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + long td_ms = timespec_milliseconds(&td); + fprintf(stderr, "NSOpenGLLayer: %ld ms / %d frames, %ld ms / frame, %f fps\n", + td_ms, tc, td_ms/tc, (tc * 1000.0) / (float)td_ms ); + fflush(NULL); + } } @end -NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, Bool opaque, int width, int height) { - return [[MyNSOpenGLLayer alloc] initWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque width: width height: height]; +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, Bool opaque, int texWidth, int texHeight) { + return [[MyNSOpenGLLayer alloc] initWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; +} + +void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + pthread_mutex_lock(&l->renderLock); + [l setSwapInterval: interval]; + pthread_mutex_unlock(&l->renderLock); +} + +void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_ms) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + BOOL ready = NO; + int wr = 0; + pthread_mutex_lock(&l->renderLock); + SYNC_PRINT("{"); + do { + if([l getSwapInterval] <= 0) { + ready = !l->shallDraw; + } + if(NO == ready) { + if(0 < to_ms) { + struct timespec to_abs; + timespec_now(&to_abs); + timespec_addms(&to_abs, to_ms); + wr = pthread_cond_timedwait(&l->renderSignal, &l->renderLock, &to_abs); + } else { + pthread_cond_wait (&l->renderSignal, &l->renderLock); + } + ready = !l->shallDraw; + } + } while (NO == ready && 0 == wr) ; + SYNC_PRINT("%d}", ready); + pthread_mutex_unlock(&l->renderLock); } void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer) { MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - l->shallDraw = YES; - if ( [NSThread isMainThread] == YES ) { - [l setNeedsDisplay]; - } else { - // [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:YES]; - [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; + @synchronized(l) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + pthread_mutex_lock(&l->renderLock); + SYNC_PRINT("["); + l->shallDraw = YES; + if([l getSwapInterval] > 0) { + // only trigger update if async mode is off (swapInterval>0) + if ( [NSThread isMainThread] == YES ) { + [l setNeedsDisplay]; + } else { + // can't wait, otherwise we may deadlock AWT + [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; + } + SYNC_PRINT("1]"); + } else { + SYNC_PRINT("0]"); + } + pthread_mutex_unlock(&l->renderLock); + // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); + [pool release]; } - // NSView* view = [l view]; - // [view setNeedsDisplay: YES]; // FIXME: JAU - // [view performSelectorOnMainThread:@selector(setNeedsDisplay:) withObject:YES waitUntilDone:YES]; - // [view performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:YES]; - DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); - [pool release]; } void releaseNSOpenGLLayer(NSOpenGLLayer* l) { |