aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/build.xml2
-rw-r--r--make/cgl-macosx.cfg5
-rw-r--r--make/stub_includes/macosx/OpenGL/OpenGL.h101
-rw-r--r--make/stub_includes/opengl/macosx-window-system.h8
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXExternalGLContext.java9
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXGLContext.java6
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXGLDrawable.java41
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXJava2DGLContext.java9
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLContext.java9
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLDrawable.java14
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLContext.java253
-rw-r--r--src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLDrawable.java98
12 files changed, 538 insertions, 17 deletions
diff --git a/make/build.xml b/make/build.xml
index f6e7f9910..726cadf11 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -584,6 +584,7 @@
<!-- Generate WGL/GLX/CGL implementation class -->
<echo message="Generating WGL/GLX/CGL implementation class" />
+ <dirset id="stub.includes.fileset.platform" dir="." includes="${stub.includes.fileset.platform.params}" />
<gluegen src="${stub.includes.platform}/window-system.c"
config="${window.cfg}"
includeRefid="stub.includes.fileset.platform"
@@ -597,7 +598,6 @@
- handle different drives in an effective manner. -->
<echo message="Generating JAWT interface class" />
<echo message="java.home.dir=${java.home.dir}" />
- <dirset id="stub.includes.fileset.platform" dir="." includes="${stub.includes.fileset.platform.params}" />
<gluegen src="${java.includes.dir.platform}/jawt_md.h"
config="${jawt.cfg}"
literalInclude="${java.includes.dir}"
diff --git a/make/cgl-macosx.cfg b/make/cgl-macosx.cfg
index 97a3bbeff..7c31f7338 100644
--- a/make/cgl-macosx.cfg
+++ b/make/cgl-macosx.cfg
@@ -9,6 +9,11 @@ Include gl-common-macosx.cfg
Opaque long void *
+# Opaque directives for low-level CGL binding (for Java2D/JOGL bridge)
+Opaque long CGLContextObj
+Opaque long CGLPBufferObj
+Opaque long CGLPixelFormatObj
+
CustomCCode #include </usr/include/machine/types.h>
CustomCCode #include "macosx-window-system.h"
diff --git a/make/stub_includes/macosx/OpenGL/OpenGL.h b/make/stub_includes/macosx/OpenGL/OpenGL.h
new file mode 100644
index 000000000..16225b46b
--- /dev/null
+++ b/make/stub_includes/macosx/OpenGL/OpenGL.h
@@ -0,0 +1,101 @@
+/* Typedefs, enums and function prototypes extracted from Apple's
+ OpenGL.h to expose portions of the low-level CGL API to Java */
+
+/* Typedefs to get things working */
+typedef struct _cglObj* CGLContextObj;
+typedef struct _cglObj* CGLPBufferObj;
+typedef struct _cglObj* CGLPixelFormatObj;
+
+/*
+** Attribute names for CGLChoosePixelFormat and CGLDescribePixelFormat.
+*/
+typedef enum _CGLPixelFormatAttribute {
+ kCGLPFAAllRenderers = 1, /* choose from all available renderers */
+ kCGLPFADoubleBuffer = 5, /* choose a double buffered pixel format */
+ kCGLPFAStereo = 6, /* stereo buffering supported */
+ kCGLPFAAuxBuffers = 7, /* number of aux buffers */
+ kCGLPFAColorSize = 8, /* number of color buffer bits */
+ kCGLPFAAlphaSize = 11, /* number of alpha component bits */
+ kCGLPFADepthSize = 12, /* number of depth buffer bits */
+ kCGLPFAStencilSize = 13, /* number of stencil buffer bits */
+ kCGLPFAAccumSize = 14, /* number of accum buffer bits */
+ kCGLPFAMinimumPolicy = 51, /* never choose smaller buffers than requested */
+ kCGLPFAMaximumPolicy = 52, /* choose largest buffers of type requested */
+ kCGLPFAOffScreen = 53, /* choose an off-screen capable renderer */
+ kCGLPFAFullScreen = 54, /* choose a full-screen capable renderer */
+ kCGLPFASampleBuffers = 55, /* number of multi sample buffers */
+ kCGLPFASamples = 56, /* number of samples per multi sample buffer */
+ kCGLPFAAuxDepthStencil = 57, /* each aux buffer has its own depth stencil */
+ kCGLPFAColorFloat = 58, /* color buffers store floating point pixels */
+ kCGLPFAMultisample = 59, /* choose multisampling */
+ kCGLPFASupersample = 60, /* choose supersampling */
+ kCGLPFASampleAlpha = 61, /* request alpha filtering */
+
+ kCGLPFARendererID = 70, /* request renderer by ID */
+ kCGLPFASingleRenderer = 71, /* choose a single renderer for all screens */
+ kCGLPFANoRecovery = 72, /* disable all failure recovery systems */
+ kCGLPFAAccelerated = 73, /* choose a hardware accelerated renderer */
+ kCGLPFAClosestPolicy = 74, /* choose the closest color buffer to request */
+ kCGLPFARobust = 75, /* renderer does not need failure recovery */
+ kCGLPFABackingStore = 76, /* back buffer contents are valid after swap */
+ kCGLPFAMPSafe = 78, /* renderer is multi-processor safe */
+ kCGLPFAWindow = 80, /* can be used to render to an onscreen window */
+ kCGLPFAMultiScreen = 81, /* single window can span multiple screens */
+ kCGLPFACompliant = 83, /* renderer is opengl compliant */
+ kCGLPFADisplayMask = 84, /* mask limiting supported displays */
+ kCGLPFAPBuffer = 90, /* can be used to render to a pbuffer */
+ kCGLPFARemotePBuffer = 91, /* can be used to render offline to a pbuffer */
+ kCGLPFAVirtualScreenCount = 128 /* number of virtual screens in this format */
+} CGLPixelFormatAttribute;
+
+/*
+** Error return values from CGLGetError.
+*/
+typedef enum _CGLError {
+ kCGLNoError = 0, /* no error */
+ kCGLBadAttribute = 10000, /* invalid pixel format attribute */
+ kCGLBadProperty = 10001, /* invalid renderer property */
+ kCGLBadPixelFormat = 10002, /* invalid pixel format */
+ kCGLBadRendererInfo = 10003, /* invalid renderer info */
+ kCGLBadContext = 10004, /* invalid context */
+ kCGLBadDrawable = 10005, /* invalid drawable */
+ kCGLBadDisplay = 10006, /* invalid graphics device */
+ kCGLBadState = 10007, /* invalid context state */
+ kCGLBadValue = 10008, /* invalid numerical value */
+ kCGLBadMatch = 10009, /* invalid share context */
+ kCGLBadEnumeration = 10010, /* invalid enumerant */
+ kCGLBadOffScreen = 10011, /* invalid offscreen drawable */
+ kCGLBadFullScreen = 10012, /* invalid offscreen drawable */
+ kCGLBadWindow = 10013, /* invalid window */
+ kCGLBadAddress = 10014, /* invalid pointer */
+ kCGLBadCodeModule = 10015, /* invalid code module */
+ kCGLBadAlloc = 10016, /* invalid memory allocation */
+ kCGLBadConnection = 10017 /* invalid CoreGraphics connection */
+} CGLError;
+
+/* Pixel format manipulation */
+CGLError CGLChoosePixelFormat(const CGLPixelFormatAttribute *attribs,
+ CGLPixelFormatObj *pix,
+ long *npix);
+CGLError CGLDestroyPixelFormat(CGLPixelFormatObj pix);
+
+/* Context manipulation */
+CGLError CGLCreateContext(CGLPixelFormatObj pix,
+ CGLContextObj share,
+ CGLContextObj* ctx);
+CGLError CGLDestroyContext(CGLContextObj ctx);
+CGLError CGLSetCurrentContext(CGLContextObj ctx);
+
+/* PBuffer manipulation */
+CGLError CGLCreatePBuffer(long width,
+ long height,
+ unsigned long target,
+ unsigned long internalFormat,
+ long max_level,
+ CGLPBufferObj* pbuffer);
+CGLError CGLDestroyPBuffer(CGLPBufferObj pbuffer);
+CGLError CGLSetPBuffer(CGLContextObj ctx,
+ CGLPBufferObj pbuffer,
+ unsigned long face,
+ long level,
+ long screen);
diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h
index 959c2352e..1d3df1a08 100644
--- a/make/stub_includes/opengl/macosx-window-system.h
+++ b/make/stub_includes/opengl/macosx-window-system.h
@@ -48,3 +48,11 @@ void setSwapInterval(void* nsContext, int interval);
/* Gamma-related functionality */
Bool setGammaRamp(int tableSize, float* redRamp, float* greenRamp, float* blueRamp);
void resetGammaRamp();
+
+/****************************************************************************************/
+/* Java2D/JOGL bridge support; need to be able to create pbuffers and
+ contexts using the CGL APIs to be able to share textures, etc. with
+ contexts created by Java2D/JOGL bridge, which are CGLContextObjs */
+
+/* Pick up copies of CGL signatures from Mac OS X stub_includes/window-system-build directory */
+#include <OpenGL/OpenGL.h>
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXExternalGLContext.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXExternalGLContext.java
index ceda14f3b..c9b6e432e 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXExternalGLContext.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXExternalGLContext.java
@@ -111,4 +111,13 @@ public class MacOSXExternalGLContext extends MacOSXGLContext {
public boolean isCreated() {
return created;
}
+
+ public void setOpenGLMode(int mode) {
+ if (mode != MacOSXGLDrawable.NSOPENGL_MODE)
+ throw new GLException("OpenGL mode switching not supported for external GLContexts");
+ }
+
+ public int getOpenGLMode() {
+ return MacOSXGLDrawable.NSOPENGL_MODE;
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXGLContext.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXGLContext.java
index d7890e369..e41ad856d 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXGLContext.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXGLContext.java
@@ -142,7 +142,7 @@ public abstract class MacOSXGLContext extends GLContextImpl
return CONTEXT_NOT_CURRENT;
}
if (DEBUG) {
- System.err.println("!!! Created GL nsContext for " + getClass().getName());
+ System.err.println("!!! Created OpenGL context " + toHexString(nsContext) + " for " + getClass().getName());
}
created = true;
}
@@ -249,6 +249,10 @@ public abstract class MacOSXGLContext extends GLContextImpl
throw new GLException("Should not call this");
}
+ // Support for "mode switching" as described in MacOSXGLDrawable
+ public abstract void setOpenGLMode(int mode);
+ public abstract int getOpenGLMode();
+
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXGLDrawable.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXGLDrawable.java
index 16f2410de..8a31d4b18 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXGLDrawable.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXGLDrawable.java
@@ -45,10 +45,42 @@ import com.sun.opengl.impl.*;
public abstract class MacOSXGLDrawable extends GLDrawableImpl {
protected static final boolean DEBUG = Debug.debug("MacOSXGLDrawable");
- protected long nsView; // NSView
protected GLCapabilities capabilities;
protected GLCapabilitiesChooser chooser;
+ // The Java2D/OpenGL pipeline on OS X uses low-level CGLContextObjs
+ // to represent the contexts for e.g. the Java2D back buffer. When
+ // the Java2D/JOGL bridge is active, this means that if we want to
+ // be able to share textures and display lists with the Java2D
+ // contexts, we need to use the CGL APIs rather than the NSOpenGL
+ // APIs on the JOGL side. For example, if we create a pbuffer using
+ // the NSOpenGL APIs and want to share textures and display lists
+ // between it and the Java2D back buffer, there is no way to do so,
+ // because the Java2D context is actually a CGLContextObj and the
+ // NSOpenGLContext's initWithFormat:shareContext: only accepts an
+ // NSOpenGLContext as its second argument. Of course there is no way
+ // to wrap an NSOpenGLContext around an arbitrary CGLContextObj.
+ //
+ // The situation we care most about is allowing a GLPbuffer to share
+ // textures, etc. with a GLJPanel when the Java2D/JOGL bridge is
+ // active; several of the demos rely on this functionality. We aim
+ // to get there by allowing a GLPBuffer to switch its implementation
+ // between using an NSOpenGLPixelBuffer and a CGLPBufferObj. In
+ // order to track whether this has been done we need to have the
+ // notion of a "mode" of both the MacOSXGLDrawable and the
+ // MacOSXGLContext. Initially the mode is "unspecified", meaning it
+ // leans toward the default (NSOpenGL). If sharing is requested
+ // between either a GLJPanel and a GLPbuffer or a GLCanvas and a
+ // GLPbuffer, the GLPbuffer will be switched into the appropriate
+ // mode: CGL mode for a GLJPanel and NSOpenGL mode for a GLCanvas.
+ // To avoid thrashing we support exactly one such switch during the
+ // lifetime of a given GLPbuffer. This is not a fully general
+ // solution (for example, you can't share textures among a
+ // GLPbuffer, a GLJPanel and a GLCanvas simultaneously) but should
+ // be enough to get things off the ground.
+ public static final int NSOPENGL_MODE = 1;
+ public static final int CGL_MODE = 2;
+
public MacOSXGLDrawable(GLCapabilities capabilities,
GLCapabilitiesChooser chooser) {
this.capabilities = (GLCapabilities) capabilities.clone();
@@ -83,11 +115,16 @@ public abstract class MacOSXGLDrawable extends GLDrawableImpl {
return availableCaps[pixelFormat];
}
+ // Only used for on-screen contexts
public long getView() {
- return nsView;
+ return 0;
}
protected static String getThreadName() {
return Thread.currentThread().getName();
}
+
+ // Support for "mode switching" as per above
+ public abstract void setOpenGLMode(int mode);
+ public abstract int getOpenGLMode();
}
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXJava2DGLContext.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXJava2DGLContext.java
index c9e4013c3..3082dd200 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXJava2DGLContext.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXJava2DGLContext.java
@@ -120,4 +120,13 @@ public class MacOSXJava2DGLContext extends MacOSXGLContext implements Java2DGLCo
public void setSwapInterval(int interval) {
// Not supported in this context implementation
}
+
+ public void setOpenGLMode(int mode) {
+ if (mode != MacOSXGLDrawable.CGL_MODE)
+ throw new GLException("OpenGL mode switching not supported for Java2D GLContexts");
+ }
+
+ public int getOpenGLMode() {
+ return MacOSXGLDrawable.CGL_MODE;
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLContext.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLContext.java
index 1e6a263de..9486f7c7b 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLContext.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLContext.java
@@ -116,4 +116,13 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
protected boolean create() {
return create(false, false);
}
+
+ public void setOpenGLMode(int mode) {
+ if (mode != MacOSXGLDrawable.NSOPENGL_MODE)
+ throw new GLException("OpenGL mode switching not supported for on-screen GLContexts");
+ }
+
+ public int getOpenGLMode() {
+ return MacOSXGLDrawable.NSOPENGL_MODE;
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLDrawable.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLDrawable.java
index c9e993237..2cb501020 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLDrawable.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXOnscreenGLDrawable.java
@@ -53,6 +53,7 @@ public class MacOSXOnscreenGLDrawable extends MacOSXGLDrawable {
public static final int LOCK_SUCCESS = 3;
protected Component component;
+ protected long nsView; // NSView
private List/*<WeakReference<GLContext>>*/ createdContexts =
new ArrayList();
@@ -126,6 +127,10 @@ public class MacOSXOnscreenGLDrawable extends MacOSXGLDrawable {
}
}
+ public long getView() {
+ return nsView;
+ }
+
public int lockSurface() throws GLException {
if (!realized) {
return LOCK_SURFACE_NOT_READY;
@@ -205,4 +210,13 @@ public class MacOSXOnscreenGLDrawable extends MacOSXGLDrawable {
macosxdsi = null;
nsView = 0;
}
+
+ public void setOpenGLMode(int mode) {
+ if (mode != NSOPENGL_MODE)
+ throw new GLException("OpenGL mode switching not supported for on-screen GLDrawables");
+ }
+
+ public int getOpenGLMode() {
+ return NSOPENGL_MODE;
+ }
}
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)
+ }
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLDrawable.java b/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLDrawable.java
index a28d945f7..5a4967f5c 100644
--- a/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLDrawable.java
+++ b/src/classes/com/sun/opengl/impl/macosx/MacOSXPbufferGLDrawable.java
@@ -43,13 +43,15 @@ import javax.media.opengl.*;
import com.sun.opengl.impl.*;
public class MacOSXPbufferGLDrawable extends MacOSXGLDrawable {
- private static final boolean DEBUG = Debug.debug("MacOSXPbufferGLContext");
+ private static final boolean DEBUG = Debug.debug("MacOSXPbufferGLDrawable");
protected int initWidth;
protected int initHeight;
+ // NSOpenGLPbuffer (for normal mode)
+ // CGLPbufferObj (for CGL_MODE situation, i.e., when Java2D/JOGL bridge is active)
protected long pBuffer;
-
+
protected int width;
protected int height;
@@ -61,7 +63,7 @@ public class MacOSXPbufferGLDrawable extends MacOSXGLDrawable {
super(capabilities, null);
this.initWidth = initialWidth;
this.initHeight = initialHeight;
-
+ initOpenGLImpl();
createPbuffer();
}
@@ -71,7 +73,7 @@ public class MacOSXPbufferGLDrawable extends MacOSXGLDrawable {
public void destroy() {
if (this.pBuffer != 0) {
- CGL.destroyPBuffer(0, pBuffer);
+ impl.destroy(pBuffer);
this.pBuffer = 0;
if (DEBUG) {
@@ -135,13 +137,13 @@ public class MacOSXPbufferGLDrawable extends MacOSXGLDrawable {
}
}
- pBuffer = CGL.createPBuffer(renderTarget, internalFormat, width, height);
+ pBuffer = impl.create(renderTarget, internalFormat, width, height);
if (pBuffer == 0) {
throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
}
if (DEBUG) {
- System.err.println("Created pbuffer 0x" + toHexString(pBuffer) + ", " + width + " x " + height + " for " + this);
+ System.err.println("Created pbuffer " + toHexString(pBuffer) + ", " + width + " x " + height + " for " + this);
}
}
@@ -157,4 +159,88 @@ public class MacOSXPbufferGLDrawable extends MacOSXGLDrawable {
}
return (1<<power);
}
+
+ //---------------------------------------------------------------------------
+ // 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 = 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");
+ }
+ destroy();
+ openGLMode = mode;
+ haveSetOpenGLMode = true;
+ if (DEBUG) {
+ System.err.println("Switching PBuffer drawable mode to " +
+ ((mode == MacOSXGLDrawable.NSOPENGL_MODE) ? "NSOPENGL_MODE" : "CGL_MODE"));
+ }
+ initOpenGLImpl();
+ createPbuffer();
+ }
+
+ public int getOpenGLMode() {
+ return openGLMode;
+ }
+
+ private void initOpenGLImpl() {
+ switch (openGLMode) {
+ case NSOPENGL_MODE:
+ impl = new NSOpenGLImpl();
+ break;
+ case CGL_MODE:
+ impl = new CGLImpl();
+ break;
+ default:
+ throw new InternalError("Illegal implementation mode " + openGLMode);
+ }
+ }
+
+ // Abstract interface for implementation of this drawable (either
+ // NSOpenGL-based or CGL-based)
+ interface Impl {
+ public long create(int renderTarget, int internalFormat, int width, int height);
+ public void destroy(long pbuffer);
+ }
+
+ // NSOpenGLPixelBuffer implementation
+ class NSOpenGLImpl implements Impl {
+ public long create(int renderTarget, int internalFormat, int width, int height) {
+ return CGL.createPBuffer(renderTarget, internalFormat, width, height);
+ }
+
+ public void destroy(long pbuffer) {
+ CGL.destroyPBuffer(0, pbuffer);
+ }
+ }
+
+ // CGL implementation
+ class CGLImpl implements Impl {
+ public long create(int renderTarget, int internalFormat, int width, int height) {
+ long[] pbuffer = new long[1];
+ int res = CGL.CGLCreatePBuffer(width, height, renderTarget, internalFormat, 0, pbuffer, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error creating CGL-based pbuffer: error code " + res);
+ }
+ return pbuffer[0];
+ }
+
+ public void destroy(long pbuffer) {
+ int res = CGL.CGLDestroyPBuffer(pbuffer);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error destroying CGL-based pbuffer: error code " + res);
+ }
+ }
+ }
}