diff options
-rw-r--r-- | make/cgl-macosx.cfg | 20 | ||||
-rw-r--r-- | make/stub_includes/macosx/window-system.c | 19 | ||||
-rw-r--r-- | src/native/jogl/ContextUpdater.h | 40 | ||||
-rw-r--r-- | src/native/jogl/ContextUpdater.m | 83 | ||||
-rw-r--r-- | src/native/jogl/MacOSXWindowSystemInterface.m | 306 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java | 57 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java | 31 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java | 84 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java | 113 |
9 files changed, 570 insertions, 183 deletions
diff --git a/make/cgl-macosx.cfg b/make/cgl-macosx.cfg index f3824f703..649fc7e30 100644 --- a/make/cgl-macosx.cfg +++ b/make/cgl-macosx.cfg @@ -12,11 +12,21 @@ Opaque long void * # FIXME: rather than put in a header file somewhere in the source tree, # this was the easiest way of sharing the prototypes between these files CustomCCode typedef int Bool; -CustomCCode extern void* createContext(void* nsView, void* shareContext); -CustomCCode extern Bool makeCurrentContext(void* nsView , void* nsContext); -CustomCCode extern Bool clearCurrentContext (void* nsView , void* nsContext); -CustomCCode extern Bool deleteContext (void* nsView , void* nsContext); -CustomCCode extern Bool flushBuffer (void* nsView , void* nsContext); + +CustomCCode extern void* createContext(void* shareContext, void* nsView); +CustomCCode extern Bool makeCurrentContext(void* nsContext, void* nsView); +CustomCCode extern Bool clearCurrentContext(void* nsContext, void* nsView); +CustomCCode extern Bool deleteContext(void* nsContext, void* nsView); +CustomCCode extern Bool flushBuffer(void* nsContext, void* nsView); + +CustomCCode extern void* updateContextRegister(void* nsContext, void* nsView); +CustomCCode extern void updateContextUnregister(void* nsContext, void* nsView, void* updater); + +CustomCCode extern void* createPBuffer(void* nsContext, int width, int height); +CustomCCode extern Bool destroyPBuffer(void* nsContext, void* pBuffer); +CustomCCode extern int bindPBuffer(void* nsContext, void* pBuffer); +CustomCCode extern void unbindPBuffer(void* nsContext, void* pBuffer, int pBufferTextureName); + CustomCCode extern void* getProcAddress(const char *procName); # Implement the first argument to getProcAddress as String instead diff --git a/make/stub_includes/macosx/window-system.c b/make/stub_includes/macosx/window-system.c index f49fd3d11..15506299b 100644 --- a/make/stub_includes/macosx/window-system.c +++ b/make/stub_includes/macosx/window-system.c @@ -3,11 +3,18 @@ typedef int Bool; -void* createContext(void* nsView, void* shareContext); -Bool makeCurrentContext(void* nsView, void* nsContext); -Bool clearCurrentContext(void* nsView, void* nsContext); -void updateContext(void* nsView, void* nsContext); -Bool deleteContext(void* nsView, void* nsContext); -Bool flushBuffer(void* nsView, void* nsContext); +void* createContext(void* shareContext, void* nsView); +Bool makeCurrentContext(void* nsContext, void* nsView); +Bool clearCurrentContext(void* nsContext, void* nsView); +Bool deleteContext(void* nsContext, void* nsView); +Bool flushBuffer(void* nsContext, void* nsView); + +void* updateContextRegister(void* nsContext, void* nsView); +void updateContextUnregister(void* nsContext, void* nsView, void* updater); + +void* createPBuffer(void* nsContext, int width, int height); +Bool destroyPBuffer(void* nsContext, void* pBuffer); +int bindPBuffer(void* nsContext, void* pBuffer); +void unbindPBuffer(void* nsContext, void* pBuffer, int pBufferTextureName); void* getProcAddress(const char *procName); diff --git a/src/native/jogl/ContextUpdater.h b/src/native/jogl/ContextUpdater.h new file mode 100644 index 000000000..e8b757fac --- /dev/null +++ b/src/native/jogl/ContextUpdater.h @@ -0,0 +1,40 @@ +/* + +Listens to NSViewGlobalFrameDidChangeNotification + +This notification is sent whenever an NSView that has an attached NSSurface changes size or changes screens (thus potentially changing graphics hardware drivers.) + +*/ + +#import <Cocoa/Cocoa.h> +#import <Foundation/Foundation.h> +#import <AppKit/NSView.h> +#import <OpenGL/OpenGL.h> +#import <OpenGL/gl.h> + +//#define DEBUG_GL_LOCKS + +#ifdef DEBUG_GL_LOCKS + #define LOCK_GL(func, line) [ContextUpdater lockInFunction:func atLine:line]; + #define UNLOCK_GL(func, line) [ContextUpdater unlockInFunction:func atLine:line]; +#else + #define LOCK_GL(func, line) [ContextUpdater lock]; + #define UNLOCK_GL(func, line) [ContextUpdater unlock]; +#endif + +// gznote: OpenGL NOT thread safe - need to sync on update and paints + +@interface ContextUpdater : NSObject +{ +} + ++ (void) lock; ++ (void) lockInFunction:(char *)func atLine:(int)line; ++ (void) unlock; ++ (void) unlockInFunction:(char *)func atLine:(int)line; + +- (void) registerFor:(NSOpenGLContext *)context with: (NSView *)window; + +- (void) update:(NSNotification *)notification; + +@end diff --git a/src/native/jogl/ContextUpdater.m b/src/native/jogl/ContextUpdater.m new file mode 100644 index 000000000..587782c98 --- /dev/null +++ b/src/native/jogl/ContextUpdater.m @@ -0,0 +1,83 @@ +#import "ContextUpdater.h" +#import <pthread.h> + +@implementation ContextUpdater +{ +} + +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); +} + ++ (void) lock +{ + if (theContext != NULL) + { + pthread_mutex_lock(&resourceLock); + } +} + ++ (void) lockInFunction:(char *)func atLine:(int)line +{ + if (theContext != NULL) + { + printLockDebugInfo("locked ", func, line); + [self lock]; + } +} + ++ (void) unlock +{ + if (theContext != NULL) + { + pthread_mutex_unlock(&resourceLock); + } +} + ++ (void) unlockInFunction:(char *)func atLine:(int)line +{ + if (theContext != NULL) + { + printLockDebugInfo("unlocked", func, line); + [self unlock]; + } +} + +- (void) registerFor:(NSOpenGLContext *)context with: (NSView *)view +{ + if (view != NULL) + { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update:) name:NSViewGlobalFrameDidChangeNotification object: view]; + theContext = context; + } +} + +- (void) update:(NSNotification *)notification +{ + [ContextUpdater lock]; + + [theContext update]; + + [ContextUpdater unlock]; +} + +- (id) init +{ + theContext = NULL; + + return [super init]; +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; +} + +@end
\ No newline at end of file diff --git a/src/native/jogl/MacOSXWindowSystemInterface.m b/src/native/jogl/MacOSXWindowSystemInterface.m index 0499984c3..ceb07a63d 100644 --- a/src/native/jogl/MacOSXWindowSystemInterface.m +++ b/src/native/jogl/MacOSXWindowSystemInterface.m @@ -1,83 +1,210 @@ #import <Cocoa/Cocoa.h> #import <OpenGL/gl.h> +#import "ContextUpdater.h" + +#ifndef GL_TEXTURE_RECTANGLE_EXT + #define GL_TEXTURE_RECTANGLE_EXT 0x84F5 +#endif typedef int Bool; -void* createContext(void* nsView, void* shareContext) { - NSView *view = nsView; - NSOpenGLContext *share = shareContext; - - // FIXME: hardcoded pixel format. Instead pass these attributes down - // as arguments. There is really no way to enumerate the possible - // pixel formats for a given window on Mac OS X, so we will assume - // that we can match the requested capabilities and leave the - // selection up to the built-in pixel format selection algorithm. - GLuint attribs[] = { - NSOpenGLPFANoRecovery, - NSOpenGLPFAWindow, - NSOpenGLPFAAccelerated, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAColorSize, 32, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 24, - NSOpenGLPFAStencilSize, 8, - NSOpenGLPFAAccumSize, 0, - 0 - }; - - NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs]; - - NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat: [fmt autorelease] shareContext: share]; - - if (view != nil) { - [context setView: view]; - - [context makeCurrentContext]; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - [context update]; - [context flushBuffer]; - } - - return context; +NSAutoreleasePool* gAutoreleasePool = NULL; + +void* createContext(void* shareContext, void* view) +{ +//fprintf(stderr, "createContext shareContext=%p view=%p\n", shareContext, view); + NSOpenGLContext *nsChareCtx = (NSOpenGLContext*)shareContext; + NSView *nsView = (NSView*)view; + + if (gAutoreleasePool == NULL) + { + gAutoreleasePool = [[NSAutoreleasePool alloc] init]; + } + + // FIXME: hardcoded pixel format. Instead pass these attributes down + // as arguments. There is really no way to enumerate the possible + // pixel formats for a given window on Mac OS X, so we will assume + // that we can match the requested capabilities and leave the + // selection up to the built-in pixel format selection algorithm. + NSOpenGLPixelFormatAttribute attribs[] = + { + NSOpenGLPFANoRecovery, YES, + NSOpenGLPFAAccelerated, YES, + NSOpenGLPFADoubleBuffer, YES, + NSOpenGLPFAColorSize, 32, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 8, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFAAccumSize, 0, + 0 + }; + + if (nsView == NULL) + { + attribs[12] = 0; // no stencil, no accums fo pBuffers + } + + NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + + NSOpenGLContext* nsContext = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nsChareCtx]; + + [fmt release]; + + if (nsView != nil) + { + [nsContext setView: nsView]; + } + + [nsContext retain]; + +//fprintf(stderr, " nsContext=%p\n", nsContext); + return nsContext; } -Bool makeCurrentContext(void* nsView, void* nsContext) { - NSOpenGLContext *context = nsContext; +Bool makeCurrentContext(void* context, void* view) +{ +//fprintf(stderr, "makeCurrentContext context=%p, view=%p\n", context, view); + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + + [nsContext makeCurrentContext]; + return true; +} - [context makeCurrentContext]; - return true; +Bool clearCurrentContext(void* context, void* view) +{ +//fprintf(stderr, "clearCurrentContext context=%p, view=%p\n", context, view); + [NSOpenGLContext clearCurrentContext]; + return true; } -Bool clearCurrentContext(void* nsView, void* nsContext) { - NSView *view = nsView; - NSOpenGLContext *context = nsContext; +Bool deleteContext(void* context, void* view) +{ +//fprintf(stderr, "deleteContext context=%p, view=%p\n", context, view); + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + + [nsContext setView: nil]; + [nsContext release]; + return true; +} - [NSOpenGLContext clearCurrentContext]; - return true; +Bool flushBuffer(void* context, void* view) +{ +//fprintf(stderr, "flushBuffer context=%p, view=%p\n", context, view); + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + + [nsContext flushBuffer]; + return true; } -void updateContext(void* nsView, void* nsContext) { - NSView *view = nsView; - NSOpenGLContext *context = nsContext; +void* updateContextRegister(void* context, void* view) +{ +//fprintf(stderr, "updateContextRegister context=%p, view=%p\n", context, view); + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + NSView *nsView = (NSView*)view; + + ContextUpdater *contextUpdater = [[ContextUpdater alloc] init]; + [contextUpdater registerFor:nsContext with:nsView]; +} - [context update]; +void updateContextUnregister(void* context, void* view, void* updater) +{ +//fprintf(stderr, "updateContextUnregister context=%p, view=%p\n", context, view); + ContextUpdater *contextUpdater = (ContextUpdater *)updater; + + [contextUpdater release]; } -Bool deleteContext(void* nsView, void* nsContext) { - NSOpenGLContext *context = nsContext; +static int getNextPowerOf2(int number) +{ + if (((number-1) & number) == 0) + { + //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 + return number; + } + int power = 0; + while (number > 0) + { + number = number>>1; + power++; + } + return (1<<power); +} - [context setView: nil]; - [context release]; - return true; +void* createPBuffer(void* context, int width, int height) +{ +//fprintf(stderr, "createPBuffer context=%p width=%d height=%d\n", context, width, height); +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + + //unsigned long taget = GL_TEXTURE_RECTANGLE_EXT; + unsigned long taget = GL_TEXTURE_2D; // texture size must be a multiple of power of 2 + + width = getNextPowerOf2(width); + height = getNextPowerOf2(height); + + NSOpenGLPixelBuffer* pBuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:taget textureInternalFormat:GL_RGBA textureMaxMipMapLevel:0 pixelsWide:width pixelsHigh:height]; + + [nsContext setPixelBuffer:pBuffer cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:0]; + + return pBuffer; +#else + return NULL; +#endif } -Bool flushBuffer(void* nsView, void* nsContext) { - NSOpenGLContext *context = nsContext; +Bool destroyPBuffer(void* context, void* buffer) +{ +//fprintf(stderr, "destroyPBuffer context=%p, buffer=%p\n", context, buffer); +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; + + [nsContext setPixelBuffer:NULL cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:0]; + [pBuffer release]; + + return true; +#else + return false; +#endif +} - [context flushBuffer]; - return true; +int bindPBuffer(void* context, void* buffer) +{ +//fprintf(stderr, "bindPBuffer context=%p, buffer=%p\n", context, buffer); +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) + NSOpenGLContext *nsContext = (NSOpenGLContext*)context; + NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; + + GLuint pBufferTextureName; + glGenTextures(1, &pBufferTextureName); + + glBindTexture([pBuffer textureTarget], pBufferTextureName); + + glTexParameteri([pBuffer textureTarget], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri([pBuffer textureTarget], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + [nsContext setTextureImageToPixelBuffer:pBuffer colorBuffer:GL_FRONT_LEFT]; + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable([pBuffer textureTarget]); + + return pBufferTextureName; +#else + return 0; +#endif } +void unbindPBuffer(void* context, void* buffer, int texture) +{ +//fprintf(stderr, "unbindPBuffer context=%p, buffer=%p\n", context, buffer); +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) + NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; + GLuint pBufferTextureName = (GLuint)texture; + + //glDisable([pBuffer textureTarget]); + glDeleteTextures(1, &pBufferTextureName); +#endif +} #include <mach-o/dyld.h> Bool imagesInitialized = false; @@ -85,32 +212,37 @@ static char libGLStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/ static char libGLUStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; static const struct mach_header *libGLImage; static const struct mach_header *libGLUImage; -void* getProcAddress(const char *procname) { - if (imagesInitialized == false) { - imagesInitialized = true; - unsigned long options = NSADDIMAGE_OPTION_RETURN_ON_ERROR; - libGLImage = NSAddImage(libGLStr, options); - libGLUImage = NSAddImage(libGLUStr, options); - } - - unsigned long options = NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR; - char underscoreName[512] = "_"; - strcat(underscoreName, procname); - - if (NSIsSymbolNameDefinedInImage(libGLImage, underscoreName) == YES) { - NSSymbol sym = NSLookupSymbolInImage(libGLImage, underscoreName, options); - return NSAddressOfSymbol(sym); - } - - if (NSIsSymbolNameDefinedInImage(libGLUImage, underscoreName) == YES) { - NSSymbol sym = NSLookupSymbolInImage(libGLUImage, underscoreName, options); - return NSAddressOfSymbol(sym); - } - - if (NSIsSymbolNameDefinedWithHint(underscoreName, "GL")) { - NSSymbol sym = NSLookupAndBindSymbol(underscoreName); - return NSAddressOfSymbol(sym); - } - - return NULL; -} +void* getProcAddress(const char *procname) +{ + if (imagesInitialized == false) + { + imagesInitialized = true; + unsigned long options = NSADDIMAGE_OPTION_RETURN_ON_ERROR; + libGLImage = NSAddImage(libGLStr, options); + libGLUImage = NSAddImage(libGLUStr, options); + } + + unsigned long options = NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR; + char underscoreName[512] = "_"; + strcat(underscoreName, procname); + + if (NSIsSymbolNameDefinedInImage(libGLImage, underscoreName) == YES) + { + NSSymbol sym = NSLookupSymbolInImage(libGLImage, underscoreName, options); + return NSAddressOfSymbol(sym); + } + + if (NSIsSymbolNameDefinedInImage(libGLUImage, underscoreName) == YES) + { + NSSymbol sym = NSLookupSymbolInImage(libGLUImage, underscoreName, options); + return NSAddressOfSymbol(sym); + } + + if (NSIsSymbolNameDefinedWithHint(underscoreName, "GL")) + { + NSSymbol sym = NSLookupAndBindSymbol(underscoreName); + return NSAddressOfSymbol(sym); + } + + return NULL; +}
\ No newline at end of file diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java index 53e5986ec..e6169a4b9 100644 --- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java +++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java @@ -49,6 +49,8 @@ public abstract class MacOSXGLContext extends GLContext { private static JAWT jawt; protected long nsContext; // NSOpenGLContext + protected long nsView; // NSView + protected long updater; // ContextUpdater // Table that holds the addresses of the native C-language entry points for // OpenGL functions. private GLProcAddressTable glProcAddressTable; @@ -61,6 +63,11 @@ public abstract class MacOSXGLContext extends GLContext super(component, capabilities, chooser, shareWith); } + protected GL createGL() + { + return new MacOSXGLImpl(this); + } + protected String mapToRealGLFunctionName(String glFunctionName) { return glFunctionName; @@ -88,11 +95,51 @@ public abstract class MacOSXGLContext extends GLContext * Creates and initializes an appropriate OpenGl nsContext. Should only be * called by {@link makeCurrent(Runnable)}. */ - protected abstract void create(); + protected void create() { + MacOSXGLContext other = (MacOSXGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getNSContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + nsContext = CGL.createContext(share, nsView); + if (nsContext == 0) { + throw new GLException("Error creating nsContext"); + } + updater = CGL.updateContextRegister(nsContext, nsView); + GLContextShareSet.contextCreated(this); + } - protected abstract boolean makeCurrent(Runnable initAction) throws GLException; + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + boolean created = false; + if (nsContext == 0) { + create(); + if (DEBUG) { + System.err.println("!!! Created GL nsContext for " + getClass().getName()); + } + created = true; + } + + if (!CGL.makeCurrentContext(nsContext, nsView)) { + throw new GLException("Error making nsContext current"); + } + + if (created) { + resetGLFunctionAvailability(); + if (initAction != null) { + initAction.run(); + } + } + return true; + } - protected abstract void free() throws GLException; + protected synchronized void free() throws GLException { + if (!CGL.clearCurrentContext(nsContext, nsView)) { + throw new GLException("Error freeing OpenGL nsContext"); + } + } protected abstract void swapBuffers() throws GLException; @@ -136,6 +183,10 @@ public abstract class MacOSXGLContext extends GLContext return nsContext; } + protected long getNSView() { + return nsView; + } + protected JAWT getJAWT() { if (jawt == null) diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java index e9f3bed24..431710a7c 100644 --- a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java +++ b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java @@ -48,12 +48,11 @@ public class MacOSXOffscreenGLContext extends MacOSXGLContext // Width and height of the underlying bitmap private int width; private int height; - + public MacOSXOffscreenGLContext(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith) { super(null, capabilities, chooser, shareWith); - System.err.println("MacOSXOffscreenGLContext not implemented yet"); } protected GL createGL() { @@ -65,15 +64,10 @@ public class MacOSXOffscreenGLContext extends MacOSXGLContext } public int getOffscreenContextBufferedImageType() { - if (capabilities.getAlphaBits() > 0) { return BufferedImage.TYPE_INT_ARGB; - } else { - return BufferedImage.TYPE_INT_RGB; - } } public int getOffscreenContextReadBuffer() { - // On Windows these nsContexts are always single-buffered return GL.GL_FRONT; } @@ -100,22 +94,23 @@ public class MacOSXOffscreenGLContext extends MacOSXGLContext } protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { - return false; + if (pendingOffscreenResize) { + if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) { + if (nsContext != 0) { + destroy(); + } + width = pendingOffscreenWidth; + height = pendingOffscreenHeight; + pendingOffscreenResize = false; + } + } + return super.makeCurrent(initAction); } protected synchronized void swapBuffers() throws GLException { - throw new GLException("Not yet implemented"); - } - - protected synchronized void free() throws GLException { - throw new GLException("Not yet implemented"); - } - - protected void create() { - throw new GLException("Not yet implemented"); } private void destroy() { - throw new GLException("Not yet implemented"); + free(); } } diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java index 8f75fd561..ec46de0d8 100644 --- a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java +++ b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java @@ -50,33 +50,17 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext { private JAWT_DrawingSurface ds; private JAWT_DrawingSurfaceInfo dsi; private JAWT_MacOSXDrawingSurfaceInfo macosxdsi; - private long nsView; // NSView - private Runnable myDeferredReshapeAction; + // Variables for pbuffer support + List pbuffersToInstantiate = new ArrayList(); + public MacOSXOnscreenGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith) { super(component, capabilities, chooser, shareWith); } - - public synchronized void invokeGL(final Runnable runnable, boolean isReshape, Runnable initAction) throws GLException { - if (isReshape) { - myDeferredReshapeAction = new Runnable() { - public void run() { - CGL.updateContext(nsView, nsContext); - runnable.run(); - } - }; - } else { - if (myDeferredReshapeAction != null) { - super.invokeGL(myDeferredReshapeAction, true, initAction); - myDeferredReshapeAction = null; - } - super.invokeGL(runnable, isReshape, initAction); - } - } - + protected GL createGL() { return new MacOSXGLImpl(this); } @@ -98,12 +82,13 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext { } public boolean canCreatePbufferContext() { - // For now say no - return false; + return true; } public synchronized GLContext createPbufferContext(GLCapabilities capabilities, int initialWidth, int initialHeight) { - throw new GLException("Not supported"); + MacOSXPbufferGLContext ctx = new MacOSXPbufferGLContext(capabilities, initialWidth, initialHeight); + pbuffersToInstantiate.add(ctx); + return ctx; } public void bindPbufferToTexture() { @@ -122,72 +107,42 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext { // yet on this platform. This method can be deleted once // the update for that release ships. } - - protected void create() { - MacOSXGLContext other = (MacOSXGLContext) GLContextShareSet.getShareContext(this); - long share = 0; - if (other != null) { - share = other.getNSContext(); - if (share == 0) { - throw new GLException("GLContextShareSet returned an invalid OpenGL context"); - } - } - nsContext = CGL.createContext(nsView, share); - if (nsContext == 0) { - throw new GLException("Error creating nsContext"); - } - GLContextShareSet.contextCreated(this); - } protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { try { if (!lockSurface()) { return false; } - - boolean created = false; - if (nsContext == 0) { - create(); - if (DEBUG) { - System.err.println("!!! Created GL nsContext for " + getClass().getName()); - } - created = true; - } - - if (!CGL.makeCurrentContext(nsView, nsContext)) { - throw new GLException("Error making nsContext current"); - } - - if (created) { - resetGLFunctionAvailability(); - if (initAction != null) { - initAction.run(); + boolean ret = super.makeCurrent(initAction); + if (ret) { + // Instantiate any pending pbuffers + while (!pbuffersToInstantiate.isEmpty()) { + MacOSXPbufferGLContext ctx = + (MacOSXPbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1); + ctx.createPbuffer(nsView, nsContext); } } - return true; + return ret; } catch (RuntimeException e) { try { unlockSurface(); } catch (Exception e2) { // do nothing if unlockSurface throws } - throw(e); } } protected synchronized void free() throws GLException { try { - if (!CGL.clearCurrentContext(nsView, nsContext)) { - throw new GLException("Error freeing OpenGL nsContext"); - } + super.free(); } finally { unlockSurface(); } } protected synchronized void swapBuffers() throws GLException { - if (!CGL.flushBuffer(nsView, nsContext)) { + if (!CGL.flushBuffer(nsContext, nsView)) { throw new GLException("Error swapping buffers"); } } @@ -212,7 +167,8 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext { // OpenGL nsContext so it will be recreated if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) { if (nsContext != 0) { - if (!CGL.deleteContext(nsView, nsContext)) { + CGL.updateContextUnregister(nsContext, nsView, updater); + if (!CGL.deleteContext(nsContext, nsView)) { throw new GLException("Unable to delete old GL nsContext after surface changed"); } } diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java new file mode 100644 index 000000000..70068ce63 --- /dev/null +++ b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java @@ -0,0 +1,113 @@ +package net.java.games.jogl.impl.macosx; + +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public class MacOSXPbufferGLContext extends MacOSXGLContext { + private static final boolean DEBUG = false; + + private int initWidth; + private int initHeight; + + private long pBuffer; + private int pBufferTextureName; + + private int width; + private int height; + + // FIXME: kept around because we create the OpenGL context lazily to + // better integrate with the MacOSXGLContext framework + private long nsContextOfParent; + + public MacOSXPbufferGLContext(GLCapabilities capabilities, int initialWidth, int initialHeight) { + super(null, capabilities, null, null); + this.initWidth = initialWidth; + this.initHeight = initialHeight; + if (initWidth <= 0 || initHeight <= 0) { + throw new GLException("Initial width and height of pbuffer must be positive (were (" + + initWidth + ", " + initHeight + "))"); + } + } + + public boolean canCreatePbufferContext() { + return false; + } + + public GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not supported"); + } + + public void bindPbufferToTexture() { + pBufferTextureName = CGL.bindPBuffer(nsContextOfParent, pBuffer); + } + + public void releasePbufferFromTexture() { + CGL.unbindPBuffer(nsContextOfParent, pBuffer, pBufferTextureName); + } + + public void createPbuffer(long parentView, long parentContext) { + GL gl = getGL(); + // Must initally grab OpenGL function pointers while parent's + // context is current because otherwise we don't have the cgl + // extensions available to us + resetGLFunctionAvailability(); + + this.pBuffer = CGL.createPBuffer(nsContext, initWidth, initHeight); + if (this.pBuffer == 0) { + throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); + } + + nsContextOfParent = parentContext; + + width = getNextPowerOf2(initWidth); + height = getNextPowerOf2(initHeight); + + if (DEBUG) { + System.err.println("Created pbuffer " + width + " x " + height); + } + } + + public void handleModeSwitch(long parentView, long parentContext) { + throw new GLException("Not yet implemented"); + } + + protected boolean isOffscreen() { + // FIXME: currently the only caller of this won't cause proper + // resizing of the pbuffer anyway. + return false; + } + + public int getOffscreenContextBufferedImageType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + protected void swapBuffers() throws GLException { + // FIXME: do we need to do anything if the pbuffer is double-buffered? + } + + int getNextPowerOf2(int number) + { + if (((number-1) & number) == 0) + { + //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 + return number; + } + int power = 0; + while (number > 0) + { + number = number>>1; + power++; + } + return (1<<power); + } +} |