aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-10-13 03:33:28 +0200
committerSven Gothel <[email protected]>2011-10-13 03:33:28 +0200
commit946c98fd196802755e9e13a9c5db75650a564466 (patch)
treec3aa9b62a1cea7e3a2dc8c306decbbbe273f3b4c /src/jogl
parent22f8e786219166019688ff2eea6ff9570c117544 (diff)
JOGL/OSX: Properly utilize NSOpenGLContext update() via ContextUpdater, which only holds the 'update' state now.
Avoid calling updater() for every makeCurrent(), but if view's frame has changed only. This solves the pixel flickering experienced on OSX. - GLContextImpl:update() -> drawableUpdatedNotify() w/ comments - ContextUpdater holds context, view, old view frame and the update state. It doesn't issue NSOpenGLContext update() by itself, but allows querying and clearing the update flag. - MacOSXOnscreenCGLContext impl drawableUpdatedNotify() - register via ContextUpdater, and use it if available.
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java48
-rw-r--r--src/jogl/native/macosx/ContextUpdater.h11
-rw-r--r--src/jogl/native/macosx/ContextUpdater.m54
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface.m23
5 files changed, 111 insertions, 41 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 99693aabe..283b0c751 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -196,8 +196,18 @@ public abstract class GLContextImpl extends GLContext {
return gl;
}
- // This is only needed for Mac OS X on-screen contexts
- protected void update() throws GLException { }
+ /**
+ * Call this method to notify the OpenGL context
+ * that the drawable has changed (size or position).
+ *
+ * <p>
+ * This is currently being used and overridden by Mac OSX,
+ * which issues the {@link jogamp.opengl.macosx.cgl.CGL#updateContext(long) NSOpenGLContext update()} call.
+ * </p>
+ *
+ * @throws GLException
+ */
+ protected void drawableUpdatedNotify() throws GLException { }
boolean lockFailFast = true;
Object lockFailFastSync = new Object();
@@ -362,7 +372,7 @@ public abstract class GLContextImpl extends GLContext {
if (current == this) {
// Assume we don't need to make this context current again
// For Mac OS X, however, we need to update the context to track resizes
- update();
+ drawableUpdatedNotify();
return CONTEXT_CURRENT;
} else {
current.release();
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
index 55d3a0853..393bd398b 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
@@ -49,41 +49,67 @@ public class MacOSXOnscreenCGLContext extends MacOSXCGLContext {
super(drawable, shareWith);
}
- @Override
+ @Override
protected void makeCurrentImpl(boolean newCreated) throws GLException {
super.makeCurrentImpl(newCreated);
- CGL.updateContext(contextHandle);
+ drawableUpdatedNotify();
}
- @Override
+ @Override
protected void releaseImpl() throws GLException {
super.releaseImpl();
}
- @Override
+ @Override
protected void swapBuffers() {
if (!CGL.flushBuffer(contextHandle)) {
throw new GLException("Error swapping buffers");
}
}
- @Override
- protected void update() throws GLException {
- if (contextHandle == 0) {
- throw new GLException("Context not created");
+ @Override
+ protected void drawableUpdatedNotify() throws GLException {
+ if(0==updateHandle || CGL.updateContextNeedsUpdate(updateHandle)) {
+ if (contextHandle == 0) {
+ throw new GLException("Context not created");
+ }
+ CGL.updateContext(contextHandle);
}
- CGL.updateContext(contextHandle);
}
-
+
+ protected long updateHandle = 0;
+
+ @Override
protected boolean createImpl() {
- return create(false, false);
+ boolean res = create(false, false);
+ if(res && isNSContext) {
+ if(0 != updateHandle) {
+ throw new InternalError("XXX1");
+ }
+ updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
+ if(0 == updateHandle) {
+ throw new InternalError("XXX2");
+ }
+ }
+ return res;
}
+ @Override
+ protected void destroyImpl() throws GLException {
+ if ( 0 != updateHandle ) {
+ CGL.updateContextUnregister(updateHandle);
+ updateHandle = 0;
+ }
+ super.destroyImpl();
+ }
+
+ @Override
public void setOpenGLMode(int mode) {
if (mode != MacOSXCGLDrawable.NSOPENGL_MODE)
throw new GLException("OpenGL mode switching not supported for on-screen GLContexts");
}
+ @Override
public int getOpenGLMode() {
return MacOSXCGLDrawable.NSOPENGL_MODE;
}
diff --git a/src/jogl/native/macosx/ContextUpdater.h b/src/jogl/native/macosx/ContextUpdater.h
index f8ce93def..2483ec403 100644
--- a/src/jogl/native/macosx/ContextUpdater.h
+++ b/src/jogl/native/macosx/ContextUpdater.h
@@ -22,10 +22,13 @@ This notification is sent whenever an NSView that has an attached NSSurface chan
#define UNLOCK_GL(func, line) [ContextUpdater unlock];
#endif
-// gznote: OpenGL NOT thread safe - need to sync on update and paints
-
@interface ContextUpdater : NSObject
{
+@protected
+ NSView * view;
+ NSRect viewRect;
+ NSOpenGLContext *ctx;
+ BOOL viewUpdated;
}
+ (void) lock;
@@ -33,8 +36,10 @@ This notification is sent whenever an NSView that has an attached NSSurface chan
+ (void) unlock;
+ (void) unlockInFunction:(char *)func atLine:(int)line;
-- (void) registerFor:(NSOpenGLContext *)context with: (NSView *)window;
+- (id) initWithContext:(NSOpenGLContext *)context view: (NSView *)nsView;
- (void) update:(NSNotification *)notification;
+- (BOOL) needsUpdate;
+
@end
diff --git a/src/jogl/native/macosx/ContextUpdater.m b/src/jogl/native/macosx/ContextUpdater.m
index 859697722..64d5ef1f9 100644
--- a/src/jogl/native/macosx/ContextUpdater.m
+++ b/src/jogl/native/macosx/ContextUpdater.m
@@ -5,18 +5,17 @@
{
}
-static NSOpenGLContext *theContext;
static pthread_mutex_t resourceLock = PTHREAD_MUTEX_INITIALIZER;
static void printLockDebugInfo(char *message, char *func, int line)
{
fprintf(stderr, "%s in function: \"%s\" at line: %d\n", message, func, line);
- fflush(stderr);
+ fflush(NULL);
}
+ (void) lock
{
- if (theContext != NULL)
+ if (ctx != NULL)
{
pthread_mutex_lock(&resourceLock);
}
@@ -24,7 +23,7 @@ static void printLockDebugInfo(char *message, char *func, int line)
+ (void) lockInFunction:(char *)func atLine:(int)line
{
- if (theContext != NULL)
+ if (ctx != NULL)
{
printLockDebugInfo("locked ", func, line);
[self lock];
@@ -33,7 +32,7 @@ static void printLockDebugInfo(char *message, char *func, int line)
+ (void) unlock
{
- if (theContext != NULL)
+ if (ctx != NULL)
{
pthread_mutex_unlock(&resourceLock);
}
@@ -41,43 +40,62 @@ static void printLockDebugInfo(char *message, char *func, int line)
+ (void) unlockInFunction:(char *)func atLine:(int)line
{
- if (theContext != NULL)
+ if (ctx != NULL)
{
printLockDebugInfo("unlocked", func, line);
[self unlock];
}
}
-- (void) registerFor:(NSOpenGLContext *)context with: (NSView *)view
+- (void) update:(NSNotification *)notification
{
- if (view != NULL)
- {
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update:) name:NSViewGlobalFrameDidChangeNotification object: view];
- theContext = context;
+ [ContextUpdater lock];
+
+ NSRect r = [view frame];
+ if(viewRect.origin.x != r.origin.x ||
+ viewRect.origin.y != r.origin.y ||
+ viewRect.size.width != r.size.width ||
+ viewRect.size.height != r.size.height) {
+ viewUpdated = TRUE;
+ viewRect = r;
}
+
+ [ContextUpdater unlock];
}
-- (void) update:(NSNotification *)notification
+- (BOOL) needsUpdate
{
+ BOOL r;
[ContextUpdater lock];
- [theContext update];
+ r = viewUpdated;
+ viewUpdated = FALSE;
[ContextUpdater unlock];
+
+ return r;
}
-- (id) init
-{
- theContext = NULL;
-
+- (id) initWithContext:(NSOpenGLContext *)context view: (NSView *)nsView
+{
+ ctx = context;
+ view = nsView;
+ [ctx retain];
+ [view retain];
+ viewRect = [view frame];
+ viewUpdated = FALSE;
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update:) name:NSViewGlobalFrameDidChangeNotification object: view];
+
return [super init];
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [view release];
+ [ctx release];
[super dealloc];
}
-@end \ No newline at end of file
+@end
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
index 86d875502..aab70791c 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
@@ -590,7 +590,8 @@ Bool deleteContext(void* nsJContext) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[nsContext clearDrawable];
- [nsContext release]; // freezes for a few seconds if ctx is shared
+ // [nsContext release]; // FIXME: JAU: freezes for a few seconds if ctx is shared
+ // [nsContext dealloc];
[pool release];
return true;
}
@@ -624,15 +625,25 @@ void copyContext(void* destContext, void* srcContext, int mask) {
[dst copyAttributesFromContext: src withMask: mask];
}
-void* updateContextRegister(void* nsJContext, void* view) {
+void* updateContextRegister(void* nsJContext, void* nsJView) {
NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext;
- NSView *nsView = (NSView*)view;
+ NSView *nsView = (NSView*)nsJView;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- ContextUpdater *contextUpdater = [[ContextUpdater alloc] init];
- [contextUpdater registerFor:nsContext with:nsView];
+ ContextUpdater *contextUpdater = [[ContextUpdater alloc] initWithContext: nsContext view: nsView];
[pool release];
- return NULL;
+ return contextUpdater;
+}
+
+Bool updateContextNeedsUpdate(void* updater) {
+ ContextUpdater *contextUpdater = (ContextUpdater *)updater;
+ BOOL res;
+
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ res = [contextUpdater needsUpdate];
+ [pool release];
+
+ return ( res == TRUE ) ? true : false;
}
void updateContextUnregister(void* updater) {