aboutsummaryrefslogtreecommitdiffstats
path: root/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2006-07-21 22:34:00 +0000
committerKenneth Russel <[email protected]>2006-07-21 22:34:00 +0000
commite552d800ee9df3761108c044342612c8bda1f304 (patch)
tree690a4a58c5beafd4fefdcd434b371bfbc793e165 /src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java
parent595b8c26d0e4446239542ba076477b557611dfa0 (diff)
Added support for sharing of textures, etc. between GLPbuffers and
GLJPanels when the Java2D/JOGL bridge is active on Mac OS X. This required adding an alternate implementation for pbuffer drawables and contexts on OS X which uses CGL rather than the NextStep OpenGL APIs. Tested with advance Mustang bits on Mac OS X; Water and HWShadowmapsSimple demos (which use pbuffers) are now working within the JRefract harness when the Java2D/JOGL bridge is active. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@855 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java')
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java253
1 files changed, 246 insertions, 7 deletions
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java
index a1251bd70..c4e3058da 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java
@@ -32,6 +32,7 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
GLContext shareWith) {
super(drawable, shareWith);
this.drawable = drawable;
+ initOpenGLImpl();
}
public void bindPbufferToTexture() {
@@ -55,8 +56,28 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
return CONTEXT_NOT_CURRENT;
}
- int res = super.makeCurrentImpl();
- if (res == CONTEXT_CURRENT_NEW) {
+ if (getOpenGLMode() != drawable.getOpenGLMode()) {
+ setOpenGLMode(drawable.getOpenGLMode());
+ }
+
+ boolean created = false;
+ if (nsContext == 0) {
+ if (!create()) {
+ return CONTEXT_NOT_CURRENT;
+ }
+ if (DEBUG) {
+ System.err.println("!!! Created OpenGL context " + toHexString(nsContext) + " for " + getClass().getName());
+ }
+ created = true;
+ }
+
+ if (!impl.makeCurrent(nsContext)) {
+ throw new GLException("Error making nsContext current");
+ }
+
+ if (created) {
+ resetGLFunctionAvailability();
+
// Initialize render-to-texture support if requested
boolean rect = drawable.getCapabilities().getPbufferRenderToTextureRectangle();
GL gl = getGL();
@@ -77,8 +98,36 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
+
+ return CONTEXT_CURRENT_NEW;
+ }
+ return CONTEXT_CURRENT;
+ }
+
+ protected void releaseImpl() throws GLException {
+ if (!impl.release(nsContext)) {
+ throw new GLException("Error releasing OpenGL nsContext");
+ }
+ }
+
+ protected void destroyImpl() throws GLException {
+ if (nsContext != 0) {
+ if (!impl.destroy(nsContext)) {
+ throw new GLException("Unable to delete OpenGL context");
+ }
+ if (DEBUG) {
+ System.err.println("!!! Destroyed OpenGL context " + nsContext);
+ }
+ nsContext = 0;
+ GLContextShareSet.contextDestroyed(this);
}
- return res;
+ }
+
+ public void setSwapInterval(int interval) {
+ if (nsContext == 0) {
+ throw new GLException("OpenGL context not current");
+ }
+ impl.setSwapInterval(nsContext, interval);
}
public int getFloatingPointMode() {
@@ -91,11 +140,201 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
!isTigerOrLater) {
throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
}
- if (!super.create(true, capabilities.getPbufferFloatingPointBuffers())) {
- return false;
+ // Change our OpenGL mode to match that of any share context before we create ourselves
+ MacOSXGLContext other = (MacOSXGLContext) GLContextShareSet.getShareContext(this);
+ if (other != null) {
+ setOpenGLMode(other.getOpenGLMode());
}
- // Must now associate the pbuffer with our newly-created context
- CGL.setContextPBuffer(nsContext, drawable.getPbuffer());
+ // Will throw exception upon error
+ nsContext = impl.create();
return true;
}
+
+ //---------------------------------------------------------------------------
+ // OpenGL "mode switching" functionality
+ //
+ private boolean haveSetOpenGLMode = false;
+ // FIXME: should consider switching the default mode based on
+ // whether the Java2D/JOGL bridge is active -- need to ask ourselves
+ // whether it's more likely that we will share with a GLCanvas or a
+ // GLJPanel when the bridge is turned on
+ private int openGLMode = MacOSXGLDrawable.NSOPENGL_MODE;
+ // Implementation object (either NSOpenGL-based or CGL-based)
+ protected Impl impl;
+
+ public void setOpenGLMode(int mode) {
+ if (mode == openGLMode) {
+ return;
+ }
+ if (haveSetOpenGLMode) {
+ throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once");
+ }
+ destroyImpl();
+ drawable.setOpenGLMode(mode);
+ openGLMode = mode;
+ haveSetOpenGLMode = true;
+ if (DEBUG) {
+ System.err.println("Switching PBuffer context mode to " +
+ ((mode == MacOSXGLDrawable.NSOPENGL_MODE) ? "NSOPENGL_MODE" : "CGL_MODE"));
+ }
+ initOpenGLImpl();
+ }
+
+ public int getOpenGLMode() {
+ return openGLMode;
+ }
+
+ private void initOpenGLImpl() {
+ switch (openGLMode) {
+ case MacOSXGLDrawable.NSOPENGL_MODE:
+ impl = new NSOpenGLImpl();
+ break;
+ case MacOSXGLDrawable.CGL_MODE:
+ impl = new CGLImpl();
+ break;
+ default:
+ throw new InternalError("Illegal implementation mode " + openGLMode);
+ }
+ }
+
+ // Abstract interface for implementation of this context (either
+ // NSOpenGL-based or CGL-based)
+ interface Impl {
+ public long create();
+ public boolean destroy(long ctx);
+ public boolean makeCurrent(long ctx);
+ public boolean release(long ctx);
+ public void setSwapInterval(long ctx, int interval);
+ }
+
+ // NSOpenGLContext-based implementation
+ class NSOpenGLImpl implements Impl {
+ public long create() {
+ GLCapabilities capabilities = drawable.getCapabilities();
+ if (capabilities.getPbufferFloatingPointBuffers() &&
+ !isTigerOrLater) {
+ throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
+ }
+ if (!MacOSXPbufferGLContext.this.create(true, capabilities.getPbufferFloatingPointBuffers())) {
+ throw new GLException("Error creating context for pbuffer");
+ }
+ // Must now associate the pbuffer with our newly-created context
+ CGL.setContextPBuffer(nsContext, drawable.getPbuffer());
+ return nsContext;
+ }
+
+ public boolean destroy(long ctx) {
+ return CGL.deleteContext(ctx);
+ }
+
+ public boolean makeCurrent(long ctx) {
+ return CGL.makeCurrentContext(ctx);
+ }
+
+ public boolean release(long ctx) {
+ return CGL.clearCurrentContext(ctx);
+ }
+
+ public void setSwapInterval(long ctx, int interval) {
+ CGL.setSwapInterval(ctx, interval);
+ }
+ }
+
+ class CGLImpl implements Impl {
+ public long create() {
+ // Find and configure share context
+ MacOSXGLContext other = (MacOSXGLContext) GLContextShareSet.getShareContext(MacOSXPbufferGLContext.this);
+ long share = 0;
+ if (other != null) {
+ // Reconfigure pbuffer-based GLContexts
+ if (other instanceof MacOSXPbufferGLContext) {
+ MacOSXPbufferGLContext ctx = (MacOSXPbufferGLContext) other;
+ ctx.setOpenGLMode(MacOSXGLDrawable.CGL_MODE);
+ } else {
+ if (other.getOpenGLMode() != MacOSXGLDrawable.CGL_MODE) {
+ throw new GLException("Can't share between NSOpenGLContexts and CGLContextObjs");
+ }
+ }
+ share = other.getNSContext();
+ // Note we don't check for a 0 return value, since switching
+ // the context's mode causes it to be destroyed and not
+ // re-initialized until the next makeCurrent
+ }
+
+ // Set up pixel format attributes
+ int[] attrs = new int[256];
+ int i = 0;
+ attrs[i++] = CGL.kCGLPFAPBuffer;
+ GLCapabilities capabilities = drawable.getCapabilities();
+ if (capabilities.getPbufferFloatingPointBuffers())
+ attrs[i++] = CGL.kCGLPFAColorFloat;
+ if (capabilities.getDoubleBuffered())
+ attrs[i++] = CGL.kCGLPFADoubleBuffer;
+ if (capabilities.getStereo())
+ attrs[i++] = CGL.kCGLPFAStereo;
+ attrs[i++] = CGL.kCGLPFAColorSize;
+ attrs[i++] = (capabilities.getRedBits() +
+ capabilities.getGreenBits() +
+ capabilities.getBlueBits());
+ attrs[i++] = CGL.kCGLPFAAlphaSize;
+ attrs[i++] = capabilities.getAlphaBits();
+ attrs[i++] = CGL.kCGLPFADepthSize;
+ attrs[i++] = capabilities.getDepthBits();
+ // FIXME: should validate stencil size as is done in MacOSXWindowSystemInterface.m
+ attrs[i++] = CGL.kCGLPFAStencilSize;
+ attrs[i++] = capabilities.getStencilBits();
+ attrs[i++] = CGL.kCGLPFAAccumSize;
+ attrs[i++] = (capabilities.getAccumRedBits() +
+ capabilities.getAccumGreenBits() +
+ capabilities.getAccumBlueBits() +
+ capabilities.getAccumAlphaBits());
+ if (capabilities.getSampleBuffers()) {
+ attrs[i++] = CGL.kCGLPFASampleBuffers;
+ attrs[i++] = 1;
+ attrs[i++] = CGL.kCGLPFASamples;
+ attrs[i++] = capabilities.getNumSamples();
+ }
+
+ // Use attribute array to select pixel format
+ long[] fmt = new long[1];
+ long[] numScreens = new long[1];
+ int res = CGL.CGLChoosePixelFormat(attrs, 0, fmt, 0, numScreens, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while choosing pixel format");
+ }
+
+ // Create new context
+ long[] ctx = new long[1];
+ if (DEBUG) {
+ System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share));
+ }
+ res = CGL.CGLCreateContext(fmt[0], share, ctx, 0);
+ CGL.CGLDestroyPixelFormat(fmt[0]);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while creating context");
+ }
+ // Attach newly-created context to the pbuffer
+ res = CGL.CGLSetPBuffer(ctx[0], drawable.getPbuffer(), 0, 0, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while attaching context to pbuffer");
+ }
+ return ctx[0];
+ }
+
+ public boolean destroy(long ctx) {
+ return (CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError);
+ }
+
+ public boolean makeCurrent(long ctx) {
+ return CGL.CGLSetCurrentContext(ctx) == CGL.kCGLNoError;
+ }
+
+ public boolean release(long ctx) {
+ return (CGL.CGLSetCurrentContext(0) == CGL.kCGLNoError);
+ }
+
+ public void setSwapInterval(long ctx, int interval) {
+ // For now not supported (not really relevant for off-screen contexts anyway)
+ }
+ }
}