summaryrefslogtreecommitdiffstats
path: root/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m')
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m673
1 files changed, 462 insertions, 211 deletions
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index f3495efff..d83ddbc22 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -1,8 +1,25 @@
#import "MacOSXWindowSystemInterface.h"
#import <QuartzCore/QuartzCore.h>
#import <pthread.h>
+#import "NativeWindowProtocols.h"
#include "timespec.h"
+#import <OpenGL/glext.h>
+
+/**
+ * Partial include of gl3.h - which we can only expect and use
+ * in case of a GL3 core context at runtime.
+ * Otherwise we would need to have 2 modules, one including GL2
+ * and one inclusing GL3 headers.
+ */
+#ifndef GL_ARB_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+extern void glBindVertexArray (GLuint array);
+extern void glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+extern void glGenVertexArrays (GLsizei n, GLuint *arrays);
+extern GLboolean glIsVertexArray (GLuint array);
+#endif
+
//
// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient.
// Use CVDisplayLink otherwise.
@@ -25,6 +42,8 @@
//
// #define DBG_PERF 1
+// #define DBG_LIFECYCLE 1
+
/**
* Capture setView(NULL), which produces a 'invalid drawable' message
*
@@ -36,6 +55,10 @@
- (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share;
- (void)setView:(NSView *)view;
- (void)update;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+#endif
- (void)dealloc;
@end
@@ -44,49 +67,85 @@
- (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share
{
- DBG_PRINT("MyNSOpenGLContext.initWithFormat.0: format %p, share %p\n", format, share);
+ DBG_PRINT("MyNSOpenGLContext::initWithFormat.0: format %p, share %p\n", format, share);
MyNSOpenGLContext * o = [super initWithFormat:format shareContext:share];
- DBG_PRINT("MyNSOpenGLContext.initWithFormat.X: new %p\n", o);
+ DBG_PRINT("MyNSOpenGLContext::initWithFormat.X: new %p\n", o);
return o;
}
- (void)setView:(NSView *)view
{
- DBG_PRINT("MyNSOpenGLContext.setView: this.0 %p, view %p\n", self, view);
+ DBG_PRINT("MyNSOpenGLContext::setView: this.0 %p, view %p\n", self, view);
+ // NSLog(@"MyNSOpenGLContext::setView: %@",[NSThread callStackSymbols]);
if(NULL != view) {
[super setView:view];
+ } else {
+ [self clearDrawable];
}
- DBG_PRINT("MyNSOpenGLContext.setView.X\n");
+ DBG_PRINT("MyNSOpenGLContext::setView.X\n");
}
- (void)update
{
- DBG_PRINT("MyNSOpenGLContext.update: this.0 %p, view %p\n", self, [self view]);
+ DBG_PRINT("MyNSOpenGLContext::update: this.0 %p, view %p\n", self, [self view]);
[super update];
- DBG_PRINT("MyNSOpenGLContext.update.X\n");
+ DBG_PRINT("MyNSOpenGLContext::update.X\n");
}
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT("MyNSOpenGLContext::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLContext::retain: %@",[NSThread callStackSymbols]);
+ id o = [super retain];
+ DBG_PRINT("MyNSOpenGLContext::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT("MyNSOpenGLContext::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+ // DBG_PRINT("MyNSOpenGLContext::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+#endif
+
- (void)dealloc
{
- DBG_PRINT("MyNSOpenGLContext.dealloc: this.0 %p\n", self);
+ DBG_PRINT("MyNSOpenGLContext::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLContext::dealloc: %@",[NSThread callStackSymbols]);
+
+ [self clearDrawable];
+
[super dealloc];
- DBG_PRINT("MyNSOpenGLContext.dealloc.X: %p\n", self);
+ DBG_PRINT("MyNSOpenGLContext::dealloc.X\n");
}
@end
-@interface MyNSOpenGLLayer: NSOpenGLLayer
+@interface MyNSOpenGLLayer: NSOpenGLLayer <NWDedicatedFrame>
{
@private
GLfloat gl_texCoords[8];
+ NSOpenGLContext* glContext;
+ Bool isGLEnabled;
@protected
- NSOpenGLContext* parentCtx;
+ GLuint gl3ShaderProgramName;
+ GLuint vboBufVert;
+ GLuint vboBufTexCoord;
+ GLint vertAttrLoc;
+ GLint texCoordAttrLoc;
NSOpenGLPixelFormat* parentPixelFmt;
+ int texWidth;
+ int texHeight;
+ volatile Bool dedicatedFrameSet;
+ volatile CGRect dedicatedFrame;
volatile NSOpenGLPixelBuffer* pbuffer;
volatile GLuint textureID;
- volatile int texWidth;
- volatile int texHeight;
+ volatile NSOpenGLPixelBuffer* newPBuffer;
#ifdef HAS_CADisplayLink
CADisplayLink* displayLink;
#else
@@ -101,35 +160,52 @@
pthread_mutex_t renderLock;
pthread_cond_t renderSignal;
volatile Bool shallDraw;
- volatile int newTexWidth;
- volatile int newTexHeight;
}
- (id) setupWithContext: (NSOpenGLContext*) parentCtx
+ gl3ShaderProgramName: (GLuint) gl3ShaderProgramName
pixelFormat: (NSOpenGLPixelFormat*) pfmt
pbuffer: (NSOpenGLPixelBuffer*) p
texIDArg: (GLuint) texID
opaque: (Bool) opaque
texWidth: (int) texWidth
- texHeight: (int) texHeight;
+ texHeight: (int) texHeight
+ winWidth: (int)winWidth
+ winHeight: (int)winHeight;
-- (Bool) validateTexSizeWithNewSize;
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight;
-- (void) setTextureID: (int) _texID;
-
-- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p;
-
-- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat;
+- (void)releaseLayer;
+- (void)deallocPBuffer;
- (void)disableAnimation;
- (void)pauseAnimation:(Bool)pause;
-- (void)deallocPBuffer;
-- (void)releaseLayer;
-- (void)dealloc;
- (void)setSwapInterval:(int)interval;
- (void)tick;
- (void)waitUntilRenderSignal: (long) to_micros;
- (Bool)isGLSourceValid;
+- (void) setGLEnabled: (Bool) enable;
+- (Bool) validateTexSize: (int)newTexWidth height:(int)newTexHeight;
+- (void) setTextureID: (int) _texID;
+
+- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p;
+- (void) setNewPBuffer: (NSOpenGLPixelBuffer*)p;
+- (void) applyNewPBuffer;
+
+- (void)setDedicatedFrame:(CGRect)frame quirks:(int)quirks; // @NWDedicatedFrame
+- (void) setFrame:(CGRect) frame;
+- (id<CAAction>)actionForKey:(NSString *)key ;
+- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask;
+- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat;
+- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp;
+- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp;
+
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+#endif
+- (void)dealloc;
+
@end
#ifndef HAS_CADisplayLink
@@ -168,13 +244,16 @@ static const GLfloat gl_verts[] = {
@implementation MyNSOpenGLLayer
-- (id) setupWithContext: (NSOpenGLContext*) _parentCtx
+- (id) setupWithContext: (NSOpenGLContext*) parentCtx
+ gl3ShaderProgramName: (GLuint) _gl3ShaderProgramName
pixelFormat: (NSOpenGLPixelFormat*) _parentPixelFmt
pbuffer: (NSOpenGLPixelBuffer*) p
texIDArg: (GLuint) texID
opaque: (Bool) opaque
texWidth: (int) _texWidth
- texHeight: (int) _texHeight;
+ texHeight: (int) _texHeight
+ winWidth: (int) _winWidth
+ winHeight: (int) _winHeight
{
pthread_mutexattr_t renderLockAttr;
pthread_mutexattr_init(&renderLockAttr);
@@ -188,17 +267,35 @@ static const GLfloat gl_verts[] = {
gl_texCoords[i] = 0.0f;
}
}
- parentCtx = _parentCtx;
- parentPixelFmt = _parentPixelFmt;
+ /**
+ * Set via
+ * - OSXUtil_SetCALayerPixelScale0
+ * - OSXUtil_AddCASublayer0
+NS_DURING
+ // Available >= 10.7
+ [self setContentsScale: (CGFloat)_texWidth/(CGFloat)_winWidth];
+NS_HANDLER
+NS_ENDHANDLER
+ */
+
+ parentPixelFmt = [_parentPixelFmt retain]; // until destruction
+ glContext = [[MyNSOpenGLContext alloc] initWithFormat:parentPixelFmt shareContext:parentCtx];
+ gl3ShaderProgramName = _gl3ShaderProgramName;
+ vboBufVert = 0;
+ vboBufTexCoord = 0;
+ vertAttrLoc = 0;
+ texCoordAttrLoc = 0;
swapInterval = 1; // defaults to on (as w/ new GL profiles)
swapIntervalCounter = 0;
timespec_now(&lastWaitTime);
shallDraw = NO;
- newTexWidth = _texWidth;
- newTexHeight = _texHeight;
- [self validateTexSizeWithNewSize];
+ isGLEnabled = YES;
+ dedicatedFrameSet = NO;
+ dedicatedFrame = CGRectMake(0, 0, _winWidth, _winHeight);
+ [self validateTexSize: _texWidth height:_texHeight];
[self setTextureID: texID];
+ newPBuffer = NULL;
pbuffer = p;
if(NULL != pbuffer) {
[pbuffer retain];
@@ -232,10 +329,11 @@ static const GLfloat gl_verts[] = {
}
}
if(NULL != displayLink) {
- cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [parentCtx CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
+ CVReturn cvres;
+ DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.1: setup DisplayLink %p\n", displayLink);
+ cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [glContext CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
if(kCVReturnSuccess != cvres) {
DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres);
- displayLink = NULL;
}
}
if(NULL != displayLink) {
@@ -257,34 +355,36 @@ static const GLfloat gl_verts[] = {
#ifdef VERBOSE_ON
CGRect lRect = [self bounds];
if(NULL != pbuffer) {
- DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf (refcnt %d)\n",
- self, parentCtx, parentPixelFmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
- lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+ DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, pctx %p, pfmt %p, pbuffer %p, ctx %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n",
+ self, parentCtx, parentPixelFmt, pbuffer, glContext, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
} else {
- DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf (refcnt %d)\n",
- self, parentCtx, parentPixelFmt, opaque, (int)textureID, texWidth, texHeight,
- lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+ DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, pctx %p, pfmt %p, ctx %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n",
+ self, parentCtx, parentPixelFmt, glContext, opaque, (int)textureID, texWidth, texHeight,
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
}
#endif
return self;
}
-- (Bool) validateTexSizeWithNewSize
+- (void) setGLEnabled: (Bool) enable
{
- return [self validateTexSize: newTexWidth texHeight: newTexHeight];
+ DBG_PRINT("MyNSOpenGLLayer::setGLEnabled: %p, %d -> %d\n", self, (int)isGLEnabled, (int)enable);
+ isGLEnabled = enable;
}
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight
+- (Bool) validateTexSize: (int)newTexWidth height:(int)newTexHeight
{
- if(_texHeight != texHeight || _texWidth != texWidth) {
- texWidth = _texWidth;
- texHeight = _texHeight;
- CGRect lRect = [self bounds];
- lRect.origin.x = 0;
- lRect.origin.y = 0;
- lRect.size.width = texWidth;
- lRect.size.height = texHeight;
- [self setFrame: lRect];
+ Bool changed;
+
+ if( newTexHeight != texHeight || newTexWidth != texWidth ) {
+ #ifdef VERBOSE_ON
+ const int oldTexWidth = texWidth;
+ const int oldTexHeight = texHeight;
+ #endif
+ texWidth = newTexWidth;
+ texHeight = newTexHeight;
+ changed = YES;
GLfloat texCoordWidth, texCoordHeight;
if(NULL != pbuffer) {
@@ -306,10 +406,20 @@ static const GLfloat gl_verts[] = {
gl_texCoords[5] = texCoordHeight;
gl_texCoords[4] = texCoordWidth;
gl_texCoords[6] = texCoordWidth;
- return YES;
+ #ifdef VERBOSE_ON
+NS_DURING
+ // Available >= 10.7
+ DBG_PRINT("MyNSOpenGLLayer::validateTexSize %p: tex %dx%d -> %dx%d, dedicatedFrame set:%d %lf/%lf %lfx%lf scale %lf\n",
+ self, oldTexWidth, oldTexHeight, newTexWidth, newTexHeight,
+ dedicatedFrameSet, dedicatedFrame.origin.x, dedicatedFrame.origin.y, dedicatedFrame.size.width, dedicatedFrame.size.height,
+ [self contentsScale]);
+NS_HANDLER
+NS_ENDHANDLER
+ #endif
} else {
- return NO;
+ changed = NO;
}
+ return changed;
}
- (void) setTextureID: (int) _texID
@@ -317,58 +427,32 @@ static const GLfloat gl_verts[] = {
textureID = _texID;
}
-- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p
+- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p
{
- if( pbuffer != p ) {
- DBG_PRINT("MyNSOpenGLLayer::validatePBuffer.0 %p, pbuffer %p, (refcnt %d)\n", self, p, (int)[self retainCount]);
-
- SYNC_PRINT("{PB-nil}");
-
- [self deallocPBuffer];
-
- pbuffer = p;
- if(NULL != pbuffer) {
- [pbuffer retain];
- }
- [self setTextureID: 0];
-
- shallDraw = NO;
- }
+ return pbuffer == p || newPBuffer == p;
}
-/**
-- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask
+- (void)setNewPBuffer: (NSOpenGLPixelBuffer*)p
{
- DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n",
- self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
- return parentPixelFmt;
-} */
-
-- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat
-{
- DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, parent %p\n",
- self, (int)[self retainCount], pixelFormat, parentCtx);
- NSOpenGLContext * nctx = [[MyNSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:parentCtx];
- DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.X: new-ctx %p\n", nctx);
- return nctx;
+ SYNC_PRINT("<NP-S %p -> %p>", pbuffer, p);
+ newPBuffer = p;
+ [newPBuffer retain];
}
-- (void)disableAnimation
+- (void) applyNewPBuffer
{
- DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
- pthread_mutex_lock(&renderLock);
- [self setAsynchronous: NO];
- if(NULL != displayLink) {
-#ifdef HAS_CADisplayLink
- [displayLink setPaused: YES];
- [displayLink release];
-#else
- CVDisplayLinkStop(displayLink);
- CVDisplayLinkRelease(displayLink);
-#endif
- displayLink = NULL;
+ if( NULL != newPBuffer ) { // volatile OK
+ SYNC_PRINT("<NP-A %p -> %p>", pbuffer, newPBuffer);
+
+ if( 0 != textureID ) {
+ glDeleteTextures(1, (GLuint *)&textureID);
+ [self setTextureID: 0];
+ }
+ [pbuffer release];
+
+ pbuffer = newPBuffer;
+ newPBuffer = NULL;
}
- pthread_mutex_unlock(&renderLock);
}
- (void)deallocPBuffer
@@ -381,71 +465,157 @@ static const GLfloat gl_verts[] = {
DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID);
if( 0 != textureID ) {
- glDeleteTextures(1, &textureID);
+ glDeleteTextures(1, (GLuint *)&textureID);
+ [self setTextureID: 0];
+ }
+ if(NULL != pbuffer) {
+ [pbuffer release];
+ pbuffer = NULL;
+ }
+ if(NULL != newPBuffer) {
+ [newPBuffer release];
+ newPBuffer = NULL;
}
- [pbuffer release];
[context clearDrawable];
} else {
DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (w/o ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID);
}
- pbuffer = NULL;
- [self setTextureID: 0];
}
}
+- (void)disableAnimation
+{
+ DBG_PRINT("MyNSOpenGLLayer::disableAnimation.0: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
+ [self setAsynchronous: NO];
+ if(NULL != displayLink) {
+#ifdef HAS_CADisplayLink
+ [displayLink setPaused: YES];
+ [displayLink release];
+#else
+ CVDisplayLinkStop(displayLink);
+ CVDisplayLinkRelease(displayLink);
+#endif
+ displayLink = NULL;
+ }
+ DBG_PRINT("MyNSOpenGLLayer::disableAnimation.X: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
+}
+
- (void)releaseLayer
{
DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
- pthread_mutex_lock(&renderLock);
+ [self setGLEnabled: NO];
[self disableAnimation];
+ pthread_mutex_lock(&renderLock);
[self deallocPBuffer];
- [[self openGLContext] release];
- [self release];
- DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ if( NULL != glContext ) {
+ [glContext release];
+ glContext = NULL;
+ }
+ if( NULL != parentPixelFmt ) {
+ [parentPixelFmt release];
+ parentPixelFmt = NULL;
+ }
pthread_mutex_unlock(&renderLock);
+ [self release];
+ DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p\n", self);
}
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT("MyNSOpenGLLayer::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLLayer::retain: %@",[NSThread callStackSymbols]);
+ id o = [super retain];
+ DBG_PRINT("MyNSOpenGLLayer::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT("MyNSOpenGLLayer::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLLayer::release: %@",[NSThread callStackSymbols]);
+ [super release];
+ // DBG_PRINT("MyNSOpenGLLayer::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+#endif
+
- (void)dealloc
{
DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
// NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]);
-
- pthread_mutex_lock(&renderLock);
[self disableAnimation];
+ pthread_mutex_lock(&renderLock);
[self deallocPBuffer];
pthread_mutex_unlock(&renderLock);
pthread_cond_destroy(&renderSignal);
pthread_mutex_destroy(&renderLock);
[super dealloc];
- DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self);
+ // DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self);
}
- (Bool)isGLSourceValid
{
- return NULL != pbuffer || 0 != textureID ;
+ return NULL != pbuffer || NULL != newPBuffer || 0 != textureID ;
+}
+
+// @NWDedicatedFrame
+- (void)setDedicatedFrame:(CGRect)dFrame quirks:(int)quirks {
+ CGRect lRect = [self frame];
+ Bool dedicatedFramePosSet = 0 != ( NW_DEDICATEDFRAME_QUIRK_POSITION & quirks );
+ Bool dedicatedFrameSizeSet = 0 != ( NW_DEDICATEDFRAME_QUIRK_SIZE & quirks );
+ Bool dedicatedLayoutSet = 0 != ( NW_DEDICATEDFRAME_QUIRK_LAYOUT & quirks );
+ dedicatedFrameSet = dedicatedFramePosSet || dedicatedFrameSizeSet || dedicatedLayoutSet;
+ dedicatedFrame = dFrame;
+
+ DBG_PRINT("MyNSOpenGLLayer::setDedicatedFrame: Quirks [%d, pos %d, size %d, lout %d], %p, texSize %dx%d, %lf/%lf %lfx%lf -> %lf/%lf %lfx%lf\n",
+ quirks, dedicatedFramePosSet, dedicatedFrameSizeSet, dedicatedLayoutSet, self, texWidth, texHeight,
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height,
+ dFrame.origin.x, dFrame.origin.y, dFrame.size.width, dFrame.size.height);
+ (void)lRect; // silence
+
+ if( dedicatedFrameSet ) {
+ [super setFrame: dedicatedFrame];
+ }
}
-- (void)resizeWithOldSuperlayerSize:(CGSize)size
- {
- CGRect lRectS = [[self superlayer] bounds];
+- (void) setFrame:(CGRect) frame {
+ if( dedicatedFrameSet ) {
+ [super setFrame: dedicatedFrame];
+ } else {
+ [super setFrame: frame];
+ }
+}
- DBG_PRINT("MyNSOpenGLLayer::resizeWithOldSuperlayerSize: %p, texSize %dx%d, bounds: %lfx%lf -> %lfx%lf (refcnt %d)\n",
- self, texWidth, texHeight, size.width, size.height, lRectS.size.width, lRectS.size.height, (int)[self retainCount]);
+- (id<CAAction>)actionForKey:(NSString *)key
+{
+ DBG_PRINT("MyNSOpenGLLayer::actionForKey.0 %p key %s -> NIL\n", self, [key UTF8String]);
+ return nil;
+ // return [super actionForKey: key];
+}
- newTexWidth = lRectS.size.width;
- newTexHeight = lRectS.size.height;
- shallDraw = YES;
- SYNC_PRINT("<SZ %dx%d>", newTexWidth, newTexHeight);
+- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask
+{
+ DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n",
+ self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
+ // We simply take over ownership of parent PixelFormat until releaseLayer..
+ return parentPixelFmt;
+}
- [super resizeWithOldSuperlayerSize: size];
+- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+{
+ DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, ctx %p, DisplayLink %p\n",
+ self, (int)[self retainCount], pixelFormat, glContext, displayLink);
+ return glContext;
}
- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
- SYNC_PRINT("<? %d>", (int)shallDraw);
- return shallDraw;
+ SYNC_PRINT("<? %d, %d>", (int)shallDraw, (int)isGLEnabled);
+ return shallDraw && isGLEnabled;
}
- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
@@ -455,21 +625,40 @@ static const GLfloat gl_verts[] = {
SYNC_PRINT("<* ");
// NSLog(@"MyNSOpenGLLayer::DRAW: %@",[NSThread callStackSymbols]);
- if( shallDraw && ( NULL != pbuffer || 0 != textureID ) ) {
+ if( isGLEnabled && shallDraw && ( NULL != pbuffer || NULL != newPBuffer || 0 != textureID ) ) {
[context makeCurrentContext];
+ if( NULL != newPBuffer ) { // volatile OK
+ [self applyNewPBuffer];
+ }
+
GLenum textureTarget;
- Bool texSizeChanged = [self validateTexSizeWithNewSize];
+ CGRect texDim = dedicatedFrameSet ? dedicatedFrame : [self bounds];
+ CGFloat _contentsScale = 1;
+NS_DURING
+ // Available >= 10.7
+ _contentsScale = [self contentsScale];
+NS_HANDLER
+NS_ENDHANDLER
+ Bool texSizeChanged = [self validateTexSize: (int)(texDim.size.width * _contentsScale + 0.5f)
+ height:(int)(texDim.size.height * _contentsScale + 0.5f)];
+ if( texSizeChanged ) {
+ [context update];
+ }
if( NULL != pbuffer ) {
if( texSizeChanged && 0 != textureID ) {
- glDeleteTextures(1, &textureID);
+ glDeleteTextures(1, (GLuint *)&textureID);
[self setTextureID: 0];
}
textureTarget = [pbuffer textureTarget];
+ if( 0 != gl3ShaderProgramName ) {
+ glUseProgram(gl3ShaderProgramName);
+ glActiveTexture(GL_TEXTURE0);
+ }
if( 0 == textureID ) {
- glGenTextures(1, &textureID);
+ glGenTextures(1, (GLuint *)&textureID);
glBindTexture(textureTarget, textureID);
glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -478,26 +667,80 @@ static const GLfloat gl_verts[] = {
} else {
glBindTexture(textureTarget, textureID);
}
- [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT];
+ [context setTextureImageToPixelBuffer: (NSOpenGLPixelBuffer*) pbuffer colorBuffer: GL_FRONT];
} else {
+ if( 0 != gl3ShaderProgramName ) {
+ glUseProgram(gl3ShaderProgramName);
+ glActiveTexture(GL_TEXTURE0);
+ }
textureTarget = GL_TEXTURE_2D;
glBindTexture(textureTarget, textureID);
}
- SYNC_PRINT(" %d*>", (int)textureID);
-
- glEnable(textureTarget);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, gl_verts);
- glTexCoordPointer(2, GL_FLOAT, 0, gl_texCoords);
-
- glDrawArrays(GL_QUADS, 0, 4);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glDisable(textureTarget);
+ SYNC_PRINT(" %d gl3Prog %d/%d*>", (int)textureID, (int)gl3ShaderProgramName, (int)glIsProgram (gl3ShaderProgramName));
+
+ if( 0 == vboBufVert ) { // Once: Init Data and Bind to Pointer
+ if( 0 != gl3ShaderProgramName ) {
+ // Install default VAO as required by GL 3.2 core!
+ GLuint vaoBuf = 0;
+ glGenVertexArrays(1, &vaoBuf);
+ glBindVertexArray(vaoBuf);
+
+ // Set texture-unit 0
+ GLint texUnitLoc = glGetUniformLocation (gl3ShaderProgramName, "mgl_Texture0");
+ glUniform1i (texUnitLoc, 0);
+ }
+ glGenBuffers( 1, &vboBufVert );
+ glBindBuffer( GL_ARRAY_BUFFER, vboBufVert );
+ glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), gl_verts, GL_STATIC_DRAW);
+ if( 0 != gl3ShaderProgramName ) {
+ vertAttrLoc = glGetAttribLocation( gl3ShaderProgramName, "mgl_Vertex" );
+ glVertexAttribPointer( vertAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL );
+ } else {
+ glVertexPointer(2, GL_FLOAT, 0, NULL);
+ }
+
+ glGenBuffers( 1, &vboBufTexCoord );
+ glBindBuffer( GL_ARRAY_BUFFER, vboBufTexCoord );
+ glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), gl_texCoords, GL_STATIC_DRAW);
+ if( 0 != gl3ShaderProgramName ) {
+ texCoordAttrLoc = glGetAttribLocation( gl3ShaderProgramName, "mgl_MultiTexCoord" );
+ glVertexAttribPointer( texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL );
+ } else {
+ glTexCoordPointer(2, GL_FLOAT, 0, NULL);
+ }
+ }
+ if( texSizeChanged ) {
+ glBindBuffer( GL_ARRAY_BUFFER, vboBufTexCoord );
+ glBufferSubData( GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), gl_texCoords);
+ if( 0 != gl3ShaderProgramName ) {
+ glVertexAttribPointer( texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL );
+ } else {
+ glTexCoordPointer(2, GL_FLOAT, 0, NULL);
+ }
+ }
+ if( 0 != gl3ShaderProgramName ) {
+ glEnableVertexAttribArray( vertAttrLoc );
+ glEnableVertexAttribArray( texCoordAttrLoc );
+ } else {
+ glEnable(textureTarget);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ if( 0 != gl3ShaderProgramName ) {
+ glDisableVertexAttribArray( vertAttrLoc );
+ glDisableVertexAttribArray( texCoordAttrLoc );
+ glUseProgram(0);
+ } else {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDisable(textureTarget);
+ }
+
glBindTexture(textureTarget, 0);
[context clearDrawable];
@@ -595,102 +838,109 @@ static const GLfloat gl_verts[] = {
- (void)waitUntilRenderSignal: (long) to_micros
{
- BOOL ready = NO;
- int wr = 0;
+ struct timespec t0, to_until;
+ BOOL tooLate;
+ int wr;
+ if( 0 >= to_micros ) {
+ to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
+ NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
+ }
pthread_mutex_lock(&renderLock);
- SYNC_PRINT("{W %ld us", to_micros);
- do {
- if(0 >= swapInterval) {
- ready = YES;
- }
- if(NO == ready) {
- #ifdef DBG_SYNC
- struct timespec t0, t1, td, td2;
- timespec_now(&t0);
- #endif
- if(0 < to_micros) {
- struct timespec to_abs = lastWaitTime;
- timespec_addmicros(&to_abs, to_micros);
- #ifdef DBG_SYNC
- timespec_subtract(&td, &to_abs, &t0);
- fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
- #endif
- wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- } else {
- pthread_cond_wait (&renderSignal, &renderLock);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- }
- ready = YES;
+ timespec_now(&t0);
+ to_until = lastWaitTime;
+ timespec_addmicros(&to_until, to_micros);
+ tooLate = timespec_compare(&to_until, &t0) < 0;
+ #ifdef DBG_SYNC
+ struct timespec td_until;
+ timespec_subtract(&td_until, &to_until, &t0);
+ SYNC_PRINT("{W %ld ms, to %ld ms, late %d", to_micros/1000, timespec_milliseconds(&td_until), tooLate);
+ #endif
+ if( 0 < swapInterval ) {
+ if( tooLate ) {
+ // adjust!
+ to_until = t0;
+ timespec_addmicros(&to_until, to_micros);
}
- } while (NO == ready && 0 == wr) ;
- SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready);
+ wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_until);
+ #ifdef DBG_SYNC
+ struct timespec t1, td, td2;
+ timespec_now(&t1);
+ timespec_subtract(&td, &t1, &t0);
+ timespec_subtract(&td2, &t1, &lastWaitTime);
+ fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
+ #endif
+ }
+ SYNC_PRINT("-%d-%d}\n", shallDraw, wr);
timespec_now(&lastWaitTime);
pthread_mutex_unlock(&renderLock);
}
@end
-NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) {
- // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ?
- // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO.
- // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
- // opaque: opaque texWidth: texWidth texHeight: texHeight];
-
- return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
- opaque: opaque texWidth: texWidth texHeight: texHeight];
+NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, int gl3ShaderProgramName, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight, int winWidth, int winHeight) {
+ return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx gl3ShaderProgramName: (GLuint)gl3ShaderProgramName pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
+ opaque: opaque texWidth: texWidth texHeight: texHeight
+ winWidth: winWidth winHeight: winHeight];
+}
+
+void setNSOpenGLLayerEnabled(NSOpenGLLayer* layer, Bool enable) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+ [l setGLEnabled: enable];
+ [pool release];
}
void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
[l setSwapInterval: interval];
[pool release];
}
void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
[l waitUntilRenderSignal: to_micros];
[pool release];
}
-void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+ Bool shallDraw;
- pthread_mutex_lock(&l->renderLock);
- [l validatePBuffer:0];
- pthread_mutex_unlock(&l->renderLock);
+ // volatile OK
+ [l setTextureID: texID];
+ shallDraw = [l isGLSourceValid];
+ l->shallDraw = shallDraw;
+ SYNC_PRINT("<! T %d>", (int)shallDraw);
+ if(shallDraw) {
+ if ( [NSThread isMainThread] == YES ) {
+ [l setNeedsDisplay];
+ } else {
+ // don't wait - using doublebuffering
+ [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
+ }
+ }
+ // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l);
[pool release];
}
-void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
Bool shallDraw;
- pthread_mutex_lock(&l->renderLock);
- [l validatePBuffer:p];
- // l->newTexWidth = texWidth;
- // l->newTexHeight = texHeight;
- [l setTextureID: texID];
+ if( NO == [l isSamePBuffer: p] ) {
+ [l setNewPBuffer: p];
+ }
+
+ // volatile OK
shallDraw = [l isGLSourceValid];
l->shallDraw = shallDraw;
- pthread_mutex_unlock(&l->renderLock);
- SYNC_PRINT("<! T%dx%d O%dx%d %d>", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw);
+ SYNC_PRINT("<! T %d>", (int)shallDraw);
if(shallDraw) {
if ( [NSThread isMainThread] == YES ) {
[l setNeedsDisplay];
@@ -704,17 +954,18 @@ void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p,
}
void releaseNSOpenGLLayer(NSOpenGLLayer* layer) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
- if ( [NSThread isMainThread] == YES ) {
- [l releaseLayer];
- } else {
- [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO];
- }
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+ DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
+ [l releaseLayer];
DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l);
+
+ [CATransaction commit];
+
[pool release];
}