aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java')
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java488
1 files changed, 354 insertions, 134 deletions
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 383594d87..45c8b9304 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -40,19 +40,62 @@
package jogamp.opengl.macosx.cgl;
-import java.nio.*;
-import java.util.*;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.util.Map;
+import java.util.StringTokenizer;
-import javax.media.opengl.*;
-import javax.media.nativewindow.*;
-import jogamp.opengl.*;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.DefaultGraphicsConfiguration;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLContextShareSet;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
+
+import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+
public abstract class MacOSXCGLContext extends GLContextImpl
{
- protected boolean isNSContext;
+ // Abstract interface for implementation of this context (either
+ // NSOpenGL-based or CGL-based)
+ protected interface GLBackendImpl {
+ boolean isNSContext();
+ boolean create(long share);
+ boolean destroy();
+ boolean copyImpl(long src, int mask);
+ boolean makeCurrent();
+ boolean release();
+ boolean setSwapInterval(int interval);
+ boolean swapBuffers(boolean isOnscreen);
+ }
+
+ private static boolean isTigerOrLater;
+
+ static {
+ String osVersion = Debug.getProperty("os.version", false, AccessController.getContext());
+ StringTokenizer tok = new StringTokenizer(osVersion, ". ");
+ int major = Integer.parseInt(tok.nextToken());
+ int minor = Integer.parseInt(tok.nextToken());
+ isTigerOrLater = ((major > 10) || (minor > 3));
+ }
+
+ private boolean haveSetOpenGLMode = false;
+ private GLBackendType openGLMode = GLBackendType.NSOPENGL;
+
+ // Implementation object (either NSOpenGL-based or CGL-based)
+ protected GLBackendImpl impl;
+
private CGLExt _cglExt;
// Table that holds the addresses of the native C-language entry points for
// CGL extension functions.
@@ -61,11 +104,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
protected MacOSXCGLContext(GLDrawableImpl drawable,
GLContext shareWith) {
super(drawable, shareWith);
+ initOpenGLImpl(getOpenGLMode());
}
@Override
protected void resetStates() {
- isNSContext = false;
// no inner state _cglExt = null;
super.resetStates();
}
@@ -74,7 +117,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return getCGLExt();
}
- protected boolean isNSContext() { return isNSContext; }
+ protected boolean isNSContext() {
+ return (null != impl) ? impl.isNSContext() : this.openGLMode == GLBackendType.NSOPENGL;
+ }
public CGLExt getCGLExt() {
if (_cglExt == null) {
@@ -107,125 +152,108 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return false;
}
- /**
- * Creates and initializes an appropriate OpenGl Context (NS). Should only be
- * called by {@link makeCurrentImpl()}.
- */
- protected boolean create(boolean pbuffer, boolean floatingPoint) {
+ protected long createImplPreset() throws GLException {
MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this);
long share = 0;
if (other != null) {
- if (!other.isNSContext()) {
- throw new GLException("GLContextShareSet is not a NS Context");
- }
+ // Change our OpenGL mode to match that of any share context before we create ourselves
+ setOpenGLMode(other.getOpenGLMode());
share = other.getHandle();
if (share == 0) {
throw new GLException("GLContextShareSet returned a NULL OpenGL context");
}
}
MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration();
- GLCapabilitiesImmutable capabilitiesRequested = (GLCapabilitiesImmutable) config.getRequestedCapabilities();
- GLProfile glProfile = capabilitiesRequested.getGLProfile();
+ GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ if (capabilitiesChosen.getPbufferFloatingPointBuffers() &&
+ !isTigerOrLater) {
+ throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
+ }
+ GLProfile glProfile = capabilitiesChosen.getGLProfile();
if(glProfile.isGL3()) {
throw new GLException("GL3 profile currently not supported on MacOSX, due to the lack of a OpenGL 3.1 implementation");
}
- // HACK .. bring in OnScreen/PBuffer selection to the DrawableFactory !!
- GLCapabilities capabilities = (GLCapabilities) capabilitiesRequested.cloneMutable();
- capabilities.setPBuffer(pbuffer);
- capabilities.setPbufferFloatingPointBuffers(floatingPoint);
-
- long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(capabilities);
- if (pixelFormat == 0) {
- throw new GLException("Unable to allocate pixel format with requested GLCapabilities");
- }
- config.setChosenPixelFormat(pixelFormat);
- try {
- int[] viewNotReady = new int[1];
- // Try to allocate a context with this
- contextHandle = CGL.createContext(share,
- drawable.getHandle(),
- pixelFormat,
- capabilities.isBackgroundOpaque(),
- viewNotReady, 0);
- if (contextHandle == 0) {
- if (viewNotReady[0] == 1) {
- if (DEBUG) {
- System.err.println("!!! View not ready for " + getClass().getName());
- }
- // View not ready at the window system level -- this is OK
- return false;
- }
- throw new GLException("Error creating NSOpenGLContext with requested pixel format");
- }
-
- if (!pbuffer && !capabilities.isBackgroundOpaque()) {
- // Set the context opacity
- CGL.setContextOpacity(contextHandle, 0);
- }
-
- GLCapabilitiesImmutable caps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(glProfile, pixelFormat);
- caps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(caps, capabilities.isBackgroundOpaque());
- config.setChosenCapabilities(caps);
- } finally {
- CGL.deletePixelFormat(pixelFormat);
+ if (DEBUG) {
+ System.err.println("!!! Share context is " + toHexString(share) + " for " + this);
}
- if (!CGL.makeCurrentContext(contextHandle)) {
- throw new GLException("Error making Context (NS) current");
+ return share;
+ }
+
+ protected boolean createImpl() throws GLException {
+ long share = createImplPreset();
+
+ // Will throw exception upon error
+ if(!impl.create(share)) {
+ return false;
+ }
+ if (!impl.makeCurrent()) {
+ throw new GLException("Error making Context (NS:"+isNSContext()+") current");
}
- isNSContext = true;
setGLFunctionAvailability(true, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY);
- GLContextShareSet.contextCreated(this);
+ if (DEBUG) {
+ System.err.println("!!! Created " + this);
+ }
return true;
}
-
+
protected void makeCurrentImpl(boolean newCreated) throws GLException {
- if ( isNSContext ) {
- if (!CGL.makeCurrentContext(contextHandle)) {
- throw new GLException("Error making Context (NS) current");
- }
- } else {
- if (CGL.kCGLNoError != CGL.CGLSetCurrentContext(contextHandle)) {
- throw new GLException("Error making Context (CGL) current");
- }
+ if (getOpenGLMode() != ((MacOSXCGLDrawable)drawable).getOpenGLMode()) {
+ setOpenGLMode(((MacOSXCGLDrawable)drawable).getOpenGLMode());
}
+
+ if (!impl.makeCurrent()) {
+ throw new GLException("Error making Context current: "+this);
+ }
}
protected void releaseImpl() throws GLException {
- if ( isNSContext ) {
- if (!CGL.clearCurrentContext(contextHandle)) {
- throw new GLException("Error freeing OpenGL Context (NS)");
- }
- } else {
- CGL.CGLReleaseContext(contextHandle);
+ if (!impl.release()) {
+ throw new GLException("Error releasing OpenGL Context: "+this);
}
}
-
+
protected void destroyImpl() throws GLException {
- if ( !isNSContext ) {
- if (CGL.kCGLNoError != CGL.CGLDestroyContext(contextHandle)) {
- throw new GLException("Unable to delete OpenGL Context (CGL)");
- }
- } else {
- if (!CGL.deleteContext(contextHandle, true)) {
- throw new GLException("Unable to delete OpenGL Context (NS) "+toHexString(contextHandle));
- }
+ if(!impl.destroy()) {
+ throw new GLException("Error destroying OpenGL Context: "+this);
}
}
protected void copyImpl(GLContext source, int mask) throws GLException {
- long dst = getHandle();
- long src = source.getHandle();
- if( !isNSContext() ) {
- if ( ((MacOSXCGLContext)source).isNSContext() ) {
- throw new GLException("Source OpenGL Context is NS ; Destination Context is CGL.");
- }
- CGL.CGLCopyContext(src, dst, mask);
+ if( isNSContext() != ((MacOSXCGLContext)source).isNSContext() ) {
+ throw new GLException("Source/Destination OpenGL Context tyoe mismatch: source "+source+", dest: "+this);
+ }
+ if(!impl.copyImpl(source.getHandle(), mask)) {
+ throw new GLException("Error copying OpenGL Context: source "+source+", dest: "+this);
+ }
+ }
+
+ protected void swapBuffers() {
+ DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration();
+ GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+ if(!impl.swapBuffers(caps.isOnscreen())) {
+ throw new GLException("Error swapping buffers: "+this);
+ }
+ }
+
+ protected void setSwapIntervalImpl(int interval) {
+ if( ! isCreated() ) {
+ throw new GLException("OpenGL context not created");
+ }
+ if(!impl.setSwapInterval(interval)) {
+ throw new GLException("Error set swap-interval: "+this);
+ }
+ if ( isNSContext() ) {
+ CGL.setSwapInterval(contextHandle, interval);
} else {
- if ( !((MacOSXCGLContext)source).isNSContext() ) {
- throw new GLException("Source OpenGL Context is CGL ; Destination Context is NS.");
- }
- CGL.copyContext(dst, src, mask);
+ int[] lval = new int[] { (int) interval } ;
+ CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0);
}
+ currentSwapInterval = interval ;
+ }
+
+ public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
+ // FIXME: apparently the Apple extension doesn't require a custom memory allocator
+ throw new GLException("Not yet implemented");
}
protected final void updateGLXProcAddressTable() {
@@ -246,8 +274,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
} else {
if (cglExtProcAddressTable == null) {
- // FIXME: cache ProcAddressTables by capability bits so we can
- // share them among contexts with the same capabilities
cglExtProcAddressTable = new CGLExtProcAddressTable(new GLProcAddressResolver());
}
resetProcAddressTable(getCGLExtProcAddressTable());
@@ -264,40 +290,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return new StringBuffer();
}
- protected void swapBuffers() {
- DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration();
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
- if(caps.isOnscreen()) {
- if(isNSContext) {
- if (!CGL.flushBuffer(contextHandle)) {
- throw new GLException("Error swapping buffers (NS)");
- }
- } else {
- if (CGL.kCGLNoError != CGL.CGLFlushDrawable(contextHandle)) {
- throw new GLException("Error swapping buffers (CGL)");
- }
- }
- }
- }
-
- protected void setSwapIntervalImpl(int interval) {
- if( ! isCreated() ) {
- throw new GLException("OpenGL context not created");
- }
- if ( isNSContext ) {
- CGL.setSwapInterval(contextHandle, interval);
- } else {
- int[] lval = new int[] { (int) interval } ;
- CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0);
- }
- currentSwapInterval = interval ;
- }
-
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- // FIXME: apparently the Apple extension doesn't require a custom memory allocator
- throw new GLException("Not yet implemented");
- }
-
public boolean isExtensionAvailable(String glExtensionName) {
if (glExtensionName.equals("GL_ARB_pbuffer") ||
glExtensionName.equals("GL_ARB_pixel_format")) {
@@ -327,6 +319,234 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
// Support for "mode switching" as described in MacOSXCGLDrawable
- public abstract void setOpenGLMode(int mode);
- public abstract int getOpenGLMode();
+ public void setOpenGLMode(GLBackendType mode) {
+ if (mode == openGLMode) {
+ return;
+ }
+ if (haveSetOpenGLMode) {
+ throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once");
+ }
+ destroyImpl();
+ ((MacOSXCGLDrawable)drawable).setOpenGLMode(mode);
+ if (DEBUG) {
+ System.err.println("Switching context mode " + openGLMode + " -> " + mode);
+ }
+ initOpenGLImpl(mode);
+ openGLMode = mode;
+ haveSetOpenGLMode = true;
+ }
+ public final GLBackendType getOpenGLMode() { return openGLMode; }
+
+ protected void initOpenGLImpl(GLBackendType backend) {
+ switch (backend) {
+ case NSOPENGL:
+ impl = new NSOpenGLImpl();
+ break;
+ case CGL:
+ impl = new CGLImpl();
+ break;
+ default:
+ throw new InternalError("Illegal implementation mode " + backend);
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ super.append(sb);
+ sb.append(", mode ");
+ sb.append(openGLMode);
+ sb.append("] ");
+ return sb.toString();
+ }
+
+ // NSOpenGLContext-based implementation
+ class NSOpenGLImpl implements GLBackendImpl {
+ public boolean isNSContext() { return true; }
+
+ public boolean create(long share) {
+ MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration();
+ GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps);
+ if (pixelFormat == 0) {
+ throw new GLException("Unable to allocate pixel format with requested GLCapabilities");
+ }
+ config.setChosenPixelFormat(pixelFormat);
+ try {
+ int[] viewNotReady = new int[1];
+ // Try to allocate a context with this
+ contextHandle = CGL.createContext(share,
+ drawable.getHandle(),
+ pixelFormat,
+ chosenCaps.isBackgroundOpaque(),
+ viewNotReady, 0);
+ if (0 == contextHandle) {
+ if (viewNotReady[0] == 1) {
+ if (DEBUG) {
+ System.err.println("!!! View not ready for " + getClass().getName());
+ }
+ // View not ready at the window system level -- this is OK
+ return false;
+ }
+ throw new GLException("Error creating NSOpenGLContext with requested pixel format");
+ }
+
+ if (!chosenCaps.isPBuffer() && !chosenCaps.isBackgroundOpaque()) {
+ // Set the context opacity
+ CGL.setContextOpacity(contextHandle, 0);
+ }
+
+ GLCapabilitiesImmutable caps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
+ caps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(caps, chosenCaps.isBackgroundOpaque());
+ config.setChosenCapabilities(caps);
+ if(caps.isPBuffer()) {
+ // Must now associate the pbuffer with our newly-created context
+ CGL.setContextPBuffer(contextHandle, drawable.getHandle());
+ }
+ } finally {
+ CGL.deletePixelFormat(pixelFormat);
+ }
+ if (!CGL.makeCurrentContext(contextHandle)) {
+ throw new GLException("Error making Context (NS) current");
+ }
+ setGLFunctionAvailability(true, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY);
+ GLContextShareSet.contextCreated(MacOSXCGLContext.this);
+ return true;
+ }
+
+ public boolean destroy() {
+ return CGL.deleteContext(contextHandle, true);
+ }
+
+ public boolean copyImpl(long src, int mask) {
+ CGL.copyContext(contextHandle, src, mask);
+ return true;
+ }
+
+ public boolean makeCurrent() {
+ return CGL.makeCurrentContext(contextHandle);
+ }
+
+ public boolean release() {
+ return CGL.clearCurrentContext(contextHandle);
+ }
+
+ public boolean setSwapInterval(int interval) {
+ CGL.setSwapInterval(contextHandle, interval);
+ return true;
+ }
+ public boolean swapBuffers(boolean isOnscreen) {
+ if(isOnscreen) {
+ return CGL.flushBuffer(contextHandle);
+ }
+ return true;
+ }
+ }
+
+ class CGLImpl implements GLBackendImpl {
+ public boolean isNSContext() { return false; }
+
+ public boolean create(long share) {
+ DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration();
+ GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+
+ // Set up pixel format attributes
+ int[] attrs = new int[256];
+ int i = 0;
+ if(chosenCaps.isPBuffer()) {
+ attrs[i++] = CGL.kCGLPFAPBuffer;
+ }
+ if (chosenCaps.getPbufferFloatingPointBuffers()) {
+ attrs[i++] = CGL.kCGLPFAColorFloat;
+ }
+ if (chosenCaps.getDoubleBuffered()) {
+ attrs[i++] = CGL.kCGLPFADoubleBuffer;
+ }
+ if (chosenCaps.getStereo()) {
+ attrs[i++] = CGL.kCGLPFAStereo;
+ }
+ attrs[i++] = CGL.kCGLPFAColorSize;
+ attrs[i++] = (chosenCaps.getRedBits() +
+ chosenCaps.getGreenBits() +
+ chosenCaps.getBlueBits());
+ attrs[i++] = CGL.kCGLPFAAlphaSize;
+ attrs[i++] = chosenCaps.getAlphaBits();
+ attrs[i++] = CGL.kCGLPFADepthSize;
+ attrs[i++] = chosenCaps.getDepthBits();
+ // FIXME: should validate stencil size as is done in MacOSXWindowSystemInterface.m
+ attrs[i++] = CGL.kCGLPFAStencilSize;
+ attrs[i++] = chosenCaps.getStencilBits();
+ attrs[i++] = CGL.kCGLPFAAccumSize;
+ attrs[i++] = (chosenCaps.getAccumRedBits() +
+ chosenCaps.getAccumGreenBits() +
+ chosenCaps.getAccumBlueBits() +
+ chosenCaps.getAccumAlphaBits());
+ if (chosenCaps.getSampleBuffers()) {
+ attrs[i++] = CGL.kCGLPFASampleBuffers;
+ attrs[i++] = 1;
+ attrs[i++] = CGL.kCGLPFASamples;
+ attrs[i++] = chosenCaps.getNumSamples();
+ }
+
+ // Use attribute array to select pixel format
+ PointerBuffer fmt = PointerBuffer.allocateDirect(1);
+ long[] numScreens = new long[1];
+ int res = CGL.CGLChoosePixelFormat(attrs, 0, fmt, numScreens, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while choosing pixel format");
+ }
+ try {
+ // Create new context
+ PointerBuffer ctx = PointerBuffer.allocateDirect(1);
+ if (DEBUG) {
+ System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share));
+ }
+ res = CGL.CGLCreateContext(fmt.get(0), share, ctx);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while creating context");
+ }
+ if(chosenCaps.isPBuffer()) {
+ // Attach newly-created context to the pbuffer
+ res = CGL.CGLSetPBuffer(ctx.get(0), drawable.getHandle(), 0, 0, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while attaching context to pbuffer");
+ }
+ }
+ contextHandle = ctx.get(0);
+ } finally {
+ CGL.CGLDestroyPixelFormat(fmt.get(0));
+ }
+ return true;
+ }
+
+ public boolean destroy() {
+ return CGL.CGLDestroyContext(contextHandle) == CGL.kCGLNoError;
+ }
+
+ public boolean copyImpl(long src, int mask) {
+ CGL.CGLCopyContext(src, contextHandle, mask);
+ return true;
+ }
+
+ public boolean makeCurrent() {
+ return CGL.CGLSetCurrentContext(contextHandle) == CGL.kCGLNoError;
+ }
+
+ public boolean release() {
+ return (CGL.CGLSetCurrentContext(0) == CGL.kCGLNoError);
+ }
+
+ public boolean setSwapInterval(int interval) {
+ int[] lval = new int[] { interval } ;
+ CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0);
+ return true;
+ }
+ public boolean swapBuffers(boolean isOnscreen) {
+ if(isOnscreen) {
+ return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle);
+ }
+ return true;
+ }
+ }
}