summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/com')
-rw-r--r--src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java4
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java6
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java6
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/Region.java2
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java4
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java10
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java8
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/DebugGL2.java21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/DebugGL3.java21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/DebugGL3bc.java21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/DebugGL4.java21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/DebugGLES2.java21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/DefaultGLCapabilitiesChooser.java304
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FBObject.java48
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FPSCounter.java117
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java236
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLArrayData.java210
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLAutoDrawable.java636
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java22
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLBase.java646
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLBufferStorage.java160
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLCapabilities.java512
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLCapabilitiesChooser.java62
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLCapabilitiesImmutable.java178
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLContext.java2038
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLDebugListener.java44
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLDebugMessage.java253
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLDrawable.java251
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java798
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLEventListener.java102
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java32
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLException.java78
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLFBODrawable.java227
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLOffscreenAutoDrawable.java69
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLPipelineFactory.java207
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLProfile.java2322
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java45
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRunnable.java58
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRunnable2.java44
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLSharedContextSetter.java181
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLUniformData.java227
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/JoglVersion.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/Threading.java226
-rw-r--r--src/jogl/classes/com/jogamp/opengl/TraceGL2.java23
-rw-r--r--src/jogl/classes/com/jogamp/opengl/TraceGL3.java23
-rw-r--r--src/jogl/classes/com/jogamp/opengl/TraceGL3bc.java23
-rw-r--r--src/jogl/classes/com/jogamp/opengl/TraceGL4.java23
-rw-r--r--src/jogl/classes/com/jogamp/opengl/TraceGLES2.java23
-rw-r--r--src/jogl/classes/com/jogamp/opengl/awt/AWTGLAutoDrawable.java51
-rw-r--r--src/jogl/classes/com/jogamp/opengl/awt/ComponentEvents.java75
-rw-r--r--src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java1643
-rw-r--r--src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java2689
-rw-r--r--src/jogl/classes/com/jogamp/opengl/fixedfunc/GLLightingFunc.java70
-rw-r--r--src/jogl/classes/com/jogamp/opengl/fixedfunc/GLMatrixFunc.java152
-rw-r--r--src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFunc.java61
-rw-r--r--src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFuncUtil.java68
-rw-r--r--src/jogl/classes/com/jogamp/opengl/glu/GLUnurbs.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/glu/GLUquadric.java33
-rw-r--r--src/jogl/classes/com/jogamp/opengl/glu/GLUtessellator.java66
-rw-r--r--src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallback.java356
-rw-r--r--src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallbackAdapter.java96
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Matrix4.java24
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java50
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Animator.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java12
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java10
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java16
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java44
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java30
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java505
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java36
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Gamma.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java15
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java17
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java22
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java16
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java197
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java16
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java37
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java38
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java12
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java10
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java10
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java26
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java10
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java10
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java2
123 files changed, 16742 insertions, 616 deletions
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java
index 3d6de2b29..bd7081002 100644
--- a/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java
@@ -33,8 +33,8 @@
package com.jogamp.audio.windows.waveout;
import java.io.*;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.opengl.GLDrawableFactory;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.opengl.GLDrawableFactory;
public class TestSpatialization {
public static void main(String[] args) {
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
index 75067a3b7..9381d318b 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -424,7 +424,7 @@ public class BuildComposablePipeline {
final ArrayList<String> imports = new ArrayList<String>();
imports.add("java.io.*");
- imports.add("javax.media.opengl.*");
+ imports.add("com.jogamp.opengl.*");
imports.add("com.jogamp.gluegen.runtime.*");
imports.add(Buffer.class.getPackage().getName()+".*");
for (final Class<?> clasS : clazzList) {
@@ -682,7 +682,7 @@ public class BuildComposablePipeline {
!type.endsWith("core") &&
!type.endsWith("Compatible") )
{
- final Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ final Class<?> clazz = BuildComposablePipeline.getClass("com.jogamp.opengl." + type);
if (clazz.isAssignableFrom(baseInterfaceClass)) {
output.println(" return true;");
} else {
@@ -705,7 +705,7 @@ public class BuildComposablePipeline {
} else if( type.equals("GLProfile") ) {
output.println(" return " + getDownstreamObjectName() + ".getGLProfile();");
} else {
- final Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ final Class<?> clazz = BuildComposablePipeline.getClass("com.jogamp.opengl." + type);
if (clazz.isAssignableFrom(baseInterfaceClass)) {
output.println(" if( is" + type + "() ) { return this; }");
output.println(" throw new GLException(\"Not a " + type + " implementation\");");
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
index 23d4fc3cf..3d23a623f 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
@@ -35,16 +35,14 @@ import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
/**
- * @author Sven Gothel
- * @author Michael Bien
+ * @author Michael Bien, et.al.
*/
public class GLProcAddressResolver implements FunctionAddressResolver {
public static final boolean DEBUG = false;
@Override
- public long resolve(final String name, final DynamicLookupHelper lookup) {
-
+ public long resolve(final String name, final DynamicLookupHelper lookup) throws SecurityException {
long newProcAddress = 0;
final int permutations = GLNameResolver.getFuncNamePermutationNumber(name);
diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java
index 023ca8373..dde3858de 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/Region.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java
@@ -87,7 +87,7 @@ public abstract class Region {
* <p>
* If set, a color channel attribute per vertex is added to the stream,
* otherwise only the
- * {@link com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(javax.media.opengl.GL2ES2, float, float, float, float) static color}
+ * {@link com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(com.jogamp.opengl.GL2ES2, float, float, float, float) static color}
* is being used.
* </p>
*/
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
index 654f9a692..d924fa9c8 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
@@ -27,8 +27,8 @@
*/
package com.jogamp.graph.curve.opengl;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
import jogamp.graph.curve.opengl.VBORegion2PMSAAES2;
import jogamp.graph.curve.opengl.VBORegion2PVBAAES2;
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
index a0f54d3b5..0c782d93e 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
@@ -30,11 +30,11 @@ package com.jogamp.graph.curve.opengl;
import java.io.IOException;
import java.util.Iterator;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLES2;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLES2;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import jogamp.graph.curve.opengl.shader.AttributeNames;
import jogamp.graph.curve.opengl.shader.UniformNames;
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
index 6ff9bf9cd..2b243e6cf 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
@@ -29,10 +29,10 @@ package com.jogamp.graph.curve.opengl;
import java.nio.FloatBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLUniformData;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLUniformData;
import jogamp.common.os.PlatformPropsImpl;
import jogamp.graph.curve.opengl.shader.UniformNames;
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
index 0fa1f49f1..5423cde95 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
@@ -31,8 +31,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLException;
import jogamp.graph.geom.plane.AffineTransform;
diff --git a/src/jogl/classes/com/jogamp/opengl/DebugGL2.java b/src/jogl/classes/com/jogamp/opengl/DebugGL2.java
new file mode 100644
index 000000000..dc0f0df50
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/DebugGL2.java
@@ -0,0 +1,21 @@
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL2 extends DebugGL4bc {
+ public DebugGL2(final GL2 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/DebugGL3.java b/src/jogl/classes/com/jogamp/opengl/DebugGL3.java
new file mode 100644
index 000000000..6b27d207b
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/DebugGL3.java
@@ -0,0 +1,21 @@
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL3 extends DebugGL4bc {
+ public DebugGL3(final GL3 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/DebugGL3bc.java b/src/jogl/classes/com/jogamp/opengl/DebugGL3bc.java
new file mode 100644
index 000000000..d92f6043f
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/DebugGL3bc.java
@@ -0,0 +1,21 @@
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL3bc extends DebugGL4bc {
+ public DebugGL3bc(final GL3bc downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/DebugGL4.java b/src/jogl/classes/com/jogamp/opengl/DebugGL4.java
new file mode 100644
index 000000000..76f5a4ac3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/DebugGL4.java
@@ -0,0 +1,21 @@
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL4 extends DebugGL4bc {
+ public DebugGL4(final GL4 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/DebugGLES2.java b/src/jogl/classes/com/jogamp/opengl/DebugGLES2.java
new file mode 100644
index 000000000..e2b280515
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/DebugGLES2.java
@@ -0,0 +1,21 @@
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGLES2 extends DebugGLES3 {
+ public DebugGLES2(final GLES2 downstream) {
+ super((GLES3)downstream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/com/jogamp/opengl/DefaultGLCapabilitiesChooser.java
new file mode 100644
index 000000000..88a88087f
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/DefaultGLCapabilitiesChooser.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.nativewindow.NativeWindowException;
+
+import java.util.List;
+
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+
+import com.jogamp.common.ExceptionUtils;
+import com.jogamp.common.util.PropertyAccess;
+
+import jogamp.opengl.Debug;
+
+/** <P> The default implementation of the {@link
+ GLCapabilitiesChooser} interface, which provides consistent visual
+ selection behavior across platforms. The precise algorithm is
+ deliberately left loosely specified. Some properties are: </P>
+
+ <UL>
+
+ <LI> As long as there is at least one available non-null
+ GLCapabilities which matches the "stereo" option, will return a
+ valid index.
+
+ <LI> Attempts to match as closely as possible the given
+ GLCapabilities, but will select one with fewer capabilities (i.e.,
+ lower color depth) if necessary.
+
+ <LI> Prefers hardware-accelerated visuals to
+ non-hardware-accelerated.
+
+ <LI> If there is no exact match, prefers a more-capable visual to
+ a less-capable one.
+
+ <LI> If there is more than one exact match, chooses an arbitrary
+ one.
+
+ <LI> May select the opposite of a double- or single-buffered
+ visual (based on the user's request) in dire situations.
+
+ <LI> Color depth (including alpha) mismatches are weighted higher
+ than depth buffer mismatches, which are in turn weighted higher
+ than accumulation buffer (including alpha) and stencil buffer
+ depth mismatches.
+
+ <LI> If a valid windowSystemRecommendedChoice parameter is
+ supplied, chooses that instead of using the cross-platform code.
+
+ </UL>
+*/
+
+public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
+ private static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.CapabilitiesChooser", true);
+ }
+
+ private final static int NO_SCORE = -9999999;
+ private final static int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000;
+ private final static int OPAQUE_MISMATCH_PENALTY = 750;
+ private final static int STENCIL_MISMATCH_PENALTY = 500;
+ private final static int MULTISAMPLE_MISMATCH_PENALTY = 500;
+ private final static int MULTISAMPLE_EXTENSION_MISMATCH_PENALTY = 250; // just a little drop, no scale
+ // Pseudo attempt to keep equal rank penalties scale-equivalent
+ // (e.g., stencil mismatch is 3 * accum because there are 3 accum
+ // components)
+ private final static int COLOR_MISMATCH_PENALTY_SCALE = 36;
+ private final static int DEPTH_MISMATCH_PENALTY_SCALE = 6;
+ private final static int ACCUM_MISMATCH_PENALTY_SCALE = 1;
+ private final static int STENCIL_MISMATCH_PENALTY_SCALE = 3;
+ private final static int MULTISAMPLE_MISMATCH_PENALTY_SCALE = 3;
+
+ @Override
+ public int chooseCapabilities(final CapabilitiesImmutable desired,
+ final List<? extends CapabilitiesImmutable> available,
+ final int windowSystemRecommendedChoice) {
+ if ( null == desired ) {
+ throw new NativeWindowException("Null desired capabilities");
+ }
+ if ( 0 == available.size() ) {
+ throw new NativeWindowException("Empty available capabilities");
+ }
+
+ final GLCapabilitiesImmutable gldes = (GLCapabilitiesImmutable) desired;
+ final int availnum = available.size();
+
+ if (DEBUG) {
+ ExceptionUtils.dumpStack(System.err);
+ System.err.println("Desired: " + gldes);
+ System.err.println("Available: " + availnum);
+ for (int i = 0; i < available.size(); i++) {
+ System.err.println(i + ": " + available.get(i));
+ }
+ System.err.println("Window system's recommended choice: " + windowSystemRecommendedChoice);
+ }
+
+ if (windowSystemRecommendedChoice >= 0 &&
+ windowSystemRecommendedChoice < availnum &&
+ null != available.get(windowSystemRecommendedChoice)) {
+ if (DEBUG) {
+ System.err.println("Choosing window system's recommended choice of " + windowSystemRecommendedChoice);
+ System.err.println(available.get(windowSystemRecommendedChoice));
+ }
+ return windowSystemRecommendedChoice;
+ }
+
+ // Create score array
+ final int[] scores = new int[availnum];
+
+ for (int i = 0; i < scores.length; i++) {
+ scores[i] = NO_SCORE;
+ }
+ final int gldes_samples = gldes.getNumSamples();
+
+ // Compute score for each
+ for (int i = 0; i < availnum; i++) {
+ final GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i);
+ if (cur == null) {
+ continue;
+ }
+ if (gldes.isOnscreen() && !cur.isOnscreen()) {
+ continue; // requested onscreen, but n/a
+ }
+ if (!gldes.isOnscreen()) {
+ /** FBO is generic ..
+ if (gldes.isFBO() && !cur.isFBO()) {
+ continue; // requested FBO, but n/a
+ } */
+ if (gldes.isPBuffer() && !cur.isPBuffer()) {
+ continue; // requested pBuffer, but n/a
+ }
+ if (gldes.isBitmap() && !cur.isBitmap()) {
+ continue; // requested pBuffer, but n/a
+ }
+ }
+ if (gldes.getStereo() != cur.getStereo()) {
+ continue;
+ }
+ final int cur_samples = cur.getNumSamples() ;
+ int score = 0;
+
+ // Compute difference in color depth
+ // (Note that this decides the direction of all other penalties)
+ score += (COLOR_MISMATCH_PENALTY_SCALE *
+ ((cur.getRedBits() + cur.getGreenBits() + cur.getBlueBits() + cur.getAlphaBits()) -
+ (gldes.getRedBits() + gldes.getGreenBits() + gldes.getBlueBits() + gldes.getAlphaBits())));
+ // Compute difference in depth buffer depth
+ score += (DEPTH_MISMATCH_PENALTY_SCALE * sign(score) *
+ Math.abs(cur.getDepthBits() - gldes.getDepthBits()));
+ // Compute difference in accumulation buffer depth
+ score += (ACCUM_MISMATCH_PENALTY_SCALE * sign(score) *
+ Math.abs((cur.getAccumRedBits() + cur.getAccumGreenBits() + cur.getAccumBlueBits() + cur.getAccumAlphaBits()) -
+ (gldes.getAccumRedBits() + gldes.getAccumGreenBits() + gldes.getAccumBlueBits() + gldes.getAccumAlphaBits())));
+ // Compute difference in stencil bits
+ score += STENCIL_MISMATCH_PENALTY_SCALE * sign(score) * (cur.getStencilBits() - gldes.getStencilBits());
+ // Compute difference in multisampling bits
+ score += MULTISAMPLE_MISMATCH_PENALTY_SCALE * sign(score) * (cur_samples - gldes_samples);
+ // double buffer
+ if (cur.getDoubleBuffered() != gldes.getDoubleBuffered()) {
+ score += sign(score) * DOUBLE_BUFFER_MISMATCH_PENALTY;
+ }
+ // opaque
+ if (cur.isBackgroundOpaque() != gldes.isBackgroundOpaque()) {
+ score += sign(score) * OPAQUE_MISMATCH_PENALTY;
+ }
+ if ((gldes.getStencilBits() > 0) && (cur.getStencilBits() == 0)) {
+ score += sign(score) * STENCIL_MISMATCH_PENALTY;
+ }
+ if (gldes_samples > 0) {
+ if (cur_samples == 0) {
+ score += sign(score) * MULTISAMPLE_MISMATCH_PENALTY;
+ }
+ if (!gldes.getSampleExtension().equals(cur.getSampleExtension())) {
+ score += sign(score) * MULTISAMPLE_EXTENSION_MISMATCH_PENALTY;
+ }
+ }
+ scores[i] = score;
+ }
+ // Now prefer hardware-accelerated visuals by pushing scores of
+ // non-hardware-accelerated visuals out
+ boolean gotHW = false;
+ int maxAbsoluteHWScore = 0;
+ for (int i = 0; i < availnum; i++) {
+ final int score = scores[i];
+ if (score == NO_SCORE) {
+ continue;
+ }
+ final GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i);
+ if (cur.getHardwareAccelerated()) {
+ final int absScore = Math.abs(score);
+ if (!gotHW ||
+ (absScore > maxAbsoluteHWScore)) {
+ gotHW = true;
+ maxAbsoluteHWScore = absScore;
+ }
+ }
+ }
+ if (gotHW) {
+ for (int i = 0; i < availnum; i++) {
+ int score = scores[i];
+ if (score == NO_SCORE) {
+ continue;
+ }
+ final GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i);
+ if (!cur.getHardwareAccelerated()) {
+ if (score <= 0) {
+ score -= maxAbsoluteHWScore;
+ } else if (score > 0) {
+ score += maxAbsoluteHWScore;
+ }
+ scores[i] = score;
+ }
+ }
+ }
+
+ if (DEBUG) {
+ System.err.print("Scores: [");
+ for (int i = 0; i < availnum; i++) {
+ if (i > 0) {
+ System.err.print(",");
+ }
+ System.err.print(" " + i +": " + scores[i]);
+ }
+ System.err.println(" ]");
+ }
+
+ // Ready to select. Choose score closest to 0.
+ int scoreClosestToZero = NO_SCORE;
+ int chosenIndex = -1;
+ for (int i = 0; i < availnum; i++) {
+ final int score = scores[i];
+ if (score == NO_SCORE) {
+ continue;
+ }
+ // Don't substitute a positive score for a smaller negative score
+ if ((scoreClosestToZero == NO_SCORE) ||
+ (Math.abs(score) < Math.abs(scoreClosestToZero) &&
+ ((sign(scoreClosestToZero) < 0) || (sign(score) > 0)))) {
+ scoreClosestToZero = score;
+ chosenIndex = i;
+ }
+ }
+ if (chosenIndex < 0) {
+ throw new NativeWindowException("Unable to select one of the provided GLCapabilities");
+ }
+ if (DEBUG) {
+ System.err.println("Chosen index: " + chosenIndex);
+ System.err.println("Chosen capabilities:");
+ System.err.println(available.get(chosenIndex));
+ }
+
+ return chosenIndex;
+ }
+
+ private static int sign(final int score) {
+ if (score < 0) {
+ return -1;
+ }
+ return 1;
+ }
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
index 03693a688..e1ddc9c66 100644
--- a/src/jogl/classes/com/jogamp/opengl/FBObject.java
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -30,20 +30,21 @@ package com.jogamp.opengl;
import java.util.Arrays;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GL3;
-import javax.media.opengl.GLBase;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GL3;
+import com.jogamp.opengl.GLBase;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
import jogamp.opengl.Debug;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.FBObject.Attachment.Type;
@@ -698,10 +699,7 @@ public class FBObject {
final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
final int dataFormat, dataType;
final boolean alpha = hasAlpha(internalFormat);
- if( gl.isGLES3() ) {
- dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
- dataType = GL.GL_UNSIGNED_BYTE;
- } else if( gl.isGLES() ) {
+ if( gl.isGLES() ) {
dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
dataType = GL.GL_UNSIGNED_BYTE;
} else {
@@ -1071,7 +1069,7 @@ public class FBObject {
vStatus = GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // always incomplete w/o attachments!
if(DEBUG) {
System.err.println("FBObject.init() END: "+this);
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
@@ -1306,7 +1304,7 @@ public class FBObject {
final int glerr = gl.glGetError();
if(DEBUG && GL.GL_NO_ERROR != glerr) {
System.err.println("Pre-existing GL error: "+toHexString(glerr));
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
return glerr;
}
@@ -1520,7 +1518,7 @@ public class FBObject {
final TextureAttachment texA = colbuf.getTextureAttachment();
if( samples > 0 ) {
removeColorAttachment(attachmentPoint, texA);
- if(initializedColorbuf) {
+ if( initializedColorbuf ) {
texA.free(gl);
}
throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
@@ -1533,9 +1531,9 @@ public class FBObject {
if(!ignoreStatus) {
updateStatus(gl);
- if(!isStatusValid()) {
+ if( !isStatusValid() ) {
detachColorbuffer(gl, attachmentPoint, true);
- throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed: "+getStatusString()+", "+this);
}
}
} else {
@@ -1548,9 +1546,9 @@ public class FBObject {
if(!ignoreStatus) {
updateStatus(gl);
- if(!isStatusValid()) {
+ if( !isStatusValid() ) {
detachColorbuffer(gl, attachmentPoint, true);
- throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed: "+getStatusString()+", "+this);
}
}
}
@@ -1796,7 +1794,7 @@ public class FBObject {
updateStatus(gl);
if( !isStatusValid() ) {
detachRenderbuffer(gl, atype, true);
- throw new GLException("renderbuffer [attachmentType "+atype+", iformat "+toHexString(internalFormat)+"] failed: "+this.getStatusString()+": "+this.toString());
+ throw new GLException("renderbuffer [attachmentType "+atype+", iformat "+toHexString(internalFormat)+"] failed: "+this.getStatusString()+", "+this.toString());
}
}
@@ -2197,7 +2195,7 @@ public class FBObject {
} */
updateStatus(gl);
if(!isStatusValid()) {
- throw new GLException("detachAllImpl failed "+getStatusString()+", "+this);
+ throw new GLException("detachAllImpl failed: "+getStatusString()+", "+this);
}
}
} finally {
@@ -2306,7 +2304,7 @@ public class FBObject {
public final boolean resetSamplingSink(final GL gl) throws GLException {
if(DEBUG) {
System.err.println("FBObject.resetSamplingSink.0");
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
if( 0 == samples ) {
diff --git a/src/jogl/classes/com/jogamp/opengl/FPSCounter.java b/src/jogl/classes/com/jogamp/opengl/FPSCounter.java
new file mode 100644
index 000000000..a3b7ccb70
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/FPSCounter.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * FPSCounter feature.<br>
+ * An implementation initially has the FPSCounter feature disabled.<br>
+ * Use {@link #setUpdateFPSFrames(int, PrintStream)} to enable and disable the FPSCounter feature.
+ */
+public interface FPSCounter {
+ public static final int DEFAULT_FRAMES_PER_INTERVAL = 5*60;
+
+ /**
+ * @param frames Update interval in frames.<br> At every rendered <i>frames</i> interval the currentTime and fps values are updated.
+ * If the <i>frames</i> interval is <= 0, no update will be issued, ie the FPSCounter feature is turned off. You may choose {@link #DEFAULT_FRAMES_PER_INTERVAL}.
+ * @param out optional print stream where the fps values gets printed if not null at every <i>frames</i> interval
+ */
+ void setUpdateFPSFrames(int frames, PrintStream out);
+
+ /**
+ * Reset all performance counter (startTime, currentTime, frame number)
+ */
+ void resetFPSCounter();
+
+ /**
+ * @return update interval in frames
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ */
+ int getUpdateFPSFrames();
+
+ /**
+ * Returns the time of the first display call in milliseconds after enabling this feature via {@link #setUpdateFPSFrames(int, PrintStream)}.<br>
+ * This value is reset via {@link #resetFPSCounter()}.
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ long getFPSStartTime();
+
+ /**
+ * Returns the time of the last update interval in milliseconds, if this feature is enabled via {@link #setUpdateFPSFrames(int, PrintStream)}.<br>
+ * This value is reset via {@link #resetFPSCounter()}.
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ long getLastFPSUpdateTime();
+
+ /**
+ * @return Duration of the last update interval in milliseconds.
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ long getLastFPSPeriod();
+
+ /**
+ * @return Last update interval's frames per seconds, {@link #getUpdateFPSFrames()} / {@link #getLastFPSPeriod()}
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ float getLastFPS();
+
+ /**
+ * @return Number of frame rendered since {@link #getFPSStartTime()} up to {@link #getLastFPSUpdateTime()}
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ int getTotalFPSFrames();
+
+ /**
+ * @return Total duration in milliseconds, {@link #getLastFPSUpdateTime()} - {@link #getFPSStartTime()}
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ long getTotalFPSDuration();
+
+
+ /**
+ * @return Total frames per seconds, {@link #getTotalFPSFrames()} / {@link #getTotalFPSDuration()}
+ *
+ * @see #setUpdateFPSFrames(int, PrintStream)
+ * @see #resetFPSCounter()
+ */
+ float getTotalFPS();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java b/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java
new file mode 100644
index 000000000..549efd569
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java
@@ -0,0 +1,236 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+/**
+ * An animator control interface,
+ * which implementation may drive a {@link com.jogamp.opengl.GLAutoDrawable} animation.
+ */
+public interface GLAnimatorControl extends FPSCounter {
+ /**
+ * A {@link GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler) registered}
+ * {@link UncaughtExceptionHandler} instance is invoked when an {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * @see #uncaughtException(GLAnimatorControl, GLAutoDrawable, Throwable)
+ * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler)
+ * @since 2.2
+ */
+ public static interface UncaughtExceptionHandler {
+ /**
+ * Method invoked when the given {@link GLAnimatorControl} is {@link GLAnimatorControl#stop() stopped} due to the
+ * given uncaught exception happened on the given {@link GLAutoDrawable}.
+ * <p>
+ * The animator thread can still be retrieved via {@link GLAnimatorControl#getThread()}.
+ * </p>
+ * <p>
+ * All {@link GLAnimatorControl} states already reflect its stopped state.
+ * </p>
+ * <p>
+ * After this handler method is called, the {@link GLAnimatorControl} is stopped.
+ * </p>
+ * <p>
+ * Any exception thrown by this method will be ignored.
+ * </p>
+ * @param animator the {@link GLAnimatorControl}
+ * @param drawable the causing {@link GLAutoDrawable}
+ * @param cause the uncaught exception
+ * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler)
+ * @since 2.2
+ */
+ void uncaughtException(final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause);
+ }
+
+ /**
+ * Indicates whether this animator has been {@link #start() started}.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #isPaused()
+ * @see #pause()
+ * @see #resume()
+ */
+ boolean isStarted();
+
+ /**
+ * Indicates whether this animator {@link #isStarted() is started} and {@link #isPaused() is not paused}.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #pause()
+ * @see #resume()
+ */
+ boolean isAnimating();
+
+ /**
+ * Indicates whether this animator {@link #isStarted() is started}
+ * and either {@link #pause() manually paused} or paused
+ * automatically due to no {@link #add(GLAutoDrawable) added} {@link GLAutoDrawable}s.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #pause()
+ * @see #resume()
+ */
+ boolean isPaused();
+
+ /**
+ * @return The animation thread if running, otherwise null.
+ *
+ * @see #start()
+ * @see #stop()
+ */
+ Thread getThread();
+
+ /**
+ * Starts this animator, if not running.
+ * <p>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ * </p>
+ * <p>
+ * Note that an animator w/o {@link #add(GLAutoDrawable) added drawables}
+ * will be paused automatically.
+ * </p>
+ * <p>
+ * If started, all counters (time, frames, ..) are reset to zero.
+ * </p>
+ *
+ * @return true is started due to this call,
+ * otherwise false, ie started already or unable to start.
+ *
+ * @see #stop()
+ * @see #isAnimating()
+ * @see #isPaused()
+ * @see #getThread()
+ */
+ boolean start();
+
+ /**
+ * Stops this animator.
+ * <p>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ * </p>
+ *
+ * @return true is stopped due to this call,
+ * otherwise false, ie not started or unable to stop.
+ *
+ * @see #start()
+ * @see #isAnimating()
+ * @see #getThread()
+ */
+ boolean stop();
+
+ /**
+ * Pauses this animator.
+ * <p>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ * </p>
+ *
+ * @return false if not started, already paused or failed to pause, otherwise true
+ *
+ * @see #resume()
+ * @see #isAnimating()
+ */
+ boolean pause();
+
+ /**
+ * Resumes animation if paused.
+ * <p>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ * </p>
+ * <p>
+ * If resumed, all counters (time, frames, ..) are reset to zero.
+ * </p>
+ *
+ * @return false if not started, not paused or unable to resume, otherwise true
+ *
+ * @see #pause()
+ * @see #isAnimating()
+ */
+ boolean resume();
+
+ /**
+ * Adds a drawable to this animator's list of rendering drawables.
+ * <p>
+ * This allows the animator thread to become {@link #isAnimating() animating},
+ * in case the first drawable is added and the animator {@link #isStarted() is started}.
+ * </p>
+ *
+ * @param drawable the drawable to be added
+ * @throws IllegalArgumentException if drawable was already added to this animator
+ */
+ void add(GLAutoDrawable drawable);
+
+ /**
+ * Removes a drawable from the animator's list of rendering drawables.
+ * <p>
+ * This method should get called in case a drawable becomes invalid,
+ * and will not be recovered.
+ * </p>
+ * <p>
+ * This allows the animator thread to become {@link #isAnimating() not animating},
+ * in case the last drawable has been removed.
+ * </p>
+ *
+ * @param drawable the drawable to be removed
+ * @throws IllegalArgumentException if drawable was not added to this animator
+ */
+ void remove(GLAutoDrawable drawable);
+
+ /**
+ * Returns the {@link UncaughtExceptionHandler} invoked when this {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * <p>
+ * Default is <code>null</code>.
+ * </p>
+ * @since 2.2
+ */
+ UncaughtExceptionHandler getUncaughtExceptionHandler();
+
+ /**
+ * Set the handler invoked when this {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * @param handler the {@link UncaughtExceptionHandler} to use as this {@link GLAnimatorControl animator}'s uncaught exception
+ * handler. Pass <code>null</code> to unset the handler.
+ * @see UncaughtExceptionHandler#uncaughtException(GLAnimatorControl, GLAutoDrawable, Throwable)
+ * @since 2.2
+ */
+ void setUncaughtExceptionHandler(final UncaughtExceptionHandler handler);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLArrayData.java b/src/jogl/classes/com/jogamp/opengl/GLArrayData.java
new file mode 100644
index 000000000..ea2dfb0f3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLArrayData.java
@@ -0,0 +1,210 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import java.nio.Buffer;
+
+import com.jogamp.opengl.fixedfunc.GLPointerFunc;
+
+/**
+ *
+ * The total number of bytes hold by the referenced buffer is:
+ * getComponentSize()* getComponentNumber() * getElementNumber()
+ *
+ */
+public interface GLArrayData {
+ /**
+ * Implementation and type dependent object association.
+ * <p>
+ * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState}
+ * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's
+ * data persistence, location and state change.<br/>
+ * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}.
+ * </p>
+ * @param obj implementation and type dependent association
+ * @param enable pass true to enable the association and false to disable it.
+ */
+ public void associate(Object obj, boolean enable);
+
+ /**
+ * Returns true if this data set is intended for a GLSL vertex shader attribute,
+ * otherwise false, ie intended for fixed function vertex pointer
+ */
+ public boolean isVertexAttribute();
+
+ /**
+ * The index of the predefined array index, see list below,
+ * or -1 in case of a shader attribute array.
+ *
+ * @see GLPointerFunc#GL_VERTEX_ARRAY
+ * @see GLPointerFunc#GL_NORMAL_ARRAY
+ * @see GLPointerFunc#GL_COLOR_ARRAY
+ * @see GLPointerFunc#GL_TEXTURE_COORD_ARRAY
+ */
+ public int getIndex();
+
+ /**
+ * The name of the reflecting shader array attribute.
+ */
+ public String getName();
+
+ /**
+ * Set a new name for this array.
+ * <p>
+ * This clears the location, i.e. sets it to -1.
+ * </p>
+ * @see #setLocation(int)
+ * @see #setLocation(GL2ES2, int)
+ */
+ public void setName(String newName);
+
+
+ /**
+ * Returns the shader attribute location for this name,
+ * -1 if not yet determined
+ */
+ public int getLocation();
+
+ /**
+ * Sets the given location of the shader attribute
+ *
+ * @return the given location
+ * @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData)
+ */
+ public int setLocation(int v);
+
+ /**
+ * Retrieves the location of the shader attribute from the linked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return &ge;0 denotes a valid attribute location as found and used in the given shader program.
+ * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
+ */
+ public int setLocation(GL2ES2 gl, int program);
+
+ /**
+ * Binds the location of the shader attribute to the given location for the unlinked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return the given location
+ */
+ public int setLocation(GL2ES2 gl, int program, int location);
+
+ /**
+ * Determines whether the data is server side (VBO) and enabled,
+ * or a client side array (false).
+ */
+ public boolean isVBO();
+
+ /**
+ * The VBO buffer offset or 0 if not a VBO
+ */
+ public long getVBOOffset();
+
+ /**
+ * The VBO name or 0 if not a VBO
+ */
+ public int getVBOName();
+
+ /**
+ * The VBO usage or 0 if not a VBO
+ * @return 0 if not a GPU buffer, otherwise {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ */
+ public int getVBOUsage();
+
+ /**
+ * The VBO target or 0 if not a VBO
+ * @return 0 if not a GPU buffer, otherwise {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
+ */
+ public int getVBOTarget();
+
+
+ /**
+ * The Buffer holding the data, may be null if a GPU buffer without client bound data
+ */
+ public Buffer getBuffer();
+
+ /**
+ * The number of components per element
+ */
+ public int getComponentCount();
+
+ /**
+ * The component's GL data type, ie. GL_FLOAT
+ */
+ public int getComponentType();
+
+ /**
+ * The component's size in bytes
+ */
+ public int getComponentSizeInBytes();
+
+ /**
+ * The current number of used elements.
+ * <p>
+ * On element consist out of {@link #getComponentCount()} components.
+ * </p>
+ * In case the buffer's position is 0 (sealed, flipped), it's based on it's limit instead of it's position.
+ */
+ public int getElementCount();
+
+ /**
+ * The currently used size in bytes.<br>
+ * In case the buffer's position is 0 (sealed, flipped), it's based on it's limit instead of it's position.
+ */
+ public int getSizeInBytes();
+
+ /**
+ * True, if GL shall normalize fixed point data while converting
+ * them into float.
+ * <p>
+ * Default behavior (of the fixed function pipeline) is <code>true</code>
+ * for fixed point data type and <code>false</code> for floating point data types.
+ * </p>
+ */
+ public boolean getNormalized();
+
+ /**
+ * @return the byte offset between consecutive components
+ */
+ public int getStride();
+
+ @Override
+ public String toString();
+
+ public void destroy(GL gl);
+
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawable.java
new file mode 100644
index 000000000..385acf082
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawable.java
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import java.util.List;
+
+import com.jogamp.nativewindow.NativeSurface;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+
+import jogamp.opengl.Debug;
+
+/** A higher-level abstraction than {@link GLDrawable} which supplies
+ an event based mechanism ({@link GLEventListener}) for performing
+ OpenGL rendering. A GLAutoDrawable automatically creates a primary
+ rendering context which is associated with the GLAutoDrawable for
+ the lifetime of the object.
+ <p>
+ Since the {@link GLContext} {@link GLContext#makeCurrent makeCurrent}
+ implementation is synchronized, i.e. blocks if the context
+ is current on another thread, the internal
+ {@link GLContext} for the GLAutoDrawable can be used for the event
+ based rendering mechanism and by end users directly.
+ </p>
+ <h5><a name="initialization">GLAutoDrawable Initialization</a></h5>
+ <p>
+ The implementation shall initialize itself as soon as possible,
+ which is only possible <i>after</i> the attached {@link com.jogamp.nativewindow.NativeSurface NativeSurface} becomes visible and and is realized.<br>
+ The following initialization sequence should be implemented:
+ <ul>
+ <li> Create the {@link GLDrawable} with the requested {@link GLCapabilities}</li>
+ <li> Notify {@link GLDrawable} to validate the {@link GLCapabilities} by calling {@link GLDrawable#setRealized setRealized(true)}.</li>
+ <li> Create the new {@link GLContext}.</li>
+ <li> Initialize all OpenGL resources by calling {@link GLEventListener#init init(..)} for all
+ registered {@link GLEventListener}s. This can be done immediately, or with the followup {@link #display display(..)} call.</li>
+ <li> Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all
+ registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.</li>
+ </ul>
+ Note: The last to {@link GLEventListener} actions shall be also performed, when {@link #addGLEventListener(GLEventListener) adding}
+ a new one to an already initialized {@link GLAutoDrawable}.
+ </p>
+ <h5><a name="reconfiguration">GLAutoDrawable Reconfiguration</a></h5>
+ <p>
+ Another implementation detail is the {@link GLDrawable} reconfiguration. One use case is where a window is being
+ dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation
+ shall be able to detect such cases in conjunction with the associated {@link com.jogamp.nativewindow.NativeSurface NativeSurface}.<br/>
+ For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()}
+ is capable to determine a display device change. This is demonstrated within {@link com.jogamp.opengl.awt.GLCanvas}'s
+ and NEWT's <code>AWTCanvas</code> {@link com.jogamp.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()}
+ specialization. Another demonstration is NEWT's {@link com.jogamp.nativewindow.NativeWindow NativeWindow}
+ implementation on the Windows platform, which utilizes the native platform's <i>MonitorFromWindow(HWND)</i> function.<br/>
+ All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has
+ to be chosen again. The following protocol shall be satisfied.
+ <ul>
+ <li> Controlled disposal:</li>
+ <ul>
+ <li> Dispose all OpenGL resources by calling {@link GLEventListener#dispose dispose(..)} for all
+ registered {@link GLEventListener}s.</li>
+ <li> Destroy the {@link GLContext}.</li>
+ <li> Notify {@link GLDrawable} of the invalid state by calling {@link GLDrawable#setRealized setRealized(false)}.</li>
+ </ul>
+ <li> Controlled regeneration:</li>
+ <ul>
+ <li> Create the new {@link GLDrawable} with the requested {@link GLCapabilities}
+ <li> Notify {@link GLDrawable} to revalidate the {@link GLCapabilities} by calling {@link GLDrawable#setRealized setRealized(true)}.</li>
+ <li> Create the new {@link GLContext}.</li>
+ <li> Initialize all OpenGL resources by calling {@link GLEventListener#init init(..)} for all
+ registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.</li>
+ <li> Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all
+ registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.</li>
+ </ul>
+ </ul>
+ Note: Current graphics driver keep the surface configuration for a given window, even if the window is moved to
+ a monitor with a different pixel configuration, ie 32bpp to 16bpp. However, it is best to not assume such behavior
+ and make your application comply with the above protocol.
+ <p>
+ Avoiding breakage with older applications and because of the situation
+ mentioned above, the <code>boolean</code> system property <code>jogl.screenchange.action</code> will control the
+ screen change action as follows:<br/>
+ <PRE>
+ -Djogl.screenchange.action=false Disable the {@link GLDrawable} reconfiguration (the default)
+ -Djogl.screenchange.action=true Enable the {@link GLDrawable} reconfiguration
+ </PRE>
+ </p>
+ <h5><a name="locking">GLAutoDrawable Locking</a></h5>
+ GLAutoDrawable implementations perform locking in the following order:
+ <ol>
+ <li> {@link #getUpstreamLock()}.{@link RecursiveLock#lock() lock()}</li>
+ <li> {@link #getNativeSurface()}.{@link NativeSurface#lockSurface() lockSurface()} </li>
+ </ol>
+ and releases the locks accordingly:
+ <ol>
+ <li> {@link #getNativeSurface()}.{@link NativeSurface#unlockSurface() unlockSurface()} </li>
+ <li> {@link #getUpstreamLock()}.{@link RecursiveLock#unlock() unlock()}</li>
+ </ol>
+ Above <i>locking order</i> is mandatory to guarantee
+ atomicity of operation and to avoid race-conditions.
+ A custom implementation or user applications requiring exclusive access
+ shall follow the <i>locking order</i>.
+ See:
+ <ul>
+ <li>{@link #getUpstreamLock()}</li>
+ <li>{@link #invoke(boolean, GLRunnable)}</li>
+ <li>{@link #invoke(boolean, List)}</li>
+ </ul>
+ </p>
+ */
+public interface GLAutoDrawable extends GLDrawable {
+ /** Flag reflecting whether the {@link GLDrawable} reconfiguration will be issued in
+ * case a screen device change occurred, e.g. in a multihead environment,
+ * where you drag the window to another monitor. */
+ public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true);
+
+ /**
+ * If the implementation uses delegation, return the delegated {@link GLDrawable} instance,
+ * otherwise return <code>this</code> instance.
+ */
+ public GLDrawable getDelegatedDrawable();
+
+ /**
+ * Returns the context associated with this drawable. The returned
+ * context will be synchronized.
+ * Don't rely on it's identity, the context may change.
+ */
+ public GLContext getContext();
+
+ /**
+ * Associate the new context, <code>newtCtx</code>, to this auto-drawable.
+ * <p>
+ * Remarks:
+ * <ul>
+ * <li>The currently associated context will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+ * otherwise it will be disassociated from this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} including {@link GL#glFinish() glFinish()}.</li>
+ * <li>The new context will be associated with this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.</li>
+ * <li>If the old context was current on this thread, it is being released after disassociating this auto-drawable.</li>
+ * <li>If the new context was current on this thread, it is being released before associating this auto-drawable
+ * and made current afterwards.</li>
+ * <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
+ * <li>The user shall take extra care of thread synchronization,
+ * i.e. lock the involved {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-locks} and {@link GLAutoDrawable#getNativeSurface() surfaces}
+ * to avoid a race condition. See <a href="#locking">GLAutoDrawable Locking</a>.</li>
+ * </ul>
+ * </p>
+ *
+ * @param newCtx the new context, maybe <code>null</code> for dis-association.
+ * @param destroyPrevCtx if <code>true</code>, destroy the previous context if exists
+ * @return the previous GLContext, maybe <code>null</code>
+ *
+ * @see GLContext#setGLDrawable(GLDrawable, boolean)
+ * @see GLContext#setGLReadDrawable(GLDrawable)
+ * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, boolean, GLContext, int)
+ */
+ public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx);
+
+ /**
+ * Adds the given {@link GLEventListener listener} to the end of this drawable queue.
+ * The {@link GLEventListener listeners} are notified of events in the order of the queue.
+ * <p>
+ * The newly added listener's {@link GLEventListener#init(GLAutoDrawable) init(..)}
+ * method will be called once before any other of it's callback methods.
+ * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+ * </p>
+ * @param listener The GLEventListener object to be inserted
+ */
+ public void addGLEventListener(GLEventListener listener);
+
+ /**
+ * Adds the given {@link GLEventListener listener} at the given index of this drawable queue.
+ * The {@link GLEventListener listeners} are notified of events in the order of the queue.
+ * <p>
+ * The newly added listener's {@link GLEventListener#init(GLAutoDrawable) init(..)}
+ * method will be called once before any other of it's callback methods.
+ * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+ * </p>
+ * @param index Position where the listener will be inserted.
+ * Should be within (0 <= index && index <= size()).
+ * An index value of -1 is interpreted as the end of the list, size().
+ * @param listener The GLEventListener object to be inserted
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1
+ */
+ public void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException;
+
+ /**
+ * Returns the number of {@link GLEventListener} of this drawable queue.
+ * @return The number of GLEventListener objects of this drawable queue.
+ */
+ public int getGLEventListenerCount();
+
+ /**
+ * Returns true if all added {@link GLEventListener} are initialized, otherwise false.
+ * @since 2.2
+ */
+ boolean areAllGLEventListenerInitialized();
+
+ /**
+ * Returns the {@link GLEventListener} at the given index of this drawable queue.
+ * @param index Position of the listener to be returned.
+ * Should be within (0 <= index && index < size()).
+ * An index value of -1 is interpreted as last listener, size()-1.
+ * @return The GLEventListener object at the given index.
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index < size()), or -1
+ */
+ public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException;
+
+ /**
+ * Retrieves whether the given {@link GLEventListener listener} is initialized or not.
+ * <p>
+ * After {@link #addGLEventListener(GLEventListener) adding} a {@link GLEventListener} it is
+ * marked <i>uninitialized</i> and added to a list of to be initialized {@link GLEventListener}.
+ * If such <i>uninitialized</i> {@link GLEventListener}'s handler methods (reshape, display)
+ * are about to be invoked, it's {@link GLEventListener#init(GLAutoDrawable) init(..)} method is invoked first.
+ * Afterwards the {@link GLEventListener} is marked <i>initialized</i>
+ * and removed from the list of to be initialized {@link GLEventListener}.
+ * </p>
+ * <p>
+ * This methods returns the {@link GLEventListener} initialized state,
+ * i.e. returns <code>false</code> if it is included in the list of to be initialized {@link GLEventListener},
+ * otherwise <code>true</code>.
+ * </p>
+ * @param listener the GLEventListener object to query it's initialized state.
+ */
+ public boolean getGLEventListenerInitState(GLEventListener listener);
+
+ /**
+ * Sets the given {@link GLEventListener listener's} initialized state.
+ * <p>
+ * This methods allows manually setting the {@link GLEventListener} initialized state,
+ * i.e. adding it to, or removing it from the list of to be initialized {@link GLEventListener}.
+ * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+ * </p>
+ * <p>
+ * <b>Warning:</b> This method does not validate whether the given {@link GLEventListener listener's}
+ * is member of this drawable queue, i.e. {@link #addGLEventListener(GLEventListener) added}.
+ * </p>
+ * <p>
+ * This method is only exposed to allow users full control over the {@link GLEventListener}'s state
+ * and is usually not recommended to change.
+ * </p>
+ * <p>
+ * One use case is moving a {@link GLContext} and their initialized {@link GLEventListener}
+ * from one {@link GLAutoDrawable} to another,
+ * where a subsequent {@link GLEventListener#init(GLAutoDrawable) init(..)} call after adding it
+ * to the new owner is neither required nor desired.
+ * See {@link com.jogamp.opengl.util.GLDrawableUtil#swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable) swapGLContextAndAllGLEventListener(..)}.
+ * </p>
+ * @param listener the GLEventListener object to perform a state change.
+ * @param initialized if <code>true</code>, mark the listener initialized, otherwise uninitialized.
+ */
+ public void setGLEventListenerInitState(GLEventListener listener, boolean initialized);
+
+ /**
+ * Disposes the given {@link GLEventListener listener} via {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)}
+ * if it has been initialized and added to this queue.
+ * <p>
+ * If <code>remove</code> is <code>true</code>, the {@link GLEventListener} is removed from this drawable queue before disposal,
+ * otherwise marked uninitialized.
+ * </p>
+ * <p>
+ * If an {@link GLAnimatorControl} is being attached and the current thread is different
+ * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+ * </p>
+ * <p>
+ * Note that this is an expensive operation, since {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)}
+ * is decorated by {@link GLContext#makeCurrent()} and {@link GLContext#release()}.
+ * </p>
+ * <p>
+ * Use {@link #removeGLEventListener(GLEventListener) removeGLEventListener(listener)} instead
+ * if you just want to remove the {@link GLEventListener listener} and <i>don't care</i> about the disposal of the it's (OpenGL) resources.
+ * </p>
+ * <p>
+ * Also note that this is done from within a particular drawable's
+ * {@link GLEventListener} handler (reshape, display, etc.), that it is not
+ * guaranteed that all other listeners will be evaluated properly
+ * during this update cycle.
+ * </p>
+ * @param listener The GLEventListener object to be disposed and removed if <code>remove</code> is <code>true</code>
+ * @param remove pass <code>true</code> to have the <code>listener</code> removed from this drawable queue, otherwise pass <code>false</code>
+ * @return the disposed and/or removed GLEventListener, or null if no action was performed, i.e. listener was not added
+ */
+ public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove);
+
+ /**
+ * Removes the given {@link GLEventListener listener} from this drawable queue.
+ * <p>
+ * This is an inexpensive operation, since the removed listener's
+ * {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)} method will <i>not</i> be called.
+ * </p>
+ * <p>
+ * Use {@link #disposeGLEventListener(GLEventListener, boolean) disposeGLEventListener(listener, true)}
+ * instead to ensure disposal of the {@link GLEventListener listener}'s (OpenGL) resources.
+ * </p>
+ * <p>
+ * Note that if this is done from within a particular drawable's
+ * {@link GLEventListener} handler (reshape, display, etc.), that it is not
+ * guaranteed that all other listeners will be evaluated properly
+ * during this update cycle.
+ * </p>
+ * @param listener The GLEventListener object to be removed
+ * @return the removed GLEventListener, or null if listener was not added
+ */
+ public GLEventListener removeGLEventListener(GLEventListener listener);
+
+ /**
+ * Registers the usage of an animator, an {@link com.jogamp.opengl.GLAnimatorControl} implementation.
+ * The animator will be queried whether it's animating, ie periodically issuing {@link #display()} calls or not.
+ * <p>
+ * This method shall be called by an animator implementation only,<br>
+ * e.g. {@link com.jogamp.opengl.util.Animator#add(com.jogamp.opengl.GLAutoDrawable)}, passing it's control implementation,<br>
+ * and {@link com.jogamp.opengl.util.Animator#remove(com.jogamp.opengl.GLAutoDrawable)}, passing <code>null</code>.
+ * </p>
+ * <p>
+ * Impacts {@link #display()} and {@link #invoke(boolean, GLRunnable)} semantics.</p><br>
+ *
+ * @param animatorControl <code>null</code> reference indicates no animator is using
+ * this <code>GLAutoDrawable</code>,<br>
+ * a valid reference indicates an animator is using this <code>GLAutoDrawable</code>.
+ *
+ * @throws GLException if an animator is already registered.
+ * @see #display()
+ * @see #invoke(boolean, GLRunnable)
+ * @see com.jogamp.opengl.GLAnimatorControl
+ */
+ public abstract void setAnimator(GLAnimatorControl animatorControl) throws GLException;
+
+ /**
+ * @return the registered {@link com.jogamp.opengl.GLAnimatorControl} implementation, using this <code>GLAutoDrawable</code>.
+ *
+ * @see #setAnimator(com.jogamp.opengl.GLAnimatorControl)
+ * @see com.jogamp.opengl.GLAnimatorControl
+ */
+ public GLAnimatorControl getAnimator();
+
+ /**
+ * Dedicates this instance's {@link GLContext} to the given thread.<br/>
+ * The thread will exclusively claim the {@link GLContext} via {@link #display()} and not release it
+ * until {@link #destroy()} or <code>setExclusiveContextThread(null)</code> has been called.
+ * <p>
+ * Default non-exclusive behavior is <i>requested</i> via <code>setExclusiveContextThread(null)</code>,
+ * which will cause the next call of {@link #display()} on the exclusive thread to
+ * release the {@link GLContext}. Only after it's async release, {@link #getExclusiveContextThread()}
+ * will return <code>null</code>.
+ * </p>
+ * <p>
+ * To release a previous made exclusive thread, a user issues <code>setExclusiveContextThread(null)</code>
+ * and may poll {@link #getExclusiveContextThread()} until it returns <code>null</code>,
+ * <i>while</i> the exclusive thread is still running.
+ * </p>
+ * <p>
+ * Note: Setting a new exclusive thread without properly releasing a previous one
+ * will throw an GLException.
+ * </p>
+ * <p>
+ * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+ * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+ * </p>
+ * <p>
+ * One scenario could be to dedicate the context to the {@link GLAnimatorControl#getThread() animator thread}
+ * and spare redundant context switches, see {@link com.jogamp.opengl.util.AnimatorBase#setExclusiveContext(boolean)}.
+ * </p>
+ * @param t the exclusive thread to claim the context, or <code>null</code> for default operation.
+ * @return previous exclusive context thread
+ * @throws GLException If an exclusive thread is still active but a new one is attempted to be set
+ * @see com.jogamp.opengl.util.AnimatorBase#setExclusiveContext(boolean)
+ */
+ public Thread setExclusiveContextThread(Thread t) throws GLException;
+
+ /**
+ * @see #setExclusiveContextThread(Thread)
+ */
+ public Thread getExclusiveContextThread();
+
+ /**
+ * Enqueues a one-shot {@link GLRunnable},
+ * which will be executed within the next {@link #display()} call
+ * after all registered {@link GLEventListener}s
+ * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
+ * methods have been called.
+ * <p>
+ * If no {@link GLAnimatorControl} is animating (default),<br>
+ * or if the current thread is the animator thread,<br>
+ * a {@link #display()} call is issued after enqueue the <code>GLRunnable</code>,
+ * hence the {@link GLRunnable} will be executed right away.<br/>
+ * </p>
+ * <p>
+ * If an {@link GLAnimatorControl animator} is running,<br>
+ * no explicit {@link #display()} call is issued, allowing the {@link GLAnimatorControl animator} to perform at due time.<br>
+ * </p>
+ * <p>
+ * If <code>wait</code> is <code>true</code> the call blocks until the <code>glRunnable</code>
+ * has been executed by the {@link GLAnimatorControl animator}, otherwise the method returns immediately.
+ * </p>
+ * <p>
+ * If <code>wait</code> is <code>true</code> <b>and</b>
+ * {@link #isRealized()} returns <code>false</code> <i>or</i> {@link #getContext()} returns <code>null</code>,
+ * the call is ignored and returns <code>false</code>.<br>
+ * This helps avoiding deadlocking the caller.
+ * </p>
+ * <p>
+ * The internal queue of {@link GLRunnable}'s is being flushed with {@link #destroy()}
+ * where all blocked callers are being notified.
+ * </p>
+ * <p>
+ * To avoid a deadlock situation which causes an {@link IllegalStateException} one should
+ * avoid issuing {@link #invoke(boolean, GLRunnable) invoke} while this <a href="#locking">GLAutoDrawable is being locked</a>.<br>
+ * Detected deadlock situations throwing an {@link IllegalStateException} are:
+ * <ul>
+ * <li>{@link #getAnimator() Animator} is running on another thread and waiting and is locked on current thread, but is not {@link #isThreadGLCapable() GL-Thread}</li>
+ * <li>No {@link #getAnimator() Animator} is running on another thread and is locked on current thread, but is not {@link #isThreadGLCapable() GL-Thread}</li>
+ * </ul>
+ * </p>
+ *
+ * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
+ * @param glRunnable the {@link GLRunnable} to execute within {@link #display()}
+ * @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>.
+ * @throws IllegalStateException in case of a detected deadlock situation ahead, see above.
+ *
+ * @see #setAnimator(GLAnimatorControl)
+ * @see #display()
+ * @see GLRunnable
+ * @see #invoke(boolean, List)
+ * @see #flushGLRunnables()
+ */
+ public boolean invoke(boolean wait, GLRunnable glRunnable) throws IllegalStateException ;
+
+ /**
+ * Extends {@link #invoke(boolean, GLRunnable)} functionality
+ * allowing to inject a list of {@link GLRunnable}s.
+ * @param wait if <code>true</code> block until execution of the last <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
+ * @param glRunnables the {@link GLRunnable}s to execute within {@link #display()}
+ * @return <code>true</code> if the {@link GLRunnable}s has been processed or queued, otherwise <code>false</code>.
+ * @throws IllegalStateException in case of a detected deadlock situation ahead, see {@link #invoke(boolean, GLRunnable)}.
+ * @see #invoke(boolean, GLRunnable)
+ * @see #flushGLRunnables()
+ */
+ public boolean invoke(boolean wait, List<GLRunnable> glRunnables) throws IllegalStateException;
+
+ /**
+ * Flushes all {@link #invoke(boolean, GLRunnable) enqueued} {@link GLRunnable} of this {@link GLAutoDrawable}
+ * including notifying waiting executor.
+ * <p>
+ * The executor which might have been blocked until notified
+ * will be unblocked and all tasks removed from the queue.
+ * </p>
+ * @see #invoke(boolean, GLRunnable)
+ * @since 2.2
+ */
+ public void flushGLRunnables();
+
+ /** Destroys all resources associated with this GLAutoDrawable,
+ inclusive the GLContext.
+ If a window is attached to it's implementation, it shall be closed.
+ Causes disposing of all OpenGL resources
+ by calling {@link GLEventListener#dispose dispose(..)} for all
+ registered {@link GLEventListener}s. Called automatically by the
+ window system toolkit upon receiving a destroy notification. This
+ routine may be called manually. */
+ public void destroy();
+
+ /**
+ * <p>
+ * Causes OpenGL rendering to be performed for this GLAutoDrawable
+ * in the following order:
+ * <ul>
+ * <li> Calling {@link GLEventListener#display display(..)} for all
+ * registered {@link GLEventListener}s. </li>
+ * <li> Executes all one-shot {@link com.jogamp.opengl.GLRunnable GLRunnable},
+ * enqueued via {@link #invoke(boolean, GLRunnable)}.</li>
+ * </ul></p>
+ * <p>
+ * May be called periodically by a running {@link com.jogamp.opengl.GLAnimatorControl} implementation,<br>
+ * which must register itself with {@link #setAnimator(com.jogamp.opengl.GLAnimatorControl)}.</p>
+ * <p>
+ * Called automatically by the window system toolkit upon receiving a repaint() request, <br>
+ * except an {@link com.jogamp.opengl.GLAnimatorControl} implementation {@link com.jogamp.opengl.GLAnimatorControl#isAnimating()}.</p>
+ * <p>
+ * This routine may also be called manually for better control over the
+ * rendering process. It is legal to call another GLAutoDrawable's
+ * display method from within the {@link GLEventListener#display
+ * display(..)} callback.</p>
+ * <p>
+ * In case of a new generated OpenGL context,
+ * the implementation shall call {@link GLEventListener#init init(..)} for all
+ * registered {@link GLEventListener}s <i>before</i> making the
+ * actual {@link GLEventListener#display display(..)} calls,
+ * in case this has not been done yet.</p>
+ *
+ * @see #setAnimator(com.jogamp.opengl.GLAnimatorControl)
+ */
+ public void display();
+
+ /** Enables or disables automatic buffer swapping for this drawable.
+ By default this property is set to true; when true, after all
+ GLEventListeners have been called for a display() event, the
+ front and back buffers are swapped, displaying the results of
+ the render. When disabled, the user is responsible for calling
+ {@link #swapBuffers(..)} manually. */
+ public void setAutoSwapBufferMode(boolean enable);
+
+ /** Indicates whether automatic buffer swapping is enabled for this
+ drawable. See {@link #setAutoSwapBufferMode}. */
+ public boolean getAutoSwapBufferMode();
+
+ /**
+ * @param flags Additional context creation flags.
+ *
+ * @see GLContext#setContextCreationFlags(int)
+ * @see GLContext#enableGLDebugMessage(boolean)
+ */
+ public void setContextCreationFlags(int flags);
+
+ /**
+ * @return Additional context creation flags
+ */
+ public int getContextCreationFlags();
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This GLAutoDrawable implementation holds it's own GLContext reference,
+ * thus created a GLContext using this methods won't replace it implicitly.
+ * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext, boolean)}.
+ * </p>
+ * <p>
+ * The GLAutoDrawable implementation shall also set the
+ * context creation flags as customized w/ {@link #setContextCreationFlags(int)}.
+ * </p>
+ */
+ @Override
+ public GLContext createContext(GLContext shareWith);
+
+ /** Returns the {@link GL} pipeline object this GLAutoDrawable uses.
+ If this method is called outside of the {@link
+ GLEventListener}'s callback methods (init, display, etc.) it may
+ return null. Users should not rely on the identity of the
+ returned GL object; for example, users should not maintain a
+ hash table with the GL object as the key. Additionally, the GL
+ object should not be cached in client code, but should be
+ re-fetched from the GLAutoDrawable at the beginning of each call
+ to init, display, etc. */
+ public GL getGL();
+
+ /** Sets the {@link GL} pipeline object this GLAutoDrawable uses.
+ This should only be called from within the GLEventListener's
+ callback methods, and usually only from within the init()
+ method, in order to install a composable pipeline. See the JOGL
+ demos for examples.
+ @return the set GL pipeline or null if not successful */
+ public GL setGL(GL gl);
+
+ /**
+ * Method <i>may</i> return the upstream UI toolkit object
+ * holding this {@link GLAutoDrawable} instance, if exist.
+ * <p>
+ * Currently known Java UI toolkits and it's known return types are:
+ *
+ * <table border="1">
+ * <tr><td>Toolkit</td> <td>GLAutoDrawable Implementation</td> <td>~</td> <td>Return Type of getUpstreamWidget()</td</tr>
+ * <tr><td>NEWT</td> <td>{@link com.jogamp.newt.opengl.GLWindow}</td> <td>has a</td> <td>{@link com.jogamp.newt.Window}</td</tr>
+ * <tr><td>SWT</td> <td>{@link com.jogamp.opengl.swt.GLCanvas}</td> <td>is a</td> <td>{@link org.eclipse.swt.widgets.Canvas}</td</tr>
+ * <tr><td>AWT</td> <td>{@link com.jogamp.opengl.awt.GLCanvas}</td> <td>is a</td> <td>{@link java.awt.Canvas}</td</tr>
+ * <tr><td>AWT</td> <td>{@link com.jogamp.opengl.awt.GLJPanel}</td> <td>is a</td> <td>{@link javax.swing.JPanel}</td</tr>
+ * </table>
+ * However, the result may be other object types than the listed above
+ * due to new supported toolkits.
+ * </p>
+ * <p>
+ * This method may also return <code>null</code> if no UI toolkit is being used,
+ * as common for offscreen rendering.
+ * </p>
+ */
+ public Object getUpstreamWidget();
+
+ /**
+ * Returns the recursive lock object of the {@link #getUpstreamWidget() upstream widget}
+ * to synchronize multithreaded access on top of {@link NativeSurface#lockSurface()}.
+ * <p>
+ * See <a href="#locking">GLAutoDrawable Locking</a>.
+ * </p>
+ * @since 2.2
+ */
+ public RecursiveLock getUpstreamLock();
+
+ /**
+ * Indicates whether the current thread is capable of
+ * performing OpenGL-related work.
+ * <p>
+ * Implementation utilizes this knowledge to determine
+ * whether {@link #display()} performs the OpenGL commands on the current thread directly
+ * or spawns them on the dedicated OpenGL thread.
+ * </p>
+ * @since 2.2
+ */
+ public boolean isThreadGLCapable();
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
index b9f1fb10c..712fcdac7 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
@@ -28,17 +28,17 @@
package com.jogamp.opengl;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.WindowClosingProtocol;
-import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLSharedContextSetter;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.WindowClosingProtocol;
+import com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLSharedContextSetter;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
diff --git a/src/jogl/classes/com/jogamp/opengl/GLBase.java b/src/jogl/classes/com/jogamp/opengl/GLBase.java
new file mode 100644
index 000000000..19b7808fc
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLBase.java
@@ -0,0 +1,646 @@
+/**
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+/**
+ * <P>The base interface from which all GL profiles derive, providing
+ * checked conversion down to concrete profiles, access to the
+ * OpenGL context associated with the GL and extension/function
+ * availability queries as described below.</P>
+ *
+ * <P> While the APIs for vendor extensions are unconditionally
+ * exposed, the underlying functions may not be present. The method
+ * {@link #isFunctionAvailable} should be used to query the
+ * availability of any non-core function before it is used for the
+ * first time; for example,
+ * <code>gl.isFunctionAvailable("glProgramStringARB")</code>. On
+ * certain platforms (Windows in particular), the most "core"
+ * functionality is only OpenGL 1.1, so in theory any routines first
+ * exposed in OpenGL 1.2, 1.3, and 1.4, 1.5, or 2.0 as well as vendor
+ * extensions should all be queried. Calling an unavailable function
+ * will cause a {@link GLException} to be raised. </P>
+ *
+ * {@link #isExtensionAvailable} may also be used to determine whether
+ * a specific extension is available before calling the routines or
+ * using the functionality it exposes: for example,
+ * <code>gl.isExtensionAvailable("GL_ARB_vertex_program");</code>.
+ * However, in this case it is up to the end user to know which
+ * routines or functionality are associated with which OpenGL
+ * extensions. It may also be used to test for the availability of a
+ * particular version of OpenGL: for example,
+ * <code>gl.isExtensionAvailable("GL_VERSION_1_5");</code>.
+ *
+ * <P> Exceptions to the window system extension naming rules:
+ *
+ * <UL>
+ *
+ * <LI> The memory allocators for the NVidia vertex_array_range (VAR)
+ * extension, in particular <code>wglAllocateMemoryNV</code> /
+ * <code>glXAllocateMemoryNV</code> and associated routines. {@link
+ * #glAllocateMemoryNV} has been provided for window system-independent
+ * access to VAR. {@link #isFunctionAvailable} will translate an argument
+ * of "glAllocateMemoryNV" or "glFreeMemoryNV" into the appropriate
+ * window system-specific name. </P>
+ *
+ * <LI> WGL_ARB_pbuffer, WGL_ARB_pixel_format, and other
+ * platform-specific pbuffer functionality; the availability of
+ * pbuffers can be queried on Windows, X11 and Mac OS X platforms by
+ * querying {@link #isExtensionAvailable} with an argument of
+ * "GL_ARB_pbuffer" or "GL_ARB_pixel_format".
+ *
+ * </UL> <P>
+ *
+ */
+public interface GLBase {
+
+ /**
+ * Indicates whether this GL object conforms to any of the OpenGL profiles.
+ */
+ public boolean isGL();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL &ge; 4.0 compatibility profile.
+ * The GL4 compatibility profile includes the GL2, GL2ES1, GL2ES2, GL3, GL3bc and GL4 profile.
+ * @see GLContext#isGL4bc()
+ */
+ public boolean isGL4bc();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL &ge; 4.0 core profile.
+ * The GL4 core profile includes the GL2ES2, and GL3 profile.
+ * @see GLContext#isGL4()
+ */
+ public boolean isGL4();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL &ge; 3.1 compatibility profile.
+ * The GL3 compatibility profile includes the GL2, GL2ES1, GL2ES2 and GL3 profile.
+ * @see GLContext#isGL3bc()
+ */
+ public boolean isGL3bc();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL &ge; 3.1 core profile.
+ * The GL3 core profile includes the GL2ES2 profile.
+ * @see GLContext#isGL3()
+ */
+ public boolean isGL3();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL &le; 3.0 profile.
+ * The GL2 profile includes the GL2ES1 and GL2ES2 profile.
+ * @see GLContext#isGL2()
+ */
+ public boolean isGL2();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL ES &ge; 1.0 profile.
+ * @see GLContext#isGLES1()
+ */
+ public boolean isGLES1();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL ES &ge; 2.0 profile.
+ * <p>
+ * Remark: ES2 compatible desktop profiles are not included.
+ * To query whether core ES2 functionality is provided, use {@link #isGLES2Compatible()}.
+ * </p>
+ * @see #isGLES2Compatible()
+ * @see GLContext#isGLES2()
+ */
+ public boolean isGLES2();
+
+ /**
+ * Indicates whether this GL object conforms to the OpenGL ES &ge; 3.0 profile.
+ * <p>
+ * Remark: ES3 compatible desktop profiles are not included.
+ * To query whether core ES3 functionality is provided, use {@link #isGLES3Compatible()}.
+ * </p>
+ * @see #isGLES3Compatible()
+ * @see GLContext#isGLES3()
+ */
+ public boolean isGLES3();
+
+ /**
+ * Indicates whether this GL object conforms to one of the OpenGL ES profiles,
+ * see {@link #isGLES1()}, {@link #isGLES2()} and {@link #isGLES3()}.
+ * @see GLContext#isGLES()
+ */
+ public boolean isGLES();
+
+ /**
+ * Indicates whether this GL object conforms to a GL2ES1 compatible profile.
+ * @see GLContext#isGL2ES1()
+ */
+ public boolean isGL2ES1();
+
+ /**
+ * Indicates whether this GL object conforms to a GL2ES2 compatible profile.
+ * @see GLContext#isGL2ES2()
+ */
+ public boolean isGL2ES2();
+
+ /**
+ * Indicates whether this GL object conforms to a either a GL2GL3 or GL3ES3 compatible profile.
+ * @see GLContext#isGL2ES3()
+ */
+ public boolean isGL2ES3();
+
+ /**
+ * Indicates whether this GL object conforms to a GL3ES3 compatible profile.
+ * @see GLContext#isGL3ES3()
+ */
+ public boolean isGL3ES3();
+
+ /**
+ * Returns true if this GL object conforms to a GL4ES3 compatible profile, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLContext#isGL4ES3()
+ */
+ public boolean isGL4ES3();
+
+ /**
+ * Indicates whether this GL object conforms to a GL2GL3 compatible profile.
+ * @see GLContext#isGL2GL3()
+ */
+ public boolean isGL2GL3();
+
+ /**
+ * Indicates whether this GL object uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ * @see GLContext#isGL4core()
+ */
+ public boolean isGL4core();
+
+ /**
+ * Indicates whether this GL object uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ * @see GLContext#isGL3core()
+ */
+ public boolean isGL3core();
+
+ /**
+ * Indicates whether this GL object uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GL2ES2 ].</p>
+ * @see GLContext#isGLcore()
+ */
+ public boolean isGLcore();
+
+ /**
+ * Indicates whether this GL object is compatible with the core OpenGL ES2 functionality.
+ * @return true if this context is an ES2 context or implements
+ * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * @see GLContext#isGLES2Compatible()
+ */
+ public boolean isGLES2Compatible();
+
+ /**
+ * Indicates whether this GL object is compatible with the core OpenGL ES3 functionality.
+ * <p>
+ * Return true if the underlying context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * </p>
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ * @see GLContext#isGLES3Compatible()
+ */
+ public boolean isGLES3Compatible();
+
+ /**
+ * Indicates whether this GL object supports GLSL.
+ * @see GLContext#hasGLSL()
+ */
+ public boolean hasGLSL();
+
+ /**
+ * Returns the downstream GL instance in case this is a wrapping pipeline, otherwise <code>null</code>.
+ * <p>
+ * See {@link #getRootGL()} for retrieving the implementing root instance.
+ * </p>
+ * @throws GLException if the downstream instance is not null and not a GL implementation
+ * @see #getRootGL()
+ */
+ public GL getDownstreamGL() throws GLException;
+
+ /**
+ * Returns the implementing root instance, considering a wrapped pipelined hierarchy, see {@link #getDownstreamGL()}.
+ * <p>
+ * If this instance is not a wrapping pipeline, i.e. has no downstream instance,
+ * this instance is returned.
+ * </p>
+ * @throws GLException if the root instance is not a GL implementation
+ */
+ public GL getRootGL() throws GLException;
+
+ /**
+ * Casts this object to the GL interface.
+ * @throws GLException if this object is not a GL implementation
+ */
+ public GL getGL() throws GLException;
+
+ /**
+ * Casts this object to the GL4bc interface.
+ * @throws GLException if this object is not a GL4bc implementation
+ */
+ public GL4bc getGL4bc() throws GLException;
+
+ /**
+ * Casts this object to the GL4 interface.
+ * @throws GLException if this object is not a GL4 implementation
+ */
+ public GL4 getGL4() throws GLException;
+
+ /**
+ * Casts this object to the GL3bc interface.
+ * @throws GLException if this object is not a GL3bc implementation
+ */
+ public GL3bc getGL3bc() throws GLException;
+
+ /**
+ * Casts this object to the GL3 interface.
+ * @throws GLException if this object is not a GL3 implementation
+ */
+ public GL3 getGL3() throws GLException;
+
+ /**
+ * Casts this object to the GL2 interface.
+ * @throws GLException if this object is not a GL2 implementation
+ */
+ public GL2 getGL2() throws GLException;
+
+ /**
+ * Casts this object to the GLES1 interface.
+ * @throws GLException if this object is not a GLES1 implementation
+ */
+ public GLES1 getGLES1() throws GLException;
+
+ /**
+ * Casts this object to the GLES2 interface.
+ * @throws GLException if this object is not a GLES2 implementation
+ */
+ public GLES2 getGLES2() throws GLException;
+
+ /**
+ * Casts this object to the GLES3 interface.
+ * @throws GLException if this object is not a GLES3 implementation
+ */
+ public GLES3 getGLES3() throws GLException;
+
+ /**
+ * Casts this object to the GL2ES1 interface.
+ * @throws GLException if this object is not a GL2ES1 implementation
+ */
+ public GL2ES1 getGL2ES1() throws GLException;
+
+ /**
+ * Casts this object to the GL2ES2 interface.
+ * @throws GLException if this object is not a GL2ES2 implementation
+ */
+ public GL2ES2 getGL2ES2() throws GLException;
+
+ /**
+ * Casts this object to the GL2ES3 interface.
+ * @throws GLException if this object is not a GL2ES3 implementation
+ */
+ public GL2ES3 getGL2ES3() throws GLException;
+
+ /**
+ * Casts this object to the GL3ES3 interface.
+ * @throws GLException if this object is not a GL3ES3 implementation
+ */
+ public GL3ES3 getGL3ES3() throws GLException;
+
+ /**
+ * Casts this object to the GL4ES3 interface.
+ * @throws GLException if this object is not a GL4ES3 implementation
+ */
+ public GL4ES3 getGL4ES3() throws GLException;
+
+ /**
+ * Casts this object to the GL2GL3 interface.
+ * @throws GLException if this object is not a GL2GL3 implementation
+ */
+ public GL2GL3 getGL2GL3() throws GLException;
+
+ /**
+ * Returns the GLProfile associated with this GL object.
+ */
+ public GLProfile getGLProfile();
+
+ /**
+ * Returns the GLContext associated which this GL object.
+ */
+ public GLContext getContext();
+
+ /**
+ * Returns true if the specified OpenGL core- or extension-function can be
+ * used successfully through this GL instance given the current host (OpenGL
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.<P>
+ * By "successfully" we mean that the function is both <i>callable</i>
+ * on the machine running the program and <i>available</i> on the current
+ * display.<P>
+ *
+ * In order to call a function successfully, the function must be both
+ * <i>callable</i> on the machine running the program and <i>available</i> on
+ * the display device that is rendering the output (note: on non-networked,
+ * single-display machines these two conditions are identical; on networked and/or
+ * multi-display machines this becomes more complicated). These conditions are
+ * met if the function is either part of the core OpenGL version supported by
+ * both the host and display, or it is an OpenGL extension function that both
+ * the host and display support. <P>
+ *
+ * A GL function is <i>callable</i> if it is successfully linked at runtime,
+ * hence the GLContext must be made current at least once.
+ *
+ * @param glFunctionName the name of the OpenGL function (e.g., use
+ * "glBindRenderbufferEXT" or "glBindRenderbuffer" to check if {@link
+ * GL#glBindRenderbuffer(int,int)} is available).
+ */
+ public boolean isFunctionAvailable(String glFunctionName);
+
+ /**
+ * Returns true if the specified OpenGL extension can be
+ * used successfully through this GL instance given the current host (OpenGL
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.<P>
+ *
+ * @param glExtensionName the name of the OpenGL extension (e.g.,
+ * "GL_ARB_vertex_program").
+ */
+ public boolean isExtensionAvailable(String glExtensionName);
+
+ /**
+ * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
+ * <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
+ * </p>
+ * <p>
+ * Basic FBO support may only include one color attachment and no multisampling,
+ * as well as limited internal formats for renderbuffer.
+ * </p>
+ * @see GLContext#hasBasicFBOSupport()
+ */
+ public boolean hasBasicFBOSupport();
+
+ /**
+ * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Full FBO is supported if the context is either GL >= core 3.0 [ES, core, compat] or implements the extensions
+ * <code>ARB_framebuffer_object</code>, or all of
+ * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
+ * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+ * </p>
+ * <p>
+ * Full FBO support includes multiple color attachments and multisampling.
+ * </p>
+ * @see GLContext#hasFullFBOSupport()
+ */
+ public boolean hasFullFBOSupport();
+
+ /**
+ * Returns the maximum number of FBO RENDERBUFFER samples
+ * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
+ * @see GLContext#getMaxRenderbufferSamples()
+ */
+ public int getMaxRenderbufferSamples();
+
+ /**
+ * Returns true if the GL context supports non power of two (NPOT) textures,
+ * otherwise false.
+ * <p>
+ * NPOT textures are supported in OpenGL >= 3, GLES2 or if the
+ * 'GL_ARB_texture_non_power_of_two' extension is available.
+ * </p>
+ */
+ public boolean isNPOTTextureAvailable();
+
+ public boolean isTextureFormatBGRA8888Available();
+
+ /** Provides a platform-independent way to specify the minimum swap
+ interval for buffer swaps. An argument of 0 disables
+ sync-to-vertical-refresh completely, while an argument of 1
+ causes the application to wait until the next vertical refresh
+ until swapping buffers. The default, which is platform-specific,
+ is usually either 0 or 1. This function is not guaranteed to
+ have an effect, and in particular only affects heavyweight
+ onscreen components.
+
+ @see #getSwapInterval
+ @throws GLException if this context is not the current
+ */
+ public void setSwapInterval(int interval);
+
+ /** Provides a platform-independent way to get the swap
+ interval set by {@link #setSwapInterval}. <br>
+
+ If the interval is not set by {@link #setSwapInterval} yet,
+ -1 is returned, indicating that the platforms default
+ is being used.
+
+ @see #setSwapInterval
+ */
+ public int getSwapInterval();
+
+ /**
+ * Returns an object through which platform-specific OpenGL extensions
+ * (EGL, GLX, WGL, etc.) may be accessed. The data type of the returned
+ * object and its associated capabilities are undefined. Most
+ * applications will never need to call this method. It is highly
+ * recommended that any applications which do call this method perform
+ * all accesses on the returned object reflectively to guard
+ * themselves against changes to the implementation.
+ */
+ public Object getPlatformGLExtensions();
+
+ /**
+ * Returns an object providing access to the specified OpenGL
+ * extension. This is intended to provide a mechanism for vendors who
+ * wish to provide access to new OpenGL extensions without changing
+ * the public API of the core package. For example, a user may request
+ * access to extension "GL_VENDOR_foo" and receive back an object
+ * which implements a vendor-specified interface which can call the
+ * OpenGL extension functions corresponding to that extension. It is
+ * up to the vendor to specify both the extension name and Java API
+ * for accessing it, including which class or interface contains the
+ * functions.
+ *
+ * <P>
+ *
+ * Note: it is the intent to add new extensions as quickly as possible
+ * to the core GL API. Therefore it is unlikely that most vendors will
+ * use this extension mechanism, but it is being provided for
+ * completeness.
+ */
+ public Object getExtension(String extensionName);
+
+ /** Aliased entrypoint of <code> void {@native glClearDepth}(GLclampd depth); </code> and <code> void {@native glClearDepthf}(GLclampf depth); </code>. */
+ public void glClearDepth( double depth );
+
+ /** Aliased entrypoint of <code> void {@native glDepthRange}(GLclampd depth); </code> and <code> void {@native glDepthRangef}(GLclampf depth); </code>. */
+ public void glDepthRange(double zNear, double zFar);
+
+ /**
+ * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, ..
+ * @return the GL buffer name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ * @see #getBufferStorage(int)
+ */
+ public int getBoundBuffer(int target);
+
+ /**
+ * @param bufferName a GL buffer name, generated with e.g. {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)}.
+ * @return the size of the given GL buffer storage, see {@link GLBufferStorage}
+ * @see #getBoundBuffer(int)
+ */
+ public GLBufferStorage getBufferStorage(int bufferName);
+
+ /**
+ * Returns the {@link GLBufferStorage} instance as mapped via OpenGL's native {@link GL#glMapBuffer(int, int) glMapBuffer(..)} implementation.
+ * <p>
+ * Throws a {@link GLException} if GL-function constraints are not met.
+ * </p>
+ * <p>
+ * {@link GL#glMapBuffer(int, int)} wrapper calls this method and returns {@link GLBufferStorage#getMappedBuffer()}.
+ * </p>
+ * <p>
+ * A zero {@link GLBufferStorage#getSize()} will avoid a native call and returns the unmapped {@link GLBufferStorage}.
+ * </p>
+ * <p>
+ * A null native mapping result indicating an error will
+ * not cause a GLException but returns the unmapped {@link GLBufferStorage}.
+ * This allows the user to handle this case.
+ * </p>
+ * @param target denotes the buffer via it's bound target
+ * @param access the mapping access mode
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ */
+ public GLBufferStorage mapBuffer(int target, int access) throws GLException;
+
+ /**
+ * Returns the {@link GLBufferStorage} instance as mapped via OpenGL's native {@link GL#glMapBufferRange(int, long, long, int) glMapBufferRange(..)} implementation.
+ * <p>
+ * Throws a {@link GLException} if GL-function constraints are not met.
+ * </p>
+ * <p>
+ * {@link GL#glMapBufferRange(int, long, long, int)} wrapper calls this method and returns {@link GLBufferStorage#getMappedBuffer()}.
+ * </p>
+ * <p>
+ * A zero {@link GLBufferStorage#getSize()} will avoid a native call and returns the unmapped {@link GLBufferStorage}.
+ * </p>
+ * <p>
+ * A null native mapping result indicating an error will
+ * not cause a GLException but returns the unmapped {@link GLBufferStorage}.
+ * This allows the user to handle this case.
+ * </p>
+ * @param target denotes the buffer via it's bound target
+ * @param offset offset of the mapped buffer's storage
+ * @param length length of the mapped buffer's storage
+ * @param access the mapping access mode
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ * @throws GLException if buffer mapping range does not fit, incl. offset
+ */
+ public GLBufferStorage mapBufferRange(final int target, final long offset, final long length, final int access) throws GLException;
+
+ /**
+ * @return true if a VBO is bound to {@link GL#GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean isVBOArrayBound();
+
+ /**
+ * @return true if a VBO is bound to {@link GL#GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean isVBOElementArrayBound();
+
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ * <p>
+ * Calls {@link GLContext#getBoundFramebuffer(int)}.
+ * </p>
+ */
+ public int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ * </p>
+ * <p>
+ * Calls {@link GLContext#getDefaultDrawFramebuffer()}.
+ * </p>
+ */
+ public int getDefaultDrawFramebuffer();
+
+ /**
+ * Return the default read framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ * </p>
+ * <p>
+ * Calls {@link GLContext#getDefaultReadFramebuffer()}.
+ * </p>
+ */
+ public int getDefaultReadFramebuffer();
+
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
+ * <p>
+ * Calls {@link GLContext#getDefaultReadBuffer()}.
+ * </p>
+ */
+ public int getDefaultReadBuffer();
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/GLBufferStorage.java b/src/jogl/classes/com/jogamp/opengl/GLBufferStorage.java
new file mode 100644
index 000000000..5db97d42f
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLBufferStorage.java
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+/**
+ * OpenGL buffer storage object reflecting it's
+ * <ul>
+ * <li>storage size</li>
+ * <li>storage memory if mapped</li>
+ * <li>mutable usage or immutable flags</li>
+ * </ul>
+ * <p>
+ * Buffer storage is created via:
+ * <ul>
+ * <li><code>glBufferStorage</code> - storage creation with target</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation with target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * </ul>
+ * Note that storage <i>recreation</i> as mentioned above also invalidate a previous storage instance,
+ * i.e. disposed the buffer's current storage if exist and attaches a new storage instance.
+ * </p>
+ * <p>
+ * Buffer storage is disposed via:
+ * <ul>
+ * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - explicit, direct, via {@link #notifyBuffersDeleted(int, IntBuffer)} or {@link #notifyBuffersDeleted(int, int[], int)}</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * </ul>
+ * </p>
+ * <p>
+ * GL buffer storage is mapped via
+ * <ul>
+ *
+ * <li>{@link GL#mapBuffer(int, int)}</li>
+ * <li>{@link GL#mapBufferRange(int, long, long, int)}</li>
+ * <li>{@link GL2#mapNamedBuffer(int, int)}</li>
+ * <li>{@link GL2#mapNamedBufferRange(int, long, long, int)}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * GL buffer storage is unmapped via
+ * <ul>
+ * <li>{@link GL#glUnmapBuffer(int)} - explicit via target</li>
+ * <li>{@link GL2#glUnmapNamedBufferEXT(int)} - explicit direct</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - buffer deletion</li>
+ * </ul>
+ * </p>
+ */
+public abstract class GLBufferStorage {
+ private final int name;
+ private /* final */ long size;
+ private /* final */ int mutableUsage;
+ private /* final */ int immutableFlags;
+ private ByteBuffer mappedBuffer;
+
+ protected GLBufferStorage(final int name, final long size, final int mutableUsage, final int immutableFlags) {
+ this.name = name;
+ this.size = size;
+ this.mutableUsage = mutableUsage;
+ this.immutableFlags = immutableFlags;
+ this.mappedBuffer = null;
+ }
+
+ protected void reset(final long size, final int mutableUsage, final int immutableFlags) {
+ this.size = size;
+ this.mutableUsage = mutableUsage;
+ this.immutableFlags = immutableFlags;
+ this.mappedBuffer = null;
+ }
+ protected void setMappedBuffer(final ByteBuffer buffer) {
+ this.mappedBuffer = buffer;
+ }
+
+ /** Return the buffer name */
+ public final int getName() { return name; }
+
+ /** Return the buffer's storage size. */
+ public final long getSize() { return size; }
+
+ /**
+ * Returns <code>true</code> if buffer's storage is mutable, i.e.
+ * created via {@link GL#glBufferData(int, long, java.nio.Buffer, int)}.
+ * <p>
+ * Returns <code>false</code> if buffer's storage is immutable, i.e.
+ * created via <code>glBufferStorage</code>. FIXME: Add GL 4.4 support!
+ * </p>
+ * @return
+ */
+ public final boolean isMutableStorage() { return 0 != mutableUsage; }
+
+ /**
+ * Returns the mutable storage usage or 0 if storage is not {@link #isMutableStorage() mutable}.
+ */
+ public final int getMutableUsage() { return mutableUsage; }
+
+ /**
+ * Returns the immutable storage flags, invalid if storage is {@link #isMutableStorage() mutable}.
+ */
+ public final int getImmutableFlags() { return immutableFlags; }
+
+ /**
+ * Returns the mapped ByteBuffer, or null if not mapped.
+ * Mapping may occur via:
+ * <ul>
+ * <li>{@link GL#glMapBuffer(int, int)}</li>
+ * <li>{@link GL#glMapBufferRange(int, long, long, int)}</li>
+ * <li>{@link GL2#glMapNamedBufferEXT(int, int)}</li>
+ * <li>{@link GL2#glMapNamedBufferRangeEXT(int, long, long, int)}
+ * </ul>
+ */
+ public final ByteBuffer getMappedBuffer() { return mappedBuffer; }
+
+ public final String toString() {
+ return toString(false);
+ }
+ public final String toString(final boolean skipMappedBuffer) {
+ final String s0;
+ if( isMutableStorage() ) {
+ s0 = String.format("%s[name %s, size %d, mutable usage 0x%X", msgClazzName, name, size, mutableUsage);
+ } else {
+ s0 = String.format("%s[name %s, size %d, immutable flags 0x%X", msgClazzName, name, size, immutableFlags);
+ }
+ if(skipMappedBuffer) {
+ return s0+"]";
+ } else {
+ return s0+", mapped "+mappedBuffer+"]";
+ }
+ }
+ private static final String msgClazzName = "GLBufferStorage";
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLCapabilities.java b/src/jogl/classes/com/jogamp/opengl/GLCapabilities.java
new file mode 100644
index 000000000..02aa47119
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLCapabilities.java
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.nativewindow.Capabilities;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+
+/** Specifies a set of OpenGL capabilities.<br>
+ At creation time of a {@link GLDrawable} using {@link GLDrawableFactory},
+ an instance of this class is passed,
+ describing the desired capabilities that a rendering context
+ must support, such as the OpenGL profile, color depth and whether stereo is enabled.<br>
+
+ The actual capabilites of created {@link GLDrawable}s are then reflected by their own
+ GLCapabilites instance, which can be queried with {@link GLDrawable#getChosenGLCapabilities()}.
+ <br>
+
+ It currently contains the minimal number of routines which allow
+ configuration on all supported window systems. */
+public class GLCapabilities extends Capabilities implements Cloneable, GLCapabilitiesImmutable {
+ private GLProfile glProfile = null;
+ private boolean isPBuffer = false;
+ private boolean isFBO = false;
+ private boolean doubleBuffered = true;
+ private boolean stereo = false;
+ private boolean hardwareAccelerated = true;
+ private int depthBits = 16;
+ private int stencilBits = 0;
+ private int accumRedBits = 0;
+ private int accumGreenBits = 0;
+ private int accumBlueBits = 0;
+ private int accumAlphaBits = 0;
+ // Shift bits from PIXELFORMATDESCRIPTOR not present because they
+ // are unlikely to be supported on Windows anyway
+
+ // Support for full-scene antialiasing (FSAA)
+ private String sampleExtension = DEFAULT_SAMPLE_EXTENSION;
+ private boolean sampleBuffers = false;
+ private int numSamples = 2;
+
+ /** Creates a GLCapabilities object. All attributes are in a default state.
+ * @param glp GLProfile, or null for the default GLProfile
+ * @throws GLException if no profile is given and no default profile is available for the default device.
+ */
+ public GLCapabilities(final GLProfile glp) throws GLException {
+ glProfile = (null!=glp)?glp:GLProfile.getDefault(GLProfile.getDefaultDevice());
+ }
+
+ @Override
+ public Object cloneMutable() {
+ return clone();
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final RuntimeException e) {
+ throw new GLException(e);
+ }
+ }
+
+ /**
+ * Copies all {@link GLCapabilitiesImmutable} values
+ * from <code>source</code> into this instance.
+ * @return this instance
+ */
+ public GLCapabilities copyFrom(final GLCapabilitiesImmutable source) {
+ super.copyFrom(source);
+ glProfile = source.getGLProfile();
+ isPBuffer = source.isPBuffer();
+ isFBO = source.isFBO();
+ doubleBuffered = source.getDoubleBuffered();
+ stereo = source.getStereo();
+ hardwareAccelerated = source.getHardwareAccelerated();
+ depthBits = source.getDepthBits();
+ stencilBits = source.getStencilBits();
+ accumRedBits = source.getAccumRedBits();
+ accumGreenBits = source.getAccumGreenBits();
+ accumBlueBits = source.getAccumBlueBits();
+ accumAlphaBits = source.getAccumAlphaBits();
+ sampleBuffers = source.getSampleBuffers();
+ numSamples = source.getNumSamples();
+ sampleExtension = source.getSampleExtension();
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = super.hashCode();
+ hash = ((hash << 5) - hash) + this.glProfile.hashCode() ;
+ hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isFBO ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isPBuffer ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.sampleBuffers ? 1 : 0 );
+ hash = ((hash << 5) - hash) + this.getNumSamples();
+ hash = ((hash << 5) - hash) + this.sampleExtension.hashCode();
+ hash = ((hash << 5) - hash) + this.depthBits;
+ hash = ((hash << 5) - hash) + this.stencilBits;
+ hash = ((hash << 5) - hash) + this.accumRedBits;
+ hash = ((hash << 5) - hash) + this.accumGreenBits;
+ hash = ((hash << 5) - hash) + this.accumBlueBits;
+ hash = ((hash << 5) - hash) + this.accumAlphaBits;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if(!(obj instanceof GLCapabilitiesImmutable)) {
+ return false;
+ }
+ final GLCapabilitiesImmutable other = (GLCapabilitiesImmutable)obj;
+ boolean res = super.equals(obj) &&
+ other.getGLProfile()==glProfile &&
+ other.isPBuffer()==isPBuffer &&
+ other.isFBO()==isFBO &&
+ other.getDoubleBuffered() == doubleBuffered &&
+ other.getStereo()==stereo &&
+ other.getHardwareAccelerated()==hardwareAccelerated &&
+ other.getDepthBits()==depthBits &&
+ other.getStencilBits()==stencilBits &&
+ other.getAccumRedBits()==accumRedBits &&
+ other.getAccumGreenBits()==accumGreenBits &&
+ other.getAccumBlueBits()==accumBlueBits &&
+ other.getAccumAlphaBits()==accumAlphaBits &&
+ other.getSampleBuffers()==sampleBuffers;
+ if(res && sampleBuffers) {
+ res = other.getNumSamples()==getNumSamples() &&
+ other.getSampleExtension().equals(sampleExtension) ;
+ }
+ return res;
+ }
+
+ /** comparing hw/sw, stereo, multisample, stencil, RGBA and depth only */
+ @Override
+ public int compareTo(final CapabilitiesImmutable o) {
+ if ( ! ( o instanceof GLCapabilitiesImmutable ) ) {
+ final Class<?> c = (null != o) ? o.getClass() : null ;
+ throw new ClassCastException("Not a GLCapabilitiesImmutable object, but " + c);
+ }
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) o;
+
+ if(hardwareAccelerated && !caps.getHardwareAccelerated()) {
+ return 1;
+ } else if(!hardwareAccelerated && caps.getHardwareAccelerated()) {
+ return -1;
+ }
+
+ if(stereo && !caps.getStereo()) {
+ return 1;
+ } else if(!stereo && caps.getStereo()) {
+ return -1;
+ }
+
+ if(doubleBuffered && !caps.getDoubleBuffered()) {
+ return 1;
+ } else if(!doubleBuffered && caps.getDoubleBuffered()) {
+ return -1;
+ }
+
+ final int ms = getNumSamples();
+ final int xms = caps.getNumSamples() ;
+
+ if(ms > xms) {
+ return 1;
+ } else if( ms < xms ) {
+ return -1;
+ }
+ // ignore the sample extension
+
+ if(stencilBits > caps.getStencilBits()) {
+ return 1;
+ } else if(stencilBits < caps.getStencilBits()) {
+ return -1;
+ }
+
+ final int sc = super.compareTo(caps); // RGBA
+ if(0 != sc) {
+ return sc;
+ }
+
+ if(depthBits > caps.getDepthBits()) {
+ return 1;
+ } else if(depthBits < caps.getDepthBits()) {
+ return -1;
+ }
+
+ return 0; // they are equal: hw/sw, stereo, multisample, stencil, RGBA and depth
+ }
+
+ @Override
+ public final GLProfile getGLProfile() {
+ return glProfile;
+ }
+
+ /** Sets the GL profile you desire */
+ public void setGLProfile(final GLProfile profile) {
+ glProfile=profile;
+ }
+
+ @Override
+ public final boolean isPBuffer() {
+ return isPBuffer;
+ }
+
+ /**
+ * Requesting offscreen pbuffer mode.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(boolean) setOnscreen(false)}.
+ * </p>
+ * <p>
+ * Defaults to false.
+ * </p>
+ * <p>
+ * Requesting offscreen pbuffer mode disables the offscreen auto selection.
+ * </p>
+ */
+ public void setPBuffer(final boolean enable) {
+ if(enable) {
+ setOnscreen(false);
+ }
+ isPBuffer = enable;
+ }
+
+ @Override
+ public final boolean isFBO() {
+ return isFBO;
+ }
+
+ /**
+ * Requesting offscreen FBO mode.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(boolean) setOnscreen(false)}.
+ * </p>
+ * <p>
+ * Defaults to false.
+ * </p>
+ * <p>
+ * Requesting offscreen FBO mode disables the offscreen auto selection.
+ * </p>
+ */
+ public void setFBO(final boolean enable) {
+ if(enable) {
+ setOnscreen(false);
+ }
+ isFBO = enable;
+ }
+
+ @Override
+ public final boolean getDoubleBuffered() {
+ return doubleBuffered;
+ }
+
+ /** Enables or disables double buffering. */
+ public void setDoubleBuffered(final boolean enable) {
+ doubleBuffered = enable;
+ }
+
+ @Override
+ public final boolean getStereo() {
+ return stereo;
+ }
+
+ /** Enables or disables stereo viewing. */
+ public void setStereo(final boolean enable) {
+ stereo = enable;
+ }
+
+ @Override
+ public final boolean getHardwareAccelerated() {
+ return hardwareAccelerated;
+ }
+
+ /** Enables or disables hardware acceleration. */
+ public void setHardwareAccelerated(final boolean enable) {
+ hardwareAccelerated = enable;
+ }
+
+ @Override
+ public final int getDepthBits() {
+ return depthBits;
+ }
+
+ /** Sets the number of bits requested for the depth buffer. */
+ public void setDepthBits(final int depthBits) {
+ this.depthBits = depthBits;
+ }
+
+ @Override
+ public final int getStencilBits() {
+ return stencilBits;
+ }
+
+ /** Sets the number of bits requested for the stencil buffer. */
+ public void setStencilBits(final int stencilBits) {
+ this.stencilBits = stencilBits;
+ }
+
+ @Override
+ public final int getAccumRedBits() {
+ return accumRedBits;
+ }
+
+ /** Sets the number of bits requested for the accumulation buffer's
+ red component. On some systems only the accumulation buffer
+ depth, which is the sum of the red, green, and blue bits, is
+ considered. */
+ public void setAccumRedBits(final int accumRedBits) {
+ this.accumRedBits = accumRedBits;
+ }
+
+ @Override
+ public final int getAccumGreenBits() {
+ return accumGreenBits;
+ }
+
+ /** Sets the number of bits requested for the accumulation buffer's
+ green component. On some systems only the accumulation buffer
+ depth, which is the sum of the red, green, and blue bits, is
+ considered. */
+ public void setAccumGreenBits(final int accumGreenBits) {
+ this.accumGreenBits = accumGreenBits;
+ }
+
+ @Override
+ public final int getAccumBlueBits() {
+ return accumBlueBits;
+ }
+
+ /** Sets the number of bits requested for the accumulation buffer's
+ blue component. On some systems only the accumulation buffer
+ depth, which is the sum of the red, green, and blue bits, is
+ considered. */
+ public void setAccumBlueBits(final int accumBlueBits) {
+ this.accumBlueBits = accumBlueBits;
+ }
+
+ @Override
+ public final int getAccumAlphaBits() {
+ return accumAlphaBits;
+ }
+
+ /** Sets number of bits requested for accumulation buffer's alpha
+ component. On some systems only the accumulation buffer depth,
+ which is the sum of the red, green, and blue bits, is
+ considered. */
+ public void setAccumAlphaBits(final int accumAlphaBits) {
+ this.accumAlphaBits = accumAlphaBits;
+ }
+
+ /**
+ * Sets the desired extension for full-scene antialiasing
+ * (FSAA), default is {@link #DEFAULT_SAMPLE_EXTENSION}.
+ */
+ public void setSampleExtension(final String se) {
+ sampleExtension = se;
+ }
+
+ @Override
+ public final String getSampleExtension() {
+ return sampleExtension;
+ }
+
+ /**
+ * Defaults to false.<br>
+ * Indicates whether sample buffers for full-scene antialiasing
+ * (FSAA) should be allocated for this drawable.<br>
+ * Mind that this requires the alpha component.<br>
+ * If enabled this method also invokes {@link #setAlphaBits(int) setAlphaBits(1)}
+ * if {@link #getAlphaBits()} == 0.<br>
+ */
+ public void setSampleBuffers(final boolean enable) {
+ sampleBuffers = enable;
+ if(sampleBuffers && getAlphaBits()==0) {
+ setAlphaBits(1);
+ }
+ }
+
+ @Override
+ public final boolean getSampleBuffers() {
+ return sampleBuffers;
+ }
+
+ /**
+ * If sample buffers are enabled, indicates the number of buffers
+ * to be allocated. Defaults to 2.
+ * @see #getNumSamples()
+ */
+ public void setNumSamples(final int numSamples) {
+ this.numSamples = numSamples;
+ }
+
+ @Override
+ public final int getNumSamples() {
+ return sampleBuffers ? numSamples : 0;
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder sink) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+
+ final int samples = sampleBuffers ? numSamples : 0 ;
+
+ super.toString(sink, false);
+
+ sink.append(", accum-rgba ").append(accumRedBits).append(ESEP).append(accumGreenBits).append(ESEP).append(accumBlueBits).append(ESEP).append(accumAlphaBits);
+ sink.append(", dp/st/ms ").append(depthBits).append(ESEP).append(stencilBits).append(ESEP).append(samples);
+ if(samples>0) {
+ sink.append(", sample-ext ").append(sampleExtension);
+ }
+ if(doubleBuffered) {
+ sink.append(", dbl");
+ } else {
+ sink.append(", one");
+ }
+ if(stereo) {
+ sink.append(", stereo");
+ } else {
+ sink.append(", mono ");
+ }
+ if(hardwareAccelerated) {
+ sink.append(", hw, ");
+ } else {
+ sink.append(", sw, ");
+ }
+ sink.append(glProfile);
+ if(isOnscreen()) {
+ sink.append(", on-scr[");
+ } else {
+ sink.append(", offscr[");
+ }
+ boolean ns=false;
+ if(isFBO()) {
+ sink.append("fbo");
+ ns = true;
+ }
+ if(isPBuffer()) {
+ if(ns) { sink.append(CSEP); }
+ sink.append("pbuffer");
+ ns = true;
+ }
+ if(isBitmap()) {
+ if(ns) { sink.append(CSEP); }
+ sink.append("bitmap");
+ ns = true;
+ }
+ if(!ns) { // !FBO !PBuffer !Bitmap
+ if(isOnscreen()) {
+ sink.append("."); // no additional off-screen modes besides on-screen
+ } else {
+ sink.append("auto-cfg"); // auto-config off-screen mode
+ }
+ }
+ sink.append("]");
+
+ return sink;
+ }
+
+ /** Returns a textual representation of this GLCapabilities
+ object. */
+ @Override
+ public String toString() {
+ final StringBuilder msg = new StringBuilder();
+ msg.append("GLCaps[");
+ toString(msg);
+ msg.append("]");
+ return msg.toString();
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLCapabilitiesChooser.java b/src/jogl/classes/com/jogamp/opengl/GLCapabilitiesChooser.java
new file mode 100644
index 000000000..9911d1314
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLCapabilitiesChooser.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import java.util.List;
+
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.nativewindow.CapabilitiesChooser;
+
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+
+/** Provides a mechanism by which applications can customize the
+ window type selection for a given {@link GLCapabilities}.
+ Developers can implement this interface and pass an instance into
+ the appropriate method of {@link GLDrawableFactory}; the chooser
+ will be called during the OpenGL context creation process. Note
+ that this is only a marker interface; its signature is the same as
+ {@link CapabilitiesChooser} and the {@link List} of
+ objects extending {@link CapabilitiesImmutable}
+ passed to {@link #chooseCapabilities chooseCapabilities}
+ is actually a {@link List} of type {@link GLCapabilitiesImmutable}. */
+
+public interface GLCapabilitiesChooser extends CapabilitiesChooser {
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/com/jogamp/opengl/GLCapabilitiesImmutable.java
new file mode 100644
index 000000000..25081a521
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLCapabilitiesImmutable.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+
+/**
+ * Specifies an immutable set of OpenGL capabilities.<br>
+ *
+ * @see com.jogamp.opengl.GLCapabilities
+ * @see com.jogamp.nativewindow.CapabilitiesImmutable
+ */
+public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
+ /**
+ * One of the platform's default sample extension
+ * <code>EGL.EGL_SAMPLES, GLX.GLX_SAMPLES, WGLExt.WGL_SAMPLES_ARB</code>
+ * if available, or any other <i>known</i> fallback one, ie <code>EGLExt.EGL_COVERAGE_SAMPLES_NV</code>
+ */
+ public static final String DEFAULT_SAMPLE_EXTENSION = "default" ;
+
+ /**
+ * Returns the GL profile you desire or used by the drawable.
+ */
+ GLProfile getGLProfile();
+
+ /**
+ * Returns the number of bits for the accumulation
+ * buffer's alpha component. On some systems only the accumulation
+ * buffer depth, which is the sum of the red, green, and blue bits,
+ * is considered.
+ */
+ int getAccumAlphaBits();
+
+ /**
+ * Returns the number of bits for the accumulation
+ * buffer's blue component. On some systems only the accumulation
+ * buffer depth, which is the sum of the red, green, and blue bits,
+ * is considered.
+ */
+ int getAccumBlueBits();
+
+ /**
+ * Returns the number of bits for the accumulation
+ * buffer's green component. On some systems only the accumulation
+ * buffer depth, which is the sum of the red, green, and blue bits,
+ * is considered.
+ */
+ int getAccumGreenBits();
+
+ /**
+ * Returns the number of bits for the accumulation
+ * buffer's red component. On some systems only the accumulation
+ * buffer depth, which is the sum of the red, green, and blue bits,
+ * is considered.
+ */
+ int getAccumRedBits();
+
+ /**
+ * Returns the number of depth buffer bits.
+ */
+ int getDepthBits();
+
+ /**
+ * Returns whether double-buffering is requested, available or chosen.
+ * <p>
+ * Default is true.
+ * </p>
+ */
+ boolean getDoubleBuffered();
+
+ /**
+ * Returns whether hardware acceleration is requested, available or chosen.
+ * <p>
+ * Default is true.
+ * </p>
+ */
+ boolean getHardwareAccelerated();
+
+ /**
+ * Returns the extension for full-scene antialiasing
+ * (FSAA).
+ * <p>
+ * Default is {@link #DEFAULT_SAMPLE_EXTENSION}.
+ * </p>
+ */
+ String getSampleExtension();
+
+ /**
+ * Returns whether sample buffers for full-scene antialiasing
+ * (FSAA) should be allocated for this drawable.
+ * <p>
+ * Default is false.
+ * </p>
+ */
+ boolean getSampleBuffers();
+
+ /**
+ * Returns the number of sample buffers to be allocated if sample
+ * buffers are enabled, otherwise returns 0.
+ * <p>
+ * Default is 0 due to disable sample buffers per default.
+ * </p>
+ */
+ int getNumSamples();
+
+ /**
+ * Returns the number of stencil buffer bits.
+ * <p>
+ * Default is 0.
+ * </p>
+ */
+ int getStencilBits();
+
+ /**
+ * Returns whether stereo is requested, available or chosen.
+ * <p>
+ * Default is false.
+ * </p>
+ */
+ boolean getStereo();
+
+ /**
+ * Returns whether pbuffer offscreen mode is requested, available or chosen.
+ * <p>
+ * Default is false.
+ * </p>
+ * <p>
+ * For chosen capabilities, only the selected offscreen surface is set to <code>true</code>.
+ * </p>
+ */
+ boolean isPBuffer();
+
+ /**
+ * Returns whether FBO offscreen mode is requested, available or chosen.
+ * <p>
+ * Default is false.
+ * </p>
+ * <p>
+ * For chosen capabilities, only the selected offscreen surface is set to <code>true</code>.
+ * </p>
+ */
+ boolean isFBO();
+
+ @Override
+ boolean equals(Object obj);
+
+ @Override
+ int hashCode();
+
+ @Override
+ String toString();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLContext.java b/src/jogl/classes/com/jogamp/opengl/GLContext.java
new file mode 100644
index 000000000..6366c4e37
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLContext.java
@@ -0,0 +1,2038 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import java.nio.IntBuffer;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeSurface;
+
+import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLContextShareSet;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
+
+/** Abstraction for an OpenGL rendering context. In order to perform
+ OpenGL rendering, a context must be "made current" on the current
+ thread. OpenGL rendering semantics specify that only one context
+ may be current on the current thread at any given time, and also
+ that a given context may be current on only one thread at any
+ given time. Because components can be added to and removed from
+ the component hierarchy at any time, it is possible that the
+ underlying OpenGL context may need to be destroyed and recreated
+ multiple times over the lifetime of a given component. This
+ process is handled by the implementation, and the GLContext
+ abstraction provides a stable object which clients can use to
+ refer to a given context. */
+public abstract class GLContext {
+
+ public static final boolean DEBUG = Debug.debug("GLContext");
+ public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
+ public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;
+
+ /**
+ * If <code>true</code> (default), bootstrapping the available GL profiles
+ * will use the highest compatible GL context for each profile,
+ * hence skipping querying lower profiles if a compatible higher one is found:
+ * <ul>
+ * <li>4.2-core -> 4.2-core, 3.3-core</li>
+ * <li>4.2-comp -> 4.2-comp, 3.3-comp, 2</li>
+ * </ul>
+ * Otherwise the dedicated GL context would be queried and used:
+ * <ul>
+ * <li>4.2-core -> 4.2-core</li>
+ * <li>3.3-core -> 3.3-core</li>
+ * <li>4.2-comp -> 4.2-comp</li>
+ * <li>3.3-comp -> 3.3-comp</li>
+ * <li>3.0-comp -> 2</li>
+ * </ul>
+ * Using aliasing speeds up initialization about:
+ * <ul>
+ * <li>Linux x86_64 - Nvidia: 28%, 700ms down to 500ms</li>
+ * <li>Linux x86_64 - AMD : 40%, 1500ms down to 900ms</li>
+ * <p>
+ * Can be turned off with property <code>jogl.debug.GLContext.NoProfileAliasing</code>.
+ * </p>
+ */
+ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true);
+
+ protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true);
+ protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true);
+ protected static final boolean FORCE_NO_COLOR_RENDERBUFFER = Debug.isPropertyDefined("jogl.fbo.force.nocolorrenderbuffer", true);
+
+ /** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
+ public static final boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
+ /** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */
+ public static final boolean TRACE_GL = Debug.isPropertyDefined("jogl.debug.TraceGL", true);
+
+ /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
+ public static final int CONTEXT_NOT_CURRENT = 0;
+ /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
+ public static final int CONTEXT_CURRENT = 1;
+ /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
+ public static final int CONTEXT_CURRENT_NEW = 2;
+
+ /** Version 1.00, i.e. GLSL 1.00 for ES 2.0. */
+ public static final VersionNumber Version1_0 = new VersionNumber(1, 0, 0);
+ /** Version 1.10, i.e. GLSL 1.10 for GL 2.0. */
+ public static final VersionNumber Version1_10 = new VersionNumber(1, 10, 0);
+ /** Version 1.20, i.e. GLSL 1.20 for GL 2.1. */
+ public static final VersionNumber Version1_20 = new VersionNumber(1, 20, 0);
+ /** Version 1.30, i.e. GLSL 1.30 for GL 3.0. */
+ public static final VersionNumber Version1_30 = new VersionNumber(1, 30, 0);
+ /** Version 1.40, i.e. GLSL 1.40 for GL 3.1. */
+ public static final VersionNumber Version1_40 = new VersionNumber(1, 40, 0);
+ /** Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
+ public static final VersionNumber Version1_50 = new VersionNumber(1, 50, 0);
+
+ /** Version 1.1, i.e. GL 1.1 */
+ public static final VersionNumber Version1_1 = new VersionNumber(1, 1, 0);
+
+ /** Version 1.2, i.e. GL 1.2 */
+ public static final VersionNumber Version1_2 = new VersionNumber(1, 2, 0);
+
+ /** Version 1.4, i.e. GL 1.4 */
+ public static final VersionNumber Version1_4 = new VersionNumber(1, 4, 0);
+
+ /** Version 1.5, i.e. GL 1.5 */
+ public static final VersionNumber Version1_5 = new VersionNumber(1, 5, 0);
+
+ /** Version 3.0. As an OpenGL version, it qualifies for desktop {@link #isGL2()} only, or ES 3.0. Or GLSL 3.00 for ES 3.0. */
+ public static final VersionNumber Version3_0 = new VersionNumber(3, 0, 0);
+
+ /** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
+ public static final VersionNumber Version3_1 = new VersionNumber(3, 1, 0);
+
+ /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
+ public static final VersionNumber Version3_2 = new VersionNumber(3, 2, 0);
+
+ /** Version 4.3. As an OpenGL version, it qualifies for <code>GL_ARB_ES3_compatibility</code> */
+ public static final VersionNumber Version4_3 = new VersionNumber(4, 3, 0);
+
+ protected static final VersionNumber Version8_0 = new VersionNumber(8, 0, 0);
+
+ private static final String S_EMPTY = "";
+
+ //
+ // Cached keys, bits [0..15]
+ //
+
+ /** Context option bits, full bit mask covering 16 bits [0..15], i.e. <code>0x0000FFFF</code>, {@value}. */
+ protected static final int CTX_IMPL_FULL_MASK = 0x0000FFFF;
+
+ /** Context option bits, cached bit mask covering 10 bits [0..9], i.e. <code>0x000003FF</code>, {@value}. Leaving 6 bits for non cached options, i.e. 10:6. */
+ protected static final int CTX_IMPL_CACHE_MASK = 0x000003FF;
+
+ /** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IS_ARB_CREATED = 1 << 0;
+ /** <code>ARB_create_context</code> related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_PROFILE_COMPAT = 1 << 1;
+ /** <code>ARB_create_context</code> related: desktop core profile. Cache key value. See {@link #isGLCoreProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_PROFILE_CORE = 1 << 2;
+ /** <code>ARB_create_context</code> related: ES profile. Cache key value. See {@link #isGLES()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_PROFILE_ES = 1 << 3;
+ /** <code>ARB_create_context</code> related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_OPTION_FORWARD = 1 << 4;
+ /** <code>ARB_create_context</code> related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ public static final int CTX_OPTION_DEBUG = 1 << 5;
+ /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 6;
+
+ //
+ // Non cached keys, 6 bits [10..15]
+ //
+
+ /** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 10;
+
+ /** <code>GL_ARB_ES3_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES3Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ES3_COMPAT = 1 << 11;
+
+ /**
+ * Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
+ * Not a cache key.
+ * @see #hasBasicFBOSupport()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FBO = 1 << 12;
+
+ /**
+ * Context supports <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points,
+ * see {@link #hasFP32CompatAPI()}.
+ * Not a cache key.
+ * @see #hasFP32CompatAPI()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 13;
+
+ private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
+
+ private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
+
+ // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock.
+ protected final RecursiveLock lock = LockFactory.createRecursiveLock(); // FIXME: Move to GLContextImpl when incr. minor version (incompatible change)
+
+ /** The underlying native OpenGL context */
+ protected volatile long contextHandle; // volatile: avoid locking for read-only access
+
+ protected GLContext() {
+ resetStates(true);
+ }
+
+ protected VersionNumber ctxVersion;
+ protected int ctxOptions;
+ protected String ctxVersionString;
+ protected VersionNumberString ctxVendorVersion;
+ protected VersionNumber ctxGLSLVersion;
+ private int currentSwapInterval;
+ protected GLRendererQuirks glRendererQuirks;
+
+ /** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */
+ protected boolean drawableRetargeted;
+
+ /**
+ * @param isInit true if called for class initialization, otherwise false (re-init or destruction).
+ */
+ protected void resetStates(final boolean isInit) {
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.resetStates(isInit "+isInit+")");
+ // Thread.dumpStack();
+ }
+ ctxVersion = VersionNumberString.zeroVersion;
+ ctxVendorVersion = VersionNumberString.zeroVersion;
+ ctxOptions=0;
+ ctxVersionString=null;
+ ctxGLSLVersion = VersionNumber.zeroVersion;
+ attachedObjects.clear();
+ contextHandle=0;
+ currentSwapInterval = -1;
+ glRendererQuirks = null;
+ drawableRetargeted = false;
+ }
+
+ /** Returns true if this GLContext is shared, otherwise false. */
+ public final boolean isShared() {
+ return GLContextShareSet.isShared(this);
+ }
+
+ /**
+ * Returns the shared master GLContext of this GLContext if shared, otherwise return <code>null</code>.
+ * <p>
+ * Returns this GLContext, if it is a shared master.
+ * </p>
+ * @since 2.2.1
+ */
+ public final GLContext getSharedMaster() {
+ return GLContextShareSet.getSharedMaster(this);
+ }
+
+ /** Returns a new list of created GLContext shared with this GLContext. */
+ public final List<GLContext> getCreatedShares() {
+ return GLContextShareSet.getCreatedShares(this);
+ }
+
+ /** Returns a new list of destroyed GLContext shared with this GLContext. */
+ public final List<GLContext> getDestroyedShares() {
+ return GLContextShareSet.getDestroyedShares(this);
+ }
+
+ /**
+ * Returns the instance of {@link GLRendererQuirks}, allowing one to determine workarounds.
+ * @return instance of {@link GLRendererQuirks} if context was made current once, otherwise <code>null</code>.
+ */
+ public final GLRendererQuirks getRendererQuirks() { return glRendererQuirks; }
+
+ /**
+ * Returns true if the <code>quirk</code> exist in {@link #getRendererQuirks()}, otherwise false.
+ * <p>
+ * Convenience method for:
+ * <pre>
+ * final GLRendererQuirks glrq = ctx.getRendererQuirks();
+ * boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ;
+ * </pre>
+ * </p>
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ */
+ public final boolean hasRendererQuirk(final int quirk) throws IllegalArgumentException {
+ return null != glRendererQuirks ? glRendererQuirks.exist(quirk) : false ;
+ }
+
+ /**
+ * Sets the read/write drawable for framebuffer operations, i.e. reassociation of the context's drawable.
+ * <p>
+ * If the arguments reflect the current state of this context
+ * this method is a no-operation and returns the old and current {@link GLDrawable}.
+ * </p>
+ * <p>
+ * Remarks:
+ * <ul>
+ * <li>{@link GL#glFinish() glFinish()} is issued if context {@link #isCreated()} and a {@link #getGLDrawable() previous drawable} was bound before disassociation.</li>
+ * <li>If the context was current on this thread, it is being released before drawable reassociation
+ * and made current afterwards.</li>
+ * <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
+ * <li>The user shall take extra care of thread synchronization,
+ * i.e. lock the involved {@link GLDrawable#getNativeSurface() drawable's} {@link NativeSurface}s
+ * to avoid a race condition. In case {@link GLAutoDrawable auto-drawable's} are used,
+ * their {@link GLAutoDrawable#getUpstreamLock() upstream-lock} must be locked beforehand
+ * see <a href="GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </ul>
+ * </p>
+ * @param readWrite The read/write drawable for framebuffer operations, maybe <code>null</code> to remove association.
+ * @param setWriteOnly Only change the write-drawable, if <code>setWriteOnly</code> is <code>true</code> and
+ * if the {@link #getGLReadDrawable() read-drawable} differs
+ * from the {@link #getGLDrawable() write-drawable}.
+ * Otherwise set both drawables, read and write.
+ * @return The previous read/write drawable if operation succeeds
+ *
+ * @throws GLException in case <code>null</code> is being passed,
+ * this context is made current on another thread
+ * or operation fails.
+ *
+ * @see #isGLReadDrawableAvailable()
+ * @see #setGLReadDrawable(GLDrawable)
+ * @see #getGLReadDrawable()
+ * @see #setGLDrawable(GLDrawable, boolean)
+ * @see #getGLDrawable()
+ */
+ public abstract GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly);
+
+ /**
+ * Returns the write-drawable this context uses for framebuffer operations.
+ * <p>
+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+ * it equals to the write-drawable (default).
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ * @see #setGLDrawable(GLDrawable, boolean)
+ * @see #setGLReadDrawable(GLDrawable)
+ */
+ public abstract GLDrawable getGLDrawable();
+
+ /**
+ * Query whether using a distinguished read-drawable is supported.
+ * @return true if using a read-drawable is supported with your driver/OS, otherwise false.
+ */
+ public abstract boolean isGLReadDrawableAvailable();
+
+ /**
+ * Set the read-Drawable for read framebuffer operations.<br>
+ * The caller should query if this feature is supported via {@link #isGLReadDrawableAvailable()}.
+ * <p>
+ * If the context was current on this thread, it is being released before switching the drawable
+ * and made current afterwards. However the user shall take extra care that not other thread
+ * attempts to make this context current. Otherwise a race condition may happen.
+ * </p>
+ *
+ * @param read the read-drawable for read framebuffer operations.
+ * If null is passed, the default write drawable will be set.
+ * @return the previous read-drawable
+ *
+ * @throws GLException in case a read drawable is not supported or
+ * this context is made current on another thread.
+ *
+ * @see #isGLReadDrawableAvailable()
+ * @see #getGLReadDrawable()
+ */
+ public abstract GLDrawable setGLReadDrawable(GLDrawable read);
+
+ /**
+ * Returns the read-Drawable this context uses for read framebuffer operations.
+ * <p>
+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+ * it equals to the write-drawable (default).
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ * @see #isGLReadDrawableAvailable()
+ * @see #setGLReadDrawable(GLDrawable)
+ * @see #getGLReadDrawable()
+ */
+ public abstract GLDrawable getGLReadDrawable();
+
+ /**
+ * Makes this GLContext current on the calling thread.
+ * <p>
+ * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
+ * </p>
+ * <p>
+ * There are two return values that indicate success and one that
+ * indicates failure.
+ * </p>
+ * <p>
+ * A return value of {@link #CONTEXT_CURRENT_NEW}
+ * indicates that that context has been made current for the 1st time,
+ * or that the state of the underlying context or drawable has
+ * changed since the last time this context was current.
+ * In this case, the application may wish to initialize the render state.
+ * </p>
+ * <p>
+ * A return value of {@link #CONTEXT_CURRENT} indicates that the context has
+ * been made current, with its previous state restored.
+ * </p>
+ * <p>
+ * If the context could not be made current (for example, because
+ * the underlying drawable has not ben realized on the display) ,
+ * a value of {@link #CONTEXT_NOT_CURRENT} is returned.
+ * </p>
+ * <p>
+ * This method is blocking, i.e. waits until another thread has
+ * released the context.
+ * </p>
+ * <p>
+ * The drawable's surface is being locked at entry
+ * and unlocked at {@link #release()}
+ * </p>
+ *
+ * @return <ul>
+ * <li>{@link #CONTEXT_CURRENT_NEW} if the context was successfully made current the 1st time,</li>
+ * <li>{@link #CONTEXT_CURRENT} if the context was successfully made current,</li>
+ * <li>{@link #CONTEXT_NOT_CURRENT} if the context could not be made current.</li>
+ * </ul>
+ *
+ * @throws GLException if the context could not be created
+ * or made current due to non-recoverable, system-specific errors.
+ */
+ public abstract int makeCurrent() throws GLException;
+
+ /**
+ * Releases control of this GLContext from the current thread.
+ * <p>
+ * Recursive call to {@link #release()} and hence {@link #makeCurrent()} are supported.
+ * </p>
+ * <p>
+ * The drawable's surface is being unlocked at exit,
+ * assumed to be locked by {@link #makeCurrent()}.
+ * </p>
+ *
+ * @throws GLException if the context had not previously been made
+ * current on the current thread
+ */
+ public abstract void release() throws GLException;
+
+ /**
+ * Copies selected groups of OpenGL state variables from the
+ * supplied source context into this one. The <code>mask</code>
+ * parameter indicates which groups of state variables are to be
+ * copied. <code>mask</code> contains the bitwise OR of the same
+ * symbolic names that are passed to the GL command {@link
+ * GL2#glPushAttrib glPushAttrib}. The single symbolic constant
+ * {@link GL2#GL_ALL_ATTRIB_BITS GL_ALL_ATTRIB_BITS} can be used to
+ * copy the maximum possible portion of rendering state. <P>
+ *
+ * Not all values for GL state can be copied. For example, pixel
+ * pack and unpack state, render mode state, and select and feedback
+ * state are not copied. The state that can be copied is exactly the
+ * state that is manipulated by the GL command {@link
+ * GL2#glPushAttrib glPushAttrib}. <P>
+ *
+ * On most platforms, this context may not be current to any thread,
+ * including the calling thread, when this method is called. Some
+ * platforms have additional requirements such as whether this
+ * context or the source context must occasionally be made current
+ * in order for the results of the copy to be seen; these
+ * requirements are beyond the scope of this specification.
+ *
+ * @param source the source OpenGL context from which to copy state
+ * @param mask a mask of symbolic names indicating which groups of state to copy
+
+ * @throws GLException if an OpenGL-related error occurred
+ */
+ public abstract void copy(GLContext source, int mask) throws GLException;
+
+ /**
+ * Returns the GL object bound to this thread current context.
+ * If no context is current, throw an GLException
+ *
+ * @return the current context's GL object on this thread
+ * @throws GLException if no context is current
+ */
+ public static GL getCurrentGL() throws GLException {
+ final GLContext glc = getCurrent();
+ if(null==glc) {
+ throw new GLException(getThreadName()+": No OpenGL context current on this thread");
+ }
+ return glc.getGL();
+ }
+
+ /**
+ * Returns this thread current context.
+ * If no context is current, returns null.
+ *
+ * @return the context current on this thread, or null if no context
+ * is current.
+ */
+ public static GLContext getCurrent() {
+ return currentContext.get();
+ }
+
+ /**
+ * @return true if this GLContext is current on this thread
+ */
+ public final boolean isCurrent() {
+ return getCurrent() == this ;
+ }
+
+ /**
+ * @throws GLException if this GLContext is not current on this thread
+ */
+ public final void validateCurrent() throws GLException {
+ if(getCurrent() != this) {
+ throw new GLException(getThreadName()+": This context is not current. Current context: "+getCurrent()+", this context "+this);
+ }
+ }
+
+ /** Returns a String representation of the {@link #makeCurrent()} result. */
+ public static final String makeCurrentResultToString(final int res) {
+ switch(res) {
+ case CONTEXT_NOT_CURRENT: return "CONTEXT_NOT_CURRENT";
+ case CONTEXT_CURRENT: return "CONTEXT_CURRENT";
+ case CONTEXT_CURRENT_NEW: return "CONTEXT_CURRENT_NEW";
+ default: return "INVALID_VALUE";
+ }
+ }
+
+ /**
+ * Sets the thread-local variable returned by {@link #getCurrent}
+ * and has no other side-effects. For use by third parties adding
+ * new GLContext implementations; not for use by end users.
+ */
+ protected static void setCurrent(final GLContext cur) {
+ if( TRACE_SWITCH ) {
+ if(null == cur) {
+ System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - NULL");
+ } else {
+ System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - obj " + toHexString(cur.hashCode()) + ", ctx " + toHexString(cur.getHandle()));
+ }
+ }
+ currentContext.set(cur);
+ }
+
+ /**
+ * Destroys this OpenGL context and frees its associated
+ * resources.
+ * <p>
+ * The context may be current w/o recursion when calling <code>destroy()</code>,
+ * in which case this method destroys the context and releases the lock.
+ * </p>
+ */
+ public abstract void destroy();
+
+ /**
+ * Returns the implementing root GL instance of this GLContext's GL object,
+ * considering a wrapped pipelined hierarchy, see {@link GLBase#getDownstreamGL()}.
+ * @throws GLException if the root instance is not a GL implementation
+ * @see GLBase#getRootGL()
+ * @see GLBase#getDownstreamGL()
+ * @see #getGL()
+ * @see #setGL(GL)
+ */
+ public abstract GL getRootGL();
+
+ /**
+ * Returns the GL pipeline object for this GLContext.
+ *
+ * @return the aggregated GL instance, or null if this context was not yet made current.
+ */
+ public abstract GL getGL();
+
+ /**
+ * Sets the GL pipeline object for this GLContext.
+ *
+ * @return the set GL pipeline or null if not successful
+ */
+ public abstract GL setGL(GL gl);
+
+ /**
+ * Returns the underlying native OpenGL context handle
+ */
+ public final long getHandle() { return contextHandle; }
+
+ /**
+ * Indicates whether the underlying native OpenGL context has been created.
+ */
+ public final boolean isCreated() {
+ return 0 != contextHandle;
+ }
+
+ /**
+ * Returns the attached user object for the given name to this GLContext.
+ */
+ public final Object getAttachedObject(final String name) {
+ return attachedObjects.get(name);
+ }
+
+ /**
+ * Sets the attached user object for the given name to this GLContext.
+ * Returns the previously set object or null.
+ */
+ public final Object attachObject(final String name, final Object obj) {
+ return attachedObjects.put(name, obj);
+ }
+
+ public final Object detachObject(final String name) {
+ return attachedObjects.remove(name);
+ }
+
+ /**
+ * Classname, GL, GLDrawable
+ */
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ this.append(sb);
+ sb.append("] ");
+ return sb.toString();
+ }
+
+ public final StringBuilder append(final StringBuilder sb) {
+ sb.append("Version ").append(getGLVersion()).append(" [GL ").append(getGLVersionNumber()).append(", vendor ").append(getGLVendorVersionNumber());
+ sb.append("], options 0x");
+ sb.append(Integer.toHexString(ctxOptions));
+ sb.append(", this ");
+ sb.append(toHexString(hashCode()));
+ sb.append(", handle ");
+ sb.append(toHexString(contextHandle));
+ sb.append(", isShared "+isShared()+", ");
+ sb.append(getGL());
+ sb.append(",\n\t quirks: ");
+ if(null != glRendererQuirks) {
+ glRendererQuirks.toString(sb);
+ } else {
+ sb.append("n/a");
+ }
+ if(getGLDrawable()!=getGLReadDrawable()) {
+ sb.append(",\n\tRead Drawable : ");
+ sb.append(getGLReadDrawable());
+ sb.append(",\n\tWrite Drawable: ");
+ sb.append(getGLDrawable());
+ } else {
+ sb.append(",\n\tDrawable: ");
+ sb.append(getGLDrawable());
+ }
+ return sb;
+ }
+
+ /**
+ * Returns true if the specified OpenGL core- or extension-function can be
+ * successfully called using this GL context given the current host (OpenGL
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
+ *
+ * See {@link GL#isFunctionAvailable(String)} for more details.
+ *
+ * @param glFunctionName the name of the OpenGL function (e.g., use
+ * "glPolygonOffsetEXT" or "glPolygonOffset" to check if the {@link
+ * com.jogamp.opengl.GL#glPolygonOffset(float,float)} is available).
+ */
+ public abstract boolean isFunctionAvailable(String glFunctionName);
+
+ /**
+ * Returns true if the specified OpenGL extension can be
+ * successfully called using this GL context given the current host (OpenGL
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
+ *
+ * See {@link GL#isExtensionAvailable(String)} for more details.
+ *
+ * @param glExtensionName the name of the OpenGL extension (e.g.,
+ * "GL_VERTEX_PROGRAM_ARB").
+ */
+ public abstract boolean isExtensionAvailable(String glExtensionName);
+
+ /** Returns the number of platform extensions */
+ public abstract int getPlatformExtensionCount();
+
+ /** Returns a non-null (but possibly empty) string containing the
+ space-separated list of available platform-dependent (e.g., WGL,
+ GLX) extensions. Can only be called while this context is
+ current. */
+ public abstract String getPlatformExtensionsString();
+
+ /** Returns the number of OpenGL extensions */
+ public abstract int getGLExtensionCount();
+
+ /** Returns a non-null (but possibly empty) string containing the
+ space-separated list of available extensions.
+ Can only be called while this context is current.
+ This is equivalent to
+ {@link com.jogamp.opengl.GL#glGetString(int) glGetString}({@link com.jogamp.opengl.GL#GL_EXTENSIONS GL_EXTENSIONS})
+ */
+ public abstract String getGLExtensionsString();
+
+ /**
+ * @return Additional context creation flags, supported: {@link GLContext#CTX_OPTION_DEBUG}.
+ */
+ public abstract int getContextCreationFlags();
+
+ /**
+ * @param flags Additional context creation flags, supported: {@link GLContext#CTX_OPTION_DEBUG}.
+ * Unsupported flags are masked out.
+ * Only affects this context state if not created yet via {@link #makeCurrent()}.
+ * @see #enableGLDebugMessage(boolean)
+ * @see GLAutoDrawable#setContextCreationFlags(int)
+ */
+ public abstract void setContextCreationFlags(int flags);
+
+ /**
+ * Returns a valid OpenGL version string, ie<br>
+ * <pre>
+ * major.minor ([option]?[options,]*) - gl-version
+ * </pre><br>
+ *
+ * <ul>
+ * <li> options
+ * <ul>
+ * <li> <code>ES profile</code> ES profile</li>
+ * <li> <code>Compatibility profile</code> Compatibility profile including fixed function pipeline and deprecated functionality</li>
+ * <li> <code>Core profile</code> Core profile</li>
+ * <li> <code>forward</code> Forward profile excluding deprecated functionality</li>
+ * <li> <code>arb</code> refers to an ARB_create_context created context</li>
+ * <li> <code>debug</code> refers to a debug context</li>
+ * <li> <code>ES2 compatible</code> refers to an ES2 compatible implementation</li>
+ * <li> <code>software</code> refers to a software implementation of the rasterizer</li>
+ * <li> <code>hardware</code> refers to a hardware implementation of the rasterizer</li>
+ * </ul></li>
+ * <li> <i>gl-version</i> the GL_VERSION string</li>
+ * </ul>
+ *
+ * e.g.:
+ * <table border="0">
+ * <tr> <td></td> <td></td> </tr>
+ * <tr>
+ * <td>row 2, cell 1</td>
+ * <td>row 2, cell 2</td>
+ * </tr>
+ * </table>
+ *
+ * <table border="0">
+ * <tr><td></td> <td>ES2</td> <td><code>2.0 (ES profile, ES2 compatible, hardware) - 2.0 ES Profile</code></td></tr>
+ * <tr><td>ATI</td><td>GL2</td> <td><code>3.0 (Compatibility profile, arb, hardware) - 3.2.9704 Compatibility Profile Context</code></td></tr>
+ * <tr><td>ATI</td><td>GL3</td> <td><code>3.3 (Core profile, any, new, hardware) - 1.4 (3.2.9704 Compatibility Profile Context)</code></td></tr>
+ * <tr><td>ATI</td><td>GL3bc</td><td><code>3.3 (Compatibility profile, arb, hardware) - 1.4 (3.2.9704 Compatibility Profile Context)</code></td></tr>
+ * <tr><td>NV</td><td>GL2</td> <td><code>3.0 (Compatibility profile, arb, hardware) - 3.0.0 NVIDIA 195.36.07.03</code></td></tr>
+ * <tr><td>NV</td><td>GL3</td> <td><code>3.3 (Core profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03</code></td></tr>
+ * <tr><td>NV</td><td>GL3bc</td> <td><code>3.3 (Compatibility profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03</code></td></tr>
+ * <tr><td>NV</td><td>GL2</td> <td><code>3.0 (Compatibility profile, arb, ES2 compatible, hardware) - 3.0.0 NVIDIA 290.10</code></td></tr>
+ * </table>
+ */
+ public final String getGLVersion() {
+ return ctxVersionString;
+ }
+
+ /**
+ * Returns this context OpenGL version.
+ * @see #getGLSLVersionNumber()
+ **/
+ public final VersionNumber getGLVersionNumber() { return ctxVersion; }
+ /**
+ * Returns the vendor's version, i.e. version number at the end of <code>GL_VERSION</code> not being the GL version.
+ * <p>
+ * In case no such version exists within <code>GL_VERSION</code>,
+ * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ * </p>
+ * <p>
+ * The vendor's version is usually the vendor's OpenGL driver version.
+ * </p>
+ */
+ public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
+ public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
+ public final boolean isGLCoreProfile() { return ( 0 != ( CTX_PROFILE_CORE & ctxOptions ) ); }
+ public final boolean isGLESProfile() { return ( 0 != ( CTX_PROFILE_ES & ctxOptions ) ); }
+ public final boolean isGLForwardCompatible() { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
+ public final boolean isGLDebugEnabled() { return ( 0 != ( CTX_OPTION_DEBUG & ctxOptions ) ); }
+ public final boolean isCreatedWithARBMethod() { return ( 0 != ( CTX_IS_ARB_CREATED & ctxOptions ) ); }
+
+ /**
+ * Returns the matching GLSL version number, queried by this context GL
+ * via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if &ge; ES2.0 or GL2.0,
+ * otherwise a static match is being utilized.
+ * <p>
+ * The context must have been current once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ * </p>
+ * <p>
+ * Examples w/ <code>major.minor</code>:
+ * <pre>
+ * 1.00 (ES 2.0), 3.00 (ES 3.0)
+ * 1.10 (GL 2.0), 1.20 (GL 2.1), 1.50 (GL 3.2),
+ * 3.30 (GL 3.3), 4.00 (GL 4.0), 4.10 (GL 4.1), 4.20 (GL 4.2)
+ * </pre >
+ * </p>
+ * <p>
+ * <i>Matching</i> could also refer to the maximum GLSL version usable by this context
+ * since <i>normal</i> GL implementations are capable of using a lower GLSL version as well.
+ * The latter is not true on OSX w/ a GL3 context.
+ * </p>
+ *
+ * @return GLSL version number if context has been made current at least once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ *
+ * @see #getGLVersionNumber()
+ */
+ public final VersionNumber getGLSLVersionNumber() {
+ return ctxGLSLVersion;
+ }
+
+ /**
+ * Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
+ * i.e. for desktop
+ * <pre>
+ * #version 110
+ * ..
+ * #version 150 core
+ * #version 330 compatibility
+ * ...
+ * </pre>
+ * And for ES:
+ * <pre>
+ * #version 100
+ * #version 300 es
+ * ..
+ * </pre>
+ * <p>
+ * If context has not been made current yet, a string of zero length is returned.
+ * </p>
+ * @see #getGLSLVersionNumber()
+ */
+ public final String getGLSLVersionString() {
+ if( ctxGLSLVersion.isZero() ) {
+ return S_EMPTY;
+ }
+ final int minor = ctxGLSLVersion.getMinor();
+ final String profileOpt;
+ if( isGLES() ) {
+ profileOpt = ctxGLSLVersion.compareTo(Version3_0) >= 0 ? " es" : S_EMPTY;
+ } else if( isGLCoreProfile() ) {
+ profileOpt = ctxGLSLVersion.compareTo(Version1_50) >= 0 ? " core" : S_EMPTY;
+ } else if( isGLCompatibilityProfile() ) {
+ profileOpt = ctxGLSLVersion.compareTo(Version1_50) >= 0 ? " compatibility" : S_EMPTY;
+ } else {
+ throw new InternalError("Neither ES, Core nor Compat: "+this); // see validateProfileBits(..)
+ }
+ return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + profileOpt + "\n" ;
+ }
+
+ protected static final VersionNumber getStaticGLSLVersionNumber(final int glMajorVersion, final int glMinorVersion, final int ctxOptions) {
+ if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
+ if( 3 == glMajorVersion ) {
+ return Version3_0; // ES 3.0 -> GLSL 3.00
+ } else if( 2 == glMajorVersion ) {
+ return Version1_0; // ES 2.0 -> GLSL 1.00
+ }
+ } else if( 1 == glMajorVersion ) {
+ return Version1_10; // GL 1.x -> GLSL 1.10
+ } else if( 2 == glMajorVersion ) {
+ switch ( glMinorVersion ) {
+ case 0: return Version1_10; // GL 2.0 -> GLSL 1.10
+ default: return Version1_20; // GL 2.1 -> GLSL 1.20
+ }
+ } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
+ switch ( glMinorVersion ) {
+ case 0: return Version1_30; // GL 3.0 -> GLSL 1.30
+ case 1: return Version1_40; // GL 3.1 -> GLSL 1.40
+ default: return Version1_50; // GL 3.2 -> GLSL 1.50
+ }
+ }
+ // The new default: GL >= 3.3, ES >= 3.0
+ return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N -> GLSL M.N
+ }
+
+ /**
+ * @return true if this context is an ES2 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code> or <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ */
+ public final boolean isGLES2Compatible() {
+ return 0 != ( ctxOptions & ( CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ) ) ;
+ }
+
+ /**
+ * Return true if this context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public final boolean isGLES3Compatible() {
+ return 0 != ( ctxOptions & CTX_IMPL_ES3_COMPAT ) ;
+ }
+
+ /**
+ * @return true if impl. is a hardware rasterizer, otherwise false.
+ * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public final boolean isHardwareRasterizer() {
+ return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
+ }
+
+ /**
+ * @return true if context supports GLSL, i.e. is either {@link #isGLES3()}, {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} <i>and</i> major-version > 1.
+ * @see GLProfile#hasGLSL()
+ */
+ public final boolean hasGLSL() {
+ return isGLES3() ||
+ isGLES2() ||
+ isGL3() ||
+ isGL2() && ctxVersion.getMajor()>1 ;
+ }
+
+ /**
+ * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
+ * <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
+ * </p>
+ * <p>
+ * Basic FBO support may only include one color attachment and no multisampling,
+ * as well as limited internal formats for renderbuffer.
+ * </p>
+ * @see #CTX_IMPL_FBO
+ */
+ public final boolean hasBasicFBOSupport() {
+ return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
+ }
+
+ /**
+ * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Full FBO is supported if the context is either GL >= 3.0 [ES, core, compat] or implements the extensions
+ * <code>ARB_framebuffer_object</code>, or all of
+ * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
+ * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+ * </p>
+ * <p>
+ * Full FBO support includes multiple color attachments and multisampling.
+ * </p>
+ */
+ public final boolean hasFullFBOSupport() {
+ return hasBasicFBOSupport() && !hasRendererQuirk(GLRendererQuirks.NoFullFBOSupport) &&
+ ( isGL3ES3() || // GL >= 3.0 [ES, core, compat]
+ isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
+ ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
+ isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+ isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+ isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
+ )
+ ) ;
+ }
+
+ /**
+ * Returns <code>true</code> if <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points available,
+ * otherwise <code>false</code>.
+ * @see #CTX_IMPL_FP32_COMPAT_API
+ */
+ public final boolean hasFP32CompatAPI() {
+ return 0 != ( ctxOptions & CTX_IMPL_FP32_COMPAT_API ) ;
+ }
+
+ /**
+ * Returns the maximum number of FBO RENDERBUFFER samples
+ * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
+ */
+ public final int getMaxRenderbufferSamples() {
+ if( hasFullFBOSupport() ) {
+ final GL gl = getGL();
+ final int[] val = new int[] { 0 } ;
+ try {
+ gl.glGetIntegerv(GL2ES3.GL_MAX_SAMPLES, val, 0);
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ return val[0];
+ } else if(DEBUG) {
+ System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (final GLException gle) { gle.printStackTrace(); }
+ }
+ return 0;
+ }
+
+ /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */
+ public boolean isNPOTTextureAvailable() {
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
+ }
+
+ public boolean isTextureFormatBGRA8888Available() {
+ return isGL2GL3() ||
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL4bc. <p>Includes [ GL4bc ].</p>
+ * @see GLProfile#isGL4bc()
+ */
+ public final boolean isGL4bc() {
+ return 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.getMajor() >= 4;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL4. <p>Includes [ GL4bc, GL4 ].</p>
+ * @see GLProfile#isGL4()
+ */
+ public final boolean isGL4() {
+ return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.getMajor() >= 4;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ */
+ public final boolean isGL4core() {
+ return 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.getMajor() >= 4;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3bc. <p>Includes [ GL4bc, GL3bc ].</p>
+ * @see GLProfile#isGL3bc()
+ */
+ public final boolean isGL3bc() {
+ return 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.compareTo(Version3_1) >= 0 ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3 ].</p>
+ * @see GLProfile#isGL3()
+ */
+ public final boolean isGL3() {
+ return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.compareTo(Version3_1) >= 0 ;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ */
+ public final boolean isGL3core() {
+ return 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version3_1) >= 0;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GLES2 ].</p>
+ */
+ public final boolean isGLcore() {
+ return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ) ||
+ ( 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version3_1) >= 0
+ ) ;
+ }
+
+ /**
+ * Indicates whether this GLContext allows CPU data sourcing (indices, vertices ..) as opposed to using a GPU buffer source (VBO),
+ * e.g. {@link GL2#glDrawElements(int, int, int, java.nio.Buffer)}.
+ * <p>Includes [GL2ES1, GLES2] == [ GL4bc, GL3bc, GL2, GLES1, GL2ES1, GLES2 ].</p>
+ * <p>See Bug 852 - https://jogamp.org/bugzilla/show_bug.cgi?id=852 </p>
+ */
+ public final boolean isCPUDataSourcingAvail() {
+ return isGL2ES1() || isGLES2();
+ }
+
+ /**
+ * Indicates whether this GLContext's native profile does not implement a <i>default vertex array object</i> (VAO),
+ * starting w/ OpenGL 3.1 core.
+ * <p>Includes [ GL4, GL3 ].</p>
+ * <pre>
+ Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
+ GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
+ there is no more default VAO buffer 0 bound, hence generating and binding one
+ to avoid INVALID_OPERATION at VertexAttribPointer.
+ More clear is GL 4.3 core spec: 10.4 (p 307).
+ * </pre>
+ * <pre>
+ ES 3.x is <i>not</i> included here.
+ Due to it's ES 2.0 backward compatibility it still supports the following features:
+ <i>client side vertex arrays</i>
+ <i>default vertex array object</i>
+
+ Binding a custom VAO with ES 3.0 would cause <i>client side vertex arrays</i> via {@link GL2ES1#glVertexPointer(int, int, int, java.nio.Buffer) glVertexPointer}
+ to produce <code>GL_INVALID_OPERATION</code>.
+
+ However, they are marked <i>deprecated</i>:
+ GL ES 3.0 spec F.1. Legacy Features (p 322).
+ GL ES 3.1 spec F.1. Legacy Features (p 454).
+ * </pre>
+ * <p>
+ * If no default VAO is implemented in the native OpenGL profile,
+ * an own default VAO is being used, see {@link #getDefaultVAO()}.
+ * </p>
+ * @see #getDefaultVAO()
+ */
+ public final boolean hasNoDefaultVAO() {
+ return // ES 3.x not included, see above. ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ) ||
+ ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version3_1) >= 0
+ ) ;
+ }
+
+ /**
+ * If this GLContext does not implement a default VAO, see {@link #hasNoDefaultVAO()},
+ * an <i>own default VAO</i> will be created and bound at context creation.
+ * <p>
+ * If this GLContext does implement a default VAO, i.e. {@link #hasNoDefaultVAO()}
+ * returns <code>false</code>, this method returns <code>0</code>.
+ * </p>
+ * <p>
+ * Otherwise this method returns the VAO object name
+ * representing this GLContext's <i>own default VAO</i>.
+ * </p>
+ * @see #hasNoDefaultVAO()
+ */
+ public abstract int getDefaultVAO();
+
+ /**
+ * Indicates whether this GLContext is capable of GL2. <p>Includes [ GL4bc, GL3bc, GL2 ].</p>
+ * @see GLProfile#isGL2()
+ */
+ public final boolean isGL2() {
+ return 0 != ( ctxOptions & CTX_PROFILE_COMPAT ) && ctxVersion.getMajor()>=1 ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2GL3()
+ */
+ public final boolean isGL2GL3() {
+ return isGL2() || isGL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES1. <p>Includes [ GLES1 ].</p>
+ * @see GLProfile#isGLES1()
+ */
+ public final boolean isGLES1() {
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 1 ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES2. <p>Includes [ GLES2, GLES3 ].</p>
+ * @see GLProfile#isGLES2()
+ */
+ public final boolean isGLES2() {
+ if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) {
+ final int major = ctxVersion.getMajor();
+ return 2 == major || 3 == major;
+ }
+ return false;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES3. <p>Includes [ GLES3 ].</p>
+ * @see GLProfile#isGLES3()
+ */
+ public final boolean isGLES3() {
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 3 ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES. <p>Includes [ GLES3, GLES1, GLES2 ].</p>
+ * @see GLProfile#isGLES()
+ */
+ public final boolean isGLES() {
+ return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p>
+ * @see GLProfile#isGL2ES1()
+ */
+ public final boolean isGL2ES1() {
+ return isGLES1() || isGL2();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p>
+ * @see GLProfile#isGL2ES2()
+ */
+ public final boolean isGL2ES2() {
+ return isGLES2() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2ES3()
+ * @see #isGL3ES3()
+ * @see #isGL2GL3()
+ */
+ public final boolean isGL2ES3() {
+ return isGL3ES3() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p>
+ * @see GLProfile#isGL3ES3()
+ */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
+ }
+
+ /**
+ * Returns true if this profile is capable of GL4ES3, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLProfile#isGL4ES3()
+ */
+ public final boolean isGL4ES3() {
+ return isGLES3Compatible() ;
+ }
+
+ /**
+ * Set the swap interval of the current context and attached drawable.
+ * @param interval Should be &ge; 0. 0 disables the vertical synchronization,
+ * where &ge; 1 is the number of vertical refreshes before a swap buffer occurs.
+ * A value &lt; 0 is ignored.
+ * @return true if the operation was successful, otherwise false
+ *
+ * @throws GLException if the context is not current.
+ */
+ public final boolean setSwapInterval(final int interval) throws GLException {
+ validateCurrent();
+ if(0<=interval) {
+ if( !drawableRetargeted || !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) ) {
+ if( setSwapIntervalImpl(interval) ) {
+ currentSwapInterval = interval;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ protected boolean setSwapIntervalImpl(final int interval) {
+ return false;
+ }
+ /** Return the current swap interval.
+ * <p>
+ * If the context has not been made current at all,
+ * the default value <code>-1</code> is returned.
+ * </p>
+ * <p>
+ * For a valid context the default value is <code>1</code>
+ * in case of an EGL based profile (ES1 or ES2) and <code>-1</code>
+ * (undefined) for desktop.
+ * </p>
+ */
+ public final int getSwapInterval() {
+ return currentSwapInterval;
+ }
+ protected final void setDefaultSwapInterval() {
+ if(this.isGLES()) {
+ currentSwapInterval = 1;
+ } else {
+ currentSwapInterval = -1;
+ }
+ }
+
+ public final boolean queryMaxSwapGroups(final int[] maxGroups, final int maxGroups_offset,
+ final int[] maxBarriers, final int maxBarriers_offset) {
+ validateCurrent();
+ return queryMaxSwapGroupsImpl(maxGroups, maxGroups_offset, maxBarriers, maxBarriers_offset);
+ }
+ protected boolean queryMaxSwapGroupsImpl(final int[] maxGroups, final int maxGroups_offset,
+ final int[] maxBarriers, final int maxBarriers_offset) { return false; }
+ public final boolean joinSwapGroup(final int group) {
+ validateCurrent();
+ return joinSwapGroupImpl(group);
+ }
+ protected boolean joinSwapGroupImpl(final int group) { /** nop per default .. **/ return false; }
+ protected int currentSwapGroup = -1; // default: not set yet ..
+ public int getSwapGroup() {
+ return currentSwapGroup;
+ }
+ public final boolean bindSwapBarrier(final int group, final int barrier) {
+ validateCurrent();
+ return bindSwapBarrierImpl(group, barrier);
+ }
+ protected boolean bindSwapBarrierImpl(final int group, final int barrier) { /** nop per default .. **/ return false; }
+
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultDrawFramebuffer();
+
+ /**
+ * Return the default read framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultReadFramebuffer();
+
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultReadBuffer();
+
+ /**
+ * Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}.
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultPixelDataType();
+
+ /**
+ * Get the default pixel data format, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}.
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultPixelDataFormat();
+
+ /**
+ * @return The extension implementing the GLDebugOutput feature,
+ * either {@link GLExtensions#ARB_debug_output} or {@link GLExtensions#AMD_debug_output}.
+ * If unavailable or called before initialized via {@link #makeCurrent()}, <i>null</i> is returned.
+ */
+ public abstract String getGLDebugMessageExtension();
+
+ /**
+ * @return the current synchronous debug behavior, set via {@link #setGLDebugSynchronous(boolean)}.
+ */
+ public abstract boolean isGLDebugSynchronous();
+
+ /**
+ * Enables or disables the synchronous debug behavior via
+ * {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS)},
+ * if extension is {@link GLExtensions#ARB_debug_output}.
+ * There is no equivalent for {@link GLExtensions#AMD_debug_output}.
+ * <p> The default is <code>true</code>, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS}.</p>
+ * @link {@link #isGLDebugSynchronous()}
+ */
+ public abstract void setGLDebugSynchronous(boolean synchronous);
+
+ /**
+ * @return true if the GLDebugOutput feature is enabled or not.
+ */
+ public abstract boolean isGLDebugMessageEnabled();
+
+ /**
+ * Enables or disables the GLDebugOutput feature of extension {@link GLExtensions#ARB_debug_output}
+ * or {@link GLExtensions#AMD_debug_output}, if available.
+ *
+ * <p>To enable the GLDebugOutput feature {@link #enableGLDebugMessage(boolean) enableGLDebugMessage(true)}
+ * or {@link #setContextCreationFlags(int) setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
+ * shall be called <b>before</b> context creation via {@link #makeCurrent()}!</p>
+ *
+ * <p>In case {@link GLAutoDrawable} are being used,
+ * {@link GLAutoDrawable#setContextCreationFlags(int) glAutoDrawable.setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
+ * shall be issued before context creation via {@link #makeCurrent()}!</p>
+ *
+ * <p>After context creation, the GLDebugOutput feature may be enabled or disabled at any time using this method.</p>
+ *
+ * @param enable If true enables, otherwise disables the GLDebugOutput feature.
+ *
+ * @throws GLException if this context is not current or GLDebugOutput registration failed (enable)
+ *
+ * @see #setContextCreationFlags(int)
+ * @see #addGLDebugListener(GLDebugListener)
+ * @see GLAutoDrawable#setContextCreationFlags(int)
+ */
+ public abstract void enableGLDebugMessage(boolean enable) throws GLException;
+
+ /**
+ * Add {@link GLDebugListener}.<br>
+ *
+ * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
+ * @see #enableGLDebugMessage(boolean)
+ * @see #removeGLDebugListener(GLDebugListener)
+ */
+ public abstract void addGLDebugListener(GLDebugListener listener);
+
+ /**
+ * Remove {@link GLDebugListener}.<br>
+ *
+ * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
+ * @see #enableGLDebugMessage(boolean)
+ * @see #addGLDebugListener(GLDebugListener)
+ */
+ public abstract void removeGLDebugListener(GLDebugListener listener);
+
+ /**
+ * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, IntBuffer, boolean)}
+ * and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, IntBuffer, boolean)} of the GLDebugOutput feature.
+ * @see #enableGLDebugMessage(boolean)
+ */
+ public abstract void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled);
+
+ /**
+ * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, int[], int, boolean)}
+ * and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, int[], int, boolean)} of the GLDebugOutput feature.
+ * @see #enableGLDebugMessage(boolean)
+ */
+ public abstract void glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled);
+
+ /**
+ * Generic entry for {@link GL2GL3#glDebugMessageInsert(int, int, int, int, int, String)}
+ * and {@link GL2GL3#glDebugMessageInsertAMD(int, int, int, int, String)} of the GLDebugOutput feature.
+ * @see #enableGLDebugMessage(boolean)
+ */
+ public abstract void glDebugMessageInsert(int source, int type, int id, int severity, String buf);
+
+ public static final int GL_VERSIONS[][] = {
+ /* 0.*/ { -1 },
+ /* 1.*/ { 0, 1, 2, 3, 4, 5 },
+ /* 2.*/ { 0, 1 },
+ /* 3.*/ { 0, 1, 2, 3 },
+ /* 4.*/ { 0, 1, 2, 3, 4, 5 } };
+
+ public static final int ES_VERSIONS[][] = {
+ /* 0.*/ { -1 },
+ /* 1.*/ { 0, 1 },
+ /* 2.*/ { 0 },
+ /* 3.*/ { 0, 1 } };
+
+ public static final int getMaxMajor(final int ctxProfile) {
+ return ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ? ES_VERSIONS.length-1 : GL_VERSIONS.length-1;
+ }
+
+ public static final int getMaxMinor(final int ctxProfile, final int major) {
+ if( 1>major ) {
+ return -1;
+ }
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
+ if( major>=ES_VERSIONS.length ) return -1;
+ return ES_VERSIONS[major].length-1;
+ } else {
+ if( major>=GL_VERSIONS.length ) return -1;
+ return GL_VERSIONS[major].length-1;
+ }
+ }
+
+ /**
+ * Returns true, if the major.minor is not inferior to the lowest
+ * valid version and does not exceed the highest known major number by more than one.
+ * <p>
+ * The minor version number is ignored by the upper limit validation
+ * and the major version number may exceed by one.
+ * </p>
+ * <p>
+ * The upper limit check is relaxed since we don't want to cut-off
+ * unforseen new GL version since the release of JOGL.
+ * </p>
+ * <p>
+ * Hence it is important to iterate through GL version from the upper limit
+ * and {@link #decrementGLVersion(int, int[], int[])} until invalid.
+ * </p>
+ */
+ public static final boolean isValidGLVersion(final int ctxProfile, final int major, final int minor) {
+ if( 1>major || 0>minor ) {
+ return false;
+ }
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( major >= ES_VERSIONS.length + 1 ) return false;
+ } else {
+ if( major>=GL_VERSIONS.length + 1 ) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Clip the given GL version to the maximum known valid version if exceeding.
+ * @return true if clipped, i.e. given value exceeds maximum, otherwise false.
+ */
+ public static final boolean clipGLVersion(final int ctxProfile, final int major[], final int minor[]) {
+ final int m = major[0];
+ final int n = minor[0];
+
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( m >= ES_VERSIONS.length ) {
+ major[0] = ES_VERSIONS.length - 1;
+ minor[0] = ES_VERSIONS[major[0]].length - 1;
+ return true;
+ }
+ if( n >= ES_VERSIONS[m].length ) {
+ minor[0] = ES_VERSIONS[m].length - 1;
+ return true;
+ }
+ } else if( m >= GL_VERSIONS.length ) { // !isES
+ major[0] = GL_VERSIONS.length - 1;
+ minor[0] = GL_VERSIONS[major[0]].length - 1;
+ return true;
+ } else if( n >= GL_VERSIONS[m].length ) { // !isES
+ minor[0] = GL_VERSIONS[m].length - 1;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Decrement the given GL version by one
+ * and return true if still valid, otherwise false.
+ * <p>
+ * If the given version exceeds the maximum known valid version,
+ * it is {@link #clipGLVersion(int, int[], int[]) clipped} and
+ * true is returned.
+ * </p>
+ *
+ * @param ctxProfile
+ * @param major
+ * @param minor
+ * @return
+ */
+ public static final boolean decrementGLVersion(final int ctxProfile, final int major[], final int minor[]) {
+ if( !clipGLVersion(ctxProfile, major, minor) ) {
+ int m = major[0];
+ int n = minor[0] - 1;
+ if(n < 0) {
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( m >= 3 ) {
+ m -= 1;
+ } else {
+ m = 0; // major decr [1,2] -> 0
+ }
+ n = ES_VERSIONS[m].length-1;
+ } else {
+ m -= 1;
+ n = GL_VERSIONS[m].length-1;
+ }
+ }
+ if( !isValidGLVersion(ctxProfile, m, n) ) {
+ return false;
+ }
+ major[0]=m;
+ minor[0]=n;
+ }
+ return true;
+ }
+
+ protected static int composeBits(final int a8, final int b8, final int c16) {
+ return ( ( a8 & 0x000000FF ) << 24 ) |
+ ( ( b8 & 0x000000FF ) << 16 ) |
+ ( ( c16 & 0x0000FFFF ) ) ;
+ }
+
+ private static void validateProfileBits(final int bits, final String argName) {
+ int num = 0;
+ if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; }
+ if( 0 != ( CTX_PROFILE_CORE & bits ) ) { num++; }
+ if( 0 != ( CTX_PROFILE_ES & bits ) ) { num++; }
+ if(1!=num) {
+ throw new GLException("Internal Error: "+argName+": 1 != num-profiles: "+num);
+ }
+ }
+
+ //
+ // version mapping
+ //
+
+ /**
+ * @see #getDeviceVersionAvailableKey(com.jogamp.nativewindow.AbstractGraphicsDevice, int, int)
+ */
+ protected static final IdentityHashMap<String, Integer> deviceVersionAvailable = new IdentityHashMap<String, Integer>();
+
+ /**
+ * @see #getUniqueDeviceString(com.jogamp.nativewindow.AbstractGraphicsDevice)
+ */
+ private static final IdentityHashMap<String, String> deviceVersionsAvailableSet = new IdentityHashMap<String, String>();
+
+ /** clears the device/context mappings as well as the GL/GLX proc address tables. */
+ protected static void shutdown() {
+ deviceVersionAvailable.clear();
+ deviceVersionsAvailableSet.clear();
+ GLContextImpl.shutdownImpl(); // well ..
+ }
+
+ protected static boolean getAvailableGLVersionsSet(final AbstractGraphicsDevice device) {
+ synchronized ( deviceVersionsAvailableSet ) {
+ return deviceVersionsAvailableSet.containsKey(device.getUniqueID());
+ }
+ }
+
+ protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device, final boolean set) {
+ synchronized ( deviceVersionsAvailableSet ) {
+ final String devKey = device.getUniqueID();
+ if( set ) {
+ deviceVersionsAvailableSet.put(devKey, devKey);
+ } else {
+ deviceVersionsAvailableSet.remove(devKey);
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
+ System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
+ }
+ }
+ }
+
+ /**
+ * Returns a unique String object using {@link String#intern()} for the given arguments,
+ * which object reference itself can be used as a key.
+ */
+ protected static String getDeviceVersionAvailableKey(final AbstractGraphicsDevice device, final int major, final int profile) {
+ final String r = device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ return r.intern();
+ }
+
+ /**
+ * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable(int,int)} not intended to be used by
+ * implementations. However, if {@link jogamp.opengl.GLContextImpl#createContextARB(long, boolean)} is not being used within
+ * {@link com.jogamp.opengl.GLDrawableFactory#getOrCreateSharedContext(com.jogamp.nativewindow.AbstractGraphicsDevice)},
+ * GLProfile has to map the available versions.
+ *
+ * @param reqMajor Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @return the old mapped value
+ *
+ * @see #createContextARBMapVersionsAvailable
+ */
+ protected static Integer mapAvailableGLVersion(final AbstractGraphicsDevice device,
+ final int reqMajor, final int profile, final int resMajor, final int resMinor, int resCtp)
+ {
+ validateProfileBits(profile, "profile");
+ validateProfileBits(resCtp, "resCtp");
+
+ if(FORCE_NO_FBO_SUPPORT) {
+ resCtp &= ~CTX_IMPL_FBO ;
+ }
+ if(DEBUG) {
+ System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
+ // Thread.dumpStack();
+ }
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile);
+ final Integer val = Integer.valueOf(composeBits(resMajor, resMinor, resCtp));
+ synchronized(deviceVersionAvailable) {
+ return deviceVersionAvailable.put( objectKey, val );
+ }
+ }
+
+ protected static StringBuilder dumpAvailableGLVersions(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ synchronized(deviceVersionAvailable) {
+ final Set<String> keys = deviceVersionAvailable.keySet();
+ boolean needsSeparator = false;
+ for(final Iterator<String> i = keys.iterator(); i.hasNext(); ) {
+ if(needsSeparator) {
+ sb.append(Platform.getNewline());
+ }
+ final String key = i.next();
+ sb.append(key).append(": ");
+ final Integer valI = deviceVersionAvailable.get(key);
+ if(null != valI) {
+ final int bits32 = valI.intValue();
+ final int major = ( bits32 & 0xFF000000 ) >>> 24 ;
+ final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ;
+ final int ctp = ( bits32 & 0x0000FFFF ) ;
+ sb.append(GLContext.getGLVersion(major, minor, ctp, null));
+ } else {
+ sb.append("n/a");
+ }
+ needsSeparator = true;
+ }
+ }
+ return sb;
+ }
+
+ /**
+ * @param device the device to request whether the profile is available for
+ * @param reqMajor Key Value either 1, 2, 3 or 4
+ * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code>
+ */
+ protected static Integer getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile) {
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
+ Integer val;
+ synchronized(deviceVersionAvailable) {
+ val = deviceVersionAvailable.get( objectKey );
+ }
+ return val;
+ }
+
+ /**
+ * @param reqMajor Key Value either 1, 2, 3 or 4
+ * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @param major if not null, returns the used major version
+ * @param minor if not null, returns the used minor version
+ * @param ctp if not null, returns the used context profile
+ */
+ protected static boolean getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile,
+ final int[] major, final int minor[], final int ctp[]) {
+
+ final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
+ if(null==valI) {
+ return false;
+ }
+
+ final int bits32 = valI.intValue();
+
+ if(null!=major) {
+ major[0] = ( bits32 & 0xFF000000 ) >>> 24 ;
+ }
+ if(null!=minor) {
+ minor[0] = ( bits32 & 0x00FF0000 ) >>> 16 ;
+ }
+ if(null!=ctp) {
+ ctp[0] = ( bits32 & 0x0000FFFF ) ;
+ }
+ return true;
+ }
+
+ /**
+ * returns the highest GLProfile string regarding the implementation version and context profile bits.
+ * @throws GLException if version and context profile bits could not be mapped to a GLProfile
+ */
+ protected static String getGLProfile(final int major, final int minor, final int ctp)
+ throws GLException {
+ if(0 != ( CTX_PROFILE_COMPAT & ctp )) {
+ if(major >= 4) { return GLProfile.GL4bc; }
+ else if(major == 3 && minor >= 1) { return GLProfile.GL3bc; }
+ else { return GLProfile.GL2; }
+ } else if(0 != ( CTX_PROFILE_CORE & ctp )) {
+ if(major >= 4) { return GLProfile.GL4; }
+ else if(major == 3 && minor >= 1) { return GLProfile.GL3; }
+ } else if(0 != ( CTX_PROFILE_ES & ctp )) {
+ if(major == 3) { return GLProfile.GLES3; }
+ else if(major == 2) { return GLProfile.GLES2; }
+ else if(major == 1) { return GLProfile.GLES1; }
+ }
+ throw new GLException("Unhandled OpenGL version/profile: "+GLContext.getGLVersion(major, minor, ctp, null));
+ }
+
+ /**
+ * Returns the GLProfile's major version number at reqMajorCTP[0] and it's context property (CTP) at reqMajorCTP[1] for availability mapping request.
+ */
+ protected static final void getRequestMajorAndCompat(final GLProfile glp, final int[/*2*/] reqMajorCTP) {
+ final GLProfile glpImpl = glp.getImpl();
+ if( glpImpl.isGL4() ) {
+ reqMajorCTP[0]=4;
+ } else if ( glpImpl.isGL3() || glpImpl.isGLES3() ) {
+ reqMajorCTP[0]=3;
+ } else if (glpImpl.isGLES1()) {
+ reqMajorCTP[0]=1;
+ } else /* if (glpImpl.isGL2() || glpImpl.isGLES2()) */ {
+ reqMajorCTP[0]=2;
+ }
+ if( glpImpl.isGLES() ) {
+ reqMajorCTP[1]=CTX_PROFILE_ES;
+ } else if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc
+ reqMajorCTP[1]=CTX_PROFILE_COMPAT;
+ } else {
+ reqMajorCTP[1]=CTX_PROFILE_CORE;
+ }
+ }
+
+ /**
+ * @param device the device the context profile is being requested for
+ * @param GLProfile the GLProfile the context profile is being requested for
+ * @return the GLProfile's context property (CTP) if available, otherwise <code>0</code>
+ */
+ protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final int[] reqMajorCTP = new int[] { 0, 0 };
+ getRequestMajorAndCompat(glp, reqMajorCTP);
+
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final int _ctp[] = { 0 };
+ if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) {
+ return _ctp[0];
+ }
+ return 0; // n/a
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @return the highest GLProfile for the device regarding availability, version and profile bits.
+ */
+ protected static GLProfile getAvailableGLProfile(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
+ throws GLException {
+ final String glpName = getAvailableGLProfileName(device, reqMajor, reqProfile);
+ return null != glpName ? GLProfile.get(device, glpName) : null;
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @return the highest GLProfile name for the device regarding availability, version and profile bits.
+ */
+ /* package */ static String getAvailableGLProfileName(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
+ throws GLException {
+ final int major[] = { 0 };
+ final int minor[] = { 0 };
+ final int ctp[] = { 0 };
+ if(GLContext.getAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp)) {
+ return GLContext.getGLProfile(major[0], minor[0], ctp[0]);
+ }
+ return null;
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ */
+ protected static String getAvailableGLVersionAsString(final AbstractGraphicsDevice device, final int major, final int profile) {
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final int _ctp[] = { 0 };
+ if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
+ return getGLVersion(_major[0], _minor[0], _ctp[0], null);
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
+ * <p>
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+ * </p>
+ * <p>
+ * FBO support is queried as described in {@link #hasBasicFBOSupport()}.
+ * </p>
+ *
+ * @param device the device to request whether FBO is available for
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasBasicFBOSupport()
+ */
+ public static final boolean isFBOAvailable(final AbstractGraphicsDevice device, final GLProfile glp) {
+ return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
+ }
+
+ /**
+ * @return <code>1</code> if using a hardware rasterizer, <code>0</code> if using a software rasterizer and <code>-1</code> if not determined yet.
+ * @see GLContext#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public static final int isHardwareRasterizer(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final int r;
+ final int ctp = getAvailableContextProperties(device, glp);
+ if(0 == ctp) {
+ r = -1;
+ } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
+ r = 1;
+ } else {
+ r = 0;
+ }
+ return r;
+ }
+
+ /**
+ * @param device the device to request whether the profile is available for
+ * @param reqMajor Key Value either 1, 2, 3 or 4
+ * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not
+ * @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false.
+ */
+ protected static boolean isGLVersionAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, final boolean isHardware[]) {
+ final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
+ if(null==valI) {
+ return false;
+ }
+ isHardware[0] = 0 == ( valI.intValue() & GLContext.CTX_IMPL_ACCEL_SOFT ) ;
+ return true;
+ }
+
+ public static boolean isGLES1Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ public static boolean isGLES2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ public static boolean isGLES3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ /**
+ * Returns true if a ES3 compatible profile is available,
+ * i.e. either a &ge; 4.3 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>,
+ * otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public static final boolean isGLES3CompatibleAvailable(final AbstractGraphicsDevice device) {
+ final int major[] = { 0 };
+ final int minor[] = { 0 };
+ final int ctp[] = { 0 };
+ boolean ok;
+
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_ES, major, minor, ctp);
+ if( !ok ) {
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, major, minor, ctp);
+ }
+ if( !ok ) {
+ GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp);
+ }
+ return 0 != ( ctp[0] & CTX_IMPL_ES3_COMPAT );
+ }
+
+ public static boolean isGL4bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware);
+ }
+
+ public static boolean isGL4Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE, isHardware);
+ }
+
+ public static boolean isGL3bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT, isHardware);
+ }
+
+ public static boolean isGL3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE, isHardware);
+ }
+
+ public static boolean isGL2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware);
+ }
+
+ protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) {
+ boolean needColon = false;
+ final StringBuilder sb = new StringBuilder();
+ sb.append(major);
+ sb.append(".");
+ sb.append(minor);
+ sb.append(" (");
+ needColon = appendString(sb, "ES profile", needColon, 0 != ( CTX_PROFILE_ES & ctp ));
+ needColon = appendString(sb, "Compat profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
+ needColon = appendString(sb, "Core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp ));
+ needColon = appendString(sb, "forward", needColon, 0 != ( CTX_OPTION_FORWARD & ctp ));
+ needColon = appendString(sb, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
+ needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
+ needColon = appendString(sb, "ES2 compat", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "ES3 compat", needColon, 0 != ( CTX_IMPL_ES3_COMPAT & ctp ));
+ needColon = appendString(sb, "FBO", needColon, 0 != ( CTX_IMPL_FBO & ctp ));
+ needColon = appendString(sb, "FP32 compat", needColon, 0 != ( CTX_IMPL_FP32_COMPAT_API & ctp ));
+ if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
+ needColon = appendString(sb, "software", needColon, true);
+ } else {
+ needColon = appendString(sb, "hardware", needColon, true);
+ }
+ sb.append(")");
+ if(null!=gl_version) {
+ sb.append(" - ");
+ sb.append(gl_version);
+ }
+ return sb.toString();
+ }
+
+ //
+ // internal string utils
+ //
+
+ protected static String toHexString(final int hex) {
+ return "0x" + Integer.toHexString(hex);
+ }
+
+ protected static String toHexString(final long hex) {
+ return "0x" + Long.toHexString(hex);
+ }
+
+ private static boolean appendString(final StringBuilder sb, final String string, boolean needColon, final boolean condition) {
+ if(condition) {
+ if(needColon) {
+ sb.append(", ");
+ }
+ sb.append(string);
+ needColon=true;
+ }
+ return needColon;
+ }
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/GLDebugListener.java b/src/jogl/classes/com/jogamp/opengl/GLDebugListener.java
new file mode 100644
index 000000000..30e1a49c2
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLDebugListener.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+/**
+ * Listener for {@link GLDebugMessage}s.
+ *
+ * <p>One can enable GLDebugOutput via {@link GLContext#enableGLDebugMessage(boolean)}
+ * and add listeners via {@link GLContext#addGLDebugListener(GLDebugListener)}.
+ */
+public interface GLDebugListener {
+ /**
+ * Handle {@link GLDebugMessage} message sent from native GL implementation.
+ *
+ * <p>Since this method is invoked directly by the GL implementation, it shall
+ * return as fast as possible.</p>
+ */
+ void messageSent(GLDebugMessage event);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLDebugMessage.java b/src/jogl/classes/com/jogamp/opengl/GLDebugMessage.java
new file mode 100644
index 000000000..a8868026b
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLDebugMessage.java
@@ -0,0 +1,253 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+import com.jogamp.common.os.Platform;
+
+/**
+ * OpenGL debug message generated by the driver
+ * and delivered via {@link GLDebugListener}.
+ */
+public class GLDebugMessage {
+ final GLContext source;
+ final long when;
+ final int dbgSource;
+ final int dbgType;
+ final int dbgId;
+ final int dbgSeverity;
+ final String dbgMsg;
+
+ /**
+ * @param source The source of the event
+ * @param when The time of the event
+ * @param dbgSource The ARB source
+ * @param dbgType The ARB type
+ * @param dbgId The ARB id
+ * @param dbgSeverity The ARB severity level
+ * @param dbgMsg The debug message
+ */
+ public GLDebugMessage(final GLContext source, final long when, final int dbgSource, final int dbgType, final int dbgId, final int dbgSeverity, final String dbgMsg) {
+ this.source = source;
+ this.when = when;
+ this.dbgSource = dbgSource;
+ this.dbgType = dbgType;
+ this.dbgId = dbgId;
+ this.dbgSeverity = dbgSeverity;
+ this.dbgMsg = dbgMsg;
+ }
+
+ /**
+ *
+ * @param source
+ * @param when
+ * @param dbgId
+ * @param amdDbgCategory
+ * @param dbgSeverity AMD severity level equals ARB severity level (value and semantic)
+ * @param dbgMsg
+ * @return
+ */
+ public static GLDebugMessage translateAMDEvent(final GLContext source, final long when, final int dbgId, final int amdDbgCategory, final int dbgSeverity, final String dbgMsg) {
+ int dbgSource, dbgType;
+
+ // AMD category == ARB source/type
+ switch(amdDbgCategory) {
+ case GL2GL3.GL_DEBUG_CATEGORY_API_ERROR_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_API;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_ERROR;
+ break;
+
+ //
+ // def source / other type
+ //
+
+ case GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
+ break;
+
+ case GL2GL3.GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
+ break;
+
+ case GL2GL3.GL_DEBUG_CATEGORY_APPLICATION_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_APPLICATION;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
+ break;
+
+
+ //
+ // other source / def type
+ //
+
+ case GL2GL3.GL_DEBUG_CATEGORY_DEPRECATION_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR;
+ break;
+
+ case GL2GL3.GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR;
+ break;
+
+ case GL2GL3.GL_DEBUG_CATEGORY_PERFORMANCE_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_PERFORMANCE;
+ break;
+
+ case GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD:
+ default:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
+ }
+
+ return new GLDebugMessage(source, when, dbgSource, dbgType, dbgId, dbgSeverity, dbgMsg);
+ }
+
+ public static int translateARB2AMDCategory(final int dbgSource, final int dbgType) {
+ switch (dbgSource) {
+ case GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ return GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD;
+
+ case GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER:
+ return GL2GL3.GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD;
+
+ case GL2ES2.GL_DEBUG_SOURCE_APPLICATION:
+ return GL2GL3.GL_DEBUG_CATEGORY_APPLICATION_AMD;
+ }
+
+ switch(dbgType) {
+ case GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ return GL2GL3.GL_DEBUG_CATEGORY_DEPRECATION_AMD;
+
+ case GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ return GL2GL3.GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD;
+
+ case GL2ES2.GL_DEBUG_TYPE_PERFORMANCE:
+ return GL2GL3.GL_DEBUG_CATEGORY_PERFORMANCE_AMD;
+ }
+
+ return GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD;
+ }
+
+ public GLContext getSource() {
+ return source;
+ }
+
+ public long getWhen() {
+ return when;
+ }
+
+ public int getDbgSource() {
+ return dbgSource;
+ }
+
+ public int getDbgType() {
+ return dbgType;
+ }
+
+ public int getDbgId() {
+ return dbgId;
+ }
+
+ public int getDbgSeverity() {
+ return dbgSeverity;
+ }
+
+ public String getDbgMsg() {
+ return dbgMsg;
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ final String crtab = Platform.getNewline()+"\t";
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("GLDebugEvent[ id ");
+ toHexString(sb, dbgId)
+ .append(crtab).append("type ").append(getDbgTypeString(dbgType))
+ .append(crtab).append("severity ").append(getDbgSeverityString(dbgSeverity))
+ .append(crtab).append("source ").append(getDbgSourceString(dbgSource))
+ .append(crtab).append("msg ").append(dbgMsg)
+ .append(crtab).append("when ").append(when);
+ if(null != source) {
+ sb.append(crtab).append("source ").append(source.getGLVersion()).append(" - hash 0x").append(Integer.toHexString(source.hashCode()));
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toString(null).toString();
+ }
+
+ public static String getDbgSourceString(final int dbgSource) {
+ switch(dbgSource) {
+ case GL2ES2.GL_DEBUG_SOURCE_API: return "GL API";
+ case GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER: return "GLSL or extension compiler";
+ case GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "Native Windowing binding";
+ case GL2ES2.GL_DEBUG_SOURCE_THIRD_PARTY: return "Third party";
+ case GL2ES2.GL_DEBUG_SOURCE_APPLICATION: return "Application";
+ case GL2ES2.GL_DEBUG_SOURCE_OTHER: return "generic";
+ default: return "Unknown (" + toHexString(dbgSource) + ")";
+ }
+ }
+
+ public static String getDbgTypeString(final int dbgType) {
+ switch(dbgType) {
+ case GL2ES2.GL_DEBUG_TYPE_ERROR: return "Error";
+ case GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "Warning: marked for deprecation";
+ case GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "Warning: undefined behavior";
+ case GL2ES2.GL_DEBUG_TYPE_PERFORMANCE: return "Warning: implementation dependent performance";
+ case GL2ES2.GL_DEBUG_TYPE_PORTABILITY: return "Warning: vendor-specific extension use";
+ case GL2ES2.GL_DEBUG_TYPE_OTHER: return "Warning: generic";
+ default: return "Unknown (" + toHexString(dbgType) + ")";
+ }
+ }
+
+ public static String getDbgSeverityString(final int dbgSeverity) {
+ switch(dbgSeverity) {
+ case GL2ES2.GL_DEBUG_SEVERITY_HIGH: return "High: dangerous undefined behavior";
+ case GL2ES2.GL_DEBUG_SEVERITY_MEDIUM: return "Medium: Severe performance/deprecation/other warnings";
+ case GL2ES2.GL_DEBUG_SEVERITY_LOW: return "Low: Performance warnings (redundancy/undefined)";
+ default: return "Unknown (" + toHexString(dbgSeverity) + ")";
+ }
+ }
+
+ public static StringBuilder toHexString(StringBuilder sb, final int i) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ return sb.append("0x").append(Integer.toHexString(i));
+ }
+ public static String toHexString(final int i) {
+ return "0x"+Integer.toHexString(i);
+ }
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLDrawable.java b/src/jogl/classes/com/jogamp/opengl/GLDrawable.java
new file mode 100644
index 000000000..c801ba463
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLDrawable.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.NativeSurfaceHolder;
+
+
+/** An abstraction for an OpenGL rendering target. A GLDrawable's
+ primary functionality is to create OpenGL contexts which can be
+ used to perform rendering. A GLDrawable does not automatically
+ create an OpenGL context, but all implementations of {@link
+ GLAutoDrawable} do so upon creation. */
+
+public interface GLDrawable extends NativeSurfaceHolder {
+ /**
+ * Creates a new context for drawing to this drawable that will
+ * optionally share buffer objects, textures and other server-side OpenGL
+ * objects with the specified GLContext.
+ * <p>
+ * The GLContext <code>share</code> need not be associated with this
+ * GLDrawable and may be null if sharing of display lists and other
+ * objects is not desired. See the note in the overview
+ * documentation
+ * <a href="../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
+ */
+ public GLContext createContext(GLContext shareWith);
+
+ /**
+ * Indicates to GLDrawable implementations whether the
+ * underlying {@link NativeSurface surface} has been created and can be drawn into.
+ * <p>
+ * If realized, the {@link #getHandle() drawable handle} may become
+ * valid while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+ * </p>
+ * <p>
+ * End users do not need to call this method; it is not necessary to
+ * call <code>setRealized</code> on a {@link GLAutoDrawable}
+ * as these perform the appropriate calls on their underlying GLDrawables internally.
+ * </p>
+ * <p>
+ * Developers implementing new OpenGL components for various window
+ * toolkits need to call this method against GLDrawables obtained
+ * from the GLDrawableFactory via the
+ * {@link GLDrawableFactory#createGLDrawable(NativeSurface)} method.
+ * It must typically be
+ * called with an argument of <code>true</code> when the component
+ * associated with the GLDrawable is realized and with an argument
+ * of <code>false</code> just before the component is unrealized.
+ * For the AWT, this means calling <code>setRealized(true)</code> in
+ * the <code>addNotify</code> method and with an argument of
+ * <code>false</code> in the <code>removeNotify</code> method.
+ * </p>
+ * <p>
+ * <code>GLDrawable</code> implementations should handle multiple
+ * cycles of <code>setRealized(true)</code> /
+ * <code>setRealized(false)</code> calls. Most, if not all, Java
+ * window toolkits have a persistent object associated with a given
+ * component, regardless of whether that component is currently
+ * realized. The <CODE>GLDrawable</CODE> object associated with a
+ * particular component is intended to be similarly persistent. A
+ * <CODE>GLDrawable</CODE> is intended to be created for a given
+ * component when it is constructed and live as long as that
+ * component. <code>setRealized</code> allows the
+ * <code>GLDrawable</code> to re-initialize and destroy any
+ * associated resources as the component becomes realized and
+ * unrealized, respectively.
+ * </p>
+ * <p>
+ * With an argument of <code>true</code>,
+ * the minimum implementation shall call
+ * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successful:
+ * <ul>
+ * <li> Update the {@link GLCapabilities}, which are associated with
+ * the attached {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.</li>
+ * <li> Release the lock with {@link NativeSurface#unlockSurface() NativeSurface's unlockSurface()}.</li>
+ * </ul><br>
+ * This is important since {@link NativeSurface#lockSurface() NativeSurface's lockSurface()}
+ * ensures resolving the window/surface handles, and the drawable's {@link GLCapabilities}
+ * might have changed.
+ * </p>
+ * <p>
+ * Calling this method has no other effects. For example, if
+ * <code>removeNotify</code> is called on a Canvas implementation
+ * for which a GLDrawable has been created, it is also necessary to
+ * destroy all OpenGL contexts associated with that GLDrawable. This
+ * is not done automatically by the implementation.
+ * </p>
+ * @see #isRealized()
+ * @see #getHandle()
+ * @see NativeSurface#lockSurface()
+ */
+ public void setRealized(boolean realized);
+
+ /**
+ * Returns <code>true</code> if this drawable is realized, otherwise <code>true</code>.
+ * <p>
+ * A drawable can be realized and unrealized via {@link #setRealized(boolean)}.
+ * </p>
+ * @see #setRealized(boolean)
+ */
+ public boolean isRealized();
+
+ /**
+ * Returns the width of this {@link GLDrawable}'s {@link #getNativeSurface() surface} client area in pixel units.
+ * @see NativeSurface#getSurfaceWidth()
+ */
+ public int getSurfaceWidth();
+
+ /**
+ * Returns the height of this {@link GLDrawable}'s {@link #getNativeSurface() surface} client area in pixel units.
+ * @see NativeSurface#getSurfaceHeight()
+ */
+ public int getSurfaceHeight();
+
+ /**
+ * Returns <code>true</code> if the drawable is rendered in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ * <p>
+ * Default impl. is <code>true</code>, i.e. OpenGL coordinate system.
+ * </p>
+ * <p>
+ * Currently only MS-Windows bitmap offscreen drawable uses a non OpenGL orientation and hence returns <code>false</code>.<br/>
+ * This removes the need of a vertical flip when used in AWT or Windows applications.
+ * </p>
+ */
+ public boolean isGLOriented();
+
+ /** Swaps the front and back buffers of this drawable. For {@link
+ GLAutoDrawable} implementations, when automatic buffer swapping
+ is enabled (as is the default), this method is called
+ automatically and should not be called by the end user. */
+ public void swapBuffers() throws GLException;
+
+ /** Fetches the {@link GLCapabilitiesImmutable} corresponding to the chosen
+ OpenGL capabilities (pixel format / visual / GLProfile) for this drawable.
+ <p>
+ This query only returns the chosen capabilities if {@link #isRealized()}.
+ </p>
+ <p>
+ On some platforms, the pixel format is not directly associated
+ with the drawable; a best attempt is made to return a reasonable
+ value in this case.
+ </p>
+ <p>
+ This object shall be directly associated to the attached {@link NativeSurface}'s
+ {@link AbstractGraphicsConfiguration}, and if changes are necessary,
+ they should reflect those as well.
+ </p>
+ @return The immutable queried instance.
+ @see #getRequestedGLCapabilities()
+ */
+ public GLCapabilitiesImmutable getChosenGLCapabilities();
+
+ /** Fetches the {@link GLCapabilitiesImmutable} corresponding to the user requested
+ OpenGL capabilities (pixel format / visual / GLProfile) for this drawable.
+ <p>
+ If {@link #isRealized() realized}, {@link #getChosenGLCapabilities() the chosen capabilities}
+ reflect the actual selected OpenGL capabilities.
+ </p>
+ @return The immutable queried instance.
+ @see #getChosenGLCapabilities()
+ @since 2.2
+ */
+ public GLCapabilitiesImmutable getRequestedGLCapabilities();
+
+ /** Fetches the {@link GLProfile} for this drawable.
+ Returns the GLProfile object, no copy.
+ */
+ public GLProfile getGLProfile();
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns the underlying {@link NativeSurface} which {@link NativeSurface#getSurfaceHandle() native handle}
+ * represents this OpenGL drawable's native resource.
+ * </p>
+ *
+ * @see #getHandle()
+ */
+ @Override
+ public NativeSurface getNativeSurface();
+
+ /**
+ * Returns the GL drawable handle,
+ * guaranteed to be valid after {@link #setRealized(boolean) realization}
+ * <i>and</i> while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+ * <p>
+ * It is usually identical to the underlying windowing toolkit {@link NativeSurface surface}'s
+ * {@link com.jogamp.nativewindow.NativeSurface#getSurfaceHandle() handle}
+ * or an intermediate layer to suite GL, e.g. an EGL surface.
+ * </p>
+ * <p>
+ * On EGL it is represented by the EGLSurface.<br>
+ * On X11/GLX it is represented by either the Window XID, GLXPixmap, or GLXPbuffer.<br>
+ * On Windows it is represented by the HDC, which may change with each {@link NativeSurface#lockSurface()}.<br>
+ * </p>
+ * @see #setRealized(boolean)
+ * @see NativeSurface#lockSurface()
+ * @see NativeSurface#unlockSurface()
+ */
+ public long getHandle();
+
+ /** Return the {@link GLDrawableFactory} being used to create this instance. */
+ public GLDrawableFactory getFactory();
+
+ @Override
+ public String toString();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java
new file mode 100644
index 000000000..07c3e77e0
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLRendererQuirks;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.nativewindow.ProxySurface;
+import com.jogamp.nativewindow.UpstreamSurfaceHook;
+
+import jogamp.opengl.Debug;
+
+/** <p> Provides a virtual machine- and operating system-independent
+ mechanism for creating {@link GLDrawable}s.
+ </p>
+ <p> The {@link com.jogamp.opengl.GLCapabilities} objects passed
+ in to the various factory methods are used as a hint for the
+ properties of the returned drawable. The default capabilities
+ selection algorithm (equivalent to passing in a null {@link
+ GLCapabilitiesChooser}) is described in {@link
+ DefaultGLCapabilitiesChooser}. Sophisticated applications needing
+ to change the selection algorithm may pass in their own {@link
+ GLCapabilitiesChooser} which can select from the available pixel
+ formats. The GLCapabilitiesChooser mechanism may not be supported
+ by all implementations or on all platforms, in which case any
+ passed GLCapabilitiesChooser will be ignored.
+ </p>
+
+ <p> Because of the multithreaded nature of the Java platform's
+ Abstract Window Toolkit, it is typically not possible to immediately
+ reject a given {@link GLCapabilities} as being unsupportable by
+ either returning <code>null</code> from the creation routines or
+ raising a {@link GLException}. The semantics of the rejection
+ process are (unfortunately) left unspecified for now. The current
+ implementation will cause a {@link GLException} to be raised
+ during the first repaint of the {@link com.jogamp.opengl.awt.GLCanvas} or {@link
+ com.jogamp.opengl.awt.GLJPanel} if the capabilities can not be met.<br>
+ {@link GLOffscreenAutoDrawable} are created lazily,
+ see {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) createOffscreenAutoDrawable(..)}.
+ </p>
+
+ <p> The concrete GLDrawableFactory subclass instantiated by {@link
+ #getFactory getFactory} can be changed by setting the system
+ property <code>opengl.factory.class.name</code> to the
+ fully-qualified name of the desired class.
+ </p>
+*/
+public abstract class GLDrawableFactory {
+
+ protected static final boolean DEBUG = Debug.debug("GLDrawable");
+
+ private static volatile boolean isInit = false;
+ private static GLDrawableFactory eglFactory;
+ private static GLDrawableFactory nativeOSFactory;
+
+ private static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
+
+ /**
+ * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones.
+ */
+ public static final void initSingleton() {
+ if (!isInit) { // volatile: ok
+ synchronized (GLDrawableFactory.class) {
+ if (!isInit) {
+ isInit=true;
+ initSingletonImpl();
+ }
+ }
+ }
+ }
+ private static final void initSingletonImpl() {
+ NativeWindowFactory.initSingleton();
+ NativeWindowFactory.addCustomShutdownHook(false /* head */, new Runnable() {
+ @Override
+ public void run() {
+ shutdown0();
+ }
+ });
+
+ final String nwt = NativeWindowFactory.getNativeWindowType(true);
+ GLDrawableFactory tmp = null;
+ String factoryClassName = PropertyAccess.getProperty("jogl.gldrawablefactory.class.name", true);
+ final ClassLoader cl = GLDrawableFactory.class.getClassLoader();
+ if (null == factoryClassName) {
+ if ( nwt == NativeWindowFactory.TYPE_X11 ) {
+ factoryClassName = "jogamp.opengl.x11.glx.X11GLXDrawableFactory";
+ } else if ( nwt == NativeWindowFactory.TYPE_WINDOWS ) {
+ factoryClassName = "jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory";
+ } else if ( nwt == NativeWindowFactory.TYPE_MACOSX ) {
+ factoryClassName = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
+ } else {
+ // may use egl*Factory ..
+ if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("GLDrawableFactory.static - No native Windowing Factory for: "+nwt+"; May use EGLDrawableFactory, if available." );
+ }
+ }
+ }
+ if (null != factoryClassName && !GLProfile.disableOpenGLDesktop) {
+ if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("GLDrawableFactory.static - Native OS Factory for: "+nwt+": "+factoryClassName);
+ }
+ try {
+ tmp = (GLDrawableFactory) ReflectionUtil.createInstance(factoryClassName, cl);
+ } catch (final Exception jre) {
+ if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("Info: GLDrawableFactory.static - Native Platform: "+nwt+" - not available: "+factoryClassName);
+ jre.printStackTrace();
+ }
+ }
+ }
+ if(null != tmp && tmp.isComplete()) {
+ nativeOSFactory = tmp;
+ }
+ tmp = null;
+
+ if(!GLProfile.disableOpenGLES) {
+ try {
+ tmp = (GLDrawableFactory) ReflectionUtil.createInstance("jogamp.opengl.egl.EGLDrawableFactory", cl);
+ } catch (final Exception jre) {
+ if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("Info: GLDrawableFactory.static - EGLDrawableFactory - not available");
+ jre.printStackTrace();
+ }
+ }
+ if(null != tmp && tmp.isComplete()) {
+ eglFactory = tmp;
+ }
+ } else if( DEBUG || GLProfile.DEBUG ) {
+ System.err.println("Info: GLDrawableFactory.static - EGLDrawableFactory - disabled!");
+ }
+ }
+
+ protected static void shutdown() {
+ if (isInit) { // volatile: ok
+ synchronized (GLDrawableFactory.class) {
+ if (isInit) {
+ isInit=false;
+ shutdown0();
+ }
+ }
+ }
+ }
+
+ private static void shutdown0() {
+ // Following code will _always_ remain in shutdown hook
+ // due to special semantics of native utils, i.e. X11Utils.
+ // The latter requires shutdown at JVM-Shutdown only.
+ synchronized(glDrawableFactories) {
+ final int gldfCount = glDrawableFactories.size();
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll "+gldfCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<gldfCount; i++) {
+ final GLDrawableFactory gldf = glDrawableFactories.get(i);
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll["+(i+1)+"/"+gldfCount+"]: "+gldf.getClass().getName());
+ }
+ try {
+ gldf.resetAllDisplayGammaNoSync();
+ gldf.shutdownImpl();
+ } catch (final Throwable t) {
+ System.err.println("GLDrawableFactory.shutdownImpl: Caught "+t.getClass().getName()+" during factory shutdown #"+(i+1)+"/"+gldfCount+" "+gldf.getClass().getName());
+ if( DEBUG ) {
+ t.printStackTrace();
+ }
+ }
+ }
+ glDrawableFactories.clear();
+
+ // both were members of glDrawableFactories and are shutdown already
+ nativeOSFactory = null;
+ eglFactory = null;
+ }
+ GLContext.shutdown();
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll.X on thread "+getThreadName());
+ }
+ }
+
+ protected GLDrawableFactory() {
+ synchronized(glDrawableFactories) {
+ glDrawableFactories.add(this);
+ }
+ }
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
+ /** Returns true if this factory is complete, i.e. ready to be used. Otherwise return false. */
+ protected abstract boolean isComplete();
+
+ protected void enterThreadCriticalZone() {};
+ protected void leaveThreadCriticalZone() {};
+
+ protected abstract void shutdownImpl();
+
+ /**
+ * Sets the gamma, brightness, and contrast of the display associated with the given <code>surface</code>.
+ * <p>
+ * This functionality is not available on all platforms and
+ * graphics hardware. Returns true if the settings were successfully
+ * changed, false if not. This method may return false for some
+ * values of the incoming arguments even on hardware which does
+ * support the underlying functionality. </p>
+ * <p>
+ * If this method returns true, the display settings will
+ * automatically be reset to their original values upon JVM exit
+ * (assuming the JVM does not crash); if the user wishes to change
+ * the display settings back to normal ahead of time,
+ * use {@link #resetDisplayGamma(NativeSurface)} or {@link #resetAllDisplayGamma()}.
+ * </p>
+ * <p>
+ * It is recommended to call {@link #resetDisplayGamma(NativeSurface)} or {@link #resetAllDisplayGamma()}
+ * before calling e.g. <code>System.exit()</code> from the application rather than
+ * rely on the shutdown hook functionality due to inevitable race
+ * conditions and unspecified behavior during JVM teardown.
+ * </p>
+ * <p>
+ * This method may be called multiple times during the application's
+ * execution, but calling {@link #resetDisplayGamma(NativeSurface)}
+ * will only reset the settings to the values
+ * before the first call to this method. </p>
+ *
+ * @param surface denominates the display device
+ * @param gamma The gamma value, typically > 1.0 (default values vary, but typically roughly 1.0)
+ * @param brightness The brightness value between -1.0 and 1.0, inclusive (default values vary, but typically 0)
+ * @param contrast The contrast, greater than 0.0 (default values vary, but typically 1)
+ *
+ * @return true if gamma settings were successfully changed, false if not
+ * @throws IllegalArgumentException if any of the parameters were out-of-bounds
+ * @see #resetDisplayGamma(NativeSurface)
+ * @see #resetAllDisplayGamma()
+ */
+ public abstract boolean setDisplayGamma(final NativeSurface surface, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException;
+
+ /**
+ * Resets the gamma, brightness and contrast values of the display associated with the given <code>surface</code>
+ * to its original values before {@link #setDisplayGamma(NativeSurface, float, float, float) setDisplayGamma}
+ * was called the first time.
+ * <p>
+ * While it is not explicitly required that this method be called before
+ * exiting manually, calling it is recommended because of the inevitable
+ * unspecified behavior during JVM teardown.
+ * </p>
+ */
+ public abstract void resetDisplayGamma(final NativeSurface surface);
+
+ /**
+ * Resets the gamma, brightness and contrast values of all modified
+ * displays to their original values before {@link #setDisplayGamma(NativeSurface, float, float, float) setDisplayGamma}
+ * was called the first time.
+ * <p>
+ * While it is not explicitly required that this method be called before
+ * exiting manually, calling it is recommended because of the inevitable
+ * unspecified behavior during JVM teardown.
+ * </p>
+ */
+ public abstract void resetAllDisplayGamma();
+
+ protected abstract void resetAllDisplayGammaNoSync();
+
+ /**
+ * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection},
+ * {@link AbstractGraphicsDevice#getUnitID() unit ID} and {@link AbstractGraphicsDevice#getUniqueID() unique ID name}. for this factory<br>
+ * The implementation must return a non <code>null</code> default device, which must not be opened, ie. it's native handle is <code>null</code>.
+ * <p>
+ * This method shall return the default device if available
+ * even if the GLDrawableFactory is not functional and hence not compatible.
+ * The latter situation may happen because no native OpenGL implementation is available for the specific implementation.
+ * </p>
+ * @return the default shared device for this factory, eg. :0.0 on X11 desktop.
+ * @see #getIsDeviceCompatible(AbstractGraphicsDevice)
+ */
+ public abstract AbstractGraphicsDevice getDefaultDevice();
+
+ /**
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @return true if the device is compatible with this factory, ie. if it can be used for GLDrawable creation. Otherwise false.
+ * This implies validation whether the implementation is functional.
+ *
+ * @see #getDefaultDevice()
+ */
+ public abstract boolean getIsDeviceCompatible(AbstractGraphicsDevice device);
+
+ protected final AbstractGraphicsDevice validateDevice(AbstractGraphicsDevice device) {
+ if(null==device) {
+ device = getDefaultDevice();
+ if(null==device) {
+ throw new InternalError("no default device available");
+ }
+ if (GLProfile.DEBUG) {
+ System.err.println("Info: "+getClass().getSimpleName()+".validateDevice: using default device : "+device);
+ }
+ }
+
+ // Always validate the device,
+ // since even the default device may not be used by this factory.
+ if( !getIsDeviceCompatible(device) ) {
+ if (GLProfile.DEBUG) {
+ System.err.println("Info: "+getClass().getSimpleName()+".validateDevice: device not compatible : "+device);
+ }
+ return null;
+ }
+ return device;
+ }
+
+ /**
+ * Validate and start the shared resource runner thread if necessary and
+ * if the implementation uses it.
+ *
+ * @return the shared resource runner thread, if implementation uses it.
+ */
+ protected abstract Thread getSharedResourceThread();
+
+ /**
+ * Create the shared resource used internally as a reference for capabilities etc.
+ * <p>
+ * Returns true if a shared resource could be created
+ * for the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}.<br>
+ * This does not imply a shared resource is mapped (ie. made persistent), but is available in general<br>.
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @return true if a shared resource could been created, otherwise false.
+ */
+ protected final boolean createSharedResource(final AbstractGraphicsDevice device) {
+ return createSharedResourceImpl(device);
+ }
+ protected abstract boolean createSharedResourceImpl(AbstractGraphicsDevice device);
+
+ /**
+ * Returns true if the <code>quirk</code> exist in the shared resource's context {@link GLRendererQuirks}.
+ * <p>
+ * Convenience method for:
+ * <pre>
+ final GLRendererQuirks glrq = factory.getRendererQuirks(device);
+ return null != glrq ? glrq.exist(quirk) : false;
+ * </pre>
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param glp {@link GLProfile} to identify the device's {@link GLRendererQuirks}, maybe {@code null}
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ * @see #getRendererQuirks(AbstractGraphicsDevice, GLProfile)
+ * @see GLRendererQuirks
+ */
+ public final boolean hasRendererQuirk(final AbstractGraphicsDevice device, final GLProfile glp, final int quirk) {
+ final GLRendererQuirks glrq = getRendererQuirks(device, glp);
+ return null != glrq ? glrq.exist(quirk) : false;
+ }
+
+ /**
+ * Returns the shared resource's context {@link GLRendererQuirks}.
+ * <p>
+ * Implementation calls {@link GLContext#getRendererQuirks()} on the shared resource context.
+ * </p>
+ * <p>
+ * In case no shared device exist yet or the implementation doesn't support tracking quirks,
+ * the result is always <code>null</code>.
+ * </p>
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param glp {@link GLProfile} to identify the device's {@link GLRendererQuirks}, maybe {@code null}
+ * @see GLContext#getRendererQuirks()
+ * @see GLRendererQuirks
+ */
+ public abstract GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device, final GLProfile glp);
+
+ /**
+ * Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null
+ */
+ public static GLDrawableFactory getDesktopFactory() {
+ GLProfile.initSingleton();
+ return nativeOSFactory;
+ }
+
+ /**
+ * Returns the sole GLDrawableFactory instance for EGL if exist or null
+ */
+ public static GLDrawableFactory getEGLFactory() {
+ GLProfile.initSingleton();
+ return eglFactory;
+ }
+
+ /**
+ * Returns the sole GLDrawableFactory instance.
+ *
+ * @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory,
+ * or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL.
+ */
+ public static GLDrawableFactory getFactory(final GLProfile glProfile) throws GLException {
+ return getFactoryImpl(glProfile.getImplName());
+ }
+
+ protected static GLDrawableFactory getFactoryImpl(final String glProfileImplName) throws GLException {
+ if ( GLProfile.usesNativeGLES(glProfileImplName) ) {
+ if(null!=eglFactory) {
+ return eglFactory;
+ }
+ } else if(null!=nativeOSFactory) {
+ return nativeOSFactory;
+ }
+ throw new GLException("No GLDrawableFactory available for profile: "+glProfileImplName);
+ }
+
+ protected static GLDrawableFactory getFactoryImpl(final AbstractGraphicsDevice device) throws GLException {
+ if(null != nativeOSFactory && nativeOSFactory.getIsDeviceCompatible(device)) {
+ return nativeOSFactory;
+ }
+ if(null != eglFactory && eglFactory.getIsDeviceCompatible(device)) {
+ return eglFactory;
+ }
+ throw new GLException("No native platform GLDrawableFactory, nor EGLDrawableFactory available: "+device);
+ }
+
+ /**
+ * Returns an array of available GLCapabilities for the device.<br>
+ * The list is sorted by the native ID, ascending.<br>
+ * The chosen GLProfile statement in the result may not refer to the maximum available profile
+ * due to implementation constraints, ie using the shared resource.
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @return A list of {@link com.jogamp.opengl.GLCapabilitiesImmutable}'s, maybe empty if none is available.
+ */
+ public final List<GLCapabilitiesImmutable> getAvailableCapabilities(AbstractGraphicsDevice device) {
+ device = validateDevice(device);
+ if(null!=device) {
+ return getAvailableCapabilitiesImpl(device);
+ }
+ return null;
+ }
+ protected abstract List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device);
+
+ //----------------------------------------------------------------------
+ // Methods to create high-level objects
+
+ /**
+ * Returns an {@link GLDrawable#isRealized() unrealized} GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br>
+ * which determines pixel format, on- and offscreen incl. PBuffer type.
+ * <p>
+ * The chosen {@link GLCapabilitiesImmutable} are referenced within the target
+ * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.<p>
+ * </p>
+ * <p>
+ * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true.
+ * </p>
+ * <p>
+ * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
+ * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
+ * </p>
+ * <p>
+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
+ * </p>
+ * <p>
+ * If not onscreen and neither FBO nor Pbuffer is available,
+ * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
+ * </p>
+ *
+ * @throws IllegalArgumentException if the passed target is null
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the GLDrawable to fail.
+ *
+ * @see #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile)
+ * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile)
+ * @see com.jogamp.opengl.GLCapabilities#isOnscreen()
+ * @see com.jogamp.opengl.GLCapabilities#isFBO()
+ * @see com.jogamp.opengl.GLCapabilities#isPBuffer()
+ * @see GraphicsConfigurationFactory#chooseGraphicsConfiguration(CapabilitiesImmutable, CapabilitiesImmutable, CapabilitiesChooser, AbstractGraphicsScreen, int)
+ */
+ public abstract GLDrawable createGLDrawable(NativeSurface target)
+ throws IllegalArgumentException, GLException;
+
+ /**
+ * Creates a {@link GLDrawable#isRealized() realized} {@link GLOffscreenAutoDrawable}
+ * incl it's offscreen {@link NativeSurface} with the given capabilites and dimensions.
+ * <p>
+ * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is {@link GLDrawable#isRealized() realized}
+ * <i>without</i> an assigned {@link GLContext}, hence not initialized completely.<br>
+ *
+ * The {@link GLContext} can be assigned later manually via {@link GLAutoDrawable#setContext(GLContext, boolean) setContext(ctx)}
+ * <i>or</i> it will be created <i>lazily</i> at the 1st {@link GLAutoDrawable#display() display()} method call.<br>
+ *
+ * <i>Lazy</i> {@link GLContext} creation will take a shared {@link GLContext} into account
+ * which has been set {@link GLOffscreenAutoDrawable#setSharedContext(GLContext) directly}
+ * or {@link GLOffscreenAutoDrawable#setSharedAutoDrawable(GLAutoDrawable) via another GLAutoDrawable}.
+ * </p>
+ * <p>
+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+ * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
+ * it is auto-configured. Auto configuration will set {@link GLCapabilitiesImmutable caps} to offscreen
+ * and FBO <i>or</i> Pbuffer, whichever is available in that order.
+ * </p>
+ * <p>
+ * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
+ * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
+ * </p>
+ * <p>
+ * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
+ * </p>
+ * <p>
+ * If neither FBO nor Pbuffer is available,
+ * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated.
+ * </p>
+ * <p>
+ * The resulting {@link GLOffscreenAutoDrawable} has it's own independent device instance using <code>device</code> details.
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param caps the requested GLCapabilties
+ * @param chooser the custom chooser, may be null for default
+ * @param width the requested offscreen width
+ * @param height the requested offscreen height
+ * @return the created and realized offscreen {@link GLOffscreenAutoDrawable} instance
+ *
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the Offscreen to fail.
+ *
+ * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int)
+ */
+ public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device,
+ GLCapabilitiesImmutable caps,
+ GLCapabilitiesChooser chooser,
+ int width, int height) throws GLException;
+
+ /**
+ * Creates a {@link GLDrawable#isRealized() realized} <i>dummy</i> {@link GLAutoDrawable}
+ * incl it's <i>dummy, invisible</i> {@link NativeSurface}
+ * as created with {@link #createDummyDrawable(AbstractGraphicsDevice, boolean, GLCapabilitiesImmutable, GLCapabilitiesChooser)}.
+ * <p>
+ * The <i>dummy</i> {@link GLAutoDrawable}'s {@link GLDrawable} is {@link GLDrawable#isRealized() realized}
+ * <i>without</i> an assigned {@link GLContext}, hence not initialized completely.<br>
+ * The {@link GLContext} can be assigned later manually via {@link GLAutoDrawable#setContext(GLContext, boolean) setContext(ctx)}
+ * <i>or</i> it will be created <i>lazily</i> at the 1st {@link GLAutoDrawable#display() display()} method call.<br>
+ * <i>Lazy</i> {@link GLContext} creation will take a shared {@link GLContext} into account
+ * which has been set {@link GLOffscreenAutoDrawable#setSharedContext(GLContext) directly}
+ * or {@link GLOffscreenAutoDrawable#setSharedAutoDrawable(GLAutoDrawable) via another GLAutoDrawable}.
+ * </p>
+ *
+ * @param deviceReq which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param createNewDevice if <code>true</code> a new independent device instance is created from the <code>deviceReq</code>, otherwise <code>deviceReq</code> is used as-is and must be valid!
+ * @param capsRequested the desired {@link GLCapabilitiesImmutable}, incl. it's {@link GLProfile}.
+ * For shared context, same {@link GLCapabilitiesImmutable#getVisualID(com.jogamp.nativewindow.VisualIDHolder.VIDType)}
+ * across shared drawables will yield best compatibility.
+ * @param chooser the custom chooser, may be null for default
+ * @return the created and realized <i>dummy</i> {@link GLAutoDrawable} instance
+ *
+ * @see #createDummyDrawable(AbstractGraphicsDevice, boolean, GLCapabilitiesImmutable, GLCapabilitiesChooser)
+ */
+ public abstract GLAutoDrawable createDummyAutoDrawable(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+
+ /**
+ * Creates an {@link GLDrawable#isRealized() unrealized} offscreen {@link GLDrawable}
+ * incl it's offscreen {@link NativeSurface} with the given capabilites and dimensions.
+ * <p>
+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+ * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
+ * it is auto-configured. The latter will set offscreen and also FBO <i>or</i> Pbuffer, whichever is available in that order.
+ * </p>
+ * <p>
+ * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
+ * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
+ * </p>
+ * <p>
+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
+ * </p>
+ * <p>
+ * If neither FBO nor Pbuffer is available,
+ * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated.
+ * </p>
+ * <p>
+ * The resulting {@link GLDrawable} has it's own independent device instance using <code>device</code> details.
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param caps the requested GLCapabilties
+ * @param chooser the custom chooser, may be null for default
+ * @param width the requested offscreen width
+ * @param height the requested offscreen height
+ *
+ * @return the created unrealized offscreen {@link GLDrawable}
+ *
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the Offscreen to fail.
+ *
+ * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)
+ */
+ public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device,
+ GLCapabilitiesImmutable caps,
+ GLCapabilitiesChooser chooser,
+ int width, int height) throws GLException;
+
+ /**
+ * Creates an {@link GLDrawable#isRealized() unrealized} dummy {@link GLDrawable}.
+ * A dummy drawable is not visible on screen and will not be used to render directly to, it maybe on- or offscreen.
+ * <p>
+ * It is used to allow the creation of a {@link GLContext} to query information.
+ * It also allows creation of framebuffer objects which are used for rendering or creating a shared GLContext w/o actually rendering to this dummy drawable's framebuffer.
+ * </p>
+ * @param deviceReq which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param createNewDevice if <code>true</code> a new independent device instance is created from the <code>deviceReq</code>, otherwise <code>deviceReq</code> is used as-is and must be valid!
+ * @param capsRequested the desired {@link GLCapabilitiesImmutable}, incl. it's {@link GLProfile}.
+ * For shared context, same {@link GLCapabilitiesImmutable#getVisualID(com.jogamp.nativewindow.VisualIDHolder.VIDType) visual ID}
+ * or {@link GLCapabilitiesImmutable caps}
+ * across shared drawables will yield best compatibility.
+ * @param chooser the custom chooser, may be null for default
+ * @return the created unrealized dummy {@link GLDrawable}
+ */
+ public abstract GLDrawable createDummyDrawable(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+
+ /**
+ * Creates a proxy {@link NativeSurface} w/ defined surface handle,
+ * i.e. a {@link jogamp.nativewindow.WrappedSurface} or {@link jogamp.nativewindow.windows.GDISurface} instance.
+ * <p>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given
+ * <code>windowHandle</code>'s native visualID if set or the given {@link GLCapabilitiesImmutable}.
+ * </p>
+ * <p>
+ * Lifecycle (creation and destruction) of the given surface handle shall be handled by the caller
+ * via {@link ProxySurface#createNotify()} and {@link ProxySurface#destroyNotify()}.
+ * </p>
+ * <p>
+ * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate}
+ * you will be able to implement a new native windowing system binding almost on-the-fly,
+ * see {@link com.jogamp.opengl.swt.GLCanvas}.
+ * </p>
+ * <p>
+ * The resulting {@link GLOffscreenAutoDrawable} has it's own independent device instance using <code>device</code> details
+ * which may be blocking depending on platform and windowing-toolkit requirements.
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * Caller has to ensure it is compatible w/ the given <code>windowHandle</code>
+ * @param screenIdx matching screen index of given <code>windowHandle</code>
+ * @param windowHandle the native window handle
+ * @param caps the requested GLCapabilties
+ * @param chooser the custom chooser, may be null for default
+ * @param upstream optional {@link UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents.
+ * @return the created {@link ProxySurface} instance w/ defined surface handle.
+ */
+ public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ int screenIdx,
+ long windowHandle,
+ GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
+
+ /**
+ * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
+ * <p>
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+ * </p>
+ * <p>
+ * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}.
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasBasicFBOSupport()
+ */
+ public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp);
+
+ /**
+ * Returns true if it is possible to create an <i>pbuffer surface</i>.
+ * <p>
+ * Some older graphics cards do not have this capability,
+ * as well as some new GL implementation, i.e. OpenGL 3 core on OSX.
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ */
+ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp);
+
+ //----------------------------------------------------------------------
+ // Methods for interacting with third-party OpenGL libraries
+
+ /**
+ * <P> Creates a GLContext object representing an existing OpenGL
+ * context in an external (third-party) OpenGL-based library. This
+ * GLContext object may be used to draw into this preexisting
+ * context using its {@link GL} and {@link
+ * com.jogamp.opengl.glu.GLU} objects. New contexts created through
+ * {@link GLDrawable}s may share textures and display lists with
+ * this external context. </P>
+ *
+ * <P> The underlying OpenGL context must be current on the current
+ * thread at the time this method is called. The user is responsible
+ * for the maintenance of the underlying OpenGL context; calls to
+ * <code>makeCurrent</code> and <code>release</code> on the returned
+ * GLContext object have no effect. If the underlying OpenGL context
+ * is destroyed, the <code>destroy</code> method should be called on
+ * the <code>GLContext</code>. A new <code>GLContext</code> object
+ * should be created for each newly-created underlying OpenGL
+ * context.
+ *
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the external GLContext to fail.
+ */
+ public abstract GLContext createExternalGLContext()
+ throws GLException;
+
+ /**
+ * Returns true if it is possible to create an external GLDrawable
+ * object via {@link #createExternalGLDrawable}.
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ */
+ public abstract boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device);
+
+ /**
+ * <P> Creates a {@link GLDrawable} object representing an existing
+ * OpenGL drawable in an external (third-party) OpenGL-based
+ * library. This GLDrawable object may be used to create new,
+ * fully-functional {@link GLContext}s on the OpenGL drawable. This
+ * is useful when interoperating with a third-party OpenGL-based
+ * library and it is essential to not perturb the state of the
+ * library's existing context, even to the point of not sharing
+ * textures or display lists with that context. </P>
+ *
+ * <P> An underlying OpenGL context must be current on the desired
+ * drawable and the current thread at the time this method is
+ * called. The user is responsible for the maintenance of the
+ * underlying drawable. If one or more contexts are created on the
+ * drawable using {@link GLDrawable#createContext}, and the drawable
+ * is deleted by the third-party library, the user is responsible
+ * for calling {@link GLContext#destroy} on these contexts. </P>
+ *
+ * <P> Calls to <code>setSize</code>, <code>getWidth</code> and
+ * <code>getHeight</code> are illegal on the returned GLDrawable. If
+ * these operations are required by the user, they must be performed
+ * by the third-party library. </P>
+ *
+ * <P> It is legal to create both an external GLContext and
+ * GLDrawable representing the same third-party OpenGL entities.
+ * This can be used, for example, to query current state information
+ * using the external GLContext and then create and set up new
+ * GLContexts using the external GLDrawable. </P>
+ *
+ * <P> This functionality may not be available on all platforms and
+ * {@link #canCreateExternalGLDrawable} should be called first to
+ * see if it is present. For example, on X11 platforms, this API
+ * requires the presence of GLX 1.3 or later.
+ *
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the external GLDrawable to fail.
+ */
+ public abstract GLDrawable createExternalGLDrawable()
+ throws GLException;
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLEventListener.java b/src/jogl/classes/com/jogamp/opengl/GLEventListener.java
new file mode 100644
index 000000000..8c5dfd3b3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLEventListener.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import java.util.EventListener;
+
+/** Declares events which client code can use to manage OpenGL
+ rendering into a {@link GLAutoDrawable}. At the time any of these
+ methods is called, the drawable has made its associated OpenGL
+ context current, so it is valid to make OpenGL calls. */
+
+public interface GLEventListener extends EventListener {
+ /** Called by the drawable immediately after the OpenGL context is
+ initialized. Can be used to perform one-time OpenGL
+ initialization per GLContext, such as setup of lights and display lists.<p>
+
+ Note that this method may be called more than once if the underlying
+ OpenGL context for the GLAutoDrawable is destroyed and
+ recreated, for example if a GLCanvas is removed from the widget
+ hierarchy and later added again.
+ */
+ public void init(GLAutoDrawable drawable);
+
+ /** Notifies the listener to perform the release of all OpenGL
+ resources per GLContext, such as memory buffers and GLSL programs.<P>
+
+ Called by the drawable before the OpenGL context is
+ destroyed by an external event, like a reconfiguration of the
+ {@link GLAutoDrawable} closing an attached window,
+ but also manually by calling {@link GLAutoDrawable#destroy destroy}.<P>
+
+ Note that this event does not imply the end of life of the application.
+ It could be produced with a followup call to {@link #init(GLAutoDrawable)}
+ in case the GLContext has been recreated,
+ e.g. due to a pixel configuration change in a multihead environment.
+ */
+ public void dispose(GLAutoDrawable drawable);
+
+ /** Called by the drawable to initiate OpenGL rendering by the
+ client. After all GLEventListeners have been notified of a
+ display event, the drawable will swap its buffers if {@link
+ GLAutoDrawable#setAutoSwapBufferMode setAutoSwapBufferMode} is
+ enabled. */
+ public void display(GLAutoDrawable drawable);
+
+ /**
+ * Called by the drawable during the first repaint after the
+ * component has been resized.
+ * <p>
+ * The client can update it's viewport associated data
+ * and view volume of the window appropriately.
+ * </p>
+ * <p>
+ * For efficiency the GL viewport has already been updated
+ * via <code>glViewport(x, y, width, height)</code> when this method is called.
+ * </p>
+ *
+ * @param drawable the triggering {@link GLAutoDrawable}
+ * @param x viewport x-coord in pixel units
+ * @param y viewport y-coord in pixel units
+ * @param width viewport width in pixel units
+ * @param height viewport height in pixel units
+ */
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
index bfd5fe115..8f0724b03 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
@@ -30,18 +30,18 @@ package com.jogamp.opengl;
import java.util.ArrayList;
import java.util.List;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.DefaultGraphicsDevice;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GLAnimatorControl;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLRunnable;
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.DefaultGraphicsDevice;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.ProxySurface;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLRunnable;
import jogamp.opengl.Debug;
@@ -173,7 +173,7 @@ public class GLEventListenerState {
* <p>
* Locking is performed on the {@link GLAutoDrawable auto-drawable's}
* {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
- * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
* </p>
*
* @param src {@link GLAutoDrawable} source to move components from
@@ -203,7 +203,7 @@ public class GLEventListenerState {
* Locking is performed on the {@link GLAutoDrawable auto-drawable's}
* {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface},
* which is <i>not released</i> if <code>keepLocked</code> is <code>true</code>.
- * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
* </p>
* <p>
* <code>keepLocked</code> may be utilized if swapping a context between drawables
@@ -321,7 +321,7 @@ public class GLEventListenerState {
* <p>
* Locking is performed on the {@link GLAutoDrawable auto-drawable's}
* {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
- * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
* </p>
* <p>
* Note: After this operation, the GLEventListenerState reference should be released.
@@ -351,7 +351,7 @@ public class GLEventListenerState {
* <p>
* Locking is performed on the {@link GLAutoDrawable auto-drawable's}
* {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
- * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
* </p>
* <p>
* If the {@link GLAutoDrawable} <code>dest</code> has been kept locked by {@link #moveFrom(GLAutoDrawable, boolean)},
diff --git a/src/jogl/classes/com/jogamp/opengl/GLException.java b/src/jogl/classes/com/jogamp/opengl/GLException.java
new file mode 100644
index 000000000..843934ab2
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLException.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+/** A generic exception for OpenGL errors used throughout the binding
+ as a substitute for {@link RuntimeException}. */
+@SuppressWarnings("serial")
+public class GLException extends RuntimeException {
+ /** Constructs a GLException object. */
+ public GLException() {
+ super();
+ }
+
+ /** Constructs a GLException object with the specified detail
+ message. */
+ public GLException(final String message) {
+ super(message);
+ }
+
+ /** Constructs a GLException object with the specified detail
+ message and root cause. */
+ public GLException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ /** Constructs a GLException object with the specified root
+ cause. */
+ public GLException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a GLException object with the specified root
+ * cause with a decorating message including the current thread name.
+ * @since 2.2
+ */
+ public static GLException newGLException(final Throwable t) {
+ return new GLException("Caught "+t.getClass().getSimpleName()+": "+t.getMessage()+" on thread "+Thread.currentThread().getName(), t);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLFBODrawable.java b/src/jogl/classes/com/jogamp/opengl/GLFBODrawable.java
new file mode 100644
index 000000000..69358743e
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLFBODrawable.java
@@ -0,0 +1,227 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.nativewindow.NativeWindowException;
+
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Colorbuffer;
+import com.jogamp.opengl.FBObject.ColorAttachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.GLRendererQuirks;
+
+/**
+ * Platform-independent {@link GLDrawable} specialization,
+ * exposing {@link FBObject} functionality.
+ *
+ * <p>
+ * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound
+ * and made current the first time, hence only then it's capabilities <i>fully</i> reflect expectations,
+ * i.e. color, depth, stencil and MSAA bits will be <i>valid</i> only after the first {@link GLContext#makeCurrent() makeCurrent()} call.
+ * On-/offscreen bits are <i>valid</i> after {@link #setRealized(boolean) setRealized(true)}.
+ * </p>
+ *
+ * <p>
+ * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}.
+ * </p>
+ * <p>
+ * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}.
+ * </p>
+ * <p>
+ * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}.
+ * Hence double buffering is always the case w/ MSAA.
+ * </p>
+ * <p>
+ * In non MSAA a second explicit {@link FBObject framebuffer} is being used.
+ * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection
+ * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}.
+ * This method also allows usage of both textures seperately.
+ * </p>
+ * <p>
+ * It would be possible to implement double buffering simply using
+ * {@link Colorbuffer}s with one {@link FBObject framebuffer}.
+ * This would require mode selection and hence complicate the API. Besides, it would
+ * not support differentiation of read and write framebuffer and hence not be spec compliant.
+ * </p>
+ * <p>
+ * Actual swapping of the {@link Colorbuffer}s and/or {@link FBObject framebuffer}
+ * is performed either in the {@link jogamp.opengl.GLContextImpl#contextMadeCurrent(boolean) context current hook}
+ * or when {@link jogamp.opengl.GLDrawableImpl#swapBuffersImpl(boolean) swapping buffers}, whatever comes first.
+ * </p>
+ */
+public interface GLFBODrawable extends GLDrawable {
+ // public enum DoubleBufferMode { NONE, TEXTURE, FBO }; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+
+ /** FBO Mode Bit: Use a {@link TextureAttachment} for the {@link #getColorbuffer(int) render colorbuffer}, see {@link #setFBOMode(int)}. */
+ public static final int FBOMODE_USE_TEXTURE = 1 << 0;
+
+ /**
+ * @return <code>true</code> if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise <code>false</code>.
+ */
+ public boolean isInitialized();
+
+ /**
+ * Set the FBO mode bits used for FBO creation.
+ * <p>
+ * Default value is: {@link #FBOMODE_USE_TEXTURE}.
+ * </p>
+ * <p>
+ * If {@link GLRendererQuirks#BuggyColorRenderbuffer} is set,
+ * {@link #FBOMODE_USE_TEXTURE} is always added at initialization.
+ * </p>
+ *
+ * @param modeBits custom FBO mode bits like {@link #FBOMODE_USE_TEXTURE}.
+ * @throws IllegalStateException if already initialized, see {@link #isInitialized()}.
+ */
+ void setFBOMode(final int modeBits) throws IllegalStateException;
+
+ /**
+ * @return the used FBO mode bits, mutable via {@link #setFBOMode(int)}
+ */
+ int getFBOMode();
+
+ /**
+ * Notify this instance about upstream size change
+ * to reconfigure the {@link FBObject}.
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
+ * @throws GLException if resize operation failed
+ */
+ void resetSize(final GL gl) throws GLException;
+
+ /**
+ * @return the used texture unit
+ */
+ int getTextureUnit();
+
+ /**
+ *
+ * @param unit the texture unit to be used
+ */
+ void setTextureUnit(final int unit);
+
+ /**
+ * Set the number of sample buffers if using MSAA
+ *
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
+ * @param newSamples new sample size
+ * @throws GLException if resetting the FBO failed
+ */
+ void setNumSamples(final GL gl, final int newSamples) throws GLException;
+
+ /**
+ * @return the number of sample buffers if using MSAA, otherwise 0
+ */
+ int getNumSamples();
+
+ /**
+ * Sets the number of buffers (FBO) being used if using {@link GLCapabilities#getDoubleBuffered() double buffering}.
+ * <p>
+ * If {@link GLCapabilities#getDoubleBuffered() double buffering} is not chosen, this is a NOP.
+ * </p>
+ * <p>
+ * Must be called before {@link #isInitialized() initialization}, otherwise an exception is thrown.
+ * </p>
+ * @return the new number of buffers (FBO) used, maybe different than the requested <code>bufferCount</code> (see above)
+ * @throws IllegalStateException if already initialized, see {@link #isInitialized()}.
+ */
+ int setNumBuffers(final int bufferCount) throws IllegalStateException, GLException;
+
+ /**
+ * @return the number of buffers (FBO) being used. 1 if not using {@link GLCapabilities#getDoubleBuffered() double buffering},
+ * otherwise &ge; 2, depending on {@link #setNumBuffers(int)}.
+ */
+ int getNumBuffers();
+
+ /**
+ * @return the used {@link DoubleBufferMode}
+ */
+ // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+
+ /**
+ * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization},
+ * otherwise an exception is thrown.
+ * <p>
+ * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}.
+ * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}
+ * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored.
+ * </p>
+ * <p>
+ * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect.
+ * </p>
+ * @throws GLException if already initialized, see {@link #isInitialized()}.
+ */
+ // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+
+ /**
+ * If MSAA is being used and {@link GL#GL_FRONT} is requested,
+ * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned.
+ *
+ * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names
+ * @return the named {@link FBObject}
+ * @throws IllegalArgumentException if an illegal buffer name is being used
+ */
+ FBObject getFBObject(final int bufferName) throws IllegalArgumentException;
+
+ /**
+ * Returns the named {@link Colorbuffer} instance.
+ * <p>
+ * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible
+ * and an exception is being thrown if {@link GL#GL_BACK} is being requested.
+ * </p>
+ * <p>
+ * Depending on the {@link #setFBOMode(int) fbo mode} the resulting {@link Colorbuffer}
+ * is either a {@link TextureAttachment} if {@link #FBOMODE_USE_TEXTURE} is set,
+ * otherwise a {@link ColorAttachment}.
+ * See {@link Colorbuffer#isTextureAttachment()}.
+ * </p>
+ * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names
+ * @return the named {@link Colorbuffer}
+ * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used
+ */
+ Colorbuffer getColorbuffer(final int bufferName) throws IllegalArgumentException;
+
+ /** Resizeable {@link GLFBODrawable} specialization */
+ public interface Resizeable extends GLFBODrawable {
+ /**
+ * Resize this {@link GLFBODrawable}'s surface.
+ * <p>
+ * This drawable is being locked during operation.
+ * </p>
+ * @param context the {@link GLContext} bound to this drawable, will be made current during operation
+ * A prev. current context will be make current after operation.
+ * @param newWidth new width in pixel units
+ * @param newHeight new width in pixel units
+ * @throws NativeWindowException in case the surface could no be locked
+ * @throws GLException in case an error during the resize operation occurred
+ */
+ void setSurfaceSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/GLOffscreenAutoDrawable.java
new file mode 100644
index 000000000..a2d0f5fdb
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLOffscreenAutoDrawable.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.nativewindow.NativeWindowException;
+
+import com.jogamp.opengl.FBObject;
+
+/**
+ * Platform-independent {@link GLAutoDrawable} specialization,
+ * exposing offscreen functionality.
+ * <p>
+ * This class distinguishes itself from {@link GLAutoDrawable}
+ * with it's {@link #setSurfaceSize(int, int)} functionality.
+ * </p>
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
+ */
+public interface GLOffscreenAutoDrawable extends GLAutoDrawable, GLSharedContextSetter {
+
+ /**
+ * Resize this {@link GLAutoDrawable}'s surface
+ * @param newWidth new width in pixel units
+ * @param newHeight new height in pixel units
+ * @throws NativeWindowException in case the surface could no be locked
+ * @throws GLException in case of an error during the resize operation
+ */
+ void setSurfaceSize(int newWidth, int newHeight) throws NativeWindowException, GLException;
+
+ /**
+ * Set the upstream UI toolkit object.
+ * @see #getUpstreamWidget()
+ */
+ void setUpstreamWidget(Object newUpstreamWidget);
+
+ /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */
+ public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable {
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLPipelineFactory.java b/src/jogl/classes/com/jogamp/opengl/GLPipelineFactory.java
new file mode 100644
index 000000000..8d8b0428b
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLPipelineFactory.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package com.jogamp.opengl;
+
+import java.lang.reflect.*;
+import java.util.StringTokenizer;
+
+import com.jogamp.common.util.ReflectionUtil;
+
+import jogamp.opengl.*;
+
+/**
+ * Factory for pipelining GL instances
+ */
+public class GLPipelineFactory {
+ public static final boolean DEBUG = Debug.debug("GLPipelineFactory");
+
+ /**
+ * Creates a pipelined GL instance using the given downstream <code>downstream</code>
+ * and optional arguments <code>additionalArgs</code> for the constructor.
+ *
+ * <p>
+ * Sample code which installs a Debug and Trace pipeline
+ * automatic w/ user defined interface, here: GL2ES2:
+ * <pre>
+ * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", GL2ES2.class, gl, null) );
+ * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", GL2ES2.class, gl, new Object[] { System.err } ) );
+ * </pre>
+ * or automatic w/ automatic defined class:
+ * <pre>
+ * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) );
+ * gl = drawable.setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) );
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * The upstream GL instance is determined as follows:
+ * <ul>
+ * <li> Use <code>pipelineClazzBaseName</code> as the class name's full basename, incl. package name</li>
+ * <li> For the <code>downstream</code> class and it's superclasses, do:</li>
+ * <ul>
+ * <li> For all <code>downstream</code> class and superclass interfaces, do:</li>
+ * <ul>
+ * <li> If <code>reqInterface</code> is not null and the interface is unequal, continue loop.</li>
+ * <li> If <code>downstream</code> is not instance of interface, continue loop.</li>
+ * <li> If upstream class is available use it, end loop.</li>
+ * </ul>
+ * </ul>
+ * </ul>
+ * </p>
+ *
+ * @param pipelineClazzBaseName the basename of the pipline class name
+ * @param reqInterface optional requested interface to be used, may be null, in which case the first matching one is used
+ * @param downstream is always the 1st argument for the upstream constructor
+ * @param additionalArgs additional arguments for the upstream constructor
+ */
+ public static final GL create(final String pipelineClazzBaseName, final Class<?> reqInterface, final GL downstream, final Object[] additionalArgs) {
+ Class<?> downstreamClazz = downstream.getClass();
+ Class<?> upstreamClazz = null;
+ Class<?> interfaceClazz = null;
+
+ if(DEBUG) {
+ System.out.println("GLPipelineFactory: Start "+downstreamClazz.getName()+", req. Interface: "+reqInterface+" -> "+pipelineClazzBaseName);
+ }
+
+ // For all classes: child -> parent
+ do {
+ // For all interfaces: right -> left == child -> parent
+ // It is important that this matches with the gluegen cfg file's 'Implements' clause !
+ final Class<?>[] clazzes = downstreamClazz.getInterfaces();
+ for(int i=clazzes.length-1; null==upstreamClazz && i>=0; i--) {
+ if(DEBUG) {
+ System.out.println("GLPipelineFactory: Try "+downstreamClazz.getName()+" Interface["+i+"]: "+clazzes[i].getName());
+ }
+ if( reqInterface != null && !reqInterface.getName().equals(clazzes[i].getName()) ) {
+ if(DEBUG) {
+ System.out.println("GLPipelineFactory: requested Interface "+reqInterface+" is _not_ "+ clazzes[i].getName());
+ }
+ continue; // not the requested one ..
+ }
+ if( ! clazzes[i].isInstance(downstream) ) {
+ if(DEBUG) {
+ System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " is _not_ instance of "+ clazzes[i].getName());
+ }
+ continue; // not a compatible one
+ } else {
+ if(DEBUG) {
+ System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " _is_ instance of "+ clazzes[i].getName());
+ }
+ }
+ upstreamClazz = getUpstreamClazz(clazzes[i], pipelineClazzBaseName);
+ if( null != upstreamClazz ) {
+ interfaceClazz = clazzes[i];
+ }
+ }
+
+ if(null==upstreamClazz) {
+ downstreamClazz = downstreamClazz.getSuperclass();
+ }
+ } while (null!=downstreamClazz && null==upstreamClazz);
+
+
+ if(null==upstreamClazz) {
+ throw new GLException("No pipeline ("+pipelineClazzBaseName+"*) available for :"+downstream.getClass().getName());
+ }
+
+ if(DEBUG) {
+ System.out.println("GLPipelineFactory: Got : "+ upstreamClazz.getName()+", base interface: "+interfaceClazz.getName());
+ }
+
+ final Class<?>[] cstrArgTypes = new Class<?>[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
+ {
+ int i = 0;
+ cstrArgTypes[i++] = interfaceClazz;
+ for(int j=0; null!=additionalArgs && j<additionalArgs.length; j++) {
+ cstrArgTypes[i++] = additionalArgs[j].getClass();
+ }
+ }
+ // throws exception if cstr not found!
+ final Constructor<?> cstr = ReflectionUtil.getConstructor(upstreamClazz, cstrArgTypes);
+ Object instance = null;
+ try {
+ final Object[] cstrArgs = new Object[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
+ {
+ int i = 0;
+ cstrArgs[i++] = downstream;
+ for(int j=0; null!=additionalArgs && j<additionalArgs.length; j++) {
+ cstrArgs[i++] = additionalArgs[j];
+ }
+ }
+ instance = cstr.newInstance( cstrArgs ) ;
+ } catch (final Throwable t) { t.printStackTrace(); }
+ if(null==instance) {
+ throw new GLException("Error: Couldn't create instance of pipeline: "+upstreamClazz.getName()+
+ " ( "+getArgsClassNameList(downstreamClazz, additionalArgs) +" )");
+ }
+ if( ! (instance instanceof GL) ) {
+ throw new GLException("Error: "+upstreamClazz.getName()+" not an instance of GL");
+ }
+ return (GL) instance;
+ }
+
+ private static final String getArgsClassNameList(final Class<?> arg0, final Object[] args) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(arg0.getName());
+ if(args!=null) {
+ for(int j=0; j<args.length; j++) {
+ sb.append(", ");
+ sb.append(args[j].getClass().getName());
+ }
+ }
+ return sb.toString();
+ }
+
+ private static final Class<?> getUpstreamClazz(final Class<?> downstreamClazz, final String pipelineClazzBaseName) {
+ final String downstreamClazzName = downstreamClazz.getName();
+
+ final StringTokenizer st = new StringTokenizer(downstreamClazzName, ".");
+ String downstreamClazzBaseName = downstreamClazzName;
+ while(st.hasMoreTokens()) {
+ downstreamClazzBaseName = st.nextToken();
+ }
+ final String upstreamClazzName = pipelineClazzBaseName+downstreamClazzBaseName;
+
+ Class<?> upstreamClazz = null;
+ try {
+ upstreamClazz = Class.forName(upstreamClazzName, true, GLPipelineFactory.class.getClassLoader());
+ } catch (final Throwable e) { e.printStackTrace(); }
+
+ return upstreamClazz;
+ }
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/GLProfile.java b/src/jogl/classes/com/jogamp/opengl/GLProfile.java
new file mode 100644
index 000000000..a36a21ad5
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLProfile.java
@@ -0,0 +1,2322 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package com.jogamp.opengl;
+
+import jogamp.opengl.Debug;
+import jogamp.opengl.GLDrawableFactoryImpl;
+import jogamp.opengl.DesktopGLDynamicLookupHelper;
+
+import com.jogamp.common.ExceptionUtils;
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.jvm.JNILibLoaderBase;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.cache.TempJarCache;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveThreadGroupLock;
+import com.jogamp.gluegen.runtime.FunctionAddressResolver;
+import com.jogamp.nativewindow.NativeWindowVersion;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.JoglVersion;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.opengl.fixedfunc.GLPointerFunc;
+
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Specifies the the OpenGL profile.
+ *
+ * This class static singleton initialization queries the availability of all OpenGL Profiles
+ * and instantiates singleton GLProfile objects for each available profile.
+ *
+ * The platform default profile may be used, using {@link GLProfile#GetProfileDefault()},
+ * or more specialized versions using the other static GetProfile methods.
+ */
+public class GLProfile {
+
+ public static final boolean DEBUG;
+
+ /**
+ * In case no native OpenGL core profiles are required
+ * and if one platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.openglcore</code> disables querying possible existing native OpenGL core profiles.
+ * <p>
+ * This exclusion is disabled for {@link Platform.OSType#MACOS}.
+ * </p>
+ */
+ public static final boolean disableOpenGLCore;
+
+ /**
+ * In case the implementation of the <i>ARB_create_context</i>
+ * context creation extension is buggy on one platform,
+ * setting the property <code>jogl.disable.openglarbcontext</code> disables utilizing it.
+ * <p>
+ * This exclusion also disables {@link #disableOpenGLES OpenGL ES}.
+ * </p>
+ * <p>
+ * This exclusion is disabled for {@link Platform.OSType#MACOS}.
+ * </p>
+ */
+ public static final boolean disableOpenGLARBContext;
+
+ /**
+ * In case no OpenGL ES profiles are required
+ * and if one platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.opengles</code> disables querying possible existing OpenGL ES profiles.
+ */
+ public static final boolean disableOpenGLES;
+
+ /**
+ * In case no OpenGL desktop profiles are required
+ * and if one platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.opengldesktop</code> disables querying possible existing OpenGL desktop profiles.
+ */
+ public static final boolean disableOpenGLDesktop;
+
+ /**
+ * Disable surfaceless OpenGL context capability and its probing
+ * by setting the property <code>jogl.disable.surfacelesscontext</code>.
+ * <p>
+ * By default surfaceless OpenGL context capability is probed,
+ * i.e. whether an OpenGL context can be made current without a default framebuffer.
+ * </p>
+ * <p>
+ * If probing fails or if this property is set, the {@link GLRendererQuirks quirk} {@link GLRendererQuirks#NoSurfacelessCtx}
+ * is being set.
+ * </p>
+ */
+ public static final boolean disableSurfacelessContext;
+
+ /**
+ * We have to disable support for ANGLE, the D3D ES2 emulation on Windows provided w/ Firefox and Chrome.
+ * When run in the mentioned browsers, the eglInitialize(..) implementation crashes.
+ * <p>
+ * This can be overridden by explicitly enabling ANGLE on Windows by setting the property
+ * <code>jogl.enable.ANGLE</code>.
+ * </p>
+ */
+ public static final boolean enableANGLE;
+
+ static {
+ // Also initializes TempJarCache if shall be used.
+ Platform.initSingleton();
+ final boolean isOSX = Platform.OSType.MACOS == Platform.getOSType();
+
+ DEBUG = Debug.debug("GLProfile");
+ disableOpenGLCore = PropertyAccess.isPropertyDefined("jogl.disable.openglcore", true) && !isOSX;
+ disableOpenGLARBContext = PropertyAccess.isPropertyDefined("jogl.disable.openglarbcontext", true) && !isOSX;
+ disableOpenGLES = disableOpenGLARBContext || PropertyAccess.isPropertyDefined("jogl.disable.opengles", true);
+ disableOpenGLDesktop = PropertyAccess.isPropertyDefined("jogl.disable.opengldesktop", true);
+ disableSurfacelessContext = PropertyAccess.isPropertyDefined("jogl.disable.surfacelesscontext", true);
+ enableANGLE = PropertyAccess.isPropertyDefined("jogl.enable.ANGLE", true);
+ }
+
+ /**
+ * @return <code>true</code> if JOGL has been initialized, i.e. manually via {@link #initSingleton()} or implicit,
+ * otherwise returns <code>false</code>.
+ *
+ * @since 2.2.1
+ */
+ public static boolean isInitialized() {
+ initLock.lock();
+ try {
+ return initialized;
+ } finally {
+ initLock.unlock();
+ }
+ }
+
+ /**
+ * Static initialization of JOGL.
+ *
+ * <p>
+ * This method shall not need to be called for other reasons than having a defined initialization sequence.
+ * </p>
+ *
+ * <P>
+ * In case this method is not invoked, GLProfile is initialized implicit by
+ * the first call to {@link #getDefault()}, {@link #get(java.lang.String)}.
+ * <P>
+ *
+ * <p>
+ * To initialize JOGL at startup ASAP, this method may be invoked in the <i>main class</i>'s
+ * static initializer block, in the <i>static main() method</i> or in the <i>Applet init() method</i>.
+ * </p>
+ *
+ * <p>
+ * Since JOGL's initialization is complex and involves multi threading, it is <b>not</b> recommended
+ * to be have it invoked on the AWT EDT thread. In case all JOGL usage is performed
+ * on the AWT EDT, invoke this method outside the AWT EDT - see above.
+ * </p>
+ *
+ */
+ public static void initSingleton() {
+ final boolean justInitialized;
+ initLock.lock();
+ try {
+ if(!initialized) {
+ initialized = true;
+ justInitialized = true;
+ if(DEBUG) {
+ System.err.println("GLProfile.initSingleton() - thread "+Thread.currentThread().getName());
+ ExceptionUtils.dumpStack(System.err);
+ }
+
+ if(ReflectionUtil.DEBUG_STATS_FORNAME) {
+ ReflectionUtil.resetForNameCount();
+ }
+
+ // run the whole static initialization privileged to speed up,
+ // since this skips checking further access
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ Platform.initSingleton();
+
+ if(TempJarCache.isInitialized()) {
+ final ClassLoader cl = GLProfile.class.getClassLoader();
+ final String newtDebugClassName = "jogamp.newt.Debug";
+ final Class<?>[] classesFromJavaJars = new Class<?>[] { jogamp.nativewindow.Debug.class, jogamp.opengl.Debug.class, null };
+ if( ReflectionUtil.isClassAvailable(newtDebugClassName, cl) ) {
+ classesFromJavaJars[2] = ReflectionUtil.getClass(newtDebugClassName, false, cl);
+ }
+ JNILibLoaderBase.addNativeJarLibsJoglCfg(classesFromJavaJars);
+ }
+ initProfilesForDefaultDevices();
+ return null;
+ }
+ });
+ if( ReflectionUtil.DEBUG_STATS_FORNAME ) {
+ if( justInitialized ) {
+ System.err.println(ReflectionUtil.getForNameStats(null).toString());
+ }
+ }
+ } else {
+ justInitialized = false;
+ }
+ } finally {
+ initLock.unlock();
+ }
+ if(DEBUG) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES3Impl ) ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
+ }
+ }
+ }
+
+ /**
+ * Trigger eager initialization of GLProfiles for the given device,
+ * in case it isn't done yet.
+ *
+ * @throws GLException if no profile for the given device is available.
+ */
+ public static void initProfiles(final AbstractGraphicsDevice device) throws GLException {
+ getProfileMap(device, true);
+ }
+
+ /**
+ * Manual shutdown method, may be called after your last JOGL use
+ * within the running JVM.<br>
+ * It releases all temporary created resources, ie issues {@link com.jogamp.opengl.GLDrawableFactory#shutdown()}.<br>
+ * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked.<br>
+ * <p>
+ * This method shall not need to be called for other reasons than issuing a proper shutdown of resources at a defined time.
+ * </p>
+ */
+ public static void shutdown() {
+ initLock.lock();
+ try {
+ if(initialized) {
+ initialized = false;
+ if(DEBUG) {
+ System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName());
+ ExceptionUtils.dumpStack(System.err);
+ }
+ GLDrawableFactory.shutdown();
+ }
+ } finally {
+ initLock.unlock();
+ }
+ }
+
+ //
+ // Query platform available OpenGL implementation
+ //
+
+ /**
+ * Returns the availability of a profile on a device.
+ *
+ * @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device.
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ * or <code>[ null, GL ]</code> for the default profile.
+ * @return true if the profile is available for the device, otherwise false.
+ */
+ public static boolean isAvailable(final AbstractGraphicsDevice device, final String profile) {
+ initSingleton();
+ return isAvailableImpl(getProfileMap(device, false), profile);
+ }
+ private static boolean isAvailableImpl(final HashMap<String /*GLProfile_name*/, GLProfile> map, final String profile) {
+ return null != map && null != map.get(profile);
+ }
+
+ /**
+ * Returns the availability of a profile on the default device.
+ *
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ * or <code>[ null, GL ]</code> for the default profile.
+ * @return true if the profile is available for the default device, otherwise false.
+ */
+ public static boolean isAvailable(final String profile) {
+ return isAvailable(null, profile);
+ }
+
+ /**
+ * Returns the availability of any profile on the default device.
+ *
+ * @return true if any profile is available for the default device, otherwise false.
+ */
+ public static boolean isAnyAvailable() {
+ return isAvailable(null, null);
+ }
+
+ public static String glAvailabilityToString(final AbstractGraphicsDevice device) {
+ return glAvailabilityToString(device, null).toString();
+ }
+
+ public static StringBuilder glAvailabilityToString(final AbstractGraphicsDevice device, final StringBuilder sb) {
+ return glAvailabilityToString(device, sb, null, 0);
+ }
+ private static StringBuilder doIndent(final StringBuilder sb, final String indent, int indentCount) {
+ while(indentCount>0) {
+ sb.append(indent);
+ indentCount--;
+ }
+ return sb;
+ }
+ public static StringBuilder glAvailabilityToString(AbstractGraphicsDevice device, StringBuilder sb, final String indent, int indentCount) {
+ boolean avail;
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final boolean useIndent = null != indent;
+
+ initSingleton();
+
+ int allCount = 0;
+ int nativeCount = 0;
+
+ if(null==device) {
+ device = defaultDevice;
+ }
+ final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, false);
+
+ if(useIndent) {
+ doIndent(sb, indent, indentCount).append("Natives");
+ indentCount++;
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4bc+" ").append(indent);
+ } else {
+ sb.append("Natives["+GL4bc+" ");
+ }
+ avail=isAvailableImpl(map, GL4bc);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 4, GLContext.CTX_PROFILE_COMPAT);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4+" ").append(indent);
+ } else {
+ sb.append(", "+GL4+" ");
+ }
+ avail=isAvailableImpl(map, GL4);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 4, GLContext.CTX_PROFILE_CORE);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES3+" ").append(indent);
+ } else {
+ sb.append(", "+GLES3+" ");
+ }
+ avail=isAvailableImpl(map, GLES3);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_ES);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL3bc+" ").append(indent);
+ } else {
+ sb.append(", "+GL3bc+" ");
+ }
+ avail=isAvailableImpl(map, GL3bc);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_COMPAT);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL3+" ").append(indent);
+ } else {
+ sb.append(", "+GL3+" ");
+ }
+ avail=isAvailableImpl(map, GL3);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_CORE);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2+" ").append(indent);
+ } else {
+ sb.append(", "+GL2+" ");
+ }
+ avail=isAvailableImpl(map, GL2);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_COMPAT);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES2+" ").append(indent);
+ } else {
+ sb.append(", "+GLES2+" ");
+ }
+ avail=isAvailableImpl(map, GLES2);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES1+" ").append(indent);
+ } else {
+ sb.append(", "+GLES1+" ");
+ }
+ avail=isAvailableImpl(map, GLES1);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 1, GLContext.CTX_PROFILE_ES);
+ }
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Count\t"+nativeCount+" / "+allCount);
+ indentCount--;
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Common");
+ indentCount++;
+ } else {
+ sb.append(", count "+nativeCount+" / "+allCount+"], Common[");
+ }
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4ES3+" ").append(indent);
+ } else {
+ sb.append(", "+GL4ES3+" ");
+ }
+ sb.append(isAvailableImpl(map, GL4ES3));
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2GL3+" ").append(indent);
+ } else {
+ sb.append(", "+GL2GL3+" ");
+ }
+ sb.append(isAvailableImpl(map, GL2GL3));
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2ES2+" ").append(indent);
+ } else {
+ sb.append(", "+GL2ES2+" ");
+ }
+ sb.append(isAvailableImpl(map, GL2ES2));
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2ES1+" ").append(indent);
+ } else {
+ sb.append(", "+GL2ES1+" ");
+ }
+ sb.append(isAvailableImpl(map, GL2ES1));
+ allCount++;
+
+ if(useIndent) {
+ indentCount--;
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Mappings");
+ indentCount++;
+ } else {
+ sb.append("], Mappings[");
+ }
+
+ int profileCount = 0;
+
+ if(null != map) {
+ for (final Map.Entry<String,GLProfile> entry : map.entrySet()) {
+ if( GL_DEFAULT != entry.getKey() ) {
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount);
+ }
+ sb.append(entry.getKey()+(useIndent?" \t":" ")+entry.getValue());
+ if(!useIndent) {
+ sb.append(", ");
+ }
+ profileCount++;
+ }
+ }
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("default ");
+ } else {
+ sb.append(", default ");
+ }
+ try {
+ sb.append(getDefault(device));
+ } catch (final GLException gle) {
+ sb.append("n/a");
+ }
+ }
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Count\t"+profileCount+" / "+allCount);
+ sb.append(Platform.getNewline());
+ } else {
+ sb.append(", count "+profileCount+" / "+allCount+"]");
+ }
+
+ return sb;
+ }
+
+ /** Uses the default device */
+ public static String glAvailabilityToString() {
+ return glAvailabilityToString(null);
+ }
+
+ //
+ // Public (user-visible) profiles
+ //
+
+ /** The desktop OpenGL compatibility profile 4.x, with x >= 0, ie GL2 plus GL4.<br>
+ <code>bc</code> stands for backward compatibility. */
+ public static final String GL4bc = "GL4bc"; // Implicitly intern(), see Bug 1059
+
+ /** The desktop OpenGL core profile 4.x, with x >= 0 */
+ public static final String GL4 = "GL4"; // Implicitly intern(), see Bug 1059
+
+ /** The desktop OpenGL compatibility profile 3.x, with x >= 1, ie GL2 plus GL3.<br>
+ <code>bc</code> stands for backward compatibility. */
+ public static final String GL3bc = "GL3bc"; // Implicitly intern(), see Bug 1059
+
+ /** The desktop OpenGL core profile 3.x, with x >= 1 */
+ public static final String GL3 = "GL3"; // Implicitly intern(), see Bug 1059
+
+ /** The desktop OpenGL profile 1.x up to 3.0 */
+ public static final String GL2 = "GL2"; // Implicitly intern(), see Bug 1059
+
+ /** The embedded OpenGL profile ES 1.x, with x >= 0 */
+ public static final String GLES1 = "GLES1"; // Implicitly intern(), see Bug 1059
+
+ /** The embedded OpenGL profile ES 2.x, with x >= 0 */
+ public static final String GLES2 = "GLES2"; // Implicitly intern(), see Bug 1059
+
+ /** The embedded OpenGL profile ES 3.x, with x >= 0 */
+ public static final String GLES3 = "GLES3"; // Implicitly intern(), see Bug 1059
+
+ /** The intersection of the desktop GL2 and embedded ES1 profile */
+ public static final String GL2ES1 = "GL2ES1"; // Implicitly intern(), see Bug 1059
+
+ /** The intersection of the desktop GL3, GL2 and embedded ES2 profile */
+ public static final String GL2ES2 = "GL2ES2"; // Implicitly intern(), see Bug 1059
+
+ /** The intersection of the desktop GL3 and GL2 profile */
+ public static final String GL2GL3 = "GL2GL3"; // Implicitly intern(), see Bug 1059
+
+ /** The intersection of the desktop GL4 and ES3 profile, available only if either ES3 or GL4 w/ <code>GL_ARB_ES3_compatibility</code> is available. */
+ public static final String GL4ES3 = "GL4ES3"; // Implicitly intern(), see Bug 1059
+
+ /** The default profile, used for the device default profile map */
+ private static final String GL_DEFAULT = "GL_DEFAULT"; // Implicitly intern(), see Bug 1059
+ /** The default profile, used for the device default profile map */
+ private static final String GL_GL = "GL"; // Implicitly intern(), see Bug 1059
+
+ /**
+ * All GL Profiles in the order of default detection.
+ * Desktop compatibility profiles (the one with fixed function pipeline) comes first
+ * from highest to lowest version.
+ * <p> This includes the generic subset profiles GL2GL3, GL2ES2 and GL2ES1.</p>
+ *
+ * <ul>
+ * <li> GL4bc </li>
+ * <li> GL3bc </li>
+ * <li> GL2 </li>
+ * <li> GL4 </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL4ES3 </li>
+ * <li> GL2GL3 </li>
+ * <li> GLES2 </li>
+ * <li> GL2ES2 </li>
+ * <li> GLES1 </li>
+ * <li> GL2ES1 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GLES3, GL4ES3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 };
+
+ /**
+ * Order of maximum profiles.
+ *
+ * <ul>
+ * <li> GL4bc </li>
+ * <li> GL4 </li>
+ * <li> GL3bc </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL2 </li>
+ * <li> GLES2 </li>
+ * <li> GLES1 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2, GLES1 };
+
+ /**
+ * Order of minimum profiles.
+ *
+ * <ul>
+ * <li> GLES1 </li>
+ * <li> GLES2 </li>
+ * <li> GL2 </li>
+ * <li> GLES3 </li>
+ * <li> GL3 </li>
+ * <li> GL3bc </li>
+ * <li> GL4 </li>
+ * <li> GL4bc </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GLES3, GL3, GL3bc, GL4, GL4bc };
+
+ /**
+ * Order of minimum original desktop profiles.
+ *
+ * <ul>
+ * <li> GL2 </li>
+ * <li> GL3bc </li>
+ * <li> GL4bc </li>
+ * <li> GL3 </li>
+ * <li> GL4 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MIN_DESKTOP = new String[] { GL2, GL3bc, GL4bc, GL3, GL4 };
+
+ /**
+ * Order of maximum fixed function profiles
+ *
+ * <ul>
+ * <li> GL4bc </li>
+ * <li> GL3bc </li>
+ * <li> GL2 </li>
+ * <li> GLES1 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MAX_FIXEDFUNC = new String[] { GL4bc, GL3bc, GL2, GLES1 };
+
+ /**
+ * Order of maximum programmable shader profiles
+ *
+ * <ul>
+ * <li> GL4bc </li>
+ * <li> GL4 </li>
+ * <li> GL3bc </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL2 </li>
+ * <li> GLES2 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2 };
+
+ /**
+ * Order of maximum programmable shader <i>core only</i> profiles
+ *
+ * <ul>
+ * <li> GL4 </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GLES2 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER_CORE = new String[] { GL4, GL3, GLES3, GLES2 };
+
+ /** Returns a default GLProfile object, reflecting the best for the running platform.
+ * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL}
+ * and favors hardware acceleration.
+ * @throws GLException if no profile is available for the device.
+ * @see #GL_PROFILE_LIST_ALL
+ */
+ public static GLProfile getDefault(final AbstractGraphicsDevice device) {
+ final GLProfile glp = get(device, GL_DEFAULT);
+ return glp;
+ }
+
+ /** Returns a default GLProfile object, reflecting the best for the running platform.
+ * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL}
+ * and favors hardware acceleration.
+ * <p>Uses the default device.</p>
+ * @throws GLException if no profile is available for the default device.
+ */
+ public static GLProfile getDefault() {
+ return getDefault(defaultDevice);
+ }
+
+ /**
+ * Returns the highest profile.
+ * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX}
+ *
+ * @throws GLException if no profile is available for the device.
+ * @see #GL_PROFILE_LIST_MAX
+ */
+ public static GLProfile getMaximum(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(device, GL_PROFILE_LIST_MAX, favorHardwareRasterizer);
+ }
+
+ /** Uses the default device
+ * @throws GLException if no profile is available for the default device.
+ * @see #GL_PROFILE_LIST_MAX
+ */
+ public static GLProfile getMaximum(final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(GL_PROFILE_LIST_MAX, favorHardwareRasterizer);
+ }
+
+ /**
+ * Returns the lowest profile.
+ * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MIN}
+ *
+ * @throws GLException if no desktop profile is available for the device.
+ * @see #GL_PROFILE_LIST_MIN
+ */
+ public static GLProfile getMinimum(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(device, GL_PROFILE_LIST_MIN, favorHardwareRasterizer);
+ }
+
+ /** Uses the default device
+ * @throws GLException if no desktop profile is available for the default device.
+ * @see #GL_PROFILE_LIST_MIN
+ */
+ public static GLProfile getMinimum(final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(GL_PROFILE_LIST_MIN, favorHardwareRasterizer);
+ }
+
+
+ /**
+ * Returns the highest profile, implementing the fixed function pipeline.
+ * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_FIXEDFUNC}
+ *
+ * @throws GLException if no fixed function profile is available for the device.
+ * @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
+ */
+ public static GLProfile getMaxFixedFunc(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer);
+ }
+
+ /** Uses the default device
+ * @throws GLException if no fixed function profile is available for the default device.
+ * @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
+ */
+ public static GLProfile getMaxFixedFunc(final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer);
+ }
+
+ /**
+ * Returns the highest profile, implementing the programmable shader pipeline.
+ * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_PROGSHADER}
+ *
+ * @throws GLException if no programmable profile is available for the device.
+ * @see #GL_PROFILE_LIST_MAX_PROGSHADER
+ */
+ public static GLProfile getMaxProgrammable(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(device, GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer);
+ }
+
+ /** Uses the default device
+ * @throws GLException if no programmable profile is available for the default device.
+ * @see #GL_PROFILE_LIST_MAX_PROGSHADER
+ */
+ public static GLProfile getMaxProgrammable(final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer);
+ }
+
+ /**
+ * Returns the highest profile, implementing the programmable shader <i>core</i> pipeline <i>only</i>.
+ * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_PROGSHADER_CORE}
+ *
+ * @throws GLException if no programmable core profile is available for the device.
+ * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE
+ */
+ public static GLProfile getMaxProgrammableCore(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(device, GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer);
+ }
+
+ /** Uses the default device
+ * @throws GLException if no programmable core profile is available for the default device.
+ * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE
+ */
+ public static GLProfile getMaxProgrammableCore(final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer);
+ }
+
+ /**
+ * Returns the GL2ES1 profile implementation, hence compatible w/ GL2ES1.<br/>
+ * It returns:
+ * <pre>
+ * GLProfile.get(device, GLProfile.GL2ES1).getImpl());
+ * </pre>
+ * <p>Selection favors hardware rasterizer.</p>
+ *
+ * @throws GLException if no GL2ES1 compatible profile is available for the default device.
+ * @see #isGL2ES1()
+ * @see #get(AbstractGraphicsDevice, String)
+ * @see #getImpl()
+ */
+ public static GLProfile getGL2ES1(final AbstractGraphicsDevice device)
+ throws GLException
+ {
+ return get(device, GL2ES1).getImpl();
+ }
+
+ /**
+ * Calls {@link #getGL2ES1(AbstractGraphicsDevice)} using the default device.
+ * <p>Selection favors hardware rasterizer.</p>
+ * @see #getGL2ES1(AbstractGraphicsDevice)
+ */
+ public static GLProfile getGL2ES1()
+ throws GLException
+ {
+ return get(defaultDevice, GL2ES1).getImpl();
+ }
+
+ /**
+ * Returns the GL2ES2 profile implementation, hence compatible w/ GL2ES2.<br/>
+ * It returns:
+ * <pre>
+ * GLProfile.get(device, GLProfile.GL2ES2).getImpl());
+ * </pre>
+ * <p>Selection favors hardware rasterizer.</p>
+ *
+ * @throws GLException if no GL2ES2 compatible profile is available for the default device.
+ * @see #isGL2ES2()
+ * @see #get(AbstractGraphicsDevice, String)
+ * @see #getImpl()
+ */
+ public static GLProfile getGL2ES2(final AbstractGraphicsDevice device)
+ throws GLException
+ {
+ return get(device, GL2ES2).getImpl();
+ }
+
+ /**
+ * Calls {@link #getGL2ES2(AbstractGraphicsDevice)} using the default device.
+ * <p>Selection favors hardware rasterizer.</p>
+ * @see #getGL2ES2(AbstractGraphicsDevice)
+ */
+ public static GLProfile getGL2ES2()
+ throws GLException
+ {
+ return get(defaultDevice, GL2ES2).getImpl();
+ }
+
+ /**
+ * Returns the GL4ES3 profile implementation, hence compatible w/ GL4ES3.<br/>
+ * It returns:
+ * <pre>
+ * GLProfile.get(device, GLProfile.GL4ES3).getImpl());
+ * </pre>
+ * <p>Selection favors hardware rasterizer.</p>
+ *
+ * @throws GLException if no GL4ES3 compatible profile is available for the default device.
+ * @see #isGL4ES3()
+ * @see #get(AbstractGraphicsDevice, String)
+ * @see #getImpl()
+ */
+ public static GLProfile getGL4ES3(final AbstractGraphicsDevice device)
+ throws GLException
+ {
+ return get(device, GL4ES3).getImpl();
+ }
+
+ /**
+ * Calls {@link #getGL4ES3(AbstractGraphicsDevice)} using the default device.
+ * <p>Selection favors hardware rasterizer.</p>
+ * @see #getGL4ES3(AbstractGraphicsDevice)
+ */
+ public static GLProfile getGL4ES3()
+ throws GLException
+ {
+ return get(defaultDevice, GL4ES3).getImpl();
+ }
+
+ /**
+ * Returns the GL2GL3 profile implementation, hence compatible w/ GL2GL3.<br/>
+ * It returns:
+ * <pre>
+ * GLProfile.get(device, GLProfile.GL2GL3).getImpl());
+ * </pre>
+ * <p>Selection favors hardware rasterizer.</p>
+ *
+ * @throws GLException if no GL2GL3 compatible profile is available for the default device.
+ * @see #isGL2GL3()
+ * @see #get(AbstractGraphicsDevice, String)
+ * @see #getImpl()
+ */
+ public static GLProfile getGL2GL3(final AbstractGraphicsDevice device)
+ throws GLException
+ {
+ return get(device, GL2GL3).getImpl();
+ }
+
+ /**
+ * Calls {@link #getGL2GL3(AbstractGraphicsDevice)} using the default device.
+ * <p>Selection favors hardware rasterizer.</p>
+ * @see #getGL2GL3(AbstractGraphicsDevice)
+ */
+ public static GLProfile getGL2GL3()
+ throws GLException
+ {
+ return get(defaultDevice, GL2GL3).getImpl();
+ }
+
+ /** Returns a GLProfile object.
+ * verifies the given profile and chooses an appropriate implementation.
+ * A generic value of <code>null</code> or <code>GL</code> will result in
+ * the default profile.
+ *
+ * @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device.
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ * or <code>[ null, GL ]</code> for the default profile.
+ * @throws GLException if the requested profile is not available for the device.
+ */
+ public static GLProfile get(final AbstractGraphicsDevice device, String profile)
+ throws GLException
+ {
+ if(null==profile || profile == GL_GL) {
+ profile = GL_DEFAULT;
+ }
+ final HashMap<String /*GLProfile_name*/, GLProfile> glpMap = getProfileMap(device, true);
+ final GLProfile glp = glpMap.get(profile);
+ if(null == glp) {
+ throw new GLException("Profile "+profile+" is not available on "+device+", but: "+glpMap.values());
+ }
+ return glp;
+ }
+
+ /** Uses the default device
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ * or <code>[ null, GL ]</code> for the default profile.
+ * @throws GLException if the requested profile is not available for the default device.
+ */
+ public static GLProfile get(final String profile)
+ throws GLException
+ {
+ return get(defaultDevice, profile);
+ }
+
+ /**
+ * Returns the first profile from the given list,
+ * where an implementation is available.
+ *
+ * @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device.
+ * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..)
+ * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false.
+ * @throws GLException if the non of the requested profiles is available for the device.
+ */
+ public static GLProfile get(final AbstractGraphicsDevice device, final String[] profiles, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ GLProfile glProfileAny = null;
+
+ final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, true);
+ for(int i=0; i<profiles.length; i++) {
+ final GLProfile glProfile = map.get(profiles[i]);
+ if(null!=glProfile) {
+ if(!favorHardwareRasterizer) {
+ return glProfile;
+ }
+ if(glProfile.isHardwareRasterizer()) {
+ return glProfile;
+ }
+ if(null==glProfileAny) {
+ glProfileAny = glProfile;
+ }
+ }
+ }
+ if(null!=glProfileAny) {
+ return glProfileAny;
+ }
+ throw new GLException("Profiles "+array2String(profiles)+" not available on device "+device);
+ }
+
+ /** Uses the default device
+ * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..)
+ * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false.
+ * @throws GLException if the non of the requested profiles is available for the default device.
+ */
+ public static GLProfile get(final String[] profiles, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(defaultDevice, profiles, favorHardwareRasterizer);
+ }
+
+ /** Indicates whether the native OpenGL ES1 profile is in use.
+ * This requires an EGL interface.
+ */
+ public static boolean usesNativeGLES1(final String profileImpl) {
+ return GLES1 == profileImpl;
+ }
+
+ /** Indicates whether the native OpenGL ES3 or ES2 profile is in use.
+ * This requires an EGL, ES3 or ES2 compatible interface.
+ */
+ public static boolean usesNativeGLES2(final String profileImpl) {
+ return GLES3 == profileImpl || GLES2 == profileImpl;
+ }
+
+ /** Indicates whether the native OpenGL ES2 profile is in use.
+ * This requires an EGL, ES3 compatible interface.
+ */
+ public static boolean usesNativeGLES3(final String profileImpl) {
+ return GLES3 == profileImpl;
+ }
+
+ /** Indicates whether either of the native OpenGL ES profiles are in use. */
+ public static boolean usesNativeGLES(final String profileImpl) {
+ return usesNativeGLES2(profileImpl) || usesNativeGLES1(profileImpl);
+ }
+
+ /** @return {@link com.jogamp.nativewindow.NativeWindowFactory#isAWTAvailable()} and
+ JOGL's AWT part */
+ public static boolean isAWTAvailable() { return isAWTAvailable; }
+
+ public static String getGLTypeName(final int type) {
+ switch (type) {
+ case GL.GL_UNSIGNED_BYTE:
+ return "GL_UNSIGNED_BYTE";
+ case GL.GL_BYTE:
+ return "GL_BYTE";
+ case GL.GL_UNSIGNED_SHORT:
+ return "GL_UNSIGNED_SHORT";
+ case GL.GL_SHORT:
+ return "GL_SHORT";
+ case GL.GL_FLOAT:
+ return "GL_FLOAT";
+ case GL.GL_FIXED:
+ return "GL_FIXED";
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ return "GL_INT";
+ case GL.GL_UNSIGNED_INT:
+ return "GL_UNSIGNED_INT";
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ return "GL_DOUBLE";
+ case com.jogamp.opengl.GL2.GL_2_BYTES:
+ return "GL_2_BYTES";
+ case com.jogamp.opengl.GL2.GL_3_BYTES:
+ return "GL_3_BYTES";
+ case com.jogamp.opengl.GL2.GL_4_BYTES:
+ return "GL_4_BYTES";
+ }
+ return null;
+ }
+
+ public static String getGLArrayName(final int array) {
+ switch(array) {
+ case GLPointerFunc.GL_VERTEX_ARRAY:
+ return "GL_VERTEX_ARRAY";
+ case GLPointerFunc.GL_NORMAL_ARRAY:
+ return "GL_NORMAL_ARRAY";
+ case GLPointerFunc.GL_COLOR_ARRAY:
+ return "GL_COLOR_ARRAY";
+ case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
+ return "GL_TEXTURE_COORD_ARRAY";
+ }
+ return null;
+ }
+
+ public final String getGLImplBaseClassName() {
+ return getGLImplBaseClassName(getImplName());
+ }
+ private static final String getGLImplBaseClassName(final String profileImpl) {
+ if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+ return "jogamp.opengl.es3.GLES3";
+ } else if( GLES1 == profileImpl ) {
+ return "jogamp.opengl.es1.GLES1";
+ } else if ( GL4bc == profileImpl ||
+ GL4 == profileImpl ||
+ GL3bc == profileImpl ||
+ GL3 == profileImpl ||
+ GL2 == profileImpl ) {
+ return "jogamp.opengl.gl4.GL4bc";
+ } else {
+ throw new GLException("unsupported profile \"" + profileImpl + "\"");
+ }
+ }
+
+ public final Constructor<?> getGLCtor(final boolean glObject) {
+ return getGLCtor(getImplName(), glObject);
+ }
+ private static final Constructor<?> getGLCtor(final String profileImpl, final boolean glObject) {
+ if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+ return glObject ? ctorGLES3Impl : ctorGLES3ProcAddr;
+ } else if( GLES1 == profileImpl ) {
+ return glObject ? ctorGLES1Impl : ctorGLES1ProcAddr;
+ } else if ( GL4bc == profileImpl ||
+ GL4 == profileImpl ||
+ GL3bc == profileImpl ||
+ GL3 == profileImpl ||
+ GL2 == profileImpl ) {
+ return glObject ? ctorGL234Impl : ctorGL234ProcAddr;
+ } else {
+ throw new GLException("unsupported profile \"" + profileImpl + "\"");
+ }
+ }
+
+ /**
+ * @param o GLProfile object to compare with
+ * @return true if given Object is a GLProfile and
+ * if both, profile and profileImpl is equal with this.
+ */
+ @Override
+ public final boolean equals(final Object o) {
+ if(this==o) { return true; }
+ if(o instanceof GLProfile) {
+ final GLProfile glp = (GLProfile)o;
+ return getName() == glp.getName() && getImplName() == glp.getImplName() ; // uses .intern()!
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 97 * hash + getImplName().hashCode();
+ hash = 97 * hash + getName().hashCode();
+ return hash;
+ }
+
+ /**
+ * @param glp GLProfile to compare with
+ * @throws GLException if given GLProfile and this aren't equal
+ */
+ public final void verifyEquality(final GLProfile glp) throws GLException {
+ if(!this.equals(glp)) {
+ throw new GLException("GLProfiles are not equal: "+this+" != "+glp);
+ }
+ }
+
+ /** return this profiles name */
+ public final String getName() {
+ return profile;
+ }
+
+ /** return this profiles implementation, eg. GL2ES2 -> GL2, or GL3 -> GL3 */
+ public final GLProfile getImpl() {
+ return null != profileImpl ? profileImpl : this;
+ }
+
+ /** return true if impl. is a hardware rasterizer, otherwise false. */
+ public final boolean isHardwareRasterizer() {
+ return isHardwareRasterizer;
+ }
+
+ /**
+ * return this profiles implementation name, eg. GL2ES2 -> GL2, or GL3 -> GL3
+ */
+ public final String getImplName() {
+ return null != profileImpl ? profileImpl.getName() : getName();
+ }
+
+ /** Indicates whether this profile is capable of GL4bc. <p>Includes [ GL4bc ].</p> */
+ public final boolean isGL4bc() {
+ return GL4bc == profile;
+ }
+
+ /** Indicates whether this profile is capable of GL4. <p>Includes [ GL4bc, GL4 ].</p> */
+ public final boolean isGL4() {
+ return isGL4bc() || GL4 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GL3bc. <p>Includes [ GL4bc, GL3bc ].</p> */
+ public final boolean isGL3bc() {
+ return isGL4bc() || GL3bc == profile;
+ }
+
+ /** Indicates whether this profile is capable of GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3 ].</p> */
+ public final boolean isGL3() {
+ return isGL4() || isGL3bc() || GL3 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GL2 . <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */
+ public final boolean isGL2() {
+ return isGL3bc() || GL2 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GLES1. <p>Includes [ GLES1 ].</p> */
+ public final boolean isGLES1() {
+ return GLES1 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES2, GLES3 ].</p> */
+ public final boolean isGLES2() {
+ return isGLES3() || GLES2 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GLES3. <p>Includes [ GLES3 ].</p> */
+ public final boolean isGLES3() {
+ return GLES3 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GLES. <p>Includes [ GLES1, GLES2, GLES3 ].</p> */
+ public final boolean isGLES() {
+ return GLES3 == profile || GLES2 == profile || GLES1 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p> */
+ public final boolean isGL2ES1() {
+ return GL2ES1 == profile || isGLES1() || isGL2();
+ }
+
+ /** Indicates whether this profile is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */
+ public final boolean isGL2GL3() {
+ return GL2GL3 == profile || isGL3() || isGL2();
+ }
+
+ /** Indicates whether this profile is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */
+ public final boolean isGL2ES2() {
+ return GL2ES2 == profile || isGLES2() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this profile is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p>
+ * @see #isGL3ES3()
+ * @see #isGL2GL3()
+ */
+ public final boolean isGL2ES3() {
+ return isGL3ES3() || isGL2GL3();
+ }
+
+ /** Indicates whether this profile is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p> */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
+ }
+
+ /** Indicates whether this profile is capable of GL4ES3. <p>Includes [ GL4bc, GL4, GLES3 ].</p> */
+ public final boolean isGL4ES3() {
+ return GL4ES3 == profile || isGLES3() || isGL4();
+ }
+
+ /** Indicates whether this profile supports GLSL, i.e. {@link #isGL2ES2()}. */
+ public final boolean hasGLSL() {
+ return isGL2ES2() ;
+ }
+
+ /** Indicates whether this profile uses the native OpenGL ES1 implementations. */
+ public final boolean usesNativeGLES1() {
+ return GLES1 == getImplName();
+ }
+
+ /** Indicates whether this profile uses the native OpenGL ES2 implementations. */
+ public final boolean usesNativeGLES2() {
+ return GLES2 == getImplName();
+ }
+
+ /** Indicates whether this profile uses the native OpenGL ES3 implementations. */
+ public final boolean usesNativeGLES3() {
+ return GLES3 == getImplName();
+ }
+
+ /** Indicates whether this profile uses either of the native OpenGL ES implementations. */
+ public final boolean usesNativeGLES() {
+ return usesNativeGLES3() || usesNativeGLES2() || usesNativeGLES1();
+ }
+
+ /**
+ * General validation if type is a valid GL data type
+ * for the current profile
+ */
+ public boolean isValidDataType(final int type, final boolean throwException) {
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case GL.GL_FIXED:
+ return true;
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ case GL.GL_UNSIGNED_INT:
+ if( isGL2ES2() ) {
+ return true;
+ }
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ if( isGL3() ) {
+ return true;
+ }
+ case com.jogamp.opengl.GL2.GL_2_BYTES:
+ case com.jogamp.opengl.GL2.GL_3_BYTES:
+ case com.jogamp.opengl.GL2.GL_4_BYTES:
+ if( isGL2() ) {
+ return true;
+ }
+ }
+ if(throwException) {
+ throw new GLException("Illegal data type on profile "+this+": "+type);
+ }
+ return false;
+ }
+
+ public boolean isValidArrayDataType(final int index, final int comps, final int type,
+ final boolean isVertexAttribPointer, final boolean throwException) {
+ final String arrayName = getGLArrayName(index);
+ if( isGLES1() ) {
+ if(isVertexAttribPointer) {
+ if(throwException) {
+ throw new GLException("Illegal array type for "+arrayName+" on profile GLES1: VertexAttribPointer");
+ }
+ return false;
+ }
+ switch(index) {
+ case GLPointerFunc.GL_VERTEX_ARRAY:
+ case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
+ switch(type) {
+ case GL.GL_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_FIXED:
+ case GL.GL_FLOAT:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GLPointerFunc.GL_NORMAL_ARRAY:
+ switch(type) {
+ case GL.GL_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_FIXED:
+ case GL.GL_FLOAT:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 3:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GLPointerFunc.GL_COLOR_ARRAY:
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_FIXED:
+ case GL.GL_FLOAT:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ }
+ } else if( isGLES2() ) {
+ // simply ignore !isVertexAttribPointer case, since it is simulated anyway ..
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case GL.GL_FIXED:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GLES2: "+type);
+ }
+ return false;
+ }
+ /** unable to validate .. could be any valid type/component combination
+ switch(comps) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GLES2: "+comps);
+ }
+ return false;
+ } */
+ } else if( isGL2ES2() ) {
+ if(isVertexAttribPointer) {
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ case GL.GL_UNSIGNED_INT:
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ } else {
+ switch(index) {
+ case GLPointerFunc.GL_VERTEX_ARRAY:
+ switch(type) {
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GLPointerFunc.GL_NORMAL_ARRAY:
+ switch(type) {
+ case GL.GL_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 3:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GLPointerFunc.GL_COLOR_ARRAY:
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ case GL.GL_UNSIGNED_INT:
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
+ switch(type) {
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case com.jogamp.opengl.GL2ES2.GL_INT:
+ case com.jogamp.opengl.GL2GL3.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "GLProfile[" + getName() + "/" + getImplName() + "."+(this.isHardwareRasterizer?"hw":"sw")+(isCustom?".custom":"")+"]";
+ }
+
+ private static /*final*/ boolean isAWTAvailable;
+
+ private static /*final*/ boolean hasDesktopGLFactory;
+ private static /*final*/ boolean hasGL234Impl;
+ private static /*final*/ boolean hasEGLFactory;
+ private static /*final*/ boolean hasGLES3Impl;
+ private static /*final*/ boolean hasGLES1Impl;
+ private static /*final*/ Constructor<?> ctorGL234Impl;
+ private static /*final*/ Constructor<?> ctorGLES3Impl;
+ private static /*final*/ Constructor<?> ctorGLES1Impl;
+ private static /*final*/ Constructor<?> ctorGL234ProcAddr;
+ private static /*final*/ Constructor<?> ctorGLES3ProcAddr;
+ private static /*final*/ Constructor<?> ctorGLES1ProcAddr;
+
+ private static /*final*/ GLDrawableFactoryImpl eglFactory = null;
+ private static /*final*/ GLDrawableFactoryImpl desktopFactory = null;
+ private static /*final*/ AbstractGraphicsDevice defaultDevice = null;
+
+ private static boolean initialized = false;
+ private static final RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+
+ private static final Class<?>[] ctorGLArgs = new Class<?>[] { GLProfile.class, jogamp.opengl.GLContextImpl.class };
+ private static final Class<?>[] ctorProcArgs = new Class<?>[] { FunctionAddressResolver.class };
+ private static final String GL4bcImplClassName = "jogamp.opengl.gl4.GL4bcImpl";
+ private static final String GL4bcProcClassName = "jogamp.opengl.gl4.GL4bcProcAddressTable";
+ private static final String GLES1ImplClassName = "jogamp.opengl.es1.GLES1Impl";
+ private static final String GLES1ProcClassName = "jogamp.opengl.es1.GLES1ProcAddressTable";
+ private static final String GLES3ImplClassName = "jogamp.opengl.es3.GLES3Impl";
+ private static final String GLES3ProcClassName = "jogamp.opengl.es3.GLES3ProcAddressTable";
+
+ private static final Constructor<?> getCtor(final String clazzName, final boolean glObject, final ClassLoader cl) {
+ try {
+ return ReflectionUtil.getConstructor(clazzName, glObject ? ctorGLArgs : ctorProcArgs, false, cl);
+ } catch (final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+t.getMessage());
+ t.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ private static final void initGLCtorImpl() {
+ final ClassLoader classloader = GLProfile.class.getClassLoader();
+
+ // depends on hasDesktopGLFactory
+ {
+ final Constructor<?> ctorGL = getCtor(GL4bcImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GL4bcProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGL234Impl = true;
+ ctorGL234Impl = ctorGL;
+ ctorGL234ProcAddr = ctorProc;
+ } else {
+ hasGL234Impl = false;
+ ctorGL234Impl = null;
+ ctorGL234ProcAddr = null;
+ }
+ }
+
+ // depends on hasEGLFactory
+ {
+ final Constructor<?> ctorGL = getCtor(GLES1ImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES1ProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGLES1Impl = true;
+ ctorGLES1Impl = ctorGL;
+ ctorGLES1ProcAddr = ctorProc;
+ } else {
+ hasGLES1Impl = false;
+ ctorGLES1Impl = null;
+ ctorGLES1ProcAddr = null;
+ }
+ }
+ {
+ final Constructor<?> ctorGL = getCtor(GLES3ImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES3ProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGLES3Impl = true;
+ ctorGLES3Impl = ctorGL;
+ ctorGLES3ProcAddr = ctorProc;
+ } else {
+ hasGLES3Impl = false;
+ ctorGLES3Impl = null;
+ ctorGLES3ProcAddr = null;
+ }
+ }
+ }
+
+ /**
+ * Tries the profiles implementation and native libraries.
+ */
+ private static void initProfilesForDefaultDevices() {
+ NativeWindowFactory.initSingleton();
+ if(DEBUG) {
+ System.err.println("GLProfile.init - thread: " + Thread.currentThread().getName());
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(GlueGenVersion.getInstance());
+ System.err.println(NativeWindowVersion.getInstance());
+ System.err.println(JoglVersion.getInstance());
+ }
+
+ final ClassLoader classloader = GLProfile.class.getClassLoader();
+
+ isAWTAvailable = NativeWindowFactory.isAWTAvailable() &&
+ ReflectionUtil.isClassAvailable("com.jogamp.opengl.awt.GLCanvas", classloader) ; // JOGL
+
+ initGLCtorImpl();
+
+ //
+ // Iteration of desktop GL availability detection
+ // utilizing the detected GL version in the shared context.
+ //
+ // - Instantiate GLDrawableFactory incl its shared dummy drawable/context,
+ // which will register at GLContext ..
+ //
+ GLDrawableFactory.initSingleton();
+
+ Throwable t=null;
+ // if successfull it has a shared dummy drawable and context created
+ try {
+ desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GL2);
+ if(null != desktopFactory) {
+ final DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(GL2);
+ if(null!=glLookupHelper) {
+ hasDesktopGLFactory = glLookupHelper.isLibComplete() && hasGL234Impl;
+ }
+ }
+ } catch (final LinkageError le) {
+ t=le;
+ } catch (final RuntimeException re) {
+ t=re;
+ } catch (final Throwable tt) {
+ t=tt;
+ }
+ if(DEBUG) {
+ if(null!=t) {
+ t.printStackTrace();
+ }
+ }
+
+ final AbstractGraphicsDevice defaultDesktopDevice;
+ if(null == desktopFactory) {
+ hasDesktopGLFactory = false;
+ hasGL234Impl = false;
+ defaultDesktopDevice = null;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Desktop GLDrawable factory not available");
+ }
+ } else {
+ defaultDesktopDevice = desktopFactory.getDefaultDevice();
+ }
+
+ if ( ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
+ t=null;
+ try {
+ eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
+ if(null != eglFactory) {
+ hasEGLFactory = true;
+ // update hasGLES1Impl, hasGLES3Impl based on EGL
+ hasGLES3Impl = null!=eglFactory.getGLDynamicLookupHelper(GLES2) && hasGLES3Impl;
+ hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(GLES1) && hasGLES1Impl;
+ }
+ } catch (final LinkageError le) {
+ t=le;
+ } catch (final SecurityException se) {
+ t=se;
+ } catch (final NullPointerException npe) {
+ t=npe;
+ } catch (final RuntimeException re) {
+ t=re;
+ }
+ if(DEBUG) {
+ if(null!=t) {
+ t.printStackTrace();
+ }
+ }
+ }
+
+ final AbstractGraphicsDevice defaultEGLDevice;
+ if(null == eglFactory) {
+ hasGLES3Impl = false;
+ hasGLES1Impl = false;
+ defaultEGLDevice = null;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - EGL GLDrawable factory not available");
+ }
+ } else {
+ defaultEGLDevice = eglFactory.getDefaultDevice();
+ }
+
+ if( null != defaultDesktopDevice ) {
+ defaultDevice = defaultDesktopDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
+ }
+ } else if ( null != defaultEGLDevice ) {
+ defaultDevice = defaultEGLDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device not available");
+ }
+ defaultDevice = null;
+ }
+
+ // we require to initialize the EGL device 1st, if available
+ final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false;
+ final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
+ final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
+
+ if(DEBUG) {
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
+ System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
+ System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
+ System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
+ System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
+ System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
+ System.err.println("GLProfile.init hasGLES3Impl "+hasGLES3Impl);
+ System.err.println("GLProfile.init defaultDevice "+defaultDevice);
+ System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice);
+ System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice);
+ System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
+ }
+ }
+
+ /**
+ * @param device the device for which profiles shall be initialized
+ * @return true if any profile for the device exists, otherwise false
+ */
+ private static boolean initProfilesForDevice(final AbstractGraphicsDevice device) {
+ if(null == device) {
+ return false;
+ }
+ initLock.lock();
+ try {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
+ factory.enterThreadCriticalZone();
+ try {
+ return initProfilesForDeviceCritical(device);
+ } finally {
+ factory.leaveThreadCriticalZone();
+ }
+ } finally {
+ initLock.unlock();
+ }
+ }
+ private static boolean initProfilesForDeviceCritical(final AbstractGraphicsDevice device) {
+ final boolean isSet = GLContext.getAvailableGLVersionsSet(device);
+
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.initProfilesForDevice: "+device+" ("+device.getClass().getName()+"), isSet "+isSet+", hasDesktopGLFactory "+hasDesktopGLFactory+", hasEGLFactory "+hasEGLFactory);
+ }
+ if(isSet) {
+ // Avoid recursion and check whether impl. is sane!
+ final String deviceKey = device.getUniqueID();
+ final HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey);
+ if( null == map ) {
+ throw new InternalError("GLContext Avail. GLVersion is set - but no profile map for device: "+device);
+ }
+ return null != map.get(GL_DEFAULT);
+ }
+
+ boolean addedDesktopProfile = false;
+ boolean addedEGLProfile = false;
+
+ final boolean deviceIsDesktopCompatible = hasDesktopGLFactory && desktopFactory.getIsDeviceCompatible(device);
+
+ if( deviceIsDesktopCompatible ) {
+ // 1st pretend we have all Desktop and EGL profiles ..
+ computeProfileMap(device, true /* desktopCtxUndef*/, true /* esCtxUndef */);
+
+ // Triggers eager initialization of share context in GLDrawableFactory for the device,
+ // hence querying all available GLProfiles
+ final Thread sharedResourceThread = desktopFactory.getSharedResourceThread();
+ if(null != sharedResourceThread) {
+ initLock.addOwner(sharedResourceThread);
+ }
+ final boolean desktopSharedCtxAvail = desktopFactory.createSharedResource(device);
+ if(null != sharedResourceThread) {
+ initLock.removeOwner(sharedResourceThread);
+ }
+ if (DEBUG) {
+ System.err.println("GLProfile.initProfilesForDevice: "+device+": desktop Shared Ctx "+desktopSharedCtxAvail);
+ }
+ if(!desktopSharedCtxAvail) {
+ hasDesktopGLFactory = false;
+ } else if( !GLContext.getAvailableGLVersionsSet(device) ) {
+ throw new InternalError("Available GLVersions not set");
+ }
+ addedDesktopProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
+ }
+
+ final boolean deviceIsEGLCompatible = hasEGLFactory && eglFactory.getIsDeviceCompatible(device);
+
+ // also test GLES1, GLES2 and GLES3 on desktop, since we have implementations / emulations available.
+ if( deviceIsEGLCompatible && ( hasGLES3Impl || hasGLES1Impl ) ) {
+ // 1st pretend we have all EGL profiles ..
+ computeProfileMap(device, true /* desktopCtxUndef*/, true /* esCtxUndef */);
+
+ // Triggers eager initialization of share context in GLDrawableFactory for the device,
+ // hence querying all available GLProfiles
+ final Thread sharedResourceThread = eglFactory.getSharedResourceThread();
+ if(null != sharedResourceThread) {
+ initLock.addOwner(sharedResourceThread);
+ }
+ final boolean eglSharedCtxAvail = eglFactory.createSharedResource(device);
+ if(null != sharedResourceThread) {
+ initLock.removeOwner(sharedResourceThread);
+ }
+ if(!eglSharedCtxAvail) {
+ // Remark: On Windows there is a libEGL.dll delivered w/ Chrome 15.0.874.121m and Firefox 8.0.1
+ // but it seems even EGL.eglInitialize(eglDisplay, null, null)
+ // fails in some scenarios (eg VirtualBox 4.1.6) w/ EGL error 0x3001 (EGL_NOT_INITIALIZED).
+ hasEGLFactory = false;
+ hasGLES3Impl = false;
+ hasGLES1Impl = false;
+ }
+ if (DEBUG) {
+ System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail);
+ }
+ addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
+ }
+
+ if( !addedDesktopProfile && !addedEGLProfile ) {
+ setProfileMap(device, new HashMap<String /*GLProfile_name*/, GLProfile>()); // empty
+ if(DEBUG) {
+ System.err.println("GLProfile: device could not be initialized: "+device);
+ System.err.println("GLProfile: compatible w/ desktop: "+deviceIsDesktopCompatible+
+ ", egl "+deviceIsEGLCompatible);
+ System.err.println("GLProfile: desktoplFactory "+desktopFactory);
+ System.err.println("GLProfile: eglFactory "+eglFactory);
+ System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl);
+ System.err.println("GLProfile: hasGLES3Impl "+hasGLES3Impl);
+ }
+ }
+
+ GLContext.setAvailableGLVersionsSet(device, true);
+
+ if (DEBUG) {
+ System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": added profile(s): desktop "+addedDesktopProfile+", egl "+addedEGLProfile);
+ System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": "+glAvailabilityToString(device));
+ if(addedDesktopProfile) {
+ dumpGLInfo(desktopFactory, device);
+ final List<GLCapabilitiesImmutable> availCaps = desktopFactory.getAvailableCapabilities(device);
+ for(int i=0; i<availCaps.size(); i++) {
+ System.err.println(availCaps.get(i));
+ }
+ } else if(addedEGLProfile) {
+ dumpGLInfo(eglFactory, device);
+ final List<GLCapabilitiesImmutable> availCaps = eglFactory.getAvailableCapabilities(device);
+ for(int i=0; i<availCaps.size(); i++) {
+ System.err.println(availCaps.get(i));
+ }
+ }
+ }
+
+ return addedDesktopProfile || addedEGLProfile;
+ }
+
+ private static void dumpGLInfo(final GLDrawableFactoryImpl factory, final AbstractGraphicsDevice device) {
+ final GLContext ctx = factory.getOrCreateSharedContext(device);
+ if(null != ctx) {
+ System.err.println("GLProfile.dumpGLInfo: "+ctx);
+ ctx.makeCurrent();
+ try {
+ System.err.println(JoglVersion.getGLInfo(ctx.getGL(), null));
+ } finally {
+ ctx.release();
+ }
+ } else {
+ System.err.println("GLProfile.dumpGLInfo: shared context n/a");
+ }
+ }
+
+ public static AbstractGraphicsDevice getDefaultDevice() {
+ initSingleton();
+ return defaultDevice;
+ }
+
+ private static String array2String(final String[] list) {
+ final StringBuilder msg = new StringBuilder();
+ msg.append("[");
+ for (int i = 0; i < list.length; i++) {
+ if (i > 0)
+ msg.append(", ");
+ msg.append(list[i]);
+ }
+ msg.append("]");
+ return msg.toString();
+ }
+
+ private static void glAvailabilityToString(final AbstractGraphicsDevice device, final StringBuilder sb, final int major, final int profile) {
+ final String str = GLContext.getAvailableGLVersionAsString(device, major, profile);
+ if(null==str) {
+ throw new GLException("Internal Error");
+ }
+ sb.append("[");
+ sb.append(str);
+ sb.append("]");
+ }
+
+ private static boolean computeProfileMap(final AbstractGraphicsDevice device, final boolean desktopCtxUndef, final boolean esCtxUndef) {
+ if (DEBUG) {
+ System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", esCtxUndef "+esCtxUndef);
+ }
+ final boolean isHardwareRasterizer[] = new boolean[1];
+ GLProfile defaultGLProfileAny = null;
+ GLProfile defaultGLProfileHW = null;
+ final HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(GL_PROFILE_LIST_ALL.length + 1 /* default */);
+ for(int i=0; i<GL_PROFILE_LIST_ALL.length; i++) {
+ final String profile = GL_PROFILE_LIST_ALL[i];
+ final String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer);
+ if( null != profileImpl ) {
+ final GLProfile glProfile;
+ if( profile.equals( profileImpl ) ) {
+ glProfile = new GLProfile(profile, null, isHardwareRasterizer[0], false /* custom */);
+ } else {
+ final GLProfile _mglp = _mappedProfiles.get( profileImpl );
+ if( null == _mglp ) {
+ throw new InternalError("XXX0 profile["+i+"]: "+profile+" -> profileImpl "+profileImpl+" !!! not mapped ");
+ }
+ glProfile = new GLProfile(profile, _mglp, isHardwareRasterizer[0], false /* custom */);
+ }
+ _mappedProfiles.put(profile, glProfile);
+ if (DEBUG) {
+ System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
+ }
+ if( null == defaultGLProfileHW && isHardwareRasterizer[0] ) {
+ defaultGLProfileHW=glProfile;
+ if (DEBUG) {
+ System.err.println("GLProfile.init map defaultHW "+glProfile+" on device "+device.getConnection());
+ }
+ } else if( null == defaultGLProfileAny ) {
+ defaultGLProfileAny=glProfile;
+ if (DEBUG) {
+ System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getConnection());
+ }
+ }
+ } else {
+ if (DEBUG) {
+ System.err.println("GLProfile.init map *** no mapping for "+profile+" on device "+device.getConnection());
+ }
+ }
+ }
+ if( null != defaultGLProfileHW ) {
+ _mappedProfiles.put(GL_DEFAULT, defaultGLProfileHW);
+ } else if( null != defaultGLProfileAny ) {
+ _mappedProfiles.put(GL_DEFAULT, defaultGLProfileAny);
+ }
+ setProfileMap(device, _mappedProfiles);
+ return _mappedProfiles.size() > 0;
+ }
+
+ /**
+ * Returns the profile implementation
+ */
+ private static String computeProfileImpl(final AbstractGraphicsDevice device, final String profile, final boolean desktopCtxUndef, final boolean esCtxUndef, final boolean isHardwareRasterizer[]) {
+ final boolean hardwareRasterizer[] = new boolean[1];
+ if ( GL2ES1 == profile ) {
+ final boolean gles1Available;
+ final boolean gles1HWAvailable;
+ if( hasGLES1Impl ) {
+ gles1Available = esCtxUndef || GLContext.isGLES1Available(device, hardwareRasterizer);
+ gles1HWAvailable = gles1Available && hardwareRasterizer[0] ;
+ } else {
+ gles1Available = false;
+ gles1HWAvailable = false;
+ }
+ if(hasGL234Impl) {
+ final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer);
+ final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer);
+ final boolean gl2HWAvailable = gl2Available && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl3bcHWAvailable || gl2HWAvailable ||
+ gles1HWAvailable ;
+
+ if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4bc;
+ }
+ if( gl3bcAvailable && ( gl3bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3bcHWAvailable;
+ return GL3bc;
+ }
+ if( ( desktopCtxUndef || gl2Available ) && ( gl2HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl2HWAvailable;
+ return GL2;
+ }
+ }
+ if( gles1Available ) {
+ isHardwareRasterizer[0] = gles1HWAvailable;
+ return GLES1;
+ }
+ } else if ( GL2ES2 == profile ) {
+ final boolean gles2Available, gles3Available;
+ final boolean gles2HWAvailable, gles3HWAvailable;
+ if( hasGLES3Impl ) {
+ gles2Available = esCtxUndef || GLContext.isGLES2Available(device, hardwareRasterizer);
+ gles2HWAvailable = gles2Available && hardwareRasterizer[0] ;
+ gles3Available = esCtxUndef || GLContext.isGLES3Available(device, hardwareRasterizer);
+ gles3HWAvailable = gles3Available && hardwareRasterizer[0] ;
+ } else {
+ gles2Available = false;
+ gles2HWAvailable = false;
+ gles3Available = false;
+ gles3HWAvailable = false;
+ }
+ if( hasGL234Impl ) {
+ final boolean gl4bcAvailable = GLContext.isGL4bcAvailable(device, hardwareRasterizer);
+ final boolean gl4bcHWAvailable = gl4bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl3Available = GLContext.isGL3Available(device, hardwareRasterizer);
+ final boolean gl3HWAvailable = gl3Available && hardwareRasterizer[0] ;
+ final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer);
+ final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer);
+ final boolean gl2HWAvailable = gl2Available && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl4bcHWAvailable || gl3HWAvailable || gl3bcHWAvailable || gl2HWAvailable ||
+ gles3HWAvailable || gles2HWAvailable ;
+
+ if( GLContext.isGL4Available(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4;
+ }
+ if( gl4bcAvailable && ( gl4bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl4bcHWAvailable;
+ return GL4bc;
+ }
+ if( gl3Available && ( gl3HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3HWAvailable;
+ return GL3;
+ }
+ if( gl3bcAvailable && ( gl3bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3bcHWAvailable;
+ return GL3bc;
+ }
+ if( ( desktopCtxUndef || gl2Available ) && ( gl2HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl2HWAvailable;
+ return GL2;
+ }
+ }
+ if( gles3Available && ( gles3HWAvailable || !gles2HWAvailable ) ) {
+ isHardwareRasterizer[0] = gles3HWAvailable;
+ return GLES3;
+ }
+ if( gles2Available ) {
+ isHardwareRasterizer[0] = gles2HWAvailable;
+ return GLES2;
+ }
+ } else if (GL4ES3 == profile) {
+ final boolean gles3CompatAvail = GLContext.isGLES3CompatibleAvailable(device);
+ if( desktopCtxUndef || esCtxUndef || gles3CompatAvail ) {
+ final boolean es3HardwareRasterizer[] = new boolean[1];
+ final boolean gles3Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, es3HardwareRasterizer) );
+ final boolean gles3HWAvailable = gles3Available && es3HardwareRasterizer[0] ;
+ if( hasGL234Impl ) {
+ final boolean gl4bcAvailable = GLContext.isGL4bcAvailable(device, hardwareRasterizer);
+ final boolean gl4bcHWAvailable = gl4bcAvailable && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl4bcHWAvailable ||
+ gles3HWAvailable;
+
+ if( GLContext.isGL4Available(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4;
+ }
+ if( ( desktopCtxUndef || gl4bcAvailable ) && ( gl4bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl4bcHWAvailable;
+ return GL4bc;
+ }
+ }
+ if(gles3Available) {
+ isHardwareRasterizer[0] = es3HardwareRasterizer[0];
+ return GLES3;
+ }
+ }
+ } else if(GL2GL3 == profile) {
+ if(hasGL234Impl) {
+ final boolean gl4Available = GLContext.isGL4Available(device, hardwareRasterizer);
+ final boolean gl4HWAvailable = gl4Available && hardwareRasterizer[0] ;
+ final boolean gl3Available = GLContext.isGL3Available(device, hardwareRasterizer);
+ final boolean gl3HWAvailable = gl3Available && hardwareRasterizer[0] ;
+ final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer);
+ final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer);
+ final boolean gl2HWAvailable = gl2Available && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl4HWAvailable || gl3HWAvailable || gl3bcHWAvailable || gl2HWAvailable;
+
+ if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4bc;
+ }
+ if( gl4Available && ( gl4HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl4HWAvailable;
+ return GL4;
+ }
+ if( gl3bcAvailable && ( gl3bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3bcHWAvailable;
+ return GL3bc;
+ }
+ if( gl3Available && ( gl3HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3HWAvailable;
+ return GL3;
+ }
+ if( desktopCtxUndef || gl2Available ) {
+ isHardwareRasterizer[0] = gl2HWAvailable;
+ return GL2;
+ }
+ }
+ } else if(GL4bc == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL4bc : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_COMPAT);
+ } else if(GL4 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL4 : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_CORE);
+ } else if(GL3bc == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL3bc : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_COMPAT);
+ } else if(GL3 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_CORE);
+ } else if(GL2 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_COMPAT);
+ } else if(GLES3 == profile && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, isHardwareRasterizer))) {
+ return esCtxUndef ? GLES3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_ES);
+ } else if(GLES2 == profile && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) {
+ return esCtxUndef ? GLES2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_ES);
+ } else if(GLES1 == profile && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, isHardwareRasterizer))) {
+ return esCtxUndef ? GLES1 : GLContext.getAvailableGLProfileName(device, 1, GLContext.CTX_PROFILE_ES);
+ }
+ return null;
+ }
+
+ private static /*final*/ HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>> deviceConn2ProfileMap =
+ new HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>>();
+
+ /**
+ * This implementation support lazy initialization, while avoiding recursion/deadlocks.<br>
+ * If no mapping 'device -> GLProfiles-Map' exists yet, it triggers<br>
+ * - create empty mapping device -> GLProfiles-Map <br>
+ * - initialization<br<
+ *
+ * @param device the key 'device -> GLProfiles-Map'
+ * @param throwExceptionOnZeroProfile true if <code>GLException</code> shall be thrown in case of no mapped profile, otherwise false.
+ * @return the GLProfile HashMap if exists, otherwise null
+ * @throws GLException if no profile for the given device is available.
+ */
+ private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device, final boolean throwExceptionOnZeroProfile)
+ throws GLException
+ {
+ initSingleton();
+
+ if(null==defaultDevice) { // avoid NPE and notify of incomplete initialization
+ throw new GLException("No default device available");
+ }
+
+ if(null==device) {
+ device = defaultDevice;
+ }
+
+ final String deviceKey = device.getUniqueID();
+ HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey);
+ if( null != map ) {
+ return map;
+ }
+ if( !initProfilesForDevice(device) ) {
+ if( throwExceptionOnZeroProfile ) {
+ throw new GLException("No Profile available for "+device);
+ } else {
+ return null;
+ }
+ }
+ map = deviceConn2ProfileMap.get(deviceKey);
+ if( null == map && throwExceptionOnZeroProfile ) {
+ throw new InternalError("initProfilesForDevice(..) didn't setProfileMap(..) for "+device);
+ }
+ return map;
+ }
+
+ private static void setProfileMap(final AbstractGraphicsDevice device, final HashMap<String /*GLProfile_name*/, GLProfile> mappedProfiles) {
+ synchronized ( deviceConn2ProfileMap ) {
+ deviceConn2ProfileMap.put(device.getUniqueID(), mappedProfiles);
+ }
+ }
+
+ private GLProfile(final String profile, final GLProfile profileImpl, final boolean isHardwareRasterizer, final boolean isCustom) {
+ this.profile = profile;
+ this.profileImpl = profileImpl;
+ this.isHardwareRasterizer = isHardwareRasterizer;
+ this.isCustom = isCustom;
+ }
+
+ public static GLProfile createCustomGLProfile(final String profile, final GLProfile profileImpl) {
+ return new GLProfile(profile, profileImpl, profileImpl.isHardwareRasterizer, true);
+ }
+
+ private final GLProfile profileImpl;
+ private final String profile;
+ private final boolean isHardwareRasterizer;
+ private final boolean isCustom;
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index e4cd5c5d9..55c02d92a 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -29,13 +29,12 @@ package com.jogamp.opengl;
import java.util.IdentityHashMap;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.opengl.GLCapabilitiesImmutable;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.common.os.Platform;
-
-import jogamp.opengl.egl.EGL;
-import jogamp.opengl.egl.EGLExt;
+import com.jogamp.opengl.egl.EGL;
+import com.jogamp.opengl.egl.EGLExt;
/**
* GLRendererQuirks contains information of known bugs of various GL renderer.
@@ -348,7 +347,7 @@ public class GLRendererQuirks {
* Some drivers wrongly claim to support pbuffers
* with accumulation buffers. However, the creation of such pbuffer fails:
* <pre>
- * javax.media.opengl.GLException: pbuffer creation error: Couldn't find a suitable pixel format
+ * com.jogamp.opengl.GLException: pbuffer creation error: Couldn't find a suitable pixel format
* </pre>
* </p>
* <p>
@@ -402,7 +401,7 @@ public class GLRendererQuirks {
* Some drivers wrongly claim to support ARB_create_context.
* However, the creation of such context fails:
* <pre>
- * javax.media.opengl.GLException: AWT-EventQueue-0: WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2
+ * com.jogamp.opengl.GLException: AWT-EventQueue-0: WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2
* requested (OpenGL >= 3.0.1). Requested: GLProfile[GL3bc/GL3bc.hw], current: 2.1 (Compat profile, FBO, hardware)
* - 2.1.8787
* </pre>
@@ -419,8 +418,36 @@ public class GLRendererQuirks {
*/
public static final int NoARBCreateContext = 21;
+ /**
+ * No support for ES or desktop GL >= 3.0 current context without surface,
+ * i.e. without a default framebuffer as read- and write drawables.
+ * <p>
+ * See <i>OpenGL spec 3.0, chapter 2.1 OpenGL Fundamentals, page 7</i> or<br>
+ * <i>OpenGL ES spec 3.0.2, chapter 2.1 OpenGL Fundamentals, page 6</i>:
+ * <pre>
+ * It is possible to use a GL context without a default framebuffer, in which case
+ * a framebuffer object must be used to perform all rendering. This is useful for
+ * applications neeting to perform offscreen rendering.
+ * </pre>
+ * </p>
+ * <p>
+ * The feature will be attempted at initialization and this quirk will be set if failing.
+ * </p>
+ * <p>
+ * Known drivers failing the specification:
+ * <ul>
+ * <li>GNU/Linux X11 Nvidia proprietary driver
+ * <ul>
+ * <li>GL_VERSION 4.4.0 NVIDIA 340.24</li>
+ * <li>Platform GNU/Linux X11</li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ */
+ public static final int NoSurfacelessCtx = 22;
+
/** Return the number of known quirks. */
- public static final int getCount() { return 22; }
+ public static final int getCount() { return 23; }
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
"NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
@@ -429,7 +456,7 @@ public class GLRendererQuirks {
"NoFullFBOSupport", "GLSLNonCompliant", "GL4NeedsGL3Request",
"GLSharedContextBuggy", "GLES3ViaEGLES2Config", "SingletonEGLDisplayOnly",
"NoMultiSamplingBuffers", "BuggyColorRenderbuffer", "NoPBufferWithAccum",
- "NeedSharedObjectSync", "NoARBCreateContext"
+ "NeedSharedObjectSync", "NoARBCreateContext", "NoSurfacelessCtx"
};
private static final IdentityHashMap<String, GLRendererQuirks> stickyDeviceQuirks = new IdentityHashMap<String, GLRendererQuirks>();
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRunnable.java b/src/jogl/classes/com/jogamp/opengl/GLRunnable.java
new file mode 100644
index 000000000..97a72d6cd
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLRunnable.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Declares a one-shot OpenGL command usable for injection
+ * via {@link GLAutoDrawable#invoke(boolean, com.jogamp.opengl.GLRunnable)}.<br>
+ * {@link GLAutoDrawable} executes the GLRunnables within it's {@link GLAutoDrawable#display() display()}
+ * method after all registered {@link GLEventListener}s
+ * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
+ * methods has been called.
+ * </p>
+ * <p>
+ * The OpenGL context is current while executing the GLRunnable.
+ * </p>
+ * <p>
+ * This might be useful to inject OpenGL commands from an I/O event listener.
+ * </p>
+ */
+public interface GLRunnable {
+ /**
+ * @param drawable the associated drawable and current context for this call
+ * @return true if the GL [back] framebuffer remains intact by this runnable, otherwise false.
+ * If returning false {@link GLAutoDrawable} will call
+ * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
+ * of all registered {@link GLEventListener}s once more.
+ * @see GLRunnable
+ */
+ boolean run(GLAutoDrawable drawable);
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRunnable2.java b/src/jogl/classes/com/jogamp/opengl/GLRunnable2.java
new file mode 100644
index 000000000..4b0c63da0
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLRunnable2.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+/**
+ * <p>
+ * Declares a one-shot OpenGL command.
+ * </p>
+ */
+public interface GLRunnable2<T,U> {
+ /**
+ * @param gl a current GL object
+ * @param args custom arguments
+ * @return the desired object
+ */
+ T run(GL gl, U args);
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/GLSharedContextSetter.java b/src/jogl/classes/com/jogamp/opengl/GLSharedContextSetter.java
new file mode 100644
index 000000000..852ebcaa7
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLSharedContextSetter.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import com.jogamp.opengl.GLRendererQuirks;
+
+/**
+ * Adds capabilities to set a shared {@link GLContext} directly or via an {@link GLAutoDrawable}.
+ * <p>
+ * Sharing of server-side OpenGL objects such as buffer objects, e.g. VBOs,
+ * and textures among OpenGL contexts is supported with this interface.
+ * </p>
+ * <p>
+ * A <i>master</i> {@link GLContext} is the {@link GLContext} which is created first.
+ * Subsequent shared {@link GLContext} w/ the <i>master</i> are referred as <i>slave</i> {@link GLContext}.
+ * </p>
+ * <p>
+ * Implementations of this interface control the <i>slave's</i> {@link GLContext} and {@link GLAutoDrawable} realization,
+ * i.e. the <i>slave</i> {@link GLAutoDrawable} will not be realized before their associated <i>master</i>.
+ * </p>
+ * <p>
+ * Using the nearest or same {@link GLCapabilitiesImmutable#getVisualID(com.jogamp.nativewindow.VisualIDHolder.VIDType) visual ID}
+ * or {@link GLCapabilitiesImmutable caps} across the shared {@link GLDrawable}s will yield best compatibility.
+ * </p>
+ * <h5><a name="lifecycle">Lifecycle Considerations</a></h5>
+ * <p>
+ * After shared objects are created on the <i>master</i>, the OpenGL pipeline
+ * might need to be synchronized w/ the <i>slaves</i>, e.g. via {@link GL#glFinish()}.
+ * At least this has been experienced w/ OSX 10.9.
+ * </p>
+ * <p>
+ * In general, destroying a <i>master</i> {@link GLContext} before their shared <i>slaves</i>
+ * shall be permissible, i.e. the OpenGL driver needs to handle pending destruction of shared resources.
+ * This is confirmed to work properly on most platform/driver combinations,
+ * see unit test <code>com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3</code> and similar.
+ * </p>
+ * <p>
+ * However, to avoid scenarios with buggy drivers, users <i>may not</i> destroy the
+ * <i>master</i> {@link GLContext} before its shared <i>slave</i> {@link GLContext} instances
+ * <i>as long as they are using them</i>.<br>
+ * Otherwise the OpenGL driver may crash w/ SIGSEGV, due to using already destroyed shared resources,
+ * if not handling the pending destruction of the latter!<br>
+ * Either proper lifecycle synchronization is implemented, e.g. by notifying the <i>slaves</i> about the loss of the shared resources,
+ * <i>or</i> the <i>slaves</i> validate whether the resources are still valid.
+ * </p>
+ * <p>
+ * To simplify above lifecycle issues, one may use a {@link GLDrawableFactory#createDummyDrawable(com.jogamp.nativewindow.AbstractGraphicsDevice, boolean, GLCapabilitiesImmutable, GLCapabilitiesChooser) dummy}
+ * {@link GLDrawable} and it's {@link GLContext} as the <i>master</i> of all shared <i>slave</i> {@link GLContext}.
+ * Since this <i>dummy instance</i> does not depend on any native windowing system, it can be controlled easily w/o being <i>in sight</i>.<br>
+ * Below code creates a {@link GLAutoDrawable} based on a <i>dummy GLDrawable</i>:
+ * <pre>
+ // GLProfile and GLCapabilities should be equal across all shared GL drawable/context.
+ final GLCapabilitiesImmutable caps = ... ;
+ final GLProfile glp = caps.getGLProfile();
+ ..
+ final boolean createNewDevice = true; // use 'own' display device!
+ final GLAutoDrawable sharedDrawable = GLDrawableFactory.getFactory(glp).createDummyAutoDrawable(null, createNewDevice, caps, null);
+ sharedDrawable.display(); // triggers GLContext object creation and native realization.
+ ...
+ // Later a shared 'slave' can be created e.g.:
+ GLWindow glad = GLWindow.create(caps); // or any other GLAutoDrawable supporting GLSharedContextSetter
+ glad.setSharedAutoDrawable(sharedDrawable);
+ glad.addGLEventListener(..);
+ glad.setVisible(true); // GLWindow creation ..
+ * </pre>
+ * </p>
+ * <h5><a name="synchronization">GL Object Synchronization</a></h5>
+ * <p>
+ * Usually synchronization of shared GL objects should not be required, if the shared GL objects
+ * are created and immutable before concurrent usage.
+ * </p>
+ * <p>
+ * However, using drivers exposing {@link GLRendererQuirks#NeedSharedObjectSync} always
+ * require the user to synchronize access of shared GL objects.
+ * </p>
+ * <p>
+ * Synchronization can be avoided if accessing the shared GL objects
+ * exclusively via a queue or {@link com.jogamp.common.util.Ringbuffer Ringbuffer}, see GLMediaPlayerImpl as an example.
+ * </p>
+ * </p>
+ * <h5><a name="driverissues">Known Driver Issues</a></h5>
+ * <h7><a name="intelmesa">Intel's Mesa >= 9.1.2 Backend for [Sandybridge/Ivybridge] on GNU/Linux</a></h7>
+ * <p>
+ * <pre>
+ * Error: 'intel_do_flush_locked: No such file or directory'
+ * JogAmp: https://jogamp.org/bugzilla/show_bug.cgi?id=873
+ * freedesktop.org: https://bugs.freedesktop.org/show_bug.cgi?id=41736#c8
+ * </pre>
+ * Shared context seems not to be supported w/ lock-free bound X11 display connections
+ * per OpenGL drawable/context. The error message above is thrown in this case.
+ * Hence the driver bug renders shared context use w/ JOGL impossible.
+ * </p>
+ * <h7><a name="hisilicon">Hisilicon's Immersion.16 on Android</a></h7>
+ * <p>
+ * We failed to create a shared ES2 context on another thread.
+ * </p>
+ */
+public interface GLSharedContextSetter extends GLAutoDrawable {
+ /**
+ * Specifies an {@link GLContext OpenGL context}, which shall be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * <p>
+ * Since the {@link GLDrawable drawable} and {@link GLContext context} is created
+ * at {@link GLAutoDrawable#initialization GLAutoDrawable initialization}
+ * this method shall be called beforehand to have any effect.
+ * </p>
+ * <p>
+ * A set <i>sharedContext</i> will block context creation, i.e. {@link GLAutoDrawable#initialization GLAutoDrawable initialization},
+ * as long it is not {@link GLContext#isCreated() created natively}.
+ * </p>
+ * <p>
+ * The <i>preferred method</i> of assigning a <i>shared context</i> is
+ * to {@link #setSharedAutoDrawable(GLAutoDrawable) set the shared GLAutoDrawable},
+ * since this method also takes the {@link GLEventListener}
+ * {@link GLAutoDrawable#areAllGLEventListenerInitialized() initialization into account}.
+ * </p>
+ * <p>
+ * See <a href="#lifecycle">Lifecycle Considerations</a>.
+ * </p>
+ *
+ * @param sharedContext The OpenGL context to be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * @throws IllegalStateException if a {@link #setSharedContext(GLContext) shared GLContext}
+ * or {@link #setSharedAutoDrawable(GLAutoDrawable) shared GLAutoDrawable} is already set,
+ * the given sharedContext is null or equal to this {@link GLAutoDrawable}'s context.
+ * @see #setSharedAutoDrawable(GLAutoDrawable)
+ */
+ void setSharedContext(GLContext sharedContext) throws IllegalStateException;
+
+ /**
+ * Specifies an {@link GLAutoDrawable}, which {@link GLContext OpenGL context} shall be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * <p>
+ * Since the {@link GLDrawable drawable} and {@link GLContext context} is created
+ * at {@link GLAutoDrawable#initialization GLAutoDrawable initialization}
+ * this method shall be called beforehand to have any effect.
+ * </p>
+ * <p>
+ * A set <i>sharedAutoDrawable</i> will block context creation, i.e. <a href="GLAutoDrawable.html#initialization">initialization</a>
+ * as long it's
+ * <ul>
+ * <li>{@link GLContext} is <code>null</code>, or</li>
+ * <li>{@link GLContext} has not been {@link GLContext#isCreated() created natively}, or</li>
+ * <li>{@link GLEventListener} are <i>not</i> {@link GLAutoDrawable#areAllGLEventListenerInitialized() completely initialized}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * See <a href="#lifecycle">Lifecycle Considerations</a>.
+ * </p>
+ *
+ * @param sharedContext The GLAutoDrawable, which OpenGL context shall be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * @throws IllegalStateException if a {@link #setSharedContext(GLContext) shared GLContext}
+ * or {@link #setSharedAutoDrawable(GLAutoDrawable) shared GLAutoDrawable} is already set,
+ * the given sharedAutoDrawable is null or equal to this GLAutoDrawable.
+ * @see #setSharedContext(GLContext)
+ */
+ void setSharedAutoDrawable(GLAutoDrawable sharedAutoDrawable) throws IllegalStateException;
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLUniformData.java b/src/jogl/classes/com/jogamp/opengl/GLUniformData.java
new file mode 100644
index 000000000..44f7f29c7
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLUniformData.java
@@ -0,0 +1,227 @@
+
+package com.jogamp.opengl;
+
+import java.nio.*;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.math.FloatUtil;
+
+public class GLUniformData {
+
+ /**
+ * int atom
+ *
+ * Number of objects is 1
+ *
+ */
+ public GLUniformData(final String name, final int val) {
+ initScalar(name, 1, Integer.valueOf(val));
+ }
+
+ /**
+ * float atom
+ *
+ * Number of objects is 1
+ *
+ */
+ public GLUniformData(final String name, final float val) {
+ initScalar(name, 1, Float.valueOf(val));
+ }
+
+ /**
+ * Multiple IntBuffer Vector
+ *
+ * Number of objects is calculated by data.limit()/components
+ *
+ * @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
+ */
+ public GLUniformData(final String name, final int components, final IntBuffer data) {
+ initBuffer(name, components, data);
+ }
+
+ /**
+ * Multiple FloatBuffer Vector
+ *
+ * Number of objects is calculated by data.limit()/components
+ *
+ * @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
+ */
+ public GLUniformData(final String name, final int components, final FloatBuffer data) {
+ initBuffer(name, components, data);
+ }
+
+ private GLUniformData(final int components, final String name) {
+ initBuffer(name, components, null);
+ }
+
+ public static GLUniformData creatEmptyVector(final String name, final int components) {
+ return new GLUniformData(components, name);
+ }
+
+ public static GLUniformData creatEmptyMatrix(final String name, final int rows, final int columns) {
+ return new GLUniformData(name, rows, columns, null);
+ }
+
+ /**
+ * Multiple FloatBuffer Matrix
+ *
+ * Number of objects is calculated by data.limit()/(rows*columns)
+ *
+ * @param rows the matrix rows
+ * @param column the matrix column
+ */
+ public GLUniformData(final String name, final int rows, final int columns, final FloatBuffer data) {
+ initBuffer(name, rows, columns, data);
+ }
+
+ public GLUniformData setData(final int data) { initScalar(Integer.valueOf(data)); return this; }
+ public GLUniformData setData(final float data) { initScalar(Float.valueOf(data)); return this; }
+ public GLUniformData setData(final IntBuffer data) { initBuffer(data); return this; }
+ public GLUniformData setData(final FloatBuffer data) { initBuffer(data); return this; }
+
+ public int intValue() { return ((Integer)data).intValue(); };
+ public float floatValue() { return ((Float)data).floatValue(); };
+ public IntBuffer intBufferValue() { return (IntBuffer)data; };
+ public FloatBuffer floatBufferValue() { return (FloatBuffer)data; };
+
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("GLUniformData[name ").append(name).
+ append(", location ").append(location).
+ append(", size ").append(rows).append("x").append(columns).
+ append(", count ").append(count).
+ append(", data ");
+ if(isMatrix() && data instanceof FloatBuffer) {
+ sb.append("\n");
+ final FloatBuffer fb = (FloatBuffer)getBuffer();
+ for(int i=0; i<count; i++) {
+ FloatUtil.matrixToString(sb, i+": ", "%10.5f", fb, i*rows*columns, rows, columns, false);
+ sb.append(",\n");
+ }
+ } else if(isBuffer()) {
+ Buffers.toString(sb, null, getBuffer());
+ } else {
+ sb.append(data);
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toString(null).toString();
+ }
+
+ private void initBuffer(final String name, final int rows, final int columns, final Buffer buffer) {
+ if( 2>rows || rows>4 || 2>columns || columns>4 ) {
+ throw new GLException("rowsXcolumns must be within [2..4]X[2..4], is: "+rows+"X"+columns);
+ }
+ this.name=name;
+ this.rows=rows;
+ this.columns=columns;
+ this.isMatrix=true;
+ this.location=-1;
+ initBuffer(buffer);
+ }
+ private void initScalar(final String name, final int components, final Object data) {
+ if( 1>components || components>4 ) {
+ throw new GLException("components must be within [1..4], is: "+components);
+ }
+ this.name=name;
+ this.columns=components;
+ this.rows=1;
+ this.isMatrix=false;
+ this.location=-1;
+ initScalar(data);
+ }
+ private void initBuffer(final String name, final int components, final Buffer buffer) {
+ if( 1>components || components>4 ) {
+ throw new GLException("components must be within [1..4], is: "+components);
+ }
+ this.name=name;
+ this.columns=components;
+ this.rows=1;
+ this.isMatrix=false;
+ this.location=-1;
+ initBuffer(buffer);
+ }
+
+ private void initScalar(final Object data) {
+ if(data instanceof Buffer) {
+ initBuffer((Buffer)data);
+ } else if( null != data ) {
+ if(isMatrix) {
+ throw new GLException("Atom type not allowed for matrix : "+this);
+ }
+ this.count=1;
+ this.data=data;
+ } else {
+ this.count=0;
+ this.data=data;
+ }
+ }
+
+ private void initBuffer(final Buffer buffer) {
+ if( null != buffer ) {
+ final int sz = rows*columns;
+ if(buffer.remaining()<sz || 0!=buffer.remaining()%sz) {
+ throw new GLException("remaining data buffer size invalid: buffer: "+buffer.toString()+"\n\t"+this);
+ }
+ this.count=buffer.remaining()/sz;
+ this.data=buffer;
+ } else {
+ this.count=0;
+ this.data=null;
+ }
+ }
+
+ public String getName() { return name; }
+
+ public int getLocation() { return location; }
+
+ /**
+ * Sets the given location of the shader uniform.
+ * @return the given location
+ */
+ public int setLocation(final int location) { this.location=location; return location; }
+
+ /**
+ * Retrieves the location of the shader uniform from the linked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return &ge;0 denotes a valid uniform location as found and used in the given shader program.
+ * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
+ */
+ public int setLocation(final GL2ES2 gl, final int program) {
+ location = gl.glGetUniformLocation(program, name);
+ return location;
+ }
+
+ public Object getObject() {
+ return data;
+ }
+ public Buffer getBuffer() {
+ return (data instanceof Buffer)?(Buffer)data:null;
+ }
+ public boolean isBuffer() {
+ return (data instanceof Buffer);
+ }
+ public boolean isMatrix() { return isMatrix; }
+
+ public int count() { return count; }
+ public int components() { return rows*columns; }
+ public int rows() { return rows; }
+ public int columns() { return columns; }
+
+ private String name;
+ private int location;
+ private int rows, columns;
+ private int count;
+ private Object data;
+ private boolean isMatrix;
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java b/src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java
index 3693f647a..46971d168 100644
--- a/src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java
+++ b/src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java
@@ -29,8 +29,8 @@
package com.jogamp.opengl;
import java.util.List;
-import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.opengl.DefaultGLCapabilitiesChooser;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.opengl.DefaultGLCapabilitiesChooser;
/**
* Ignores windowSystemRecommendedChoice parameter,
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 8d6765036..5070f3e4e 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -29,7 +29,7 @@
package com.jogamp.opengl;
import com.jogamp.common.GlueGenVersion;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionUtil;
@@ -37,7 +37,7 @@ import com.jogamp.common.util.JogampVersion;
import java.util.List;
import java.util.jar.Manifest;
-import javax.media.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
public class JoglVersion extends JogampVersion {
@@ -51,7 +51,7 @@ public class JoglVersion extends JogampVersion {
if(null == jogampCommonVersionInfo) { // volatile: ok
synchronized(JoglVersion.class) {
if( null == jogampCommonVersionInfo ) {
- final String packageName = "javax.media.opengl";
+ final String packageName = "com.jogamp.opengl";
final Manifest mf = VersionUtil.getManifest(JoglVersion.class.getClassLoader(), packageName);
jogampCommonVersionInfo = new JoglVersion(packageName, mf);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/Threading.java b/src/jogl/classes/com/jogamp/opengl/Threading.java
new file mode 100644
index 000000000..852c8081f
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/Threading.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl;
+
+import jogamp.opengl.ThreadingImpl;
+
+/** This API provides access to the threading model for the implementation of
+ the classes in this package.
+
+ <P>
+
+ OpenGL is specified as a thread-safe API, but in practice there
+ are multithreading-related issues on most, if not all, of the
+ platforms which support it. For example, some OpenGL
+ implementations do not behave well when one context is made
+ current first on one thread, released, and then made current on a
+ second thread, although this is legal according to the OpenGL
+ specification. On other platforms there are other problems.
+
+ <P>
+
+ Due to these limitations, and due to the inherent multithreading
+ in the Java platform (in particular, in the Abstract Window
+ Toolkit), it is often necessary to limit the multithreading
+ occurring in the typical application using the OpenGL API.
+
+ <P>
+
+ In the current reference implementation, for instance, multithreading
+ has been limited by
+ forcing all OpenGL-related work for GLAutoDrawables on to a single
+ thread. In other words, if an application uses only the
+ GLAutoDrawable and GLEventListener callback mechanism, it is
+ guaranteed to have the most correct single-threaded behavior on
+ all platforms.
+
+ <P>
+
+ Applications using the GLContext makeCurrent/release API directly
+ will inherently break this single-threaded model, as these methods
+ require that the OpenGL context be made current on the current
+ thread immediately. For applications wishing to integrate better
+ with an implementation that uses the single-threaded model, this
+ class provides public access to the mechanism used by the implementation.
+
+ <P>
+
+ Users can execute Runnables on the
+ internal thread used for performing OpenGL work, and query whether
+ the current thread is already this thread. Using these mechanisms
+ the user can move work from the current thread on to the internal
+ OpenGL thread if desired.
+
+ <P>
+
+ This class also provides mechanisms for querying whether this
+ internal serialization of OpenGL work is in effect, and a
+ programmatic way of disabling it. In the current reference
+ implementation it is enabled by default, although it could be
+ disabled in the future if OpenGL drivers become more robust on
+ all platforms.
+
+ <P>
+
+ In addition to specifying programmatically whether the single
+ thread for OpenGL work is enabled, users may switch it on and off
+ using the system property <code>jogl.1thread</code>. Valid values
+ for this system property are:
+
+ <PRE>
+ -Djogl.1thread=false Disable single-threading of OpenGL work, hence use multithreading.
+ -Djogl.1thread=true Enable single-threading of OpenGL work (default -- on a newly-created worker thread)
+ -Djogl.1thread=auto Select default single-threading behavior (currently on)
+ -Djogl.1thread=awt Enable single-threading of OpenGL work on AWT event dispatch thread (current default on all
+ platforms, and also the default behavior older releases)
+ -Djogl.1thread=worker Enable single-threading of OpenGL work on newly-created worker thread (not suitable for Mac
+ OS X or X11 platforms, and risky on Windows in applet environments)
+ </PRE>
+*/
+
+public class Threading {
+ public static enum Mode {
+ /**
+ * Full multithreaded OpenGL,
+ * i.e. any {@link Threading#invoke(boolean, Runnable, Object) invoke}
+ * {@link Threading#invokeOnOpenGLThread(boolean, Runnable) commands}
+ * will be issued on the current thread immediately.
+ */
+ MT(0),
+
+ /** Single-Threaded OpenGL on AWT EDT */
+ ST_AWT(1),
+
+ /** Single-Threaded OpenGL on dedicated worker thread. */
+ ST_WORKER(2);
+
+ public final int id;
+
+ Mode(final int id){
+ this.id = id;
+ }
+ }
+
+ /** No reason to ever instantiate this class */
+ private Threading() {}
+
+ /** Returns the threading mode */
+ public static Mode getMode() {
+ return ThreadingImpl.getMode();
+ }
+
+ /** If an implementation of the com.jogamp.opengl APIs offers a
+ multithreading option but the default behavior is single-threading,
+ this API provides a mechanism for end users to disable single-threading
+ in this implementation. Users are strongly discouraged from
+ calling this method unless they are aware of all of the
+ consequences and are prepared to enforce some amount of
+ threading restrictions in their applications. Disabling
+ single-threading, for example, may have unintended consequences
+ on GLAutoDrawable implementations such as GLCanvas and GLJPanel.
+ Currently there is no supported way to re-enable it
+ once disabled, partly to discourage careless use of this
+ method. This method should be called as early as possible in an
+ application. */
+ public static final void disableSingleThreading() {
+ ThreadingImpl.disableSingleThreading();
+ }
+
+ /** Indicates whether OpenGL work is being automatically forced to a
+ single thread in this implementation. */
+ public static final boolean isSingleThreaded() {
+ return ThreadingImpl.isSingleThreaded();
+ }
+
+ /** Indicates whether the current thread is the designated toolkit thread,
+ if such semantics exists. */
+ public static final boolean isToolkitThread() throws GLException {
+ return ThreadingImpl.isToolkitThread();
+ }
+
+ /**
+ * Indicates whether the current thread is capable of
+ * performing OpenGL-related work.
+ * <p>
+ * Method always returns <code>true</code>
+ * if {@link #getMode()} == {@link Mode#MT} or {@link #isSingleThreaded()} == <code>false</code>.
+ * </p>
+ */
+ public static final boolean isOpenGLThread() throws GLException {
+ return ThreadingImpl.isOpenGLThread();
+ }
+
+ /** Executes the passed Runnable on the single thread used for all
+ OpenGL work in this com.jogamp.opengl API implementation. It is
+ not specified exactly which thread is used for this
+ purpose. This method should only be called if the single-thread
+ model is in use and if the current thread is not the OpenGL
+ thread (i.e., if <code>isOpenGLThread()</code> returns
+ false). It is up to the end user to check to see whether the
+ current thread is the OpenGL thread and either execute the
+ Runnable directly or perform the work inside it.
+ **/
+ public static final void invokeOnOpenGLThread(final boolean wait, final Runnable r) throws GLException {
+ ThreadingImpl.invokeOnOpenGLThread(wait, r);
+ }
+
+ /**
+ * If not {@link #isOpenGLThread()}
+ * <b>and</b> the <code>lock</code> is not being hold by this thread,
+ * invoke Runnable <code>r</code> on the OpenGL thread via {@link #invokeOnOpenGLThread(boolean, Runnable)}.
+ * <p>
+ * Otherwise invoke Runnable <code>r</code> on the current thread.
+ * </p>
+ *
+ * @param wait set to true for waiting until Runnable <code>r</code> is finished, otherwise false.
+ * @param r the Runnable to be executed
+ * @param lock optional lock object to be tested
+ * @throws GLException
+ */
+ public static final void invoke(final boolean wait, final Runnable r, final Object lock) throws GLException {
+ if ( !isOpenGLThread() &&
+ ( null == lock || !Thread.holdsLock(lock) ) ) {
+ invokeOnOpenGLThread(wait, r);
+ } else {
+ r.run();
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/TraceGL2.java b/src/jogl/classes/com/jogamp/opengl/TraceGL2.java
new file mode 100644
index 000000000..1609398e7
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/TraceGL2.java
@@ -0,0 +1,23 @@
+package com.jogamp.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL2 extends TraceGL4bc {
+ public TraceGL2(final GL2 downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/TraceGL3.java b/src/jogl/classes/com/jogamp/opengl/TraceGL3.java
new file mode 100644
index 000000000..fd95d6392
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/TraceGL3.java
@@ -0,0 +1,23 @@
+package com.jogamp.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL3 extends TraceGL4bc {
+ public TraceGL3(final GL3 downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/TraceGL3bc.java b/src/jogl/classes/com/jogamp/opengl/TraceGL3bc.java
new file mode 100644
index 000000000..7daa9e392
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/TraceGL3bc.java
@@ -0,0 +1,23 @@
+package com.jogamp.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL3bc extends TraceGL4bc {
+ public TraceGL3bc(final GL3bc downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/TraceGL4.java b/src/jogl/classes/com/jogamp/opengl/TraceGL4.java
new file mode 100644
index 000000000..b0c817105
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/TraceGL4.java
@@ -0,0 +1,23 @@
+package com.jogamp.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL4 extends TraceGL4bc {
+ public TraceGL4(final GL4 downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/TraceGLES2.java b/src/jogl/classes/com/jogamp/opengl/TraceGLES2.java
new file mode 100644
index 000000000..7c7956b68
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/TraceGLES2.java
@@ -0,0 +1,23 @@
+package com.jogamp.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGLES2 extends TraceGLES3 {
+ public TraceGLES2(final GLES2 downstream, final PrintStream stream) {
+ super((GLES3)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/awt/AWTGLAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/awt/AWTGLAutoDrawable.java
new file mode 100644
index 000000000..6e273e4e6
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/awt/AWTGLAutoDrawable.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl.awt;
+
+import com.jogamp.opengl.GLAutoDrawable;
+
+public interface AWTGLAutoDrawable extends GLAutoDrawable, ComponentEvents {
+ /** Requests a new width and height for this AWTGLAutoDrawable. */
+ public void setSize(int width, int height);
+
+ /** Schedules a repaint of the component at some point in the
+ future. */
+ public void repaint();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/awt/ComponentEvents.java b/src/jogl/classes/com/jogamp/opengl/awt/ComponentEvents.java
new file mode 100644
index 000000000..996776c9b
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/awt/ComponentEvents.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl.awt;
+
+import com.jogamp.opengl.*;
+import java.awt.event.*;
+import java.beans.PropertyChangeListener;
+
+/** Factors out the listener manipulation for the events supported by
+ all of the {@link GLDrawable} implementations. Provided to reduce
+ clutter in the documentation for GLDrawable. */
+
+public interface ComponentEvents {
+ public void addComponentListener(ComponentListener l);
+ public void removeComponentListener(ComponentListener l);
+ public void addFocusListener(FocusListener l);
+ public void removeFocusListener(FocusListener l);
+ public void addHierarchyBoundsListener(HierarchyBoundsListener l);
+ public void removeHierarchyBoundsListener(HierarchyBoundsListener l);
+ public void addHierarchyListener(HierarchyListener l);
+ public void removeHierarchyListener(HierarchyListener l);
+ public void addInputMethodListener(InputMethodListener l);
+ public void removeInputMethodListener(InputMethodListener l);
+ public void addKeyListener(KeyListener l);
+ public void removeKeyListener(KeyListener l);
+ public void addMouseListener(MouseListener l);
+ public void removeMouseListener(MouseListener l);
+ public void addMouseMotionListener(MouseMotionListener l);
+ public void removeMouseMotionListener(MouseMotionListener l);
+ public void addMouseWheelListener(MouseWheelListener l);
+ public void removeMouseWheelListener(MouseWheelListener l);
+ public void addPropertyChangeListener(PropertyChangeListener listener);
+ public void removePropertyChangeListener(PropertyChangeListener listener);
+ public void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener);
+ public void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java
new file mode 100644
index 000000000..11d217535
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java
@@ -0,0 +1,1643 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl.awt;
+
+import java.beans.Beans;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.awt.EventQueue;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.OffscreenLayerOption;
+import com.jogamp.nativewindow.ScalableSurface;
+import com.jogamp.nativewindow.VisualIDHolder;
+import com.jogamp.nativewindow.WindowClosingProtocol;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.GraphicsConfigurationFactory;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLCapabilitiesChooser;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLOffscreenAutoDrawable;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.GLRunnable;
+import com.jogamp.opengl.GLSharedContextSetter;
+import com.jogamp.opengl.Threading;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
+import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
+import com.jogamp.nativewindow.awt.JAWTWindow;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.TileRenderer;
+
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.awt.AWTTilePainter;
+
+// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
+// context whenever the displayChanged() function is called on our
+// GLEventListeners
+
+/** A heavyweight AWT component which provides OpenGL rendering
+ support. This is the primary implementation of an AWT {@link GLDrawable};
+ {@link GLJPanel} is provided for compatibility with Swing user
+ interfaces when adding a heavyweight doesn't work either because
+ of Z-ordering or LayoutManager problems.
+ *
+ * <h5><a name="offscreenlayer">Offscreen Layer Remarks</a></h5>
+ *
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
+ * the underlying JAWT mechanism to composite the image, if supported.
+ * <p>
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is <code>false</code>.
+ * </p>
+ *
+ * <h5><a name="java2dgl">Java2D OpenGL Remarks</a></h5>
+ *
+ * To avoid any conflicts with a potential Java2D OpenGL context,<br>
+ * you shall consider setting the following JVM properties:<br>
+ * <ul>
+ * <li><pre>sun.java2d.opengl=false</pre></li>
+ * <li><pre>sun.java2d.noddraw=true</pre></li>
+ * </ul>
+ * This is especially true in case you want to utilize a GLProfile other than
+ * {@link GLProfile#GL2}, eg. using {@link GLProfile#getMaxFixedFunc()}.<br>
+ * On the other hand, if you like to experiment with GLJPanel's utilization
+ * of Java2D's OpenGL pipeline, you have to set them to
+ * <ul>
+ * <li><pre>sun.java2d.opengl=true</pre></li>
+ * <li><pre>sun.java2d.noddraw=true</pre></li>
+ * </ul>
+ *
+ * <h5><a name="backgrounderase">Disable Background Erase</a></h5>
+ *
+ * GLCanvas tries to disable background erase for the AWT Canvas
+ * before native peer creation (X11) and after it (Windows), <br>
+ * utilizing the optional {@link java.awt.Toolkit} method <code>disableBeackgroundErase(java.awt.Canvas)</code>.<br>
+ * However if this does not give you the desired results, you may want to disable AWT background erase in general:
+ * <ul>
+ * <li><pre>sun.awt.noerasebackground=true</pre></li>
+ * </ul>
+ *
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
+ */
+
+@SuppressWarnings("serial")
+public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption,
+ AWTPrintLifecycle, GLSharedContextSetter, ScalableSurface {
+
+ private static final boolean DEBUG = Debug.debug("GLCanvas");
+
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+ private final GLDrawableHelper helper = new GLDrawableHelper();
+ private AWTGraphicsConfiguration awtConfig;
+ private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
+ private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
+ private volatile GLContextImpl context; // volatile: avoid locking for read-only access
+ private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
+ private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ // copy of the cstr args, mainly for recreation
+ private final GLCapabilitiesImmutable capsReqUser;
+ private final GLCapabilitiesChooser chooser;
+ private int additionalCtxCreationFlags = 0;
+ private final GraphicsDevice device;
+ private boolean shallUseOffscreenLayer = false;
+
+ private volatile boolean isShowing;
+ private final HierarchyListener hierarchyListener = new HierarchyListener() {
+ @Override
+ public void hierarchyChanged(final HierarchyEvent e) {
+ isShowing = GLCanvas.this.isShowing();
+ }
+ };
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
+ new AWTWindowClosingProtocol(this, new Runnable() {
+ @Override
+ public void run() {
+ GLCanvas.this.destroyImpl( true );
+ }
+ }, null);
+
+ /** Creates a new GLCanvas component with a default set of OpenGL
+ capabilities, using the default OpenGL capabilities selection
+ mechanism, on the default screen device.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
+ * @throws GLException if no default profile is available for the default desktop device.
+ */
+ public GLCanvas() throws GLException {
+ this(null);
+ }
+
+ /** Creates a new GLCanvas component with the requested set of
+ OpenGL capabilities, using the default OpenGL capabilities
+ selection mechanism, on the default screen device.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
+ * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
+ * @see GLCanvas#GLCanvas(com.jogamp.opengl.GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesChooser, com.jogamp.opengl.GLContext, java.awt.GraphicsDevice)
+ */
+ public GLCanvas(final GLCapabilitiesImmutable capsReqUser) throws GLException {
+ this(capsReqUser, null, null);
+ }
+
+ /** Creates a new GLCanvas component. The passed GLCapabilities
+ specifies the OpenGL capabilities for the component; if null, a
+ default set of capabilities is used. The GLCapabilitiesChooser
+ specifies the algorithm for selecting one of the available
+ GLCapabilities for the component; a DefaultGLCapabilitesChooser
+ is used if null is passed for this argument.
+ The passed GraphicsDevice indicates the screen on
+ which to create the GLCanvas; the GLDrawableFactory uses the
+ default screen device of the local GraphicsEnvironment if null
+ is passed for this argument.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
+ * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
+ */
+ public GLCanvas(final GLCapabilitiesImmutable capsReqUser,
+ final GLCapabilitiesChooser chooser,
+ final GraphicsDevice device)
+ throws GLException
+ {
+ /*
+ * Determination of the native window is made in 'super.addNotify()',
+ * which creates the native peer using AWT's GraphicsConfiguration.
+ * GraphicsConfiguration is returned by this class overwritten
+ * 'getGraphicsConfiguration()', which returns our OpenGL compatible
+ * 'chosen' GraphicsConfiguration.
+ */
+ super();
+
+ if(null==capsReqUser) {
+ this.capsReqUser = new GLCapabilities(GLProfile.getDefault(GLProfile.getDefaultDevice()));
+ } else {
+ // don't allow the user to change data
+ this.capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
+ }
+ if( !this.capsReqUser.isOnscreen() ) {
+ setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
+ }
+
+ if(null==device) {
+ final GraphicsConfiguration gc = super.getGraphicsConfiguration();
+ if(null!=gc) {
+ this.device = gc.getDevice();
+ } else {
+ this.device = null;
+ }
+ } else {
+ this.device = device;
+ }
+
+ // instantiation will be issued in addNotify()
+ this.chooser = chooser;
+
+ this.addHierarchyListener(hierarchyListener);
+ this.isShowing = isShowing();
+ }
+
+ @Override
+ public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.context, sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
+ public final RecursiveLock getUpstreamLock() { return lock; }
+
+ @Override
+ public final boolean isThreadGLCapable() { return Threading.isOpenGLThread(); }
+
+ @Override
+ public void setShallUseOffscreenLayer(final boolean v) {
+ shallUseOffscreenLayer = v;
+ }
+
+ @Override
+ public final boolean getShallUseOffscreenLayer() {
+ return shallUseOffscreenLayer;
+ }
+
+ @Override
+ public final boolean isOffscreenLayerSurfaceEnabled() {
+ final JAWTWindow _jawtWindow = jawtWindow;
+ if(null != _jawtWindow) {
+ return _jawtWindow.isOffscreenLayerSurfaceEnabled();
+ }
+ return false;
+ }
+
+
+ /**
+ * Overridden to choose a GraphicsConfiguration on a parent container's
+ * GraphicsDevice because both devices
+ */
+ @Override
+ public GraphicsConfiguration getGraphicsConfiguration() {
+ /*
+ * Workaround for problems with Xinerama and java.awt.Component.checkGD
+ * when adding to a container on a different graphics device than the
+ * one that this Canvas is associated with.
+ *
+ * GC will be null unless:
+ * - A native peer has assigned it. This means we have a native
+ * peer, and are already comitted to a graphics configuration.
+ * - This canvas has been added to a component hierarchy and has
+ * an ancestor with a non-null GC, but the native peer has not
+ * yet been created. This means we can still choose the GC on
+ * all platforms since the peer hasn't been created.
+ */
+ final GraphicsConfiguration gc = super.getGraphicsConfiguration();
+
+ if( Beans.isDesignTime() ) {
+ return gc;
+ }
+
+ /*
+ * chosen is only non-null on platforms where the GLDrawableFactory
+ * returns a non-null GraphicsConfiguration (in the GLCanvas
+ * constructor).
+ *
+ * if gc is from this Canvas' native peer then it should equal chosen,
+ * otherwise it is from an ancestor component that this Canvas is being
+ * added to, and we go into this block.
+ */
+ GraphicsConfiguration chosen = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
+
+ if (gc != null && chosen != null && !chosen.equals(gc)) {
+ /*
+ * Check for compatibility with gc. If they differ by only the
+ * device then return a new GCconfig with the super-class' GDevice
+ * (and presumably the same visual ID in Xinerama).
+ *
+ */
+ if (!chosen.getDevice().getIDstring().equals(gc.getDevice().getIDstring())) {
+ /*
+ * Here we select a GraphicsConfiguration on the alternate
+ * device that is presumably identical to the chosen
+ * configuration, but on the other device.
+ *
+ * Should really check to ensure that we select a configuration
+ * with the same X visual ID for Xinerama screens, otherwise the
+ * GLDrawable may have the wrong visual ID (I don't think this
+ * ever gets updated). May need to add a method to
+ * X11GLDrawableFactory to do this in a platform specific
+ * manner.
+ *
+ * However, on platforms where we can actually get into this
+ * block, both devices should have the same visual list, and the
+ * same configuration should be selected here.
+ */
+ final AWTGraphicsConfiguration config = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(),
+ (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities(),
+ chooser, gc.getDevice());
+ final GraphicsConfiguration compatible = config.getAWTGraphicsConfiguration();
+ final boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info:");
+ System.err.println("Created Config (n): HAVE GC "+chosen);
+ System.err.println("Created Config (n): THIS GC "+gc);
+ System.err.println("Created Config (n): Choosen GC "+compatible);
+ System.err.println("Created Config (n): HAVE CF "+awtConfig);
+ System.err.println("Created Config (n): Choosen CF "+config);
+ System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
+ // Thread.dumpStack();
+ }
+
+ if (compatible != null) {
+ /*
+ * Save the new GC for equals test above, and to return to
+ * any outside callers of this method.
+ */
+ chosen = compatible;
+
+ if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) {
+ // complete destruction!
+ destroyImpl( true );
+ // recreation!
+ awtConfig = config;
+ createJAWTDrawableAndContext();
+ validateGLDrawable();
+ } else {
+ awtConfig = config;
+ }
+ }
+ }
+
+ /*
+ * If a compatible GC was not found in the block above, this will
+ * return the GC that was selected in the constructor (and might
+ * cause an exception in Component.checkGD when adding to a
+ * container, but in this case that would be the desired behavior).
+ *
+ */
+ return chosen;
+ } else if (gc == null) {
+ /*
+ * The GC is null, which means we have no native peer, and are not
+ * part of a (realized) component hierarchy. So we return the
+ * desired visual that was selected in the constructor (possibly
+ * null).
+ */
+ return chosen;
+ }
+
+ /*
+ * Otherwise we have not explicitly selected a GC in the constructor, so
+ * just return what Canvas would have.
+ */
+ return gc;
+ }
+
+ @Override
+ public GLContext createContext(final GLContext shareWith) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if(drawable != null) {
+ final GLContext _ctx = drawable.createContext(shareWith);
+ _ctx.setContextCreationFlags(additionalCtxCreationFlags);
+ return _ctx;
+ }
+ return null;
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ private final void setRealizedImpl(final boolean realized) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawable _drawable = drawable;
+ if( null == _drawable || realized == _drawable.isRealized() ||
+ realized && ( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) ) {
+ return;
+ }
+ _drawable.setRealized(realized);
+ if( realized && _drawable.isRealized() ) {
+ sendReshape=true; // ensure a reshape is being send ..
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ private final Runnable realizeOnEDTAction = new Runnable() {
+ @Override
+ public void run() { setRealizedImpl(true); }
+ };
+ private final Runnable unrealizeOnEDTAction = new Runnable() {
+ @Override
+ public void run() { setRealizedImpl(false); }
+ };
+
+ @Override
+ public final void setRealized(final boolean realized) {
+ // Make sure drawable realization happens on AWT-EDT and only there. Consider the AWTTree lock!
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), false /* allowOnNonEDT */, true /* wait */, realized ? realizeOnEDTAction : unrealizeOnEDTAction);
+ }
+
+ @Override
+ public boolean isRealized() {
+ final GLDrawable _drawable = drawable;
+ return ( null != _drawable ) ? _drawable.isRealized() : false;
+ }
+
+ @Override
+ public WindowClosingMode getDefaultCloseOperation() {
+ return awtWindowClosingProtocol.getDefaultCloseOperation();
+ }
+
+ @Override
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
+ return awtWindowClosingProtocol.setDefaultCloseOperation(op);
+ }
+
+ @Override
+ public void display() {
+ if( !validateGLDrawable() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
+ }
+ return; // not yet available ..
+ }
+ if( isShowing && !printActive ) {
+ Threading.invoke(true, displayOnEDTAction, getTreeLock());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * This impl. only destroys all GL related resources.
+ * </p>
+ * <p>
+ * This impl. does not remove the GLCanvas from it's parent AWT container
+ * so this class's {@link #removeNotify()} AWT override won't get called.
+ * To do so, remove this component from it's parent AWT container.
+ * </p>
+ */
+ @Override
+ public void destroy() {
+ destroyImpl( false );
+ }
+
+ protected void destroyImpl(final boolean destroyJAWTWindowAndAWTDevice) {
+ Threading.invoke(true, destroyOnEDTAction, getTreeLock());
+ if( destroyJAWTWindowAndAWTDevice ) {
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, disposeJAWTWindowAndAWTDeviceOnEDT);
+ }
+ }
+
+ /** Overridden to cause OpenGL rendering to be performed during
+ repaint cycles. Subclasses which override this method must call
+ super.paint() in their paint() method in order to function
+ properly.
+ */
+ @Override
+ public void paint(final Graphics g) {
+ if( Beans.isDesignTime() ) {
+ // Make GLCanvas behave better in NetBeans GUI builder
+ g.setColor(Color.BLACK);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ final FontMetrics fm = g.getFontMetrics();
+ String name = getName();
+ if (name == null) {
+ name = getClass().getName();
+ final int idx = name.lastIndexOf('.');
+ if (idx >= 0) {
+ name = name.substring(idx + 1);
+ }
+ }
+ final Rectangle2D bounds = fm.getStringBounds(name, g);
+ g.setColor(Color.WHITE);
+ g.drawString(name,
+ (int) ((getWidth() - bounds.getWidth()) / 2),
+ (int) ((getHeight() + bounds.getHeight()) / 2));
+ } else if( !this.helper.isAnimatorAnimatingOnOtherThread() ) {
+ display();
+ }
+ }
+
+ /** Overridden to track when this component is added to a container.
+ Subclasses which override this method must call
+ super.addNotify() in their addNotify() method in order to
+ function properly. <P>
+
+ <B>Overrides:</B>
+ <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ @SuppressWarnings("deprecation")
+ @Override
+ public void addNotify() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final boolean isBeansDesignTime = Beans.isDesignTime();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()+", isBeansDesignTime "+isBeansDesignTime);
+ // Thread.dumpStack();
+ }
+
+ if( isBeansDesignTime ) {
+ super.addNotify();
+ } else {
+ /**
+ * 'super.addNotify()' determines the GraphicsConfiguration,
+ * while calling this class's overriden 'getGraphicsConfiguration()' method
+ * after which it creates the native peer.
+ * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
+ * is being used in getGraphicsConfiguration().
+ * This code order also allows recreation, ie re-adding the GLCanvas.
+ */
+ awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
+ if(null==awtConfig) {
+ throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ }
+
+ // before native peer is valid: X11
+ disableBackgroundErase();
+
+ // issues getGraphicsConfiguration() and creates the native peer
+ super.addNotify();
+
+ // after native peer is valid: Windows
+ disableBackgroundErase();
+
+ createJAWTDrawableAndContext();
+
+ // init drawable by paint/display makes the init sequence more equal
+ // for all launch flavors (applet/javaws/..)
+ // validateGLDrawable();
+ }
+ awtWindowClosingProtocol.addClosingListener();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ @Override
+ public final boolean setSurfaceScale(final float[] pixelScale) {
+ System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
+ if( isRealized() && isShowing ) {
+ Threading.invoke(true, setSurfaceScaleOnEDTAction, getTreeLock());
+ return true;
+ } else {
+ return false;
+ }
+ }
+ private final Runnable setSurfaceScaleOnEDTAction = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( null != drawable && drawable.isRealized() ) {
+ if( setSurfaceScaleImpl(jawtWindow) ) {
+ reshapeImpl(getWidth(), getHeight());
+ if( !helper.isAnimatorAnimatingOnOtherThread() ) {
+ helper.invokeGL(drawable, context, displayAction, initAction); // display
+ }
+ }
+ }
+ } finally {
+ _lock.unlock();
+ }
+ } };
+ private final boolean setSurfaceScaleImpl(final ScalableSurface ns) {
+ if( ns.setSurfaceScale(reqPixelScale) ) {
+ ns.getCurrentSurfaceScale(hasPixelScale);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private final boolean updatePixelScale() {
+ if( jawtWindow.hasPixelScaleChanged() ) {
+ jawtWindow.getMaximumSurfaceScale(maxPixelScale);
+ jawtWindow.getMinimumSurfaceScale(minPixelScale);
+ return setSurfaceScaleImpl(jawtWindow);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public final float[] getRequestedSurfaceScale(final float[] result) {
+ System.arraycopy(reqPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final float[] getCurrentSurfaceScale(final float[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public float[] getMinimumSurfaceScale(final float[] result) {
+ System.arraycopy(minPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public float[] getMaximumSurfaceScale(final float[] result) {
+ System.arraycopy(maxPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ private void createJAWTDrawableAndContext() {
+ if ( !Beans.isDesignTime() ) {
+ jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+ jawtWindow.lockSurface();
+ try {
+ jawtWindow.setSurfaceScale(reqPixelScale);
+ drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
+ createContextImpl(drawable);
+ jawtWindow.getCurrentSurfaceScale(hasPixelScale);
+ jawtWindow.getMinimumSurfaceScale(minPixelScale);
+ jawtWindow.getMaximumSurfaceScale(maxPixelScale);
+ } finally {
+ jawtWindow.unlockSurface();
+ }
+ }
+ }
+ private boolean createContextImpl(final GLDrawable drawable) {
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ context = (GLContextImpl) drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Context created: has shared "+(null != shareWith[0]));
+ }
+ return true;
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Context !created: pending share");
+ }
+ return false;
+ }
+ }
+
+ private boolean validateGLDrawable() {
+ if( Beans.isDesignTime() || !isDisplayable() ) {
+ return false; // early out!
+ }
+ final GLDrawable _drawable = drawable;
+ if ( null != _drawable ) {
+ boolean res = _drawable.isRealized();
+ if( !res ) {
+ // re-try drawable creation
+ if( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) {
+ return false; // early out!
+ }
+ setRealized(true);
+ res = _drawable.isRealized();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
+ // Thread.dumpStack();
+ }
+ }
+ if( res && null == context ) {
+ // re-try context creation
+ res = createContextImpl(_drawable); // pending creation.
+ }
+ return res;
+ }
+ return false;
+ }
+
+ /** <p>Overridden to track when this component is removed from a
+ container. Subclasses which override this method must call
+ super.removeNotify() in their removeNotify() method in order to
+ function properly. </p>
+ <p>User shall not call this method outside of EDT, read the AWT/Swing specs
+ about this.</p>
+ <B>Overrides:</B>
+ <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ @SuppressWarnings("deprecation")
+ @Override
+ public void removeNotify() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: removeNotify - start");
+ // Thread.dumpStack();
+ }
+
+ awtWindowClosingProtocol.removeClosingListener();
+
+ if( Beans.isDesignTime() ) {
+ super.removeNotify();
+ } else {
+ try {
+ destroyImpl( true );
+ } finally {
+ super.removeNotify();
+ }
+ }
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: removeNotify - end, peer: "+getPeer());
+ }
+ }
+
+ /** Overridden to cause {@link GLDrawableHelper#reshape} to be
+ called on all registered {@link GLEventListener}s. Subclasses
+ which override this method must call super.reshape() in
+ their reshape() method in order to function properly. <P>
+
+ <B>Overrides:</B>
+ <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ @SuppressWarnings("deprecation")
+ @Override
+ public void reshape(final int x, final int y, final int width, final int height) {
+ synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
+ super.reshape(x, y, width, height);
+ reshapeImpl(width, height);
+ }
+ }
+ private void reshapeImpl(final int width, final int height) {
+ final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]);
+ final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]);
+
+ if(DEBUG) {
+ final NativeSurface ns = getNativeSurface();
+ final long nsH = null != ns ? ns.getSurfaceHandle() : 0;
+ System.err.println(getThreadName()+": GLCanvas.reshape.0 "+this.getName()+" resize"+(printActive?"WithinPrint":"")+
+ " [ this "+getWidth()+"x"+getHeight()+", pixelScale "+getPixelScaleStr()+
+ "] -> "+(printActive?"[skipped] ":"") + width+"x"+height+" * "+getPixelScaleStr()+" -> "+scaledWidth+"x"+scaledHeight+
+ " - surfaceHandle 0x"+Long.toHexString(nsH));
+ // Thread.dumpStack();
+ }
+ if( validateGLDrawable() && !printActive ) {
+ final GLDrawableImpl _drawable = drawable;
+ if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, scaledWidth, scaledHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ drawable = _drawableNew;
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+ }
+ }
+
+ /**
+ * Overridden from Canvas to prevent the AWT's clearing of the
+ * canvas from interfering with the OpenGL rendering.
+ */
+ @Override
+ public void update(final Graphics g) {
+ paint(g);
+ }
+
+ private volatile boolean printActive = false;
+ private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
+ private AWTTilePainter printAWTTiles = null;
+
+ @Override
+ public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ printActive = true;
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
+ }
+ private final Runnable setupPrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !validateGLDrawable() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ if( !isVisible() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, canvas not visible");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ sendReshape = false; // clear reshape flag
+ printAnimator = helper.getAnimator();
+ if( null != printAnimator ) {
+ printAnimator.remove(GLCanvas.this);
+ }
+ printGLAD = GLCanvas.this; // _not_ default, shall be replaced by offscreen GLAD
+ final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
+ final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
+ GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
+ final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
+ final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
+ printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
+ final boolean reqNewGLADOnscrn = gladCaps.isOnscreen();
+
+ final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
+ newGLADCaps.setDoubleBuffered(false);
+ newGLADCaps.setOnscreen(false);
+ if( printNumSamples != newGLADCaps.getNumSamples() ) {
+ newGLADCaps.setSampleBuffers(0 < printNumSamples);
+ newGLADCaps.setNumSamples(printNumSamples);
+ }
+ final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
+
+ final boolean reqNewGLAD = ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
+
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
+ ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
+ ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
+ ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
+ ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
+ }
+ if( reqNewGLAD ) {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
+ GLOffscreenAutoDrawable offGLAD = null;
+ try {
+ offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
+ printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
+ } catch (final GLException gle) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+gle.getMessage());
+ gle.printStackTrace();
+ }
+ }
+ if( null != offGLAD ) {
+ printGLAD = offGLAD;
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
+ printDrawable = printGLAD.getDelegatedDrawable();
+ }
+ }
+ printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
+ printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
+ printAWTTiles.renderer.attachAutoDrawable(printGLAD);
+ if( DEBUG ) {
+ System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
+ System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
+ System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void releasePrint() {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ sendReshape = false; // clear reshape flag
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
+ }
+ private final Runnable releasePrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( DEBUG ) {
+ System.err.println("AWT print.release "+printAWTTiles);
+ }
+ printAWTTiles.dispose();
+ printAWTTiles= null;
+ if( printGLAD != GLCanvas.this ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLCanvas.this);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
+ if( null != printAnimator ) {
+ printAnimator.add(GLCanvas.this);
+ printAnimator = null;
+ }
+ sendReshape = true; // trigger reshape, i.e. gl-viewport and -listener - this component might got resized!
+ printActive = false;
+ display();
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void print(final Graphics graphics) {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ if(DEBUG && !EventQueue.isDispatchThread()) {
+ System.err.println(getThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
+ // we cannot dispatch print on AWT-EDT due to printing internal locking ..
+ }
+ sendReshape = false; // clear reshape flag
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ try {
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ if( !tileRenderer.eot() ) {
+ try {
+ do {
+ if( printGLAD != GLCanvas.this ) {
+ tileRenderer.display();
+ } else {
+ Threading.invoke(true, displayOnEDTAction, getTreeLock());
+ }
+ } while ( !tileRenderer.eot() );
+ if( DEBUG ) {
+ System.err.println("AWT print.1: "+printAWTTiles);
+ }
+ } finally {
+ tileRenderer.reset();
+ printAWTTiles.resetGraphics2D();
+ }
+ }
+ } catch (final NoninvertibleTransformException nte) {
+ System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
+ nte.printStackTrace();
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.X: "+printAWTTiles);
+ }
+ }
+
+ @Override
+ public void addGLEventListener(final GLEventListener listener) {
+ helper.addGLEventListener(listener);
+ }
+
+ @Override
+ public void addGLEventListener(final int index, final GLEventListener listener) throws IndexOutOfBoundsException {
+ helper.addGLEventListener(index, listener);
+ }
+
+ @Override
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
+ }
+
+ @Override
+ public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
+ }
+
+ @Override
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(final GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ Threading.invoke(true, r, getTreeLock());
+ return r.listener;
+ }
+
+ @Override
+ public GLEventListener removeGLEventListener(final GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
+ public void setAnimator(final GLAnimatorControl animatorControl) {
+ helper.setAnimator(animatorControl);
+ }
+
+ @Override
+ public GLAnimatorControl getAnimator() {
+ return helper.getAnimator();
+ }
+
+ @Override
+ public final Thread setExclusiveContextThread(final Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, context);
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnable);
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnables);
+ }
+
+ @Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
+ public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ return oldCtx;
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ @Override
+ public final GLDrawable getDelegatedDrawable() {
+ return drawable;
+ }
+
+ @Override
+ public GLContext getContext() {
+ return context;
+ }
+
+ @Override
+ public GL getGL() {
+ if( Beans.isDesignTime() ) {
+ return null;
+ }
+ final GLContext _context = context;
+ return (_context == null) ? null : _context.getGL();
+ }
+
+ @Override
+ public GL setGL(final GL gl) {
+ final GLContext _context = context;
+ if (_context != null) {
+ _context.setGL(gl);
+ return gl;
+ }
+ return null;
+ }
+
+
+ @Override
+ public void setAutoSwapBufferMode(final boolean onOrOff) {
+ helper.setAutoSwapBufferMode(onOrOff);
+ }
+
+ @Override
+ public boolean getAutoSwapBufferMode() {
+ return helper.getAutoSwapBufferMode();
+ }
+
+ @Override
+ public void swapBuffers() {
+ Threading.invoke(true, swapBuffersOnEDTAction, getTreeLock());
+ }
+
+ @Override
+ public void setContextCreationFlags(final int flags) {
+ additionalCtxCreationFlags = flags;
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
+ }
+ }
+
+ @Override
+ public int getContextCreationFlags() {
+ return additionalCtxCreationFlags;
+ }
+
+ @Override
+ public GLProfile getGLProfile() {
+ return capsReqUser.getGLProfile();
+ }
+
+ @Override
+ public GLCapabilitiesImmutable getChosenGLCapabilities() {
+ if( Beans.isDesignTime() ) {
+ return capsReqUser;
+ } else if( null == awtConfig ) {
+ throw new GLException("No AWTGraphicsConfiguration: "+this);
+ }
+ return (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities();
+ }
+
+ @Override
+ public GLCapabilitiesImmutable getRequestedGLCapabilities() {
+ if( null == awtConfig ) {
+ return capsReqUser;
+ }
+ return (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities();
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ return SurfaceScaleUtils.scale(getWidth(), hasPixelScale[0]);
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return SurfaceScaleUtils.scale(getHeight(), hasPixelScale[1]);
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
+ @Override
+ public NativeSurface getNativeSurface() {
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getNativeSurface() : null;
+ }
+
+ @Override
+ public long getHandle() {
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getHandle() : 0;
+ }
+
+ @Override
+ public GLDrawableFactory getFactory() {
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getFactory() : null;
+ }
+
+ @Override
+ public String toString() {
+ final GLDrawable _drawable = drawable;
+ final int dw = (null!=_drawable) ? _drawable.getSurfaceWidth() : -1;
+ final int dh = (null!=_drawable) ? _drawable.getSurfaceHeight() : -1;
+
+ return "AWT-GLCanvas[Realized "+isRealized()+
+ ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
+ ",\n\tFactory "+getFactory()+
+ ",\n\thandle 0x"+Long.toHexString(getHandle())+
+ ",\n\tDrawable size "+dw+"x"+dh+" surface["+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
+ ",\n\tAWT[pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
+ ",\n\tvisible "+isVisible()+", displayable "+isDisplayable()+", showing "+isShowing+
+ ",\n\t"+awtConfig+"]]";
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; }
+
+ private final Runnable destroyOnEDTAction = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLAnimatorControl animator = getAnimator();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: destroyOnEDTAction() - START, hasContext " +
+ (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
+ // Thread.dumpStack();
+ }
+
+ final boolean animatorPaused;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
+ }
+
+ GLException exceptionOnDisposeGL = null;
+
+ // OLS will be detached by disposeGL's context destruction below
+ if( null != context ) {
+ if( context.isCreated() ) {
+ try {
+ helper.disposeGL(GLCanvas.this, context, true);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": destroyOnEDTAction() - post ctx: "+context);
+ }
+ } catch (final GLException gle) {
+ exceptionOnDisposeGL = gle;
+ }
+ }
+ context = null;
+ }
+
+ Throwable exceptionOnUnrealize = null;
+ if( null != drawable ) {
+ try {
+ drawable.setRealized(false);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": destroyOnEDTAction() - post drawable: "+drawable);
+ }
+ } catch( final Throwable re ) {
+ exceptionOnUnrealize = re;
+ }
+ drawable = null;
+ }
+
+ if(animatorPaused) {
+ animator.resume();
+ }
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
+ }
+ if( null != exceptionOnUnrealize ) {
+ throw GLException.newGLException(exceptionOnUnrealize);
+ }
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": dispose() - END, animator "+animator);
+ }
+
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ /**
+ * Disposes the JAWTWindow and AbstractGraphicsDevice within EDT,
+ * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
+ * <p>
+ * The drawable and context handle are null'ed as well, assuming {@link #destroy()} has been called already.
+ * </p>
+ *
+ * @see #chooseGraphicsConfiguration(com.jogamp.opengl.GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
+ */
+ private final Runnable disposeJAWTWindowAndAWTDeviceOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ context=null;
+ drawable=null;
+
+ if( null != jawtWindow ) {
+ jawtWindow.destroy();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
+ }
+ jawtWindow=null;
+ }
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ if(null != awtConfig) {
+ final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
+ final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
+ final String adeviceMsg;
+ if(DEBUG) {
+ adeviceMsg = adevice.toString();
+ } else {
+ adeviceMsg = null;
+ }
+ final boolean closed = adevice.close();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post GraphicsDevice: "+adeviceMsg+", result: "+closed);
+ }
+ }
+ awtConfig=null;
+ }
+ };
+
+ private final Runnable initAction = new Runnable() {
+ @Override
+ public void run() {
+ helper.init(GLCanvas.this, !sendReshape);
+ }
+ };
+
+ private final Runnable displayAction = new Runnable() {
+ @Override
+ public void run() {
+ if (sendReshape) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Reshape: "+getSurfaceWidth()+"x"+getSurfaceHeight());
+ }
+ // Note: we ignore the given x and y within the parent component
+ // since we are drawing directly into this heavyweight component.
+ helper.reshape(GLCanvas.this, 0, 0, getSurfaceWidth(), getSurfaceHeight());
+ sendReshape = false;
+ }
+
+ helper.display(GLCanvas.this);
+ }
+ };
+
+ private final Runnable displayOnEDTAction = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( null != drawable && drawable.isRealized() ) {
+ if( GLCanvas.this.updatePixelScale() ) {
+ GLCanvas.this.reshapeImpl(getWidth(), getHeight());
+ }
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ private final Runnable swapBuffersOnEDTAction = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( null != drawable && drawable.isRealized() ) {
+ drawable.swapBuffers();
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ private class DisposeGLEventListenerAction implements Runnable {
+ GLEventListener listener;
+ private final boolean remove;
+ private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
+
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ // Disables the AWT's erasing of this Canvas's background on Windows
+ // in Java SE 6. This internal API is not available in previous
+ // releases, but the system property
+ // -Dsun.awt.noerasebackground=true can be specified to get similar
+ // results globally in previous releases.
+ private static boolean disableBackgroundEraseInitialized;
+ private static Method disableBackgroundEraseMethod;
+ private void disableBackgroundErase() {
+ if (!disableBackgroundEraseInitialized) {
+ try {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ Class<?> clazz = getToolkit().getClass();
+ while (clazz != null && disableBackgroundEraseMethod == null) {
+ try {
+ disableBackgroundEraseMethod =
+ clazz.getDeclaredMethod("disableBackgroundErase",
+ new Class[] { Canvas.class });
+ disableBackgroundEraseMethod.setAccessible(true);
+ } catch (final Exception e) {
+ clazz = clazz.getSuperclass();
+ }
+ }
+ } catch (final Exception e) {
+ }
+ return null;
+ }
+ });
+ } catch (final Exception e) {
+ }
+ disableBackgroundEraseInitialized = true;
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas: TK disableBackgroundErase method found: "+
+ (null!=disableBackgroundEraseMethod));
+ }
+ }
+ if (disableBackgroundEraseMethod != null) {
+ Throwable t=null;
+ try {
+ disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this });
+ } catch (final Exception e) {
+ t = e;
+ }
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas: TK disableBackgroundErase error: "+t);
+ }
+ }
+ }
+
+ /**
+ * Issues the GraphicsConfigurationFactory's choosing facility within EDT,
+ * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
+ *
+ * @param capsChosen
+ * @param capsRequested
+ * @param chooser
+ * @param device
+ * @return the chosen AWTGraphicsConfiguration
+ *
+ * @see #disposeJAWTWindowAndAWTDeviceOnEDT
+ */
+ private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen,
+ final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser,
+ final GraphicsDevice device) {
+ // Make GLCanvas behave better in NetBeans GUI builder
+ if( Beans.isDesignTime() ) {
+ return null;
+ }
+
+ final AbstractGraphicsScreen aScreen = null != device ?
+ AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT):
+ AWTGraphicsScreen.createDefault();
+ AWTGraphicsConfiguration config = null;
+
+ if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
+ config = (AWTGraphicsConfiguration)
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
+ capsRequested,
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
+ } else {
+ try {
+ final ArrayList<AWTGraphicsConfiguration> bucket = new ArrayList<AWTGraphicsConfiguration>(1);
+ EventQueue.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ final AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
+ capsRequested,
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
+ bucket.add(c);
+ }
+ });
+ config = ( bucket.size() > 0 ) ? bucket.get(0) : null ;
+ } catch (final InvocationTargetException e) {
+ throw new GLException(e.getTargetException());
+ } catch (final InterruptedException e) {
+ throw new GLException(e);
+ }
+ }
+
+ if ( null == config ) {
+ throw new GLException("Error: Couldn't fetch AWTGraphicsConfiguration");
+ }
+
+ return config;
+ }
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
+ /**
+ * A most simple JOGL AWT test entry
+ */
+ public static void main(final String args[]) {
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(GlueGenVersion.getInstance());
+ // System.err.println(NativeWindowVersion.getInstance());
+ System.err.println(JoglVersion.getInstance());
+
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
+
+ final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
+ final Frame frame = new Frame("JOGL AWT Test");
+
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ frame.add(glCanvas);
+ frame.setSize(128, 128);
+
+ glCanvas.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(JoglVersion.getGLInfo(gl, null));
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) { }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+ });
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.setVisible(true);
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ }
+ glCanvas.display();
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.dispose();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java b/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java
new file mode 100644
index 000000000..91b2f5e0c
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java
@@ -0,0 +1,2689 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.opengl.awt;
+
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Rectangle;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.beans.Beans;
+import java.nio.IntBuffer;
+import java.util.List;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.ScalableSurface;
+import com.jogamp.nativewindow.SurfaceUpdatedListener;
+import com.jogamp.nativewindow.WindowClosingProtocol;
+import com.jogamp.nativewindow.util.PixelFormat;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLCapabilitiesChooser;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLFBODrawable;
+import com.jogamp.opengl.GLOffscreenAutoDrawable;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.GLRunnable;
+import com.jogamp.opengl.GLSharedContextSetter;
+import com.jogamp.opengl.Threading;
+import javax.swing.JPanel;
+
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.nativewindow.WrappedSurface;
+import jogamp.nativewindow.jawt.JAWTUtil;
+import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLDrawableFactoryImpl;
+import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.awt.AWTTilePainter;
+import jogamp.opengl.awt.Java2D;
+import jogamp.opengl.util.glsl.GLSLTextureRaster;
+
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
+import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.SingletonGLPixelBufferProvider;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.GLPixelStorageModes;
+import com.jogamp.opengl.util.TileRenderer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.texture.TextureState;
+
+/** A lightweight Swing component which provides OpenGL rendering
+ support. Provided for compatibility with Swing user interfaces
+ when adding a heavyweight doesn't work either because of
+ Z-ordering or LayoutManager problems.
+ <p>
+ The GLJPanel can be made transparent by creating it with a
+ GLCapabilities object with alpha bits specified and calling {@link
+ #setOpaque}(false). Pixels with resulting OpenGL alpha values less
+ than 1.0 will be overlaid on any underlying Swing rendering.
+ </p>
+ <p>
+ This component attempts to use hardware-accelerated rendering via FBO or pbuffers and
+ falls back on to software rendering if none of the former are available
+ using {@link GLDrawableFactory#createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) GLDrawableFactory.createOffscreenDrawable(..)}.<br/>
+ </p>
+ <p>
+ <a name="verticalFlip">A vertical-flip is required</a>, if the drawable {@link #isGLOriented()} and {@link #setSkipGLOrientationVerticalFlip(boolean) vertical flip is not skipped}.<br>
+ In this case this component performs the required vertical flip to bring the content from OpenGL's orientation into AWT's orientation.<br>
+ In case <a href="#fboGLSLVerticalFlip">GLSL based vertical-flip</a> is not available,
+ the CPU intensive {@link System#arraycopy(Object, int, Object, int, int) System.arraycopy(..)} is used line by line.
+ See details about <a href="#fboGLSLVerticalFlip">FBO and GLSL vertical flipping</a>.
+ </p>
+ <p>
+ For performance reasons, as well as for <a href="#bug842">GL state sideeffects</a>,
+ <b>{@link #setSkipGLOrientationVerticalFlip(boolean) skipping vertical flip} is highly recommended</b>!
+ </p>
+ <p>
+ The OpenGL path is concluded by copying the rendered pixels an {@link BufferedImage} via {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+ for later Java2D composition.
+ </p>
+ <p>
+ Finally the Java2D compositioning takes place via via {@link Graphics#drawImage(java.awt.Image, int, int, int, int, java.awt.image.ImageObserver) Graphics.drawImage(...)}
+ on the prepared {@link BufferedImage} as described above.
+ </p>
+ <P>
+ * Please read <a href="GLCanvas.html#java2dgl">Java2D OpenGL Remarks</a>.
+ * </P>
+ *
+ <a name="fboGLSLVerticalFlip"><h5>FBO / GLSL Vertical Flip</h5></a>
+ If <a href="#verticalFlip">vertical flip is required</a>,
+ FBO is used, GLSL is available and {@link #setSkipGLOrientationVerticalFlip(boolean) vertical flip is not skipped}, a fragment shader is utilized
+ to flip the FBO texture vertically. This hardware-accelerated step can be disabled via system property <code>jogl.gljpanel.noglsl</code>.
+ <p>
+ The FBO / GLSL code path uses one texture-unit and binds the FBO texture to it's active texture-target,
+ see {@link #setTextureUnit(int)} and {@link #getTextureUnit()}.
+ </p>
+ <p>
+ The active and dedicated texture-unit's {@link GL#GL_TEXTURE_2D} state is preserved via {@link TextureState}.
+ See also {@link Texture#textureCallOrder Order of Texture Commands}.
+ </p>
+ <p>
+ The current gl-viewport is preserved.
+ </p>
+ <p>
+ <a name="bug842"><i>Warning (Bug 842)</i></a>: Certain GL states other than viewport and texture (see above)
+ influencing rendering, will also influence the GLSL vertical flip, e.g. {@link GL#glFrontFace(int) glFrontFace}({@link GL#GL_CCW}).
+ It is recommended to reset those states to default when leaving the {@link GLEventListener#display(GLAutoDrawable)} method!
+ We may change this behavior in the future, i.e. preserve all influencing states.
+ </p>
+ <p>
+ <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ To share a {@link GLContext} see the following note in the documentation overview:
+ <a href="../../../../overview-summary.html#SHARING">context sharing</a>
+ as well as {@link GLSharedContextSetter}.
+ </p>
+*/
+
+@SuppressWarnings("serial")
+public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol, AWTPrintLifecycle, GLSharedContextSetter, ScalableSurface {
+ private static final boolean DEBUG;
+ private static final boolean DEBUG_FRAMES;
+ private static final boolean DEBUG_VIEWPORT;
+ private static final boolean USE_GLSL_TEXTURE_RASTERIZER;
+ private static final boolean SKIP_VERTICAL_FLIP_DEFAULT;
+
+ /** Indicates whether the Java 2D OpenGL pipeline is requested by user. */
+ private static final boolean java2dOGLEnabledByProp;
+
+ /** Indicates whether the Java 2D OpenGL pipeline is enabled, resource-compatible and requested by user. */
+ private static final boolean useJava2DGLPipeline;
+
+ /** Indicates whether the Java 2D OpenGL pipeline's usage is error free. */
+ private static boolean java2DGLPipelineOK;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.debug("GLJPanel");
+ DEBUG_FRAMES = PropertyAccess.isPropertyDefined("jogl.debug.GLJPanel.Frames", true);
+ DEBUG_VIEWPORT = PropertyAccess.isPropertyDefined("jogl.debug.GLJPanel.Viewport", true);
+ USE_GLSL_TEXTURE_RASTERIZER = !PropertyAccess.isPropertyDefined("jogl.gljpanel.noglsl", true);
+ SKIP_VERTICAL_FLIP_DEFAULT = PropertyAccess.isPropertyDefined("jogl.gljpanel.noverticalflip", true);
+ boolean enabled = PropertyAccess.getBooleanProperty("sun.java2d.opengl", false);
+ java2dOGLEnabledByProp = enabled && !PropertyAccess.isPropertyDefined("jogl.gljpanel.noogl", true);
+
+ enabled = false;
+ if( java2dOGLEnabledByProp ) {
+ // Force eager initialization of part of the Java2D class since
+ // otherwise it's likely it will try to be initialized while on
+ // the Queue Flusher Thread, which is not allowed
+ if (Java2D.isOGLPipelineResourceCompatible() && Java2D.isFBOEnabled()) {
+ if( null != Java2D.getShareContext(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()) ) {
+ enabled = true;
+ }
+ }
+ }
+ useJava2DGLPipeline = enabled;
+ java2DGLPipelineOK = enabled;
+ if( DEBUG ) {
+ System.err.println("GLJPanel: DEBUG_VIEWPORT "+DEBUG_VIEWPORT);
+ System.err.println("GLJPanel: USE_GLSL_TEXTURE_RASTERIZER "+USE_GLSL_TEXTURE_RASTERIZER);
+ System.err.println("GLJPanel: SKIP_VERTICAL_FLIP_DEFAULT "+SKIP_VERTICAL_FLIP_DEFAULT);
+ System.err.println("GLJPanel: java2dOGLEnabledByProp "+java2dOGLEnabledByProp);
+ System.err.println("GLJPanel: useJava2DGLPipeline "+useJava2DGLPipeline);
+ System.err.println("GLJPanel: java2DGLPipelineOK "+java2DGLPipelineOK);
+ }
+ }
+
+ private static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider = null;
+ private static synchronized SingleAWTGLPixelBufferProvider getSingleAWTGLPixelBufferProvider() {
+ if( null == singleAWTGLPixelBufferProvider ) {
+ singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( true /* allowRowStride */ );
+ }
+ return singleAWTGLPixelBufferProvider;
+ }
+
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+
+ private final GLDrawableHelper helper;
+ private boolean autoSwapBufferMode;
+
+ private volatile boolean isInitialized;
+
+ //
+ // Data used for either pbuffers or pixmap-based offscreen surfaces
+ //
+ private AWTGLPixelBufferProvider customPixelBufferProvider = null;
+ /** Requested single buffered offscreen caps */
+ private volatile GLCapabilitiesImmutable reqOffscreenCaps;
+ private volatile GLDrawableFactoryImpl factory;
+ private final GLCapabilitiesChooser chooser;
+ private int additionalCtxCreationFlags = 0;
+
+ // Lazy reshape notification: reshapeWidth -> panelWidth -> backend.width
+ private boolean handleReshape = false;
+ private boolean sendReshape = true;
+
+ private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ /** For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width in pixel units (scaled) */
+ private int reshapeWidth;
+ /** For handling reshape events lazily: reshapeHeight -> panelHeight -> backend.height in pixel units (scaled) */
+ private int reshapeHeight;
+
+ /** Scaled pixel width of the actual GLJPanel: reshapeWidth -> panelWidth -> backend.width */
+ private int panelWidth = 0;
+ /** Scaled pixel height of the actual GLJPanel: reshapeHeight -> panelHeight -> backend.height */
+ private int panelHeight = 0;
+
+ // These are always set to (0, 0) except when the Java2D / OpenGL
+ // pipeline is active
+ private int viewportX;
+ private int viewportY;
+
+ private int requestedTextureUnit = 0; // default
+
+ // The backend in use
+ private volatile Backend backend;
+
+ private boolean skipGLOrientationVerticalFlip = SKIP_VERTICAL_FLIP_DEFAULT;
+
+ // Used by all backends either directly or indirectly to hook up callbacks
+ private final Updater updater = new Updater();
+
+ private boolean oglPipelineUsable() {
+ return null == customPixelBufferProvider && useJava2DGLPipeline && java2DGLPipelineOK;
+ }
+
+ private volatile boolean isShowing;
+ private final HierarchyListener hierarchyListener = new HierarchyListener() {
+ @Override
+ public void hierarchyChanged(final HierarchyEvent e) {
+ isShowing = GLJPanel.this.isShowing();
+ }
+ };
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
+ new AWTWindowClosingProtocol(this, new Runnable() {
+ @Override
+ public void run() {
+ GLJPanel.this.destroy();
+ }
+ }, null);
+
+ /** Creates a new GLJPanel component with a default set of OpenGL
+ capabilities and using the default OpenGL capabilities selection
+ mechanism.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
+ * @throws GLException if no default profile is available for the default desktop device.
+ */
+ public GLJPanel() throws GLException {
+ this(null);
+ }
+
+ /** Creates a new GLJPanel component with the requested set of
+ OpenGL capabilities, using the default OpenGL capabilities
+ selection mechanism.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
+ * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
+ */
+ public GLJPanel(final GLCapabilitiesImmutable userCapsRequest) throws GLException {
+ this(userCapsRequest, null);
+ }
+
+ /** Creates a new GLJPanel component. The passed GLCapabilities
+ specifies the OpenGL capabilities for the component; if null, a
+ default set of capabilities is used. The GLCapabilitiesChooser
+ specifies the algorithm for selecting one of the available
+ GLCapabilities for the component; a DefaultGLCapabilitesChooser
+ is used if null is passed for this argument.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
+ * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
+ */
+ public GLJPanel(final GLCapabilitiesImmutable userCapsRequest, final GLCapabilitiesChooser chooser)
+ throws GLException
+ {
+ super();
+
+ // Works around problems on many vendors' cards; we don't need a
+ // back buffer for the offscreen surface anyway
+ {
+ GLCapabilities caps;
+ if (userCapsRequest != null) {
+ caps = (GLCapabilities) userCapsRequest.cloneMutable();
+ } else {
+ caps = new GLCapabilities(GLProfile.getDefault(GLProfile.getDefaultDevice()));
+ }
+ caps.setDoubleBuffered(false);
+ reqOffscreenCaps = caps;
+ }
+ this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.getGLProfile() ); // pre-fetch, reqOffscreenCaps may changed
+ this.chooser = chooser;
+
+ helper = new GLDrawableHelper();
+ autoSwapBufferMode = helper.getAutoSwapBufferMode();
+
+ this.setFocusable(true); // allow keyboard input!
+ this.addHierarchyListener(hierarchyListener);
+ this.isShowing = isShowing();
+ }
+
+ /**
+ * Attempts to initialize the backend, if not initialized yet.
+ * <p>
+ * If backend is already initialized method returns <code>true</code>.
+ * </p>
+ * <p>
+ * If <code>offthread</code> is <code>true</code>, initialization will kicked off
+ * on a <i>short lived</i> arbitrary thread and method returns immediately.<br/>
+ * If platform supports such <i>arbitrary thread</i> initialization method returns
+ * <code>true</code>, otherwise <code>false</code>.
+ * </p>
+ * <p>
+ * If <code>offthread</code> is <code>false</code>, initialization be performed
+ * on the current thread and method returns after initialization.<br/>
+ * Method returns <code>true</code> if initialization was successful, otherwise <code>false</code>.
+ * <p>
+ * @param offthread
+ */
+ public final boolean initializeBackend(final boolean offthread) {
+ if( offthread ) {
+ new Thread(getThreadName()+"-GLJPanel_Init") {
+ public void run() {
+ if( !isInitialized ) {
+ initializeBackendImpl();
+ }
+ } }.start();
+ return true;
+ } else {
+ if( !isInitialized ) {
+ return initializeBackendImpl();
+ } else {
+ return true;
+ }
+ }
+ }
+
+ @Override
+ public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.getContext(), sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
+ public AWTGLPixelBufferProvider getCustomPixelBufferProvider() { return customPixelBufferProvider; }
+
+ /**
+ * @param custom custom {@link AWTGLPixelBufferProvider}
+ * @throws IllegalArgumentException if <code>custom</code> is <code>null</code>
+ * @throws IllegalStateException if backend is already realized, i.e. this instanced already painted once.
+ */
+ public void setPixelBufferProvider(final AWTGLPixelBufferProvider custom) throws IllegalArgumentException, IllegalStateException {
+ if( null == custom ) {
+ throw new IllegalArgumentException("Null PixelBufferProvider");
+ }
+ if( null != backend ) {
+ throw new IllegalStateException("Backend already realized.");
+ }
+ customPixelBufferProvider = custom;
+ }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
+ public final RecursiveLock getUpstreamLock() { return lock; }
+
+ @Override
+ public final boolean isThreadGLCapable() { return EventQueue.isDispatchThread(); }
+
+ @Override
+ public void display() {
+ if( isShowing || ( printActive && isVisible() ) ) {
+ if (EventQueue.isDispatchThread()) {
+ // Want display() to be synchronous, so call paintImmediately()
+ paintImmediatelyAction.run();
+ } else {
+ // Multithreaded redrawing of Swing components is not allowed,
+ // so do everything on the event dispatch thread
+ try {
+ EventQueue.invokeAndWait(paintImmediatelyAction);
+ } catch (final Exception e) {
+ throw new GLException(e);
+ }
+ }
+ }
+ }
+
+ protected void dispose(final Runnable post) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.dispose() - start");
+ // Thread.dumpStack();
+ }
+
+ if (backend != null && backend.getContext() != null) {
+ final boolean animatorPaused;
+ final GLAnimatorControl animator = getAnimator();
+ if(null!=animator) {
+ animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
+ }
+
+ if(backend.getContext().isCreated()) {
+ Threading.invoke(true, disposeAction, getTreeLock());
+ }
+ if(null != backend) {
+ // not yet destroyed due to backend.isUsingOwnThreadManagment() == true
+ backend.destroy();
+ isInitialized = false;
+ }
+ if( null != post ) {
+ post.run();
+ }
+
+ if( animatorPaused ) {
+ animator.resume();
+ }
+ }
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.dispose() - stop");
+ }
+ }
+
+ /**
+ * Just an alias for removeNotify
+ */
+ @Override
+ public void destroy() {
+ removeNotify();
+ }
+
+ /** Overridden to cause OpenGL rendering to be performed during
+ repaint cycles. Subclasses which override this method must call
+ super.paintComponent() in their paintComponent() method in order
+ to function properly. <P>
+
+ <DL><DD><CODE>paintComponent</CODE> in class <CODE>javax.swing.JComponent</CODE></DD></DL> */
+ @Override
+ protected void paintComponent(final Graphics g) {
+ if (Beans.isDesignTime()) {
+ // Make GLJPanel behave better in NetBeans GUI builder
+ g.setColor(Color.BLACK);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ final FontMetrics fm = g.getFontMetrics();
+ String name = getName();
+ if (name == null) {
+ name = getClass().getName();
+ final int idx = name.lastIndexOf('.');
+ if (idx >= 0) {
+ name = name.substring(idx + 1);
+ }
+ }
+ final Rectangle2D bounds = fm.getStringBounds(name, g);
+ g.setColor(Color.WHITE);
+ g.drawString(name,
+ (int) ((getWidth() - bounds.getWidth()) / 2),
+ (int) ((getHeight() + bounds.getHeight()) / 2));
+ return;
+ }
+
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !isInitialized ) {
+ initializeBackendImpl();
+ }
+
+ if (!isInitialized || printActive) {
+ return;
+ }
+
+ // NOTE: must do this when the context is not current as it may
+ // involve destroying the pbuffer (current context) and
+ // re-creating it -- tricky to do properly while the context is
+ // current
+ if( !printActive ) {
+ updatePixelScale(backend);
+ if ( handleReshape ) {
+ handleReshape = false;
+ sendReshape = handleReshape();
+ }
+
+ if( isShowing ) {
+ updater.setGraphics(g);
+ backend.doPaintComponent(g);
+ }
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ private final void updateWrappedSurfaceScale(final GLDrawable d) {
+ final NativeSurface s = d.getNativeSurface();
+ if( s instanceof WrappedSurface ) {
+ ((WrappedSurface)s).setSurfaceScale(hasPixelScale);
+ }
+ }
+
+ @Override
+ public final boolean setSurfaceScale(final float[] pixelScale) { // HiDPI support
+ System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
+ final Backend b = backend;
+ if ( isInitialized && null != b && isShowing ) {
+ if( isShowing || ( printActive && isVisible() ) ) {
+ if (EventQueue.isDispatchThread()) {
+ setSurfaceScaleAction.run();
+ } else {
+ try {
+ EventQueue.invokeAndWait(setSurfaceScaleAction);
+ } catch (final Exception e) {
+ throw new GLException(e);
+ }
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ private final Runnable setSurfaceScaleAction = new Runnable() {
+ @Override
+ public void run() {
+ final Backend b = backend;
+ if( null != b && setSurfaceScaleImpl(b) ) {
+ if( !helper.isAnimatorAnimatingOnOtherThread() ) {
+ paintImmediatelyAction.run(); // display
+ }
+ }
+ }
+ };
+
+ private final boolean setSurfaceScaleImpl(final Backend b) {
+ if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null) ) {
+ reshapeImpl(getWidth(), getHeight());
+ updateWrappedSurfaceScale(b.getDrawable());
+ return true;
+ }
+ return false;
+ }
+
+ private final boolean updatePixelScale(final Backend b) {
+ if( JAWTUtil.getPixelScale(getGraphicsConfiguration(), minPixelScale, maxPixelScale) ) {
+ return setSurfaceScaleImpl(b);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public final float[] getRequestedSurfaceScale(final float[] result) {
+ System.arraycopy(reqPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final float[] getCurrentSurfaceScale(final float[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public float[] getMinimumSurfaceScale(final float[] result) {
+ System.arraycopy(minPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public float[] getMaximumSurfaceScale(final float[] result) {
+ System.arraycopy(maxPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ /** Overridden to track when this component is added to a container.
+ Subclasses which override this method must call
+ super.addNotify() in their addNotify() method in order to
+ function properly. <P>
+
+ <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ @Override
+ public void addNotify() {
+ super.addNotify();
+ awtWindowClosingProtocol.addClosingListener();
+
+ // HiDPI support
+ JAWTUtil.getPixelScale(getGraphicsConfiguration(), minPixelScale, maxPixelScale);
+ SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null);
+
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.addNotify()");
+ }
+ }
+
+ /** Overridden to track when this component is removed from a
+ container. Subclasses which override this method must call
+ super.removeNotify() in their removeNotify() method in order to
+ function properly. <P>
+
+ <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ @Override
+ public void removeNotify() {
+ awtWindowClosingProtocol.removeClosingListener();
+
+ dispose(null);
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ super.removeNotify();
+ }
+
+ /** Overridden to cause {@link GLDrawableHelper#reshape} to be
+ called on all registered {@link GLEventListener}s. Subclasses
+ which override this method must call super.reshape() in
+ their reshape() method in order to function properly. <P>
+ *
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("deprecation")
+ @Override
+ public void reshape(final int x, final int y, final int width, final int height) {
+ super.reshape(x, y, width, height);
+ reshapeImpl(width, height);
+ }
+
+ private void reshapeImpl(final int width, final int height) {
+ final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]);
+ final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]);
+ if( !printActive && ( handleReshape || scaledWidth != panelWidth || scaledHeight != panelHeight ) ) {
+ reshapeWidth = scaledWidth;
+ reshapeHeight = scaledHeight;
+ handleReshape = true;
+ }
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.reshape.0 "+this.getName()+" resize ["+(printActive?"printing":"paint")+
+ "] [ this "+getWidth()+"x"+getHeight()+", pixelScale "+getPixelScaleStr()+
+ ", panel "+panelWidth+"x"+panelHeight +
+ "] -> "+(handleReshape?"":"[skipped] ") + width+"x"+height+" * "+getPixelScaleStr()+
+ " -> "+scaledWidth+"x"+scaledHeight+", reshapeSize "+reshapeWidth+"x"+reshapeHeight);
+ }
+ }
+
+ private volatile boolean printActive = false;
+ private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
+ private AWTTilePainter printAWTTiles = null;
+
+ @Override
+ public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ printActive = true;
+ if( DEBUG ) {
+ System.err.printf(getThreadName()+": GLJPanel.setupPrint: scale %f / %f, samples %d, tileSz %d x %d%n", scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight);
+ }
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
+ }
+ private final Runnable setupPrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !isInitialized ) {
+ initializeBackendImpl();
+ }
+ if (!isInitialized) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable not valid yet");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ if( !isVisible() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, panel not visible");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ sendReshape = false; // clear reshape flag
+ handleReshape = false; // ditto
+ printAnimator = helper.getAnimator();
+ if( null != printAnimator ) {
+ printAnimator.remove(GLJPanel.this);
+ }
+
+ printGLAD = GLJPanel.this; // default: re-use
+ final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
+ final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
+ GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
+ final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
+ final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
+ printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
+
+ final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
+ newGLADCaps.setDoubleBuffered(false);
+ newGLADCaps.setOnscreen(false);
+ if( printNumSamples != newGLADCaps.getNumSamples() ) {
+ newGLADCaps.setSampleBuffers(0 < printNumSamples);
+ newGLADCaps.setNumSamples(printNumSamples);
+ }
+ final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
+
+ final boolean reqNewGLAD = ( reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
+
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
+ ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
+ ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
+ ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
+ ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
+ }
+ if( reqNewGLAD ) {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
+ GLOffscreenAutoDrawable offGLAD = null;
+ try {
+ offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
+ printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
+ } catch (final GLException gle) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+gle.getMessage());
+ gle.printStackTrace();
+ }
+ }
+ if( null != offGLAD ) {
+ printGLAD = offGLAD;
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
+ printDrawable = printGLAD.getDelegatedDrawable();
+ }
+ }
+ printAWTTiles.setGLOrientation( !GLJPanel.this.skipGLOrientationVerticalFlip && printGLAD.isGLOriented(), printGLAD.isGLOriented() );
+ printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
+ printAWTTiles.renderer.attachAutoDrawable(printGLAD);
+ if( DEBUG ) {
+ System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
+ System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
+ System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void releasePrint() {
+ if( !printActive ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ sendReshape = false; // clear reshape flag
+ handleReshape = false; // ditto
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
+ }
+
+ private final Runnable releasePrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.releasePrintOnEDT.0 "+printAWTTiles);
+ }
+ printAWTTiles.dispose();
+ printAWTTiles= null;
+ if( printGLAD != GLJPanel.this ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLJPanel.this);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
+ if( null != printAnimator ) {
+ printAnimator.add(GLJPanel.this);
+ printAnimator = null;
+ }
+
+ // trigger reshape, i.e. gl-viewport and -listener - this component might got resized!
+ final int awtWidth = GLJPanel.this.getWidth();
+ final int awtHeight= GLJPanel.this.getHeight();
+ final int scaledAWTWidth = SurfaceScaleUtils.scale(awtWidth, hasPixelScale[0]);
+ final int scaledAWTHeight= SurfaceScaleUtils.scale(awtHeight, hasPixelScale[1]);
+ final GLDrawable drawable = GLJPanel.this.getDelegatedDrawable();
+ if( scaledAWTWidth != panelWidth || scaledAWTHeight != panelHeight ||
+ drawable.getSurfaceWidth() != panelWidth || drawable.getSurfaceHeight() != panelHeight ) {
+ // -> !( awtSize == panelSize == drawableSize )
+ if ( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.releasePrintOnEDT.0: resize [printing] panel " +panelWidth+"x"+panelHeight + " @ scale "+getPixelScaleStr()+
+ ", draw "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+
+ " -> " + awtWidth+"x"+awtHeight+" * "+getPixelScaleStr()+" -> "+scaledAWTWidth+"x"+scaledAWTHeight);
+ }
+ reshapeWidth = scaledAWTWidth;
+ reshapeHeight = scaledAWTHeight;
+ sendReshape = handleReshape(); // reshapeSize -> panelSize, backend reshape w/ GL reshape
+ } else {
+ sendReshape = true; // only GL reshape
+ }
+ printActive = false;
+ display();
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void print(final Graphics graphics) {
+ if( !printActive ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ if(DEBUG && !EventQueue.isDispatchThread()) {
+ System.err.println(getThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
+ // we cannot dispatch print on AWT-EDT due to printing internal locking ..
+ }
+ sendReshape = false; // clear reshape flag
+ handleReshape = false; // ditto
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ try {
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ if( !tileRenderer.eot() ) {
+ try {
+ do {
+ if( printGLAD != GLJPanel.this ) {
+ tileRenderer.display();
+ } else {
+ backend.doPlainPaint();
+ }
+ } while ( !tileRenderer.eot() );
+ if( DEBUG ) {
+ System.err.println("AWT print.1: "+printAWTTiles);
+ }
+ } finally {
+ tileRenderer.reset();
+ printAWTTiles.resetGraphics2D();
+ }
+ }
+ } catch (final NoninvertibleTransformException nte) {
+ System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
+ nte.printStackTrace();
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.X: "+printAWTTiles);
+ }
+ }
+ @Override
+ protected void printComponent(final Graphics g) {
+ if( DEBUG ) {
+ System.err.println("AWT printComponent.X: "+printAWTTiles);
+ }
+ print(g);
+ }
+
+ @Override
+ public void setOpaque(final boolean opaque) {
+ if (backend != null) {
+ backend.setOpaque(opaque);
+ }
+ super.setOpaque(opaque);
+ }
+
+ @Override
+ public void addGLEventListener(final GLEventListener listener) {
+ helper.addGLEventListener(listener);
+ }
+
+ @Override
+ public void addGLEventListener(final int index, final GLEventListener listener) {
+ helper.addGLEventListener(index, listener);
+ }
+
+ @Override
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
+ }
+
+ @Override
+ public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
+ }
+
+ @Override
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(final GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ if (EventQueue.isDispatchThread()) {
+ r.run();
+ } else {
+ // Multithreaded redrawing of Swing components is not allowed,
+ // so do everything on the event dispatch thread
+ try {
+ EventQueue.invokeAndWait(r);
+ } catch (final Exception e) {
+ throw new GLException(e);
+ }
+ }
+ return r.listener;
+ }
+
+ @Override
+ public GLEventListener removeGLEventListener(final GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
+ public void setAnimator(final GLAnimatorControl animatorControl) {
+ helper.setAnimator(animatorControl);
+ }
+
+ @Override
+ public GLAnimatorControl getAnimator() {
+ return helper.getAnimator();
+ }
+
+ @Override
+ public final Thread setExclusiveContextThread(final Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, getContext());
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnable);
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnables);
+ }
+
+ @Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
+ public GLContext createContext(final GLContext shareWith) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.createContext(shareWith);
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ @Override
+ public void setRealized(final boolean realized) {
+ }
+
+ @Override
+ public boolean isRealized() {
+ return isInitialized;
+ }
+
+ @Override
+ public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ final GLContext oldCtx = b.getContext();
+ GLDrawableHelper.switchContext(b.getDrawable(), oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
+ b.setContext(newCtx);
+ return oldCtx;
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+
+ @Override
+ public final GLDrawable getDelegatedDrawable() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.getDrawable();
+ }
+
+ @Override
+ public GLContext getContext() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.getContext();
+ }
+
+ @Override
+ public GL getGL() {
+ if (Beans.isDesignTime()) {
+ return null;
+ }
+ final GLContext context = getContext();
+ return (context == null) ? null : context.getGL();
+ }
+
+ @Override
+ public GL setGL(final GL gl) {
+ final GLContext context = getContext();
+ if (context != null) {
+ context.setGL(gl);
+ return gl;
+ }
+ return null;
+ }
+
+ @Override
+ public void setAutoSwapBufferMode(final boolean enable) {
+ this.autoSwapBufferMode = enable;
+ boolean backendHandlesSwapBuffer = false;
+ if( isInitialized ) {
+ final Backend b = backend;
+ if ( null != b ) {
+ backendHandlesSwapBuffer= b.handlesSwapBuffer();
+ }
+ }
+ if( !backendHandlesSwapBuffer ) {
+ helper.setAutoSwapBufferMode(enable);
+ }
+ }
+
+ @Override
+ public boolean getAutoSwapBufferMode() {
+ return autoSwapBufferMode;
+ }
+
+ @Override
+ public void swapBuffers() {
+ if( isInitialized ) {
+ final Backend b = backend;
+ if ( null != b ) {
+ b.swapBuffers();
+ }
+ }
+ }
+
+ @Override
+ public void setContextCreationFlags(final int flags) {
+ additionalCtxCreationFlags = flags;
+ }
+
+ @Override
+ public int getContextCreationFlags() {
+ return additionalCtxCreationFlags;
+ }
+
+ /** For a translucent GLJPanel (one for which {@link #setOpaque
+ setOpaque}(false) has been called), indicates whether the
+ application should preserve the OpenGL color buffer
+ (GL_COLOR_BUFFER_BIT) for correct rendering of the GLJPanel and
+ underlying widgets which may show through portions of the
+ GLJPanel with alpha values less than 1. Most Swing
+ implementations currently expect the GLJPanel to be completely
+ cleared (e.g., by <code>glClear(GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT)</code>), but for certain optimized Swing
+ implementations which use OpenGL internally, it may be possible
+ to perform OpenGL rendering using the GLJPanel into the same
+ OpenGL drawable as the Swing implementation uses. */
+ public boolean shouldPreserveColorBufferIfTranslucent() {
+ return oglPipelineUsable();
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ return panelWidth; // scaled surface width in pixel units, current as-from reshape
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return panelHeight; // scaled surface height in pixel units, current as-from reshape
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Method returns a valid value only <i>after</i>
+ * the backend has been initialized, either {@link #initializeBackend(boolean) eagerly}
+ * or manually via the first display call.<br/>
+ * Method always returns a valid value when called from within a {@link GLEventListener}.
+ * </p>
+ */
+ @Override
+ public boolean isGLOriented() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return true;
+ }
+ return b.getDrawable().isGLOriented();
+ }
+
+ /**
+ * Skip {@link #isGLOriented()} based vertical flip,
+ * which usually is required by the offscreen backend,
+ * see details about <a href="#verticalFlip">vertical flip</a>
+ * and <a href="#fboGLSLVerticalFlip">FBO / GLSL vertical flip</a>.
+ * <p>
+ * If set to <code>true</code>, user needs to flip the OpenGL rendered scene
+ * <i>if {@link #isGLOriented()} == true</i>, e.g. via the projection matrix.<br/>
+ * See constraints of {@link #isGLOriented()}.
+ * </p>
+ */
+ public final void setSkipGLOrientationVerticalFlip(final boolean v) {
+ skipGLOrientationVerticalFlip = v;
+ }
+ /** See {@link #setSkipGLOrientationVerticalFlip(boolean)}. */
+ public final boolean getSkipGLOrientationVerticalFlip() {
+ return skipGLOrientationVerticalFlip;
+ }
+
+ @Override
+ public GLCapabilitiesImmutable getChosenGLCapabilities() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.getChosenGLCapabilities();
+ }
+
+ @Override
+ public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
+ return reqOffscreenCaps;
+ }
+
+ /**
+ * Set a new requested {@link GLCapabilitiesImmutable} for this GLJPanel
+ * allowing reconfiguration.
+ * <p>
+ * Method shall be invoked from the {@link #isThreadGLCapable() AWT-EDT thread}.
+ * In case it is not invoked on the AWT-EDT thread, an attempt is made to do so.
+ * </p>
+ * <p>
+ * Method will dispose a previous {@link #isRealized() realized} GLContext and offscreen backend!
+ * </p>
+ * @param caps new capabilities.
+ */
+ public final void setRequestedGLCapabilities(final GLCapabilitiesImmutable caps) {
+ if( null == caps ) {
+ throw new IllegalArgumentException("null caps");
+ }
+ Threading.invoke(true,
+ new Runnable() {
+ @Override
+ public void run() {
+ dispose( new Runnable() {
+ @Override
+ public void run() {
+ // switch to new caps and re-init backend
+ // after actual dispose, but before resume animator
+ reqOffscreenCaps = caps;
+ initializeBackendImpl();
+ } } );
+ }
+ }, getTreeLock());
+ }
+
+ @Override
+ public final GLProfile getGLProfile() {
+ return reqOffscreenCaps.getGLProfile();
+ }
+
+ @Override
+ public NativeSurface getNativeSurface() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.getDrawable().getNativeSurface();
+ }
+
+ @Override
+ public long getHandle() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return 0;
+ }
+ return b.getDrawable().getNativeSurface().getSurfaceHandle();
+ }
+
+ @Override
+ public final GLDrawableFactory getFactory() {
+ return factory;
+ }
+
+ /**
+ * Returns the used texture unit, i.e. a value of [0..n], or -1 if non used.
+ * <p>
+ * If implementation uses a texture-unit, it will be known only after the first initialization, i.e. display call.
+ * </p>
+ * <p>
+ * See <a href="#fboGLSLVerticalFlip">FBO / GLSL Vertical Flip</a>.
+ * </p>
+ */
+ public final int getTextureUnit() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return -1;
+ }
+ return b.getTextureUnit();
+ }
+
+ /**
+ * Allows user to request a texture unit to be used,
+ * must be called before the first initialization, i.e. {@link #display()} call.
+ * <p>
+ * Defaults to <code>0</code>.
+ * </p>
+ * <p>
+ * See <a href="#fboGLSLVerticalFlip">FBO / GLSL Vertical Flip</a>.
+ * </p>
+ *
+ * @param v requested texture unit
+ * @see #getTextureUnit()
+ */
+ public final void setTextureUnit(final int v) {
+ requestedTextureUnit = v;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private final Object initSync = new Object();
+ private boolean initializeBackendImpl() {
+ synchronized(initSync) {
+ if( !isInitialized ) {
+ if( handleReshape ) {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.createAndInitializeBackend.1: ["+(printActive?"printing":"paint")+"] "+
+ panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr() + " -> " +
+ reshapeWidth+"x"+reshapeHeight+" @ scale "+getPixelScaleStr());
+ }
+ panelWidth = reshapeWidth;
+ panelHeight = reshapeHeight;
+ handleReshape = false;
+ } else {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.createAndInitializeBackend.0: ["+(printActive?"printing":"paint")+"] "+
+ panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr());
+ }
+ }
+
+ if ( 0 >= panelWidth || 0 >= panelHeight ) {
+ return false;
+ }
+
+ if ( null == backend ) {
+ if ( oglPipelineUsable() ) {
+ backend = new J2DOGLBackend();
+ } else {
+ backend = new OffscreenBackend(customPixelBufferProvider);
+ }
+ isInitialized = false;
+ }
+
+ if (!isInitialized) {
+ this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.getGLProfile() ); // reqOffscreenCaps may have changed
+ backend.initialize();
+ }
+ return isInitialized;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; }
+
+ @Override
+ public WindowClosingMode getDefaultCloseOperation() {
+ return awtWindowClosingProtocol.getDefaultCloseOperation();
+ }
+
+ @Override
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
+ return awtWindowClosingProtocol.setDefaultCloseOperation(op);
+ }
+
+ private boolean handleReshape() {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.handleReshape: "+
+ panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr() + " -> " +
+ reshapeWidth+"x"+reshapeHeight+" @ scale "+getPixelScaleStr());
+ }
+ panelWidth = reshapeWidth;
+ panelHeight = reshapeHeight;
+
+ return backend.handleReshape();
+ }
+
+ // This is used as the GLEventListener for the pbuffer-based backend
+ // as well as the callback mechanism for the other backends
+ class Updater implements GLEventListener {
+ private Graphics g;
+
+ public void setGraphics(final Graphics g) {
+ this.g = g;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if (!backend.preGL(g)) {
+ return;
+ }
+ helper.init(GLJPanel.this, !sendReshape);
+ backend.postGL(g, false);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ helper.disposeAllGLEventListener(GLJPanel.this, false);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if (!backend.preGL(g)) {
+ return;
+ }
+ if (sendReshape) {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + " @ scale "+getPixelScaleStr()+")");
+ }
+ helper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight);
+ sendReshape = false;
+ }
+
+ helper.display(GLJPanel.this);
+ backend.postGL(g, true);
+ }
+
+ public void plainPaint(final GLAutoDrawable drawable) {
+ helper.display(GLJPanel.this);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ // This is handled above and dispatched directly to the appropriate context
+ }
+ }
+
+ @Override
+ public String toString() {
+ final GLDrawable d = ( null != backend ) ? backend.getDrawable() : null;
+ return "AWT-GLJPanel[ drawableType "+ ( ( null != d ) ? d.getClass().getName() : "null" ) +
+ ", chosenCaps " + getChosenGLCapabilities() +
+ "]";
+ }
+
+ private final Runnable disposeAction = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if ( null != backend ) {
+ final GLContext _context = backend.getContext();
+ final boolean backendDestroy = !backend.isUsingOwnLifecycle();
+
+ GLException exceptionOnDisposeGL = null;
+ if( null != _context && _context.isCreated() ) {
+ try {
+ helper.disposeGL(GLJPanel.this, _context, !backendDestroy);
+ } catch (final GLException gle) {
+ exceptionOnDisposeGL = gle;
+ }
+ }
+ Throwable exceptionBackendDestroy = null;
+ if ( backendDestroy ) {
+ try {
+ backend.destroy();
+ } catch( final Throwable re ) {
+ exceptionBackendDestroy = re;
+ }
+ backend = null;
+ isInitialized = false;
+ }
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
+ }
+ if( null != exceptionBackendDestroy ) {
+ throw GLException.newGLException(exceptionBackendDestroy);
+ }
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ private final Runnable updaterInitAction = new Runnable() {
+ @Override
+ public void run() {
+ updater.init(GLJPanel.this);
+ }
+ };
+
+ private final Runnable updaterDisplayAction = new Runnable() {
+ @Override
+ public void run() {
+ updater.display(GLJPanel.this);
+ }
+ };
+
+ private final Runnable updaterPlainDisplayAction = new Runnable() {
+ @Override
+ public void run() {
+ updater.plainPaint(GLJPanel.this);
+ }
+ };
+
+ private final Runnable paintImmediatelyAction = new Runnable() {
+ @Override
+ public void run() {
+ paintImmediately(0, 0, getWidth(), getHeight());
+ }
+ };
+
+ private class DisposeGLEventListenerAction implements Runnable {
+ GLEventListener listener;
+ private final boolean remove;
+ private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
+
+ @Override
+ public void run() {
+ final Backend b = backend;
+ if ( null != b ) {
+ listener = helper.disposeGLEventListener(GLJPanel.this, b.getDrawable(), b.getContext(), listener, remove);
+ }
+ }
+ };
+
+ private int getGLInteger(final GL gl, final int which) {
+ final int[] tmp = new int[1];
+ gl.glGetIntegerv(which, tmp, 0);
+ return tmp[0];
+ }
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
+ //----------------------------------------------------------------------
+ // Implementations of the various backends
+ //
+
+ /**
+ * Abstraction of the different rendering backends: i.e., pure
+ * software / pixmap rendering, pbuffer-based acceleration, Java 2D
+ * JOGL bridge
+ */
+ static interface Backend {
+ /** Create, Destroy, .. */
+ public boolean isUsingOwnLifecycle();
+
+ /** Called each time the backend needs to initialize itself */
+ public void initialize();
+
+ /** Called when the backend should clean up its resources */
+ public void destroy();
+
+ /** Called when the opacity of the GLJPanel is changed */
+ public void setOpaque(boolean opaque);
+
+ /**
+ * Called to manually create an additional OpenGL context against
+ * this GLJPanel
+ */
+ public GLContext createContext(GLContext shareWith);
+
+ /** Called to set the current backend's GLContext */
+ public void setContext(GLContext ctx);
+
+ /** Called to get the current backend's GLContext */
+ public GLContext getContext();
+
+ /** Called to get the current backend's GLDrawable */
+ public GLDrawable getDrawable();
+
+ /** Returns the used texture unit, i.e. a value of [0..n], or -1 if non used. */
+ public int getTextureUnit();
+
+ /** Called to fetch the "real" GLCapabilities for the backend */
+ public GLCapabilitiesImmutable getChosenGLCapabilities();
+
+ /** Called to fetch the "real" GLProfile for the backend */
+ public GLProfile getGLProfile();
+
+ /**
+ * Called to handle a reshape event. When this is called, the
+ * OpenGL context associated with the backend is not current, to
+ * make it easier to destroy and re-create pbuffers if necessary.
+ */
+ public boolean handleReshape();
+
+ /**
+ * Called before the OpenGL work is done in init() and display().
+ * If false is returned, this render is aborted.
+ */
+ public boolean preGL(Graphics g);
+
+ /**
+ * Return true if backend handles 'swap buffer' itself
+ * and hence the helper's setAutoSwapBuffer(enable) shall not be called.
+ * In this case {@link GLJPanel#autoSwapBufferMode} is being used
+ * in the backend to determine whether to swap buffers or not.
+ */
+ public boolean handlesSwapBuffer();
+
+ /**
+ * Shall invoke underlying drawable's swapBuffer.
+ */
+ public void swapBuffers();
+
+ /**
+ * Called after the OpenGL work is done in init() and display().
+ * The isDisplay argument indicates whether this was called on
+ * behalf of a call to display() rather than init().
+ */
+ public void postGL(Graphics g, boolean isDisplay);
+
+ /** Called from within paintComponent() to initiate the render */
+ public void doPaintComponent(Graphics g);
+
+ /** Called from print .. no backend update desired onscreen */
+ public void doPlainPaint();
+ }
+
+ // Base class used by both the software (pixmap) and pbuffer
+ // backends, both of which rely on reading back the OpenGL frame
+ // buffer and drawing it with a BufferedImage
+ class OffscreenBackend implements Backend {
+ private final AWTGLPixelBufferProvider pixelBufferProvider;
+ private final boolean useSingletonBuffer;
+ private AWTGLPixelBuffer pixelBuffer;
+ private BufferedImage alignedImage;
+
+ // One of these is used to store the read back pixels before storing
+ // in the BufferedImage
+ protected IntBuffer readBackIntsForCPUVFlip;
+
+ // Implementation using software rendering
+ private volatile GLDrawable offscreenDrawable; // volatile: avoid locking for read-only access
+ private boolean offscreenIsFBO;
+ private FBObject fboFlipped;
+ private GLSLTextureRaster glslTextureRaster;
+
+ private volatile GLContextImpl offscreenContext; // volatile: avoid locking for read-only access
+ private boolean flipVertical;
+ private int frameCount = 0;
+
+ // For saving/restoring of OpenGL state during ReadPixels
+ private final GLPixelStorageModes psm = new GLPixelStorageModes();
+
+ OffscreenBackend(final AWTGLPixelBufferProvider custom) {
+ if(null == custom) {
+ pixelBufferProvider = getSingleAWTGLPixelBufferProvider();
+ } else {
+ pixelBufferProvider = custom;
+ }
+ if( pixelBufferProvider instanceof SingletonGLPixelBufferProvider ) {
+ useSingletonBuffer = true;
+ } else {
+ useSingletonBuffer = false;
+ }
+ }
+
+ @Override
+ public final boolean isUsingOwnLifecycle() { return false; }
+
+ @Override
+ public final void initialize() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": OffscreenBackend: initialize() - frameCount "+frameCount);
+ }
+ GLException glException = null;
+ try {
+ final GLContext[] shareWith = { null };
+ if( helper.isSharedGLContextPending(shareWith) ) {
+ return; // pending ..
+ }
+ offscreenDrawable = factory.createOffscreenDrawable(
+ null /* default platform device */,
+ reqOffscreenCaps,
+ chooser,
+ panelWidth, panelHeight);
+ updateWrappedSurfaceScale(offscreenDrawable);
+ offscreenDrawable.setRealized(true);
+ if( DEBUG_FRAMES ) {
+ offscreenDrawable.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
+ @Override
+ public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ System.err.println(getThreadName()+": OffscreenBackend.swapBuffers - frameCount "+frameCount);
+ } } );
+ }
+
+ //
+ // Pre context configuration
+ //
+ flipVertical = !GLJPanel.this.skipGLOrientationVerticalFlip && offscreenDrawable.isGLOriented();
+ offscreenIsFBO = offscreenDrawable.getRequestedGLCapabilities().isFBO();
+ final boolean useGLSLFlip_pre = flipVertical && offscreenIsFBO && reqOffscreenCaps.getGLProfile().isGL2ES2() && USE_GLSL_TEXTURE_RASTERIZER;
+ if( offscreenIsFBO && !useGLSLFlip_pre ) {
+ // Texture attachment only required for GLSL vertical flip, hence simply use a color-renderbuffer attachment.
+ ((GLFBODrawable)offscreenDrawable).setFBOMode(0);
+ }
+
+ offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]);
+ offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ isInitialized = true;
+ helper.setAutoSwapBufferMode(false); // we handle swap-buffers, see handlesSwapBuffer()
+
+ final GL gl = offscreenContext.getGL();
+ // Remedy for Bug 1020, i.e. OSX/Nvidia's FBO needs to be cleared before blitting,
+ // otherwise first MSAA frame lacks antialiasing.
+ // Clearing of FBO is performed within GLFBODrawableImpl.initialize(..):
+ // gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
+ final boolean glslCompliant = !offscreenContext.hasRendererQuirk(GLRendererQuirks.GLSLNonCompliant);
+ final boolean useGLSLFlip = useGLSLFlip_pre && gl.isGL2ES2() && glslCompliant;
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": OffscreenBackend.initialize: useGLSLFlip "+useGLSLFlip+
+ " [flip "+flipVertical+", isFBO "+offscreenIsFBO+", isGL2ES2 "+gl.isGL2ES2()+
+ ", noglsl "+!USE_GLSL_TEXTURE_RASTERIZER+", glslNonCompliant "+!glslCompliant+
+ ", isGL2ES2 " + gl.isGL2ES2()+"\n "+offscreenDrawable+"]");
+ }
+ if( useGLSLFlip ) {
+ final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
+ fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
+ try {
+ fboFlipped = new FBObject();
+ fboFlipped.init(gl, panelWidth, panelHeight, 0);
+ fboFlipped.attachColorbuffer(gl, 0, chosenCaps.getAlphaBits()>0);
+ // fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT); // Bug 1020 (see above), cannot do in FBObject due to unknown 'first bind' state.
+ glslTextureRaster = new GLSLTextureRaster(fboDrawable.getTextureUnit(), true);
+ glslTextureRaster.init(gl.getGL2ES2());
+ glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ if(null != glslTextureRaster) {
+ glslTextureRaster.dispose(gl.getGL2ES2());
+ glslTextureRaster = null;
+ }
+ if(null != fboFlipped) {
+ fboFlipped.destroy(gl);
+ fboFlipped = null;
+ }
+ }
+ } else {
+ fboFlipped = null;
+ glslTextureRaster = null;
+ }
+ offscreenContext.release();
+ } else {
+ isInitialized = false;
+ }
+ } catch( final GLException gle ) {
+ glException = gle;
+ } finally {
+ if( !isInitialized ) {
+ if(null != offscreenContext) {
+ offscreenContext.destroy();
+ offscreenContext = null;
+ }
+ if(null != offscreenDrawable) {
+ offscreenDrawable.setRealized(false);
+ offscreenDrawable = null;
+ }
+ }
+ if( null != glException ) {
+ throw new GLException("Caught GLException: "+glException.getMessage(), glException);
+ }
+ }
+ }
+
+ @Override
+ public final void destroy() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - frameCount "+frameCount);
+ }
+ if ( null != offscreenContext && offscreenContext.isCreated() ) {
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ try {
+ final GL gl = offscreenContext.getGL();
+ if(null != glslTextureRaster) {
+ glslTextureRaster.dispose(gl.getGL2ES2());
+ }
+ if(null != fboFlipped) {
+ fboFlipped.destroy(gl);
+ }
+ } finally {
+ offscreenContext.destroy();
+ }
+ }
+ }
+ offscreenContext = null;
+ glslTextureRaster = null;
+ fboFlipped = null;
+ offscreenContext = null;
+
+ if (offscreenDrawable != null) {
+ final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ offscreenDrawable.setRealized(false);
+ offscreenDrawable = null;
+ if(null != adevice) {
+ adevice.close();
+ }
+ }
+ offscreenIsFBO = false;
+
+ if( null != readBackIntsForCPUVFlip ) {
+ readBackIntsForCPUVFlip.clear();
+ readBackIntsForCPUVFlip = null;
+ }
+ if( null != pixelBuffer ) {
+ if( !useSingletonBuffer ) {
+ pixelBuffer.dispose();
+ }
+ pixelBuffer = null;
+ }
+ alignedImage = null;
+ }
+
+ @Override
+ public final void setOpaque(final boolean opaque) {
+ if ( opaque != isOpaque() && !useSingletonBuffer ) {
+ pixelBuffer.dispose();
+ pixelBuffer = null;
+ alignedImage = null;
+ }
+ }
+
+ @Override
+ public final boolean preGL(final Graphics g) {
+ // Empty in this implementation
+ return true;
+ }
+
+ @Override
+ public final boolean handlesSwapBuffer() {
+ return true;
+ }
+
+ @Override
+ public final void swapBuffers() {
+ final GLDrawable d = offscreenDrawable;
+ if( null != d ) {
+ d.swapBuffers();
+ }
+ }
+
+ @Override
+ public final void postGL(final Graphics g, final boolean isDisplay) {
+ if (isDisplay) {
+ if( DEBUG_FRAMES ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: - frameCount "+frameCount);
+ }
+
+ final GL gl = offscreenContext.getGL();
+
+ //
+ // Save TextureState ASAP, i.e. the user values for the used FBO texture-unit
+ // and the current active texture-unit (if not same)
+ //
+ final TextureState usrTexState, fboTexState;
+ final int fboTexUnit;
+
+ if( offscreenIsFBO ) {
+ fboTexUnit = GL.GL_TEXTURE0 + ((GLFBODrawable)offscreenDrawable).getTextureUnit();
+ usrTexState = new TextureState(gl, GL.GL_TEXTURE_2D);
+ if( fboTexUnit != usrTexState.getUnit() ) {
+ // glActiveTexture(..) + glBindTexture(..) are implicit performed in GLFBODrawableImpl's
+ // swapBuffers/contextMadeCurent -> swapFBOImpl.
+ // We need to cache the texture unit's bound texture-id before it's overwritten.
+ gl.glActiveTexture(fboTexUnit);
+ fboTexState = new TextureState(gl, fboTexUnit, GL.GL_TEXTURE_2D);
+ } else {
+ fboTexState = usrTexState;
+ }
+ } else {
+ fboTexUnit = 0;
+ usrTexState = null;
+ fboTexState = null;
+ }
+
+
+ if( autoSwapBufferMode ) {
+ // Since we only use a single-buffer non-MSAA or double-buffered MSAA offscreenDrawable,
+ // we can always swap!
+ offscreenDrawable.swapBuffers();
+ }
+
+ final int componentCount;
+ final int alignment;
+ if( isOpaque() ) {
+ // w/o alpha
+ componentCount = 3;
+ alignment = 1;
+ } else {
+ // with alpha
+ componentCount = 4;
+ alignment = 4;
+ }
+
+ final PixelFormat awtPixelFormat = pixelBufferProvider.getAWTPixelFormat(gl.getGLProfile(), componentCount);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount, true);
+
+ if( useSingletonBuffer ) { // attempt to fetch the latest AWTGLPixelBuffer
+ pixelBuffer = (AWTGLPixelBuffer) ((SingletonGLPixelBufferProvider)pixelBufferProvider).getSingleBuffer(awtPixelFormat.comp, pixelAttribs, true);
+ }
+ if( null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, panelWidth, panelHeight, 0) ) {
+ pixelBuffer.dispose();
+ pixelBuffer = null;
+ alignedImage = null;
+ }
+ final boolean DEBUG_INIT;
+ if ( null == pixelBuffer ) {
+ if (0 >= panelWidth || 0 >= panelHeight ) {
+ return;
+ }
+ pixelBuffer = pixelBufferProvider.allocate(gl, awtPixelFormat.comp, pixelAttribs, true, panelWidth, panelHeight, 1, 0);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelBufferProvider isSingletonBufferProvider "+useSingletonBuffer+", 0x"+Integer.toHexString(pixelBufferProvider.hashCode())+", "+pixelBufferProvider.getClass().getSimpleName());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelBuffer 0x"+Integer.toHexString(pixelBuffer.hashCode())+", "+pixelBuffer+", alignment "+alignment);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster)+", isGL2ES3 "+gl.isGL2ES3());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" panelSize "+panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelAttribs "+pixelAttribs);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" awtPixelFormat "+awtPixelFormat);
+ DEBUG_INIT = true;
+ } else {
+ DEBUG_INIT = false;
+ }
+ } else {
+ DEBUG_INIT = false;
+ }
+ if( offscreenDrawable.getSurfaceWidth() != panelWidth || offscreenDrawable.getSurfaceHeight() != panelHeight ) {
+ throw new InternalError("OffscreenDrawable panelSize mismatch (reshape missed): panelSize "+panelWidth+"x"+panelHeight+" != drawable "+offscreenDrawable.getSurfaceWidth()+"x"+offscreenDrawable.getSurfaceHeight()+", on thread "+getThreadName());
+ }
+ if( null == alignedImage ||
+ panelWidth != alignedImage.getWidth() || panelHeight != alignedImage.getHeight() ||
+ !pixelBuffer.isDataBufferSource(alignedImage) ) {
+ alignedImage = pixelBuffer.getAlignedImage(panelWidth, panelHeight);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" new alignedImage "+alignedImage.getWidth()+"x"+alignedImage.getHeight()+" @ scale "+getPixelScaleStr()+", "+alignedImage+", pixelBuffer "+pixelBuffer.width+"x"+pixelBuffer.height+", "+pixelBuffer);
+ }
+ }
+ final IntBuffer readBackInts;
+
+ if( !flipVertical || null != glslTextureRaster ) {
+ readBackInts = (IntBuffer) pixelBuffer.buffer;
+ } else {
+ if( null == readBackIntsForCPUVFlip || pixelBuffer.width * pixelBuffer.height > readBackIntsForCPUVFlip.remaining() ) {
+ readBackIntsForCPUVFlip = IntBuffer.allocate(pixelBuffer.width * pixelBuffer.height);
+ }
+ readBackInts = readBackIntsForCPUVFlip;
+ }
+
+ // Must now copy pixels from offscreen context into surface
+ if( DEBUG_FRAMES ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.readPixels: - frameCount "+frameCount);
+ }
+
+ // Save PACK modes, reset them to defaults and set alignment
+ psm.setPackAlignment(gl, alignment);
+ if( gl.isGL2ES3() ) {
+ final GL2ES3 gl2es3 = gl.getGL2ES3();
+ psm.setPackRowLength(gl2es3, panelWidth);
+ gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
+ if( DEBUG_INIT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: fboDrawable "+offscreenDrawable);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl2es3.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: def-readBuffer 0x"+Integer.toHexString(gl2es3.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: def-readFBO 0x"+Integer.toHexString(gl2es3.getDefaultReadFramebuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: bound-readFBO 0x"+Integer.toHexString(gl2es3.getBoundFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER)));
+ }
+ }
+
+ if(null != glslTextureRaster) { // implies flippedVertical
+ final boolean viewportChange;
+ final int[] usrViewport = new int[] { 0, 0, 0, 0 };
+ gl.glGetIntegerv(GL.GL_VIEWPORT, usrViewport, 0);
+ viewportChange = 0 != usrViewport[0] || 0 != usrViewport[1] ||
+ panelWidth != usrViewport[2] || panelHeight != usrViewport[3];
+ if( DEBUG_VIEWPORT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL: "+GLJPanel.this.getName()+" Viewport: change "+viewportChange+
+ ", "+usrViewport[0]+"/"+usrViewport[1]+" "+usrViewport[2]+"x"+usrViewport[3]+
+ " -> 0/0 "+panelWidth+"x"+panelHeight);
+ }
+ if( viewportChange ) {
+ gl.glViewport(0, 0, panelWidth, panelHeight);
+ }
+
+ // perform vert-flipping via OpenGL/FBO
+ final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
+ final FBObject.TextureAttachment fboTex = fboDrawable.getColorbuffer(GL.GL_FRONT).getTextureAttachment();
+
+ fboFlipped.bind(gl);
+
+ // gl.glActiveTexture(GL.GL_TEXTURE0 + fboDrawable.getTextureUnit()); // implicit by GLFBODrawableImpl: swapBuffers/contextMadeCurent -> swapFBOImpl
+ gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
+ // gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
+
+ glslTextureRaster.display(gl.getGL2ES2());
+ if( DEBUG_INIT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: fboDrawable "+fboDrawable);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: read from fbo-rb "+fboFlipped.getReadFramebuffer()+", fbo "+fboFlipped);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: def-readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: def-readFBO 0x"+Integer.toHexString(gl.getDefaultReadFramebuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: bound-readFBO 0x"+Integer.toHexString(gl.getBoundFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER)));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: "+GLJPanel.this.getName()+" pixelAttribs "+pixelAttribs);
+ }
+ gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
+
+ fboFlipped.unbind(gl);
+ if( DEBUG_INIT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: fboDrawable "+fboDrawable);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: read from fbo-rb "+fboFlipped.getReadFramebuffer()+", fbo "+fboFlipped);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: def-readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: def-readFBO 0x"+Integer.toHexString(gl.getDefaultReadFramebuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: bound-readFBO 0x"+Integer.toHexString(gl.getBoundFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER)));
+ }
+ if( viewportChange ) {
+ gl.glViewport(usrViewport[0], usrViewport[1], usrViewport[2], usrViewport[3]);
+ }
+ } else {
+ gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
+
+ if ( flipVertical ) {
+ // Copy temporary data into raster of BufferedImage for faster
+ // blitting Note that we could avoid this copy in the cases
+ // where !offscreenDrawable.isGLOriented(),
+ // but that's the software rendering path which is very slow anyway.
+ final BufferedImage image = alignedImage;
+ final int[] src = readBackInts.array();
+ final int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final int incr = panelWidth;
+ int srcPos = 0;
+ int destPos = (panelHeight - 1) * panelWidth;
+ for (; destPos >= 0; srcPos += incr, destPos -= incr) {
+ System.arraycopy(src, srcPos, dest, destPos, incr);
+ }
+ }
+ }
+ if( 0 != fboTexUnit ) { // implies offscreenIsFBO
+ fboTexState.restore(gl);
+ if( fboTexUnit != usrTexState.getUnit() ) {
+ usrTexState.restore(gl);
+ }
+ }
+
+ // Restore saved modes.
+ psm.restore(gl);
+
+ // Note: image will be drawn back in paintComponent() for
+ // correctness on all platforms
+ }
+ }
+
+ @Override
+ public final int getTextureUnit() {
+ if(null != glslTextureRaster && null != offscreenDrawable) { // implies flippedVertical
+ return ((GLFBODrawable)offscreenDrawable).getTextureUnit();
+ }
+ return -1;
+ }
+
+ @Override
+ public final void doPaintComponent(final Graphics g) {
+ helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
+
+ if ( null != alignedImage ) {
+ if( DEBUG_FRAMES ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount);
+ }
+ // Draw resulting image in one shot
+ g.drawImage(alignedImage, 0, 0,
+ SurfaceScaleUtils.scaleInv(alignedImage.getWidth(), hasPixelScale[0]),
+ SurfaceScaleUtils.scaleInv(alignedImage.getHeight(), hasPixelScale[1]), null); // Null ImageObserver since image data is ready.
+ }
+ frameCount++;
+ }
+
+ @Override
+ public final void doPlainPaint() {
+ helper.invokeGL(offscreenDrawable, offscreenContext, updaterPlainDisplayAction, updaterInitAction);
+ }
+
+ @Override
+ public final boolean handleReshape() {
+ GLDrawableImpl _drawable = (GLDrawableImpl)offscreenDrawable;
+ {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ _drawable = _drawableNew;
+ offscreenDrawable = _drawableNew;
+ updateWrappedSurfaceScale(offscreenDrawable);
+ }
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.handleReshape: " +panelWidth+"x"+panelHeight + " @ scale "+getPixelScaleStr() + " -> " + _drawable.getSurfaceWidth()+"x"+_drawable.getSurfaceHeight());
+ }
+ panelWidth = _drawable.getSurfaceWidth();
+ panelHeight = _drawable.getSurfaceHeight();
+
+ if( null != glslTextureRaster ) {
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ try {
+ final GL gl = offscreenContext.getGL();
+ fboFlipped.reset(gl, panelWidth, panelHeight, 0);
+ glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
+ } finally {
+ offscreenContext.release();
+ }
+ }
+ }
+ return _drawable.isRealized();
+ }
+
+ @Override
+ public final GLContext createContext(final GLContext shareWith) {
+ return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null;
+ }
+
+ @Override
+ public final void setContext(final GLContext ctx) {
+ offscreenContext=(GLContextImpl)ctx;
+ }
+
+ @Override
+ public final GLContext getContext() {
+ return offscreenContext;
+ }
+
+ @Override
+ public final GLDrawable getDrawable() {
+ return offscreenDrawable;
+ }
+
+ @Override
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
+ if (offscreenDrawable == null) {
+ return null;
+ }
+ return offscreenDrawable.getChosenGLCapabilities();
+ }
+
+ @Override
+ public final GLProfile getGLProfile() {
+ if (offscreenDrawable == null) {
+ return null;
+ }
+ return offscreenDrawable.getGLProfile();
+ }
+ }
+
+ class J2DOGLBackend implements Backend {
+ // Opaque Object identifier representing the Java2D surface we are
+ // drawing to; used to determine when to destroy and recreate JOGL
+ // context
+ private Object j2dSurface;
+ // Graphics object being used during Java2D update action
+ // (absolutely essential to cache this)
+ // No-op context representing the Java2D OpenGL context
+ private GLContext j2dContext;
+ // Context associated with no-op drawable representing the JOGL
+ // OpenGL context
+ private GLDrawable joglDrawable;
+ // The real OpenGL context JOGL uses to render
+ private GLContext joglContext;
+ // State captured from Java2D OpenGL context necessary in order to
+ // properly render into Java2D back buffer
+ private final int[] drawBuffer = new int[1];
+ private final int[] readBuffer = new int[1];
+ // This is required when the FBO option of the Java2D / OpenGL
+ // pipeline is active
+ private final int[] frameBuffer = new int[1];
+ // Current (as of this writing) NVidia drivers have a couple of bugs
+ // relating to the sharing of framebuffer and renderbuffer objects
+ // between contexts. It appears we have to (a) reattach the color
+ // attachment and (b) actually create new depth buffer storage and
+ // attach it in order for the FBO to behave properly in our context.
+ private boolean checkedForFBObjectWorkarounds;
+ private boolean fbObjectWorkarounds;
+ private int[] frameBufferDepthBuffer;
+ private int[] frameBufferTexture;
+ private boolean createNewDepthBuffer;
+ // Current (as of this writing) ATI drivers have problems when the
+ // same FBO is bound in two different contexts. Here we check for
+ // this case and explicitly release the FBO from Java2D's context
+ // before switching to ours. Java2D will re-bind the FBO when it
+ // makes its context current the next time. Interestingly, if we run
+ // this code path on NVidia hardware, it breaks the rendering
+ // results -- no output is generated. This doesn't appear to be an
+ // interaction with the abovementioned NVidia-specific workarounds,
+ // as even if we disable that code the FBO is still reported as
+ // incomplete in our context.
+ private boolean checkedGLVendor;
+ private boolean vendorIsATI;
+
+ // Holding on to this GraphicsConfiguration is a workaround for a
+ // problem in the Java 2D / JOGL bridge when FBOs are enabled; see
+ // comment related to Issue 274 below
+ private GraphicsConfiguration workaroundConfig;
+
+ @Override
+ public final boolean isUsingOwnLifecycle() { return true; }
+
+ @Override
+ public final void initialize() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": J2DOGL: initialize()");
+ }
+ // No-op in this implementation; everything is done lazily
+ isInitialized = true;
+ }
+
+ @Override
+ public final void destroy() {
+ Java2D.invokeWithOGLContextCurrent(null, new Runnable() {
+ @Override
+ public void run() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": J2DOGL: destroy() - joglContext: "+(null!=joglContext)+" - joglDrawable: "+(null!=joglDrawable));
+ }
+ if (joglContext != null) {
+ joglContext.destroy();
+ joglContext = null;
+ }
+ joglDrawable = null;
+ if (j2dContext != null) {
+ j2dContext.destroy();
+ j2dContext = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public final void setOpaque(final boolean opaque) {
+ // Empty in this implementation
+ }
+
+ @Override
+ public final GLContext createContext(final GLContext shareWith) {
+ if(null != shareWith) {
+ throw new GLException("J2DOGLBackend cannot create context w/ additional shared context, since it already needs to share the context w/ J2D.");
+ }
+ return (null != joglDrawable && null != j2dContext) ? joglDrawable.createContext(j2dContext) : null;
+ }
+
+ @Override
+ public final void setContext(final GLContext ctx) {
+ joglContext=ctx;
+ }
+
+ @Override
+ public final GLContext getContext() {
+ return joglContext;
+ }
+
+ @Override
+ public final GLDrawable getDrawable() {
+ return joglDrawable;
+ }
+
+ @Override
+ public final int getTextureUnit() { return -1; }
+
+ @Override
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
+ // FIXME: should do better than this; is it possible to query J2D Caps ?
+ return new GLCapabilities(null);
+ }
+
+ @Override
+ public final GLProfile getGLProfile() {
+ // FIXME: should do better than this; is it possible to query J2D's Profile ?
+ return GLProfile.getDefault(GLProfile.getDefaultDevice());
+ }
+
+ @Override
+ public final boolean handleReshape() {
+ // Empty in this implementation
+ return true;
+ }
+
+ @Override
+ public final boolean preGL(final Graphics g) {
+ final GL2 gl = joglContext.getGL().getGL2();
+ // Set up needed state in JOGL context from Java2D context
+ gl.glEnable(GL.GL_SCISSOR_TEST);
+ final Rectangle r = Java2D.getOGLScissorBox(g);
+
+ if (r == null) {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": Java2D.getOGLScissorBox() returned null");
+ }
+ return false;
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: gl.glScissor(" + r.x + ", " + r.y + ", " + r.width + ", " + r.height + ")");
+ }
+
+ gl.glScissor(r.x, r.y, r.width, r.height);
+ final Rectangle oglViewport = Java2D.getOGLViewport(g, panelWidth, panelHeight);
+ // If the viewport X or Y changes, in addition to the panel's
+ // width or height, we need to send a reshape operation to the
+ // client
+ if ((viewportX != oglViewport.x) ||
+ (viewportY != oglViewport.y)) {
+ sendReshape = true;
+ if (DEBUG) {
+ System.err.println(getThreadName()+": Sending reshape because viewport changed");
+ System.err.println(" viewportX (" + viewportX + ") ?= oglViewport.x (" + oglViewport.x + ")");
+ System.err.println(" viewportY (" + viewportY + ") ?= oglViewport.y (" + oglViewport.y + ")");
+ }
+ }
+ viewportX = oglViewport.x;
+ viewportY = oglViewport.y;
+
+ // If the FBO option is active, bind to the FBO from the Java2D
+ // context.
+ // Note that all of the plumbing in the context sharing stuff will
+ // allow us to bind to this object since it's in our namespace.
+ if (Java2D.isFBOEnabled() &&
+ Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
+
+ // The texture target for Java2D's OpenGL pipeline when using FBOs
+ // -- either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB
+ final int fboTextureTarget = Java2D.getOGLTextureType(g);
+
+ if (!checkedForFBObjectWorkarounds) {
+ checkedForFBObjectWorkarounds = true;
+ gl.glBindTexture(fboTextureTarget, 0);
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBuffer[0]);
+ final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
+ // Need to do workarounds
+ fbObjectWorkarounds = true;
+ createNewDepthBuffer = true;
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: ERR GL_FRAMEBUFFER_BINDING: Discovered Invalid J2D FBO("+frameBuffer[0]+"): "+FBObject.getStatusString(status) +
+ ", frame_buffer_object workarounds to be necessary");
+ }
+ } else {
+ // Don't need the frameBufferTexture temporary any more
+ frameBufferTexture = null;
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
+ }
+ }
+ }
+
+ if (fbObjectWorkarounds && createNewDepthBuffer) {
+ if (frameBufferDepthBuffer == null)
+ frameBufferDepthBuffer = new int[1];
+
+ // Create our own depth renderbuffer and associated storage
+ // If we have an old one, delete it
+ if (frameBufferDepthBuffer[0] != 0) {
+ gl.glDeleteRenderbuffers(1, frameBufferDepthBuffer, 0);
+ frameBufferDepthBuffer[0] = 0;
+ }
+
+ gl.glBindTexture(fboTextureTarget, frameBufferTexture[0]);
+ final int[] width = new int[1];
+ final int[] height = new int[1];
+ gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2GL3.GL_TEXTURE_WIDTH, width, 0);
+ gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2GL3.GL_TEXTURE_HEIGHT, height, 0);
+
+ gl.glGenRenderbuffers(1, frameBufferDepthBuffer, 0);
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: Generated frameBufferDepthBuffer " + frameBufferDepthBuffer[0] +
+ " with width " + width[0] + ", height " + height[0]);
+ }
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, frameBufferDepthBuffer[0]);
+ // FIXME: may need a loop here like in Java2D
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, width[0], height[0]);
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0);
+ createNewDepthBuffer = false;
+ }
+
+ gl.glBindTexture(fboTextureTarget, 0);
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBuffer[0]);
+
+ if (fbObjectWorkarounds) {
+ // Hook up the color and depth buffer attachment points for this framebuffer
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0,
+ fboTextureTarget,
+ frameBufferTexture[0],
+ 0);
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: frameBufferDepthBuffer: " + frameBufferDepthBuffer[0]);
+ }
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_DEPTH_ATTACHMENT,
+ GL.GL_RENDERBUFFER,
+ frameBufferDepthBuffer[0]);
+ }
+
+ if (DEBUG) {
+ final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
+ throw new GLException("Error: framebuffer was incomplete: status = 0x" +
+ Integer.toHexString(status));
+ }
+ }
+ } else {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: Setting up drawBuffer " + drawBuffer[0] +
+ " and readBuffer " + readBuffer[0]);
+ }
+
+ gl.glDrawBuffer(drawBuffer[0]);
+ gl.glReadBuffer(readBuffer[0]);
+ }
+
+ return true;
+ }
+
+ @Override
+ public final boolean handlesSwapBuffer() {
+ return false;
+ }
+
+ @Override
+ public final void swapBuffers() {
+ final GLDrawable d = joglDrawable;
+ if( null != d ) {
+ d.swapBuffers();
+ }
+ }
+
+ @Override
+ public final void postGL(final Graphics g, final boolean isDisplay) {
+ // Cause OpenGL pipeline to flush its results because
+ // otherwise it's possible we will buffer up multiple frames'
+ // rendering results, resulting in apparent mouse lag
+ final GL gl = joglContext.getGL();
+ gl.glFinish();
+
+ if (Java2D.isFBOEnabled() &&
+ Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
+ // Unbind the framebuffer from our context to work around
+ // apparent driver bugs or at least unspecified behavior causing
+ // OpenGL to run out of memory with certain cards and drivers
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
+ }
+ }
+
+ @Override
+ public final void doPaintComponent(final Graphics g) {
+ // This is a workaround for an issue in the Java 2D / JOGL
+ // bridge (reported by an end user as JOGL Issue 274) where Java
+ // 2D can occasionally leave its internal OpenGL context current
+ // to the on-screen window rather than its internal "scratch"
+ // pbuffer surface to which the FBO is attached. JOGL expects to
+ // find a stable OpenGL drawable (on Windows, an HDC) upon which
+ // it can create another OpenGL context. It turns out that, on
+ // Windows, when Java 2D makes its internal OpenGL context
+ // current against the window in order to put pixels on the
+ // screen, it gets the device context for the window, makes its
+ // context current, and releases the device context. This means
+ // that when JOGL's Runnable gets to run below, the HDC is
+ // already invalid. The workaround for this is to force Java 2D
+ // to make its context current to the scratch surface, which we
+ // can do by executing an empty Runnable with the "shared"
+ // context current. This will be fixed in a Java SE 6 update
+ // release, hopefully 6u2.
+ if (Java2D.isFBOEnabled()) {
+ if (workaroundConfig == null) {
+ workaroundConfig = GraphicsEnvironment.
+ getLocalGraphicsEnvironment().
+ getDefaultScreenDevice().
+ getDefaultConfiguration();
+ }
+ Java2D.invokeWithOGLSharedContextCurrent(workaroundConfig, new Runnable() { @Override
+ public void run() {}});
+ }
+
+ Java2D.invokeWithOGLContextCurrent(g, new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.invokeWithOGLContextCurrent");
+ }
+
+ // Create no-op context representing Java2D context
+ if (j2dContext == null) {
+ j2dContext = factory.createExternalGLContext();
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.Created External Context: "+j2dContext);
+ }
+ if (DEBUG) {
+// j2dContext.setGL(new DebugGL2(j2dContext.getGL().getGL2()));
+ }
+
+ // Check to see whether we can support the requested
+ // capabilities or need to fall back to a pbuffer
+ // FIXME: add more checks?
+
+ j2dContext.makeCurrent();
+ final GL gl = j2dContext.getGL();
+ if ((getGLInteger(gl, GL.GL_RED_BITS) < reqOffscreenCaps.getRedBits()) ||
+ (getGLInteger(gl, GL.GL_GREEN_BITS) < reqOffscreenCaps.getGreenBits()) ||
+ (getGLInteger(gl, GL.GL_BLUE_BITS) < reqOffscreenCaps.getBlueBits()) ||
+ // (getGLInteger(gl, GL.GL_ALPHA_BITS) < offscreenCaps.getAlphaBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) < reqOffscreenCaps.getAccumRedBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) < reqOffscreenCaps.getAccumGreenBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) < reqOffscreenCaps.getAccumBlueBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) < reqOffscreenCaps.getAccumAlphaBits()) ||
+ // (getGLInteger(gl, GL2.GL_DEPTH_BITS) < offscreenCaps.getDepthBits()) ||
+ (getGLInteger(gl, GL.GL_STENCIL_BITS) < reqOffscreenCaps.getStencilBits())) {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: Falling back to pbuffer-based support because Java2D context insufficient");
+ System.err.println(" Available Required");
+ System.err.println("GL_RED_BITS " + getGLInteger(gl, GL.GL_RED_BITS) + " " + reqOffscreenCaps.getRedBits());
+ System.err.println("GL_GREEN_BITS " + getGLInteger(gl, GL.GL_GREEN_BITS) + " " + reqOffscreenCaps.getGreenBits());
+ System.err.println("GL_BLUE_BITS " + getGLInteger(gl, GL.GL_BLUE_BITS) + " " + reqOffscreenCaps.getBlueBits());
+ System.err.println("GL_ALPHA_BITS " + getGLInteger(gl, GL.GL_ALPHA_BITS) + " " + reqOffscreenCaps.getAlphaBits());
+ System.err.println("GL_ACCUM_RED_BITS " + getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) + " " + reqOffscreenCaps.getAccumRedBits());
+ System.err.println("GL_ACCUM_GREEN_BITS " + getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) + " " + reqOffscreenCaps.getAccumGreenBits());
+ System.err.println("GL_ACCUM_BLUE_BITS " + getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) + " " + reqOffscreenCaps.getAccumBlueBits());
+ System.err.println("GL_ACCUM_ALPHA_BITS " + getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) + " " + reqOffscreenCaps.getAccumAlphaBits());
+ System.err.println("GL_DEPTH_BITS " + getGLInteger(gl, GL.GL_DEPTH_BITS) + " " + reqOffscreenCaps.getDepthBits());
+ System.err.println("GL_STENCIL_BITS " + getGLInteger(gl, GL.GL_STENCIL_BITS) + " " + reqOffscreenCaps.getStencilBits());
+ }
+ isInitialized = false;
+ backend = null;
+ java2DGLPipelineOK = false;
+ handleReshape = true;
+ j2dContext.destroy();
+ j2dContext = null;
+ return;
+ }
+ } else {
+ j2dContext.makeCurrent();
+ }
+ try {
+ captureJ2DState(j2dContext.getGL(), g);
+ final Object curSurface = Java2D.getOGLSurfaceIdentifier(g);
+ if (curSurface != null) {
+ if (j2dSurface != curSurface) {
+ if (joglContext != null) {
+ joglContext.destroy();
+ joglContext = null;
+ joglDrawable = null;
+ sendReshape = true;
+ if (DEBUG) {
+ System.err.println(getThreadName()+": Sending reshape because surface changed");
+ System.err.println("New surface = " + curSurface);
+ }
+ }
+ j2dSurface = curSurface;
+ if (DEBUG) {
+ System.err.print(getThreadName()+": Surface type: ");
+ final int surfaceType = Java2D.getOGLSurfaceType(g);
+ if (surfaceType == Java2D.UNDEFINED) {
+ System.err.println("UNDEFINED");
+ } else if (surfaceType == Java2D.WINDOW) {
+ System.err.println("WINDOW");
+ } else if (surfaceType == Java2D.PBUFFER) {
+ System.err.println("PBUFFER");
+ } else if (surfaceType == Java2D.TEXTURE) {
+ System.err.println("TEXTURE");
+ } else if (surfaceType == Java2D.FLIP_BACKBUFFER) {
+ System.err.println("FLIP_BACKBUFFER");
+ } else if (surfaceType == Java2D.FBOBJECT) {
+ System.err.println("FBOBJECT");
+ } else {
+ System.err.println("(Unknown surface type " + surfaceType + ")");
+ }
+ }
+ }
+ if (joglContext == null) {
+ final AbstractGraphicsDevice device = j2dContext.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ if (factory.canCreateExternalGLDrawable(device)) {
+ joglDrawable = factory.createExternalGLDrawable();
+ joglContext = joglDrawable.createContext(j2dContext);
+ if (DEBUG) {
+ System.err.println("-- Created External Drawable: "+joglDrawable);
+ System.err.println("-- Created Context: "+joglContext);
+ }
+ }
+ if (Java2D.isFBOEnabled() &&
+ Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT &&
+ fbObjectWorkarounds) {
+ createNewDepthBuffer = true;
+ }
+ }
+ helper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction);
+ }
+ } finally {
+ j2dContext.release();
+ }
+ }
+ });
+ }
+
+ @Override
+ public final void doPlainPaint() {
+ helper.invokeGL(joglDrawable, joglContext, updaterPlainDisplayAction, updaterInitAction);
+ }
+
+ private final void captureJ2DState(final GL gl, final Graphics g) {
+ gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, drawBuffer, 0);
+ gl.glGetIntegerv(GL2ES3.GL_READ_BUFFER, readBuffer, 0);
+ if (Java2D.isFBOEnabled() &&
+ Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
+ gl.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, frameBuffer, 0);
+ if(!gl.glIsFramebuffer(frameBuffer[0])) {
+ checkedForFBObjectWorkarounds=true;
+ fbObjectWorkarounds = true;
+ createNewDepthBuffer = true;
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: Fetched ERR GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]+" - NOT A FBO"+
+ ", frame_buffer_object workarounds to be necessary");
+ }
+ } else if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: Fetched OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
+ }
+
+ if(fbObjectWorkarounds || !checkedForFBObjectWorkarounds) {
+ // See above for description of what we are doing here
+ if (frameBufferTexture == null)
+ frameBufferTexture = new int[1];
+
+ // Query the framebuffer for its color buffer so we can hook
+ // it back up in our context (should not be necessary)
+ gl.glGetFramebufferAttachmentParameteriv(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0,
+ GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+ frameBufferTexture, 0);
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel: FBO COLOR_ATTACHMENT0: " + frameBufferTexture[0]);
+ }
+ }
+
+ if (!checkedGLVendor) {
+ checkedGLVendor = true;
+ final String vendor = gl.glGetString(GL.GL_VENDOR);
+
+ if ((vendor != null) &&
+ vendor.startsWith("ATI")) {
+ vendorIsATI = true;
+ }
+ }
+
+ if (vendorIsATI) {
+ // Unbind the FBO from Java2D's context as it appears that
+ // driver bugs on ATI's side are causing problems if the FBO is
+ // simultaneously bound to more than one context. Java2D will
+ // re-bind the FBO during the next validation of its context.
+ // Note: this breaks rendering at least on NVidia hardware
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
+ }
+ }
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLLightingFunc.java b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLLightingFunc.java
new file mode 100644
index 000000000..cf7b9da46
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLLightingFunc.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.fixedfunc;
+
+public interface GLLightingFunc {
+ public static final int GL_LIGHT0 = 0x4000;
+ public static final int GL_LIGHT1 = 0x4001;
+ public static final int GL_LIGHT2 = 0x4002;
+ public static final int GL_LIGHT3 = 0x4003;
+ public static final int GL_LIGHT4 = 0x4004;
+ public static final int GL_LIGHT5 = 0x4005;
+ public static final int GL_LIGHT6 = 0x4006;
+ public static final int GL_LIGHT7 = 0x4007;
+ public static final int GL_LIGHTING = 0xB50;
+ public static final int GL_AMBIENT = 0x1200;
+ public static final int GL_DIFFUSE = 0x1201;
+ public static final int GL_SPECULAR = 0x1202;
+ public static final int GL_POSITION = 0x1203;
+ public static final int GL_SPOT_DIRECTION = 0x1204;
+ public static final int GL_SPOT_EXPONENT = 0x1205;
+ public static final int GL_SPOT_CUTOFF = 0x1206;
+ public static final int GL_CONSTANT_ATTENUATION = 0x1207;
+ public static final int GL_LINEAR_ATTENUATION = 0x1208;
+ public static final int GL_QUADRATIC_ATTENUATION = 0x1209;
+ public static final int GL_EMISSION = 0x1600;
+ public static final int GL_SHININESS = 0x1601;
+ public static final int GL_AMBIENT_AND_DIFFUSE = 0x1602;
+ public static final int GL_COLOR_MATERIAL = 0xB57;
+ public static final int GL_NORMALIZE = 0xBA1;
+
+ public static final int GL_FLAT = 0x1D00;
+ public static final int GL_SMOOTH = 0x1D01;
+
+ public void glLightfv(int light, int pname, java.nio.FloatBuffer params);
+ public void glLightfv(int light, int pname, float[] params, int params_offset);
+ public void glMaterialf(int face, int pname, float param);
+ public void glMaterialfv(int face, int pname, java.nio.FloatBuffer params);
+ public void glMaterialfv(int face, int pname, float[] params, int params_offset);
+ public void glColor4f(float red, float green, float blue, float alpha);
+ public void glShadeModel(int mode);
+
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLMatrixFunc.java b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLMatrixFunc.java
new file mode 100644
index 000000000..90f13faf1
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLMatrixFunc.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.fixedfunc;
+
+import java.nio.*;
+
+import com.jogamp.opengl.GL;
+
+/**
+ * Subset of OpenGL fixed function pipeline's matrix operations.
+ */
+public interface GLMatrixFunc {
+
+ public static final int GL_MATRIX_MODE = 0x0BA0;
+ /** Matrix mode modelview */
+ public static final int GL_MODELVIEW = 0x1700;
+ /** Matrix mode projection */
+ public static final int GL_PROJECTION = 0x1701;
+ // public static final int GL_TEXTURE = 0x1702; // Use GL.GL_TEXTURE due to ambiguous GL usage
+ /** Matrix access name for modelview */
+ public static final int GL_MODELVIEW_MATRIX = 0x0BA6;
+ /** Matrix access name for projection */
+ public static final int GL_PROJECTION_MATRIX = 0x0BA7;
+ /** Matrix access name for texture */
+ public static final int GL_TEXTURE_MATRIX = 0x0BA8;
+
+ /**
+ * Copy the named matrix into the given storage.
+ * @param pname {@link #GL_MODELVIEW_MATRIX}, {@link #GL_PROJECTION_MATRIX} or {@link #GL_TEXTURE_MATRIX}
+ * @param params the FloatBuffer's position remains unchanged,
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glGetFloatv(int pname, java.nio.FloatBuffer params);
+
+ /**
+ * Copy the named matrix to the given storage at offset.
+ * @param pname {@link #GL_MODELVIEW_MATRIX}, {@link #GL_PROJECTION_MATRIX} or {@link #GL_TEXTURE_MATRIX}
+ * @param params storage
+ * @param params_offset storage offset
+ */
+ public void glGetFloatv(int pname, float[] params, int params_offset);
+
+ /**
+ * glGetIntegerv
+ * @param pname {@link #GL_MATRIX_MODE} to receive the current matrix mode
+ * @param params the FloatBuffer's position remains unchanged
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glGetIntegerv(int pname, IntBuffer params);
+ public void glGetIntegerv(int pname, int[] params, int params_offset);
+
+ /**
+ * Sets the current matrix mode.
+ * @param mode {@link #GL_MODELVIEW}, {@link #GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}.
+ */
+ public void glMatrixMode(int mode) ;
+
+ /**
+ * Push the current matrix to it's stack, while preserving it's values.
+ * <p>
+ * There exist one stack per matrix mode, i.e. {@link #GL_MODELVIEW}, {@link #GL_PROJECTION} and {@link GL#GL_TEXTURE GL_TEXTURE}.
+ * </p>
+ */
+ public void glPushMatrix();
+
+ /**
+ * Pop the current matrix from it's stack.
+ * @see #glPushMatrix()
+ */
+ public void glPopMatrix();
+
+ /**
+ * Load the current matrix with the identity matrix
+ */
+ public void glLoadIdentity() ;
+
+ /**
+ * Load the current matrix w/ the provided one.
+ * @param params the FloatBuffer's position remains unchanged,
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glLoadMatrixf(java.nio.FloatBuffer m) ;
+ /**
+ * Load the current matrix w/ the provided one.
+ */
+ public void glLoadMatrixf(float[] m, int m_offset);
+
+ /**
+ * Multiply the current matrix: [c] = [c] x [m]
+ * @param m the FloatBuffer's position remains unchanged,
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glMultMatrixf(java.nio.FloatBuffer m) ;
+ /**
+ * Multiply the current matrix: [c] = [c] x [m]
+ */
+ public void glMultMatrixf(float[] m, int m_offset);
+
+ /**
+ * Translate the current matrix.
+ */
+ public void glTranslatef(float x, float y, float z) ;
+
+ /**
+ * Rotate the current matrix.
+ */
+ public void glRotatef(float angle, float x, float y, float z);
+
+ /**
+ * Scale the current matrix.
+ */
+ public void glScalef(float x, float y, float z) ;
+
+ /**
+ * {@link #glMultMatrixf(FloatBuffer) Multiply} the current matrix with the orthogonal matrix.
+ */
+ public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) ;
+
+ /**
+ * {@link #glMultMatrixf(FloatBuffer) Multiply} the current matrix with the frustum matrix.
+ */
+ public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar);
+
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFunc.java b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFunc.java
new file mode 100644
index 000000000..852d4ebba
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFunc.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.fixedfunc;
+
+import com.jogamp.opengl.*;
+
+public interface GLPointerFunc {
+ public static final int GL_VERTEX_ARRAY = 0x8074;
+ public static final int GL_NORMAL_ARRAY = 0x8075;
+ public static final int GL_COLOR_ARRAY = 0x8076;
+ public static final int GL_TEXTURE_COORD_ARRAY = 0x8078;
+
+ public void glEnableClientState(int arrayName);
+ public void glDisableClientState(int arrayName);
+
+ public void glVertexPointer(GLArrayData array);
+ public void glVertexPointer(int size, int type, int stride, java.nio.Buffer pointer);
+ public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset);
+
+ public void glColorPointer(GLArrayData array);
+ public void glColorPointer(int size, int type, int stride, java.nio.Buffer pointer);
+ public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset);
+ public void glColor4f(float red, float green, float blue, float alpha);
+
+ public void glNormalPointer(GLArrayData array);
+ public void glNormalPointer(int type, int stride, java.nio.Buffer pointer);
+ public void glNormalPointer(int type, int stride, long pointer_buffer_offset);
+
+ public void glTexCoordPointer(GLArrayData array);
+ public void glTexCoordPointer(int size, int type, int stride, java.nio.Buffer pointer);
+ public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset);
+
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFuncUtil.java b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFuncUtil.java
new file mode 100644
index 000000000..cb1ff3827
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/fixedfunc/GLPointerFuncUtil.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.fixedfunc;
+
+public class GLPointerFuncUtil {
+ public static final String mgl_Vertex = "mgl_Vertex";
+ public static final String mgl_Normal = "mgl_Normal";
+ public static final String mgl_Color = "mgl_Color";
+ public static final String mgl_MultiTexCoord = "mgl_MultiTexCoord" ;
+ public static final String mgl_InterleaveArray = "mgl_InterleaveArray" ; // magic name for interleaved arrays w/ sub-arrays
+
+ /**
+ * @param glArrayIndex the fixed function array index
+ * @return default fixed function array name
+ */
+ public static String getPredefinedArrayIndexName(final int glArrayIndex) {
+ return getPredefinedArrayIndexName(glArrayIndex, -1);
+ }
+
+ /**
+ * @param glArrayIndex the fixed function array index
+ * @param multiTexCoordIndex index for multiTexCoordIndex
+ * @return default fixed function array name
+ */
+ public static String getPredefinedArrayIndexName(final int glArrayIndex, final int multiTexCoordIndex) {
+ switch(glArrayIndex) {
+ case GLPointerFunc.GL_VERTEX_ARRAY:
+ return mgl_Vertex;
+ case GLPointerFunc.GL_NORMAL_ARRAY:
+ return mgl_Normal;
+ case GLPointerFunc.GL_COLOR_ARRAY:
+ return mgl_Color;
+ case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
+ if(0<=multiTexCoordIndex) {
+ return mgl_MultiTexCoord+multiTexCoordIndex;
+ } else {
+ return mgl_MultiTexCoord+multiTexCoordIndex;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/glu/GLUnurbs.java b/src/jogl/classes/com/jogamp/opengl/glu/GLUnurbs.java
new file mode 100644
index 000000000..0dbd54674
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/glu/GLUnurbs.java
@@ -0,0 +1,8 @@
+package com.jogamp.opengl.glu;
+
+/**
+ * Wrapper for a GLU NURBS object.
+ */
+
+public interface GLUnurbs {
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/glu/GLUquadric.java b/src/jogl/classes/com/jogamp/opengl/glu/GLUquadric.java
new file mode 100644
index 000000000..45b2d054d
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/glu/GLUquadric.java
@@ -0,0 +1,33 @@
+package com.jogamp.opengl.glu;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.util.ImmModeSink;
+
+/**
+ * Wrapper for a GLU quadric object.
+ */
+
+public interface GLUquadric {
+ // enable/disables the Immediate Mode Sink module.
+ // This defaults to false for GLUgl2,
+ // and is always true for GLUes1.
+ public void enableImmModeSink(boolean val);
+
+ public boolean isImmModeSinkEnabled();
+
+ // set Immediate Mode usage.
+ // This defaults to false at GLU creation time.
+ // If enabled rendering will happen immediately,
+ // otherwise rendering will be hold in the ImmModeSink
+ // object, to be rendered deferred.
+ public void setImmMode(boolean val);
+
+ public boolean getImmMode();
+
+ // creates a new ImmModeSink (VBO Buffers) and
+ // returns the old vbo buffer with it's rendering result
+ public ImmModeSink replaceImmModeSink();
+
+ // gl may be null, then the GL client states are not disabled
+ public void resetImmModeSink(GL gl);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellator.java b/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellator.java
new file mode 100644
index 000000000..ce9fda8e7
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellator.java
@@ -0,0 +1,66 @@
+/*
+* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc.
+* All rights reserved.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 2.0 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** NOTE: The Original Code (as defined below) has been licensed to Sun
+** Microsystems, Inc. ("Sun") under the SGI Free Software License B
+** (Version 1.1), shown above ("SGI License"). Pursuant to Section
+** 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+** you under an alternative license ("Alternative License"). This
+** Alternative License includes all of the provisions of the SGI License
+** except that Section 2.2 and 11 are omitted. Any differences between
+** the Alternative License and the SGI License are offered solely by Sun
+** and not by SGI.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** Author: Eric Veach, July 1994
+** Java Port: Pepijn Van Eeckhoudt, July 2003
+** Java Port: Nathan Parker Burg, August 2003
+*/
+package com.jogamp.opengl.glu;
+
+/**
+ * The <b>GLUtessellator</b> object is used to hold the data, such as the
+ * vertices, edges and callback objects, to describe and tessellate complex
+ * polygons. A <b>GLUtessellator</b> object is used with the
+ * {@link GLU GLU} tessellator methods and
+ * {@link GLUtessellatorCallback GLU callbacks}.
+ *
+ * @author Eric Veach, July 1994
+ * @author Java Port: Pepijn Van Eechhoudt, July 2003
+ * @author Java Port: Nathan Parker Burg, August 2003
+ */
+public interface GLUtessellator {}
diff --git a/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallback.java b/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallback.java
new file mode 100644
index 000000000..c616bca38
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallback.java
@@ -0,0 +1,356 @@
+/*
+* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc.
+* All rights reserved.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 2.0 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** NOTE: The Original Code (as defined below) has been licensed to Sun
+** Microsystems, Inc. ("Sun") under the SGI Free Software License B
+** (Version 1.1), shown above ("SGI License"). Pursuant to Section
+** 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+** you under an alternative license ("Alternative License"). This
+** Alternative License includes all of the provisions of the SGI License
+** except that Section 2.2 and 11 are omitted. Any differences between
+** the Alternative License and the SGI License are offered solely by Sun
+** and not by SGI.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** Author: Eric Veach, July 1994
+** Java Port: Pepijn Van Eeckhoudt, July 2003
+** Java Port: Nathan Parker Burg, August 2003
+*/
+package com.jogamp.opengl.glu;
+
+/**
+ * <b>GLUtessellatorCallback</b> interface provides methods that the user will
+ * override to define the callbacks for a tessellation object.
+ *
+ * @author Eric Veach, July 1994
+ * @author Java Port: Pepijn Van Eeckhoudt, July 2003
+ * @author Java Port: Nathan Parker Burg, August 2003
+ */
+public interface GLUtessellatorCallback {
+ /**
+ * The <b>begin</b> callback method is invoked like
+ * {@link com.jogamp.opengl.GL#glBegin glBegin} to indicate the start of a
+ * (triangle) primitive. The method takes a single argument of type int. If
+ * the <b>GLU_TESS_BOUNDARY_ONLY</b> property is set to <b>GL_FALSE</b>, then
+ * the argument is set to either <b>GL_TRIANGLE_FAN</b>,
+ * <b>GL_TRIANGLE_STRIP</b>, or <b>GL_TRIANGLES</b>. If the
+ * <b>GLU_TESS_BOUNDARY_ONLY</b> property is set to <b>GL_TRUE</b>, then the
+ * argument will be set to <b>GL_LINE_LOOP</b>.
+ *
+ * @param type
+ * Specifics the type of begin/end pair being defined. The following
+ * values are valid: <b>GL_TRIANGLE_FAN</b>, <b>GL_TRIANGLE_STRIP</b>,
+ * <b>GL_TRIANGLES</b> or <b>GL_LINE_LOOP</b>.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #end end
+ * @see #begin begin
+ */
+ public void begin(int type);
+
+ /**
+ * The same as the {@link #begin begin} callback method except that
+ * it takes an additional reference argument. This reference is
+ * identical to the opaque reference provided when {@link
+ * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called.
+ *
+ * @param type
+ * Specifics the type of begin/end pair being defined. The following
+ * values are valid: <b>GL_TRIANGLE_FAN</b>, <b>GL_TRIANGLE_STRIP</b>,
+ * <b>GL_TRIANGLES</b> or <b>GL_LINE_LOOP</b>.
+ * @param polygonData
+ * Specifics a reference to user-defined data.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #endData endData
+ * @see #begin begin
+ */
+ public void beginData(int type, Object polygonData);
+
+
+ /**
+ * The <b>edgeFlag</b> callback method is similar to
+ * {@link com.jogamp.opengl.GL#glEdgeFlag glEdgeFlag}. The method takes
+ * a single boolean boundaryEdge that indicates which edges lie on the
+ * polygon boundary. If the boundaryEdge is <b>GL_TRUE</b>, then each vertex
+ * that follows begins an edge that lies on the polygon boundary, that is,
+ * an edge that separates an interior region from an exterior one. If the
+ * boundaryEdge is <b>GL_FALSE</b>, then each vertex that follows begins an
+ * edge that lies in the polygon interior. The edge flag callback (if
+ * defined) is invoked before the first vertex callback.<P>
+ *
+ * Since triangle fans and triangle strips do not support edge flags, the
+ * begin callback is not called with <b>GL_TRIANGLE_FAN</b> or
+ * <b>GL_TRIANGLE_STRIP</b> if a non-null edge flag callback is provided.
+ * (If the callback is initialized to null, there is no impact on
+ * performance). Instead, the fans and strips are converted to independent
+ * triangles.
+ *
+ * @param boundaryEdge
+ * Specifics which edges lie on the polygon boundary.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #edgeFlagData edgeFlagData
+ */
+ public void edgeFlag(boolean boundaryEdge);
+
+
+ /**
+ * The same as the {@link #edgeFlag edgeFlage} callback method
+ * except that it takes an additional reference argument. This
+ * reference is identical to the opaque reference provided when
+ * {@link GLU#gluTessBeginPolygon gluTessBeginPolygon} was called.
+ *
+ * @param boundaryEdge
+ * Specifics which edges lie on the polygon boundary.
+ * @param polygonData
+ * Specifics a reference to user-defined data.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #edgeFlag edgeFlag
+ */
+ public void edgeFlagData(boolean boundaryEdge, Object polygonData);
+
+
+ /**
+ * The <b>vertex</b> callback method is invoked between the {@link
+ * #begin begin} and {@link #end end} callback methods. It is
+ * similar to {@link com.jogamp.opengl.GL#glVertex3f glVertex3f},
+ * and it defines the vertices of the triangles created by the
+ * tessellation process. The method takes a reference as its only
+ * argument. This reference is identical to the opaque reference
+ * provided by the user when the vertex was described (see {@link
+ * GLU#gluTessVertex gluTessVertex}).
+ *
+ * @param vertexData
+ * Specifics a reference to the vertices of the triangles created
+ * by the tessellation process.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #vertexData vertexData
+ */
+ public void vertex(Object vertexData);
+
+
+ /**
+ * The same as the {@link #vertex vertex} callback method except
+ * that it takes an additional reference argument. This reference is
+ * identical to the opaque reference provided when {@link
+ * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called.
+ *
+ * @param vertexData
+ * Specifics a reference to the vertices of the triangles created
+ * by the tessellation process.
+ * @param polygonData
+ * Specifics a reference to user-defined data.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #vertex vertex
+ */
+ public void vertexData(Object vertexData, Object polygonData);
+
+
+ /**
+ * The end callback serves the same purpose as
+ * {@link com.jogamp.opengl.GL#glEnd glEnd}. It indicates the end of a
+ * primitive and it takes no arguments.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #begin begin
+ * @see #endData endData
+ */
+ public void end();
+
+
+ /**
+ * The same as the {@link #end end} callback method except that it
+ * takes an additional reference argument. This reference is
+ * identical to the opaque reference provided when {@link
+ * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called.
+ *
+ * @param polygonData
+ * Specifics a reference to user-defined data.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #beginData beginData
+ * @see #end end
+ */
+ public void endData(Object polygonData);
+
+
+ /**
+ * The <b>combine</b> callback method is called to create a new vertex when
+ * the tessellation detects an intersection, or wishes to merge features. The
+ * method takes four arguments: an array of three elements each of type
+ * double, an array of four references, an array of four elements each of
+ * type float, and a reference to a reference.<P>
+ *
+ * The vertex is defined as a linear combination of up to four existing
+ * vertices, stored in <i>data</i>. The coefficients of the linear combination
+ * are given by <i>weight</i>; these weights always add up to 1. All vertex
+ * pointers are valid even when some of the weights are 0. <i>coords</i> gives
+ * the location of the new vertex.<P>
+ *
+ * The user must allocate another vertex, interpolate parameters using
+ * <i>data</i> and <i>weight</i>, and return the new vertex pointer in
+ * <i>outData</i>. This handle is supplied during rendering callbacks. The
+ * user is responsible for freeing the memory some time after
+ * {@link GLU#gluTessEndPolygon gluTessEndPolygon} is
+ * called.<P>
+ *
+ * For example, if the polygon lies in an arbitrary plane in 3-space, and a
+ * color is associated with each vertex, the <b>GLU_TESS_COMBINE</b>
+ * callback might look like this:
+ * </UL>
+ * <PRE>
+ * void myCombine(double[] coords, Object[] data,
+ * float[] weight, Object[] outData)
+ * {
+ * MyVertex newVertex = new MyVertex();
+ *
+ * newVertex.x = coords[0];
+ * newVertex.y = coords[1];
+ * newVertex.z = coords[2];
+ * newVertex.r = weight[0]*data[0].r +
+ * weight[1]*data[1].r +
+ * weight[2]*data[2].r +
+ * weight[3]*data[3].r;
+ * newVertex.g = weight[0]*data[0].g +
+ * weight[1]*data[1].g +
+ * weight[2]*data[2].g +
+ * weight[3]*data[3].g;
+ * newVertex.b = weight[0]*data[0].b +
+ * weight[1]*data[1].b +
+ * weight[2]*data[2].b +
+ * weight[3]*data[3].b;
+ * newVertex.a = weight[0]*data[0].a +
+ * weight[1]*data[1].a +
+ * weight[2]*data[2].a +
+ * weight[3]*data[3].a;
+ * outData = newVertex;
+ * }</PRE>
+ *
+ * @param coords
+ * Specifics the location of the new vertex.
+ * @param data
+ * Specifics the vertices used to create the new vertex.
+ * @param weight
+ * Specifics the weights used to create the new vertex.
+ * @param outData
+ * Reference user the put the coodinates of the new vertex.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #combineData combineData
+ */
+ public void combine(double[] coords, Object[] data,
+ float[] weight, Object[] outData);
+
+
+ /**
+ * The same as the {@link #combine combine} callback method except
+ * that it takes an additional reference argument. This reference is
+ * identical to the opaque reference provided when {@link
+ * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called.
+ *
+ * @param coords
+ * Specifics the location of the new vertex.
+ * @param data
+ * Specifics the vertices used to create the new vertex.
+ * @param weight
+ * Specifics the weights used to create the new vertex.
+ * @param outData
+ * Reference user the put the coodinates of the new vertex.
+ * @param polygonData
+ * Specifics a reference to user-defined data.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #combine combine
+ */
+ public void combineData(double[] coords, Object[] data,
+ float[] weight, Object[] outData,
+ Object polygonData);
+
+
+ /**
+ * The <b>error</b> callback method is called when an error is encountered.
+ * The one argument is of type int; it indicates the specific error that
+ * occurred and will be set to one of <b>GLU_TESS_MISSING_BEGIN_POLYGON</b>,
+ * <b>GLU_TESS_MISSING_END_POLYGON</b>, <b>GLU_TESS_MISSING_BEGIN_CONTOUR</b>,
+ * <b>GLU_TESS_MISSING_END_CONTOUR</b>, <b>GLU_TESS_COORD_TOO_LARGE</b>,
+ * <b>GLU_TESS_NEED_COMBINE_CALLBACK</b> or <b>GLU_OUT_OF_MEMORY</b>.
+ * Character strings describing these errors can be retrieved with the
+ * {@link GLU#gluErrorString gluErrorString} call.<P>
+ *
+ * The GLU library will recover from the first four errors by inserting the
+ * missing call(s). <b>GLU_TESS_COORD_TOO_LARGE</b> indicates that some
+ * vertex coordinate exceeded the predefined constant
+ * <b>GLU_TESS_MAX_COORD</b> in absolute value, and that the value has been
+ * clamped. (Coordinate values must be small enough so that two can be
+ * multiplied together without overflow.)
+ * <b>GLU_TESS_NEED_COMBINE_CALLBACK</b> indicates that the tessellation
+ * detected an intersection between two edges in the input data, and the
+ * <b>GLU_TESS_COMBINE</b> or <b>GLU_TESS_COMBINE_DATA</b> callback was not
+ * provided. No output is generated. <b>GLU_OUT_OF_MEMORY</b> indicates that
+ * there is not enough memory so no output is generated.
+ *
+ * @param errnum
+ * Specifics the error number code.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #errorData errorData
+ */
+ public void error(int errnum);
+
+
+ /**
+ * The same as the {@link #error error} callback method except that
+ * it takes an additional reference argument. This reference is
+ * identical to the opaque reference provided when {@link
+ * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called.
+ *
+ * @param errnum
+ * Specifics the error number code.
+ * @param polygonData
+ * Specifics a reference to user-defined data.
+ *
+ * @see GLU#gluTessCallback gluTessCallback
+ * @see #error error
+ */
+ public void errorData(int errnum, Object polygonData);
+
+ //void mesh(jogamp.opengl.tessellator.GLUmesh mesh);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallbackAdapter.java b/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallbackAdapter.java
new file mode 100644
index 000000000..b9503f12e
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/glu/GLUtessellatorCallbackAdapter.java
@@ -0,0 +1,96 @@
+/*
+* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc.
+* All rights reserved.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 2.0 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** NOTE: The Original Code (as defined below) has been licensed to Sun
+** Microsystems, Inc. ("Sun") under the SGI Free Software License B
+** (Version 1.1), shown above ("SGI License"). Pursuant to Section
+** 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+** you under an alternative license ("Alternative License"). This
+** Alternative License includes all of the provisions of the SGI License
+** except that Section 2.2 and 11 are omitted. Any differences between
+** the Alternative License and the SGI License are offered solely by Sun
+** and not by SGI.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** Author: Eric Veach, July 1994
+** Java Port: Pepijn Van Eeckhoudt, July 2003
+** Java Port: Nathan Parker Burg, August 2003
+*/
+package com.jogamp.opengl.glu;
+
+/**
+ * The <b>GLUtessellatorCallbackAdapter</b> provides a default implementation of
+ * {@link GLUtessellatorCallback GLUtessellatorCallback}
+ * with empty callback methods. This class can be extended to provide user
+ * defined callback methods.
+ *
+ * @author Eric Veach, July 1994
+ * @author Java Port: Pepijn Van Eechhoudt, July 2003
+ * @author Java Port: Nathan Parker Burg, August 2003
+ */
+
+public class GLUtessellatorCallbackAdapter implements GLUtessellatorCallback {
+ @Override
+ public void begin(final int type) {}
+ @Override
+ public void edgeFlag(final boolean boundaryEdge) {}
+ @Override
+ public void vertex(final Object vertexData) {}
+ @Override
+ public void end() {}
+// public void mesh(jogamp.opengl.tessellator.GLUmesh mesh) {}
+ @Override
+ public void error(final int errnum) {}
+ @Override
+ public void combine(final double[] coords, final Object[] data,
+ final float[] weight, final Object[] outData) {}
+ @Override
+ public void beginData(final int type, final Object polygonData) {}
+ @Override
+ public void edgeFlagData(final boolean boundaryEdge,
+ final Object polygonData) {}
+ @Override
+ public void vertexData(final Object vertexData, final Object polygonData) {}
+ @Override
+ public void endData(final Object polygonData) {}
+ @Override
+ public void errorData(final int errnum, final Object polygonData) {}
+ @Override
+ public void combineData(final double[] coords, final Object[] data,
+ final float[] weight, final Object[] outData,
+ final Object polygonData) {}
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
index 1a8924c8f..a04055430 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -29,7 +29,7 @@ package com.jogamp.opengl.math;
import java.nio.FloatBuffer;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GLException;
import jogamp.opengl.Debug;
@@ -491,16 +491,18 @@ public final class FloatUtil {
* @param zNear
* @param zFar
* @return given matrix for chaining
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0,
+ * or if left == right, or bottom == top, or zNear == zFar.
*/
public static float[] makeFrustum(final float[] m, final int m_offset, final boolean initM,
final float left, final float right,
final float bottom, final float top,
- final float zNear, final float zFar) {
- if(zNear<=0.0f||zFar<0.0f) {
+ final float zNear, final float zFar) throws GLException {
+ if( zNear <= 0.0f || zFar < 0.0f ) {
throw new GLException("GL_INVALID_VALUE: zNear and zFar must be positive, and zNear>0");
}
- if(left==right || top==bottom) {
- throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal");
+ if( left == right || top == bottom || zNear == zFar ) {
+ throw new GLException("GL_INVALID_VALUE: top,bottom and left,right and zNear,zFar must not be equal");
}
if( initM ) {
// m[m_offset+0+4*0] = 1f;
@@ -563,9 +565,10 @@ public final class FloatUtil {
* @param zNear
* @param zFar
* @return given matrix for chaining
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0, or if zNear == zFar.
*/
public static float[] makePerspective(final float[] m, final int m_off, final boolean initM,
- final float fovy_rad, final float aspect, final float zNear, final float zFar) {
+ final float fovy_rad, final float aspect, final float zNear, final float zFar) throws GLException {
final float top = tan(fovy_rad/2f) * zNear; // use tangent of half-fov !
final float bottom = -1.0f * top;
final float left = aspect * bottom;
@@ -588,9 +591,10 @@ public final class FloatUtil {
* @param zNear
* @param zFar
* @return given matrix for chaining
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0, or if zNear == zFar.
*/
public static float[] makePerspective(final float[] m, final int m_offset, final boolean initM,
- final FovHVHalves fovhv, final float zNear, final float zFar) {
+ final FovHVHalves fovhv, final float zNear, final float zFar) throws GLException {
final FovHVHalves fovhvTan = fovhv.toTangents(); // use tangent of half-fov !
final float top = fovhvTan.top * zNear;
final float bottom = -1.0f * fovhvTan.bottom * zNear;
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java b/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java
index 830f1a882..421bb909f 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java
@@ -28,7 +28,8 @@
package com.jogamp.opengl.math;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.opengl.util.PMVMatrix;
@@ -139,11 +140,28 @@ public class Matrix4 {
multMatrix( FloatUtil.makeOrtho(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar) );
}
- public final void makeFrustum(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
+ /**
+ * @param left
+ * @param right
+ * @param bottom
+ * @param top
+ * @param zNear
+ * @param zFar
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0,
+ * or if left == right, or bottom == top, or zNear == zFar.
+ */
+ public final void makeFrustum(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) throws GLException {
multMatrix( FloatUtil.makeFrustum(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar) );
}
- public final void makePerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) {
+ /**
+ * @param fovy_rad
+ * @param aspect
+ * @param zNear
+ * @param zFar
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0, or if zNear == zFar.
+ */
+ public final void makePerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) throws GLException {
multMatrix( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_rad, aspect, zNear, zFar) );
}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 28f572d7d..58b5bbcb9 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -29,31 +29,31 @@ package com.jogamp.opengl.swt;
import java.util.List;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.AbstractGraphicsScreen;
-import javax.media.nativewindow.GraphicsConfigurationFactory;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.UpstreamSurfaceHook;
-import javax.media.nativewindow.VisualIDHolder;
-import javax.media.nativewindow.VisualIDHolder.VIDType;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLAnimatorControl;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLCapabilitiesChooser;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
-import javax.media.opengl.GLRunnable;
-import javax.media.opengl.GLSharedContextSetter;
-import javax.media.opengl.Threading;
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.GraphicsConfigurationFactory;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.ProxySurface;
+import com.jogamp.nativewindow.UpstreamSurfaceHook;
+import com.jogamp.nativewindow.VisualIDHolder;
+import com.jogamp.nativewindow.VisualIDHolder.VIDType;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLCapabilitiesChooser;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.GLRunnable;
+import com.jogamp.opengl.GLSharedContextSetter;
+import com.jogamp.opengl.Threading;
import jogamp.nativewindow.x11.X11Util;
import jogamp.opengl.Debug;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
index 62df3faca..76d64963f 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
@@ -45,7 +45,7 @@ import java.util.Map;
import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
-import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
index b38a42ee3..066709316 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
@@ -40,8 +40,8 @@
package com.jogamp.opengl.util;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLException;
/** <P> An Animator can be attached to one or more {@link
GLAutoDrawable}s to drive their display() methods in a loop. </P>
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
index 5f2db20bd..aafdf63f8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -34,10 +34,12 @@ import jogamp.opengl.FPSCounterImpl;
import java.io.PrintStream;
import java.util.ArrayList;
-import javax.media.opengl.GLAnimatorControl;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
+
+import com.jogamp.common.ExceptionUtils;
/**
* Base implementation of GLAnimatorControl<br>
@@ -625,7 +627,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
" - " + getThreadName());
System.err.println(" - "+toString());
if(nok) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
return res;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java b/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java
index 86443087e..222833c7d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java
@@ -27,8 +27,8 @@
*/
package com.jogamp.opengl.util;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLEventListener;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLEventListener;
/**
* Extended {@link GLEventListener} interface
diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
index 6b1485a6a..6cded29d9 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
@@ -35,7 +35,7 @@ package com.jogamp.opengl.util;
import java.util.ArrayList;
-import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
index 54d40f285..320873ede 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
@@ -42,8 +42,10 @@ package com.jogamp.opengl.util;
import java.util.Timer;
import java.util.TimerTask;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLException;
+
+import com.jogamp.common.ExceptionUtils;
/**
* An Animator subclass which attempts to achieve a target
@@ -392,7 +394,7 @@ public class FPSAnimator extends AnimatorBase {
if( null != task ) {
if( DEBUG ) {
System.err.println("FPSAnimator.resume() Ops: !pauseIssued, but task != null: "+toString());
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
task.cancel();
task = null;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
index 1a9ec2782..542da4bf1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
@@ -35,9 +35,9 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLPointerFuncUtil;
import jogamp.opengl.util.GLArrayHandler;
import jogamp.opengl.util.GLFixedArrayHandler;
@@ -67,7 +67,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* @param normalized Whether the data shall be normalized
* @param initialElementCount
*
- * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ * @see com.jogamp.opengl.GLContext#getPredefinedArrayIndexName(int)
*/
public static GLArrayDataClient createFixed(final int index, final int comps, final int dataType, final boolean normalized, final int initialElementCount)
throws GLException
@@ -97,7 +97,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* @param stride
* @param buffer the user define data
*
- * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ * @see com.jogamp.opengl.GLContext#getPredefinedArrayIndexName(int)
*/
public static GLArrayDataClient createFixed(final int index, final int comps, final int dataType, final boolean normalized, final int stride,
final Buffer buffer)
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java
index 9a0f1cb37..7524fe1d1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java
@@ -1,7 +1,7 @@
package com.jogamp.opengl.util;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import java.nio.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
index 51c55e326..6b7c31d13 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
@@ -34,12 +34,12 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLArrayData;
-import javax.media.opengl.GLBufferStorage;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLArrayData;
+import com.jogamp.opengl.GLBufferStorage;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLPointerFuncUtil;
import com.jogamp.common.nio.Buffers;
@@ -79,7 +79,7 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
* @param buffer the user define data
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*
- * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ * @see com.jogamp.opengl.GLContext#getPredefinedArrayIndexName(int)
*/
public static GLArrayDataServer createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int stride,
final Buffer buffer, final int vboUsage)
@@ -111,7 +111,7 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
* @param initialElementCount
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*
- * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ * @see com.jogamp.opengl.GLContext#getPredefinedArrayIndexName(int)
*/
public static GLArrayDataServer createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount,
final int vboUsage)
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
index 867bc00ac..3f759c6d8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
@@ -34,13 +34,13 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLArrayData;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
-import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES1;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLArrayData;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.fixedfunc.GLPointerFuncUtil;
import com.jogamp.common.nio.Buffers;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index d4ab4e4f4..6a2a02387 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -41,14 +41,14 @@ package com.jogamp.opengl.util;
import java.nio.Buffer;
import java.nio.ByteBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLES2;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLES2;
+import com.jogamp.opengl.GLException;
import com.jogamp.common.nio.Buffers;
@@ -372,29 +372,29 @@ public class GLBuffers extends Buffers {
int skipImages = 0;
if (pack) {
- alignment = glGetInteger(gl, GL.GL_PACK_ALIGNMENT, tmp);
+ alignment = glGetInteger(gl, GL.GL_PACK_ALIGNMENT, tmp); // es2, es3, gl3
if( gl.isGL2ES3() ) {
- rowLength = glGetInteger(gl, GL2ES3.GL_PACK_ROW_LENGTH, tmp);
- skipRows = glGetInteger(gl, GL2ES3.GL_PACK_SKIP_ROWS, tmp);
- skipPixels = glGetInteger(gl, GL2ES3.GL_PACK_SKIP_PIXELS, tmp);
- if (depth > 1 && gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 ) {
- imageHeight = glGetInteger(gl, GL2GL3.GL_PACK_IMAGE_HEIGHT, tmp);
- skipImages = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_IMAGES, tmp);
+ rowLength = glGetInteger(gl, GL2ES3.GL_PACK_ROW_LENGTH, tmp); // es3, gl3
+ skipRows = glGetInteger(gl, GL2ES3.GL_PACK_SKIP_ROWS, tmp); // es3, gl3
+ skipPixels = glGetInteger(gl, GL2ES3.GL_PACK_SKIP_PIXELS, tmp); // es3, gl3
+ if (depth > 1 && gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_2) >= 0 ) {
+ imageHeight = glGetInteger(gl, GL2GL3.GL_PACK_IMAGE_HEIGHT, tmp); // gl3, GL_VERSION_1_2
+ skipImages = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_IMAGES, tmp); // gl3, GL_VERSION_1_2
}
}
} else {
- alignment = glGetInteger(gl, GL.GL_UNPACK_ALIGNMENT, tmp);
+ alignment = glGetInteger(gl, GL.GL_UNPACK_ALIGNMENT, tmp); // es2, es3, gl3
if( gl.isGL2ES3() ) {
- rowLength = glGetInteger(gl, GL2ES2.GL_UNPACK_ROW_LENGTH, tmp);
- skipRows = glGetInteger(gl, GL2ES2.GL_UNPACK_SKIP_ROWS, tmp);
- skipPixels = glGetInteger(gl, GL2ES2.GL_UNPACK_SKIP_PIXELS, tmp);
+ rowLength = glGetInteger(gl, GL2ES2.GL_UNPACK_ROW_LENGTH, tmp); // es3, gl3
+ skipRows = glGetInteger(gl, GL2ES2.GL_UNPACK_SKIP_ROWS, tmp); // es3, gl3
+ skipPixels = glGetInteger(gl, GL2ES2.GL_UNPACK_SKIP_PIXELS, tmp); // es3, gl3
if( depth > 1 &&
( gl.isGL3ES3() ||
- ( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 )
+ ( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_2) >= 0 )
)
) {
- imageHeight = glGetInteger(gl, GL2ES3.GL_UNPACK_IMAGE_HEIGHT, tmp);
- skipImages = glGetInteger(gl, GL2ES3.GL_UNPACK_SKIP_IMAGES, tmp);
+ imageHeight = glGetInteger(gl, GL2ES3.GL_UNPACK_IMAGE_HEIGHT, tmp);// es3, gl3, GL_VERSION_1_2
+ skipImages = glGetInteger(gl, GL2ES3.GL_UNPACK_SKIP_IMAGES, tmp); // es3, gl3, GL_VERSION_1_2
}
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index 634cfeaed..4cf752b4c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -27,18 +27,18 @@
*/
package com.jogamp.opengl.util;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.opengl.GLAnimatorControl;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLBase;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLRunnable;
-import javax.media.opengl.Threading;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLBase;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLRunnable;
+import com.jogamp.opengl.Threading;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.opengl.GLEventListenerState;
@@ -215,7 +215,7 @@ public class GLDrawableUtil {
* During operation, both {@link GLAutoDrawable auto-drawable's}
* {@link GLAutoDrawable#getUpstreamLock() upstream-locks} and {@link GLAutoDrawable#getNativeSurface() surfaces} are locked,
* hence atomicity of operation is guaranteed,
- * see <a href="../../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.
+ * see <a href="../../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.
* </p>
* <p>
* Because of above mentioned locking, if this method is not performed
@@ -256,7 +256,7 @@ public class GLDrawableUtil {
* During operation, both {@link GLAutoDrawable auto-drawable's}
* {@link GLAutoDrawable#getUpstreamLock() upstream-locks} and {@link GLAutoDrawable#getNativeSurface() surfaces} are locked,
* hence atomicity of operation is guaranteed,
- * see <a href="../../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.
+ * see <a href="../../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.
* </p>
* <p>
* Because of above mentioned locking, if this method is not performed
@@ -333,7 +333,7 @@ public class GLDrawableUtil {
* in which case {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling reading pixels, the default.
* </p>
* <p>
- * However, <i>multisampling</i> offscreen {@link javax.media.opengl.GLFBODrawable}s
+ * However, <i>multisampling</i> offscreen {@link com.jogamp.opengl.GLFBODrawable}s
* utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
* the multisamples into the readable sampling sink.
* In this case, we require {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> reading pixels.
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
index a09321d75..4575de959 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -30,14 +30,14 @@ package com.jogamp.opengl.util;
import java.nio.Buffer;
import java.nio.ByteBuffer;
-import javax.media.nativewindow.util.PixelFormat;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
+import com.jogamp.nativewindow.util.PixelFormat;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.texture.TextureData;
@@ -58,41 +58,100 @@ public class GLPixelBuffer {
/** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */
boolean getAllowRowStride();
- /** Called first to determine {@link GLPixelAttributes}. */
- GLPixelAttributes getAttributes(GL gl, int componentCount);
+ /**
+ * Returns RGB[A] {@link GLPixelAttributes} matching {@link GL}, {@code componentCount} and {@code pack}.
+ *
+ * @param gl the corresponding current {@link GL} context object
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ */
+ GLPixelAttributes getAttributes(GL gl, int componentCount, boolean pack);
+
+ /**
+ * Returns the host {@link PixelFormat.Composition} matching {@link GL} and {@code componentCount}
+ * if required by implementation, otherwise {@code null}.
+ *
+ * @param glp the corresponding current {@link GL} context object
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ */
+ PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount);
/**
* Allocates a new {@link GLPixelBuffer} object.
* <p>
- * Being called to gather the initial {@link GLPixelBuffer},
- * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
- * </p>
- * <p>
* The minimum required {@link Buffer#remaining() remaining} byte size equals to <code>minByteSize</code>, if &gt; 0,
* otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)}
* to calculate it.
* </p>
*
- * @param gl the corresponding current GL context object
- * @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param gl the corresponding current {@link GL} context object
+ * @param hostPixComp host {@link PixelFormat pixel format}, i.e. of the source or sink depending on {@code pack},
+ * e.g. fetched via {@link #getHostPixelComp(GLProfile, int)}.
+ * If {@code null}, {@code pixelAttributes} instance maybe used or an exception is thrown,
+ * depending on implementation semantics.
+ * @param pixelAttributes the desired {@link GLPixelAttributes}, e.g. fetched via {@link #getAttributes(GL, int, boolean)}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
* @param width in pixels
* @param height in pixels
* @param depth in pixels
- * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
* @param minByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
+ * @see #getHostPixelComp(GLProfile, int)
+ * @see #getAttributes(GL, int, boolean)
*/
- GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize);
+ GLPixelBuffer allocate(GL gl, PixelFormat.Composition hostPixComp, GLPixelAttributes pixelAttributes,
+ boolean pack, int width, int height, int depth, int minByteSize);
}
/** Single {@link GLPixelBuffer} provider. */
public static interface SingletonGLPixelBufferProvider extends GLPixelBufferProvider {
- /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link GLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */
- GLPixelBuffer getSingleBuffer(GLPixelAttributes pixelAttributes);
/**
- * Initializes the single {@link GLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * {@inheritDoc}
+ * <p>
+ * Being called to gather the initial {@link GLPixelBuffer},
+ * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ */
+ @Override
+ GLPixelBuffer allocate(GL gl, PixelFormat.Composition hostPixComp, GLPixelAttributes pixelAttributes,
+ boolean pack, int width, int height, int depth, int minByteSize);
+
+ /**
+ * Return the last {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated} {@link GLPixelBuffer}
+ * matching the given parameter.
+ * <p>
+ * May return {@code null} if none has been allocated yet.
+ * </p>
+ * <p>
+ * Returned {@link GLPixelBuffer} may be {@link GLPixelBuffer#isValid() invalid}.
+ * </p>
+ * @param hostPixComp host {@link PixelFormat pixel format}, i.e. of the source or sink depending on {@code pack},
+ * e.g. fetched via {@link #getHostPixelComp(GLProfile, int)}.
+ * If {@code null}, {@code pixelAttributes} instance maybe used or an exception is thrown,
+ * depending on implementation semantics.
+ * @param pixelAttributes the desired {@link GLPixelAttributes}, e.g. fetched via {@link #getAttributes(GL, int, boolean)}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ */
+ GLPixelBuffer getSingleBuffer(PixelFormat.Composition hostPixelComp, GLPixelAttributes pixelAttributes, boolean pack);
+ /**
+ * Initializes the single {@link GLPixelBuffer} w/ a given size,
+ * if not yet {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
+ *
+ * @param glp
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ * @param width
+ * @param height
+ * @param depth
* @return the newly initialized single {@link GLPixelBuffer}, or null if already allocated.
*/
- GLPixelBuffer initSingleton(int componentCount, int width, int height, int depth, boolean pack);
+ GLPixelBuffer initSingleton(GLProfile glp, int componentCount, boolean pack, int width, int height, int depth);
+
+ /** Dispose all resources.*/
+ void dispose();
}
public static class DefaultGLPixelBufferProvider implements GLPixelBufferProvider {
@@ -110,36 +169,24 @@ public class GLPixelBuffer {
public boolean getAllowRowStride() { return allowRowStride; }
@Override
- public GLPixelAttributes getAttributes(final GL gl, final int componentCount) {
- final GLContext ctx = gl.getContext();
- final int dFormat, dType;
-
- if( 1 == componentCount ) {
- if( gl.isGL3ES3() ) {
- // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
- dFormat = GL2ES2.GL_RED;
- } else {
- // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
- dFormat = GL.GL_ALPHA;
- }
- dType = GL.GL_UNSIGNED_BYTE;
- } else if( 3 == componentCount ) {
- dFormat = GL.GL_RGB;
- dType = GL.GL_UNSIGNED_BYTE;
- } else if( 4 == componentCount ) {
- final int _dFormat = ctx.getDefaultPixelDataFormat();
- final int dComps = GLBuffers.componentCount(_dFormat);
- if( dComps == componentCount ) {
- dFormat = _dFormat;
- dType = ctx.getDefaultPixelDataType();
- } else {
- dFormat = GL.GL_RGBA;
- dType = GL.GL_UNSIGNED_BYTE;
- }
- } else {
+ public GLPixelAttributes getAttributes(final GL gl, final int componentCount, final boolean pack) {
+ final GLPixelAttributes res = GLPixelAttributes.convert(gl, componentCount, pack);
+ if( null == res ) {
throw new GLException("Unsupported componentCount "+componentCount+", contact maintainer to enhance");
+ } else {
+ return res;
}
- return new GLPixelAttributes(componentCount, dFormat, dType);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns {@code null}!
+ * </p>
+ */
+ @Override
+ public PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount) {
+ return null;
}
/**
@@ -149,13 +196,15 @@ public class GLPixelBuffer {
* </p>
*/
@Override
- public GLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
+ public GLPixelBuffer allocate(final GL gl, final PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes,
+ final boolean pack, final int width, final int height, final int depth, final int minByteSize) {
+ // unused: hostPixComp
if( minByteSize > 0 ) {
- return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride());
+ return new GLPixelBuffer(pixelAttributes, pack, width, height, depth, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride());
} else {
final int[] tmp = { 0 };
- final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, width, height, depth, pack);
- return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(byteSize), getAllowRowStride());
+ final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.pfmt.comp.bytesPerPixel(), width, height, depth, pack);
+ return new GLPixelBuffer(pixelAttributes, pack, width, height, depth, Buffers.newDirectByteBuffer(byteSize), getAllowRowStride());
}
}
}
@@ -163,74 +212,190 @@ public class GLPixelBuffer {
/**
* Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>false</code>,
* utilizing best match for {@link GLPixelAttributes}
- * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ * and {@link GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocating} a {@link ByteBuffer}.
*/
public static final GLPixelBufferProvider defaultProviderNoRowStride = new DefaultGLPixelBufferProvider(false);
/**
* Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>true</code>,
* utilizing best match for {@link GLPixelAttributes}
- * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ * and {@link GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocating} a {@link ByteBuffer}.
*/
public static final GLPixelBufferProvider defaultProviderWithRowStride = new DefaultGLPixelBufferProvider(true);
/** Pixel attributes. */
public static class GLPixelAttributes {
/** Undefined instance of {@link GLPixelAttributes}, having componentCount:=0, format:=0 and type:= 0. */
- public static final GLPixelAttributes UNDEF = new GLPixelAttributes(0, 0, 0, false);
-
- /** Pixel <i>source</i> component count, i.e. number of meaningful components. */
- public final int componentCount;
- /** The OpenGL pixel data format */
- public final int format;
- /** The OpenGL pixel data type */
- public final int type;
- /** The OpenGL pixel size in bytes */
- public final int bytesPerPixel;
+ public static final GLPixelAttributes UNDEF = new GLPixelAttributes(null, PixelFormat.LUMINANCE, 0, 0, true, false);
/**
- * Deriving {@link #componentCount} via GL <code>dataFormat</code>, i.e. {@link GLBuffers#componentCount(int)} if &gt; 0.
- * @param dataFormat GL data format
- * @param dataType GL data type
+ * Returns the matching {@link PixelFormat} for the given GL format and type if exists,
+ * otherwise returns <code>null</code>.
*/
- public GLPixelAttributes(final int dataFormat, final int dataType) {
- this(0 < dataFormat ? GLBuffers.componentCount(dataFormat) : 0, dataFormat, dataType);
+ public static final PixelFormat getPixelFormat(final int glFormat, final int glDataType) {
+ PixelFormat pixFmt = null;
+
+ switch(glFormat) {
+ case GL.GL_ALPHA:
+ case GL.GL_LUMINANCE:
+ case GL2ES2.GL_RED:
+ pixFmt = PixelFormat.LUMINANCE;
+ break;
+ case GL.GL_RGB:
+ switch(glDataType) {
+ case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
+ pixFmt = PixelFormat.RGB565;
+ break;
+ case GL.GL_UNSIGNED_SHORT_5_6_5:
+ pixFmt = PixelFormat.BGR565;
+ break;
+ case GL.GL_UNSIGNED_BYTE:
+ pixFmt = PixelFormat.RGB888;
+ break;
+ }
+ break;
+ case GL.GL_RGBA:
+ switch(glDataType) {
+ case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ pixFmt = PixelFormat.RGBA5551;
+ break;
+ case GL.GL_UNSIGNED_SHORT_5_5_5_1:
+ pixFmt = PixelFormat.ABGR1555;
+ break;
+ case GL.GL_UNSIGNED_BYTE:
+ pixFmt = PixelFormat.RGBA8888;
+ break;
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ pixFmt = PixelFormat.ABGR8888;
+ break;
+ }
+ break;
+ case GL2GL3.GL_BGR:
+ if( GL.GL_UNSIGNED_BYTE == glDataType ) {
+ pixFmt = PixelFormat.BGR888;
+ }
+ break;
+ case GL.GL_BGRA:
+ switch(glDataType) {
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ pixFmt = PixelFormat.ARGB8888;
+ break;
+ case GL.GL_UNSIGNED_BYTE:
+ pixFmt = PixelFormat.BGRA8888;
+ break;
+ }
+ break;
+ }
+ return pixFmt;
}
+
/**
- * Using user specified source {@link #componentCount}.
- * @param componentCount source component count
- * @param dataFormat GL data format
- * @param dataType GL data type
+ * Returns the matching {@link GLPixelAttributes} for the given byte sized RGBA {@code componentCount} and {@link GL} if exists,
+ * otherwise returns {@code null}.
+ *
+ * @param gl the corresponding current {@link GL} context object
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
*/
- public GLPixelAttributes(final int componentCount, final int dataFormat, final int dataType) {
- this(componentCount, dataFormat, dataType, true);
+ public static GLPixelAttributes convert(final GL gl, final int componentCount, final boolean pack) {
+ final int dFormat, dType;
+ final boolean glesReadMode = pack && gl.isGLES();
+
+ if( 1 == componentCount && !glesReadMode ) {
+ if( gl.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
+ dFormat = GL2ES2.GL_RED;
+ } else {
+ // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ dFormat = GL.GL_ALPHA;
+ }
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else if( 3 == componentCount && !glesReadMode ) {
+ dFormat = GL.GL_RGB;
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else if( 4 == componentCount || glesReadMode ) {
+ final GLContext ctx = gl.getContext();
+ final int _dFormat = ctx.getDefaultPixelDataFormat();
+ final int dComps = GLBuffers.componentCount(_dFormat);
+ if( dComps == componentCount || 4 == dComps ) { // accept if desired component count or 4 components
+ dFormat = _dFormat;
+ dType = ctx.getDefaultPixelDataType();
+ } else {
+ dFormat = GL.GL_RGBA;
+ dType = GL.GL_UNSIGNED_BYTE;
+ }
+ } else {
+ return null;
+ }
+ return new GLPixelAttributes(dFormat, dType);
}
/**
- * Returns the matching {@link GLPixelAttributes} for the given {@link PixelFormat} and {@link GLProfile} if exists,
- * otherwise returns <code>null</code>.
+ * Returns the matching {@link GLPixelAttributes} for the given {@link GLProfile}, {@link PixelFormat} and {@code pack} if exists,
+ * otherwise returns {@code null}.
+ * @param glp the corresponding {@link GLProfile}
+ * @param pixFmt the to be matched {@link PixelFormat pixel format}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
*/
- public static final GLPixelAttributes convert(final PixelFormat pixFmt, final GLProfile glp) {
+ public static final GLPixelAttributes convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack) {
+ final int[] df = new int[1];
+ final int[] dt = new int[1];
+ convert(glp, pixFmt, pack, df, dt);
+ if( 0 != df[0] ) {
+ return new GLPixelAttributes(null, pixFmt, df[0], dt[0], true /* not used */, true);
+ }
+ return null;
+ }
+ private static final int convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack,
+ final int[] dfRes, final int[] dtRes) {
+ final boolean glesReadMode = pack && glp.isGLES();
int df = 0; // format
int dt = GL.GL_UNSIGNED_BYTE; // data type
switch(pixFmt) {
case LUMINANCE:
- if( glp.isGL3ES3() ) {
- // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
- df = GL2ES2.GL_RED;
- } else {
- // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
- df = GL.GL_LUMINANCE;
+ if( !glesReadMode ) {
+ if( glp.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
+ df = GL2ES2.GL_RED;
+ } else {
+ // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ df = GL.GL_LUMINANCE;
+ }
}
break;
- case BGR888:
+ case RGB565:
if( glp.isGL2GL3() ) {
- df = GL2GL3.GL_BGR;
+ df = GL.GL_RGB; dt = GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV;
+ }
+ break;
+ case BGR565:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGB; dt = GL.GL_UNSIGNED_SHORT_5_6_5;
+ }
+ break;
+ case RGBA5551:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ }
+ break;
+ case ABGR1555:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGBA; dt = GL.GL_UNSIGNED_SHORT_5_5_5_1;
}
break;
case RGB888:
- df = GL.GL_RGB;
+ if( !glesReadMode ) {
+ df = GL.GL_RGB;
+ }
+ break;
+ case BGR888:
+ if( glp.isGL2GL3() ) {
+ df = GL2GL3.GL_BGR;
+ }
break;
+ case RGBx8888:
case RGBA8888:
df = GL.GL_RGBA;
break;
@@ -239,85 +404,107 @@ public class GLPixelBuffer {
df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
}
break;
- case BGRA8888:
- df = GL.GL_BGRA;
- break;
case ARGB8888:
if( glp.isGL2GL3() ) {
df = GL.GL_BGRA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
}
break;
- default:
+ case BGRx8888:
+ case BGRA8888:
+ if( glp.isGL2GL3() ) { // FIXME: or if( !glesReadMode ) ? BGRA n/a on GLES
+ df = GL.GL_BGRA;
+ }
break;
}
- if( 0 != df ) {
- return new GLPixelAttributes(pixFmt.componentCount, df, dt, true);
- }
- return null;
+ dfRes[0] = df;
+ dtRes[0] = dt;
+ return df;
}
- private GLPixelAttributes(final int componentCount, final int dataFormat, final int dataType, final boolean checkArgs) {
- this.componentCount = componentCount;
- this.format = dataFormat;
- this.type = dataType;
- this.bytesPerPixel = ( 0 < dataFormat && 0 < dataType ) ? GLBuffers.bytesPerPixel(dataFormat, dataType) : 0;
- if( checkArgs ) {
- if( 0 == componentCount || 0 == format || 0 == type ) {
- throw new GLException("Zero components, format and/or type: "+this);
- }
- if( 0 == bytesPerPixel ) {
- throw new GLException("Zero bytesPerPixel: "+this);
- }
+
+ /** The OpenGL pixel data format */
+ public final int format;
+ /** The OpenGL pixel data type */
+ public final int type;
+
+ /** {@link PixelFormat} describing the {@link PixelFormat.Composition component} layout */
+ public final PixelFormat pfmt;
+
+ @Override
+ public final int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = pfmt.hashCode();
+ hash = ((hash << 5) - hash) + format;
+ return ((hash << 5) - hash) + type;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if( obj instanceof GLPixelAttributes ) {
+ final GLPixelAttributes other = (GLPixelAttributes) obj;
+ return format == other.format &&
+ type == other.type &&
+ pfmt.equals(other.pfmt);
+ } else {
+ return false;
}
}
/**
- * Returns the matching {@link PixelFormat} of this {@link GLPixelAttributes} if exists,
- * otherwise returns <code>null</code>.
+ * Create a new {@link GLPixelAttributes} instance based on GL format and type.
+ * @param dataFormat GL data format
+ * @param dataType GL data type
+ * @throws GLException if {@link PixelFormat} could not be determined, see {@link #getPixelFormat(int, int)}.
*/
- public final PixelFormat getPixelFormat() {
- final PixelFormat pixFmt;
- // FIXME: Take 'type' into consideration and complete mapping!
- switch(format) {
- case GL.GL_ALPHA:
- case GL.GL_LUMINANCE:
- case GL2ES2.GL_RED:
- pixFmt = PixelFormat.LUMINANCE;
- break;
- case GL.GL_RGB:
- pixFmt = PixelFormat.RGB888;
- break;
- case GL.GL_RGBA:
- pixFmt = PixelFormat.RGBA8888;
- break;
- case GL2GL3.GL_BGR:
- pixFmt = PixelFormat.BGR888;
- break;
- case GL.GL_BGRA:
- pixFmt = PixelFormat.BGRA8888;
- break;
- default:
- switch( bytesPerPixel ) {
- case 1:
- pixFmt = PixelFormat.LUMINANCE;
- break;
- case 3:
- pixFmt = PixelFormat.RGB888;
- break;
- case 4:
- pixFmt = PixelFormat.RGBA8888;
- break;
- default:
- pixFmt = null;
- break;
- }
- break;
+ public GLPixelAttributes(final int dataFormat, final int dataType) throws GLException {
+ this(null, null, dataFormat, dataType, true /* not used */, true);
+ }
+
+ /**
+ * Create a new {@link GLPixelAttributes} instance based on {@link GLProfile}, {@link PixelFormat} and {@code pack}.
+ * @param glp the corresponding {@link GLProfile}
+ * @param pixFmt the to be matched {@link PixelFormat pixel format}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ * @throws GLException if GL format or type could not be determined, see {@link #convert(GLProfile, PixelFormat, boolean)}.
+ */
+ public GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt, final boolean pack) throws GLException {
+ this(glp, pixFmt, 0, 0, pack, true);
+ }
+
+ private GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt,
+ final int dataFormat, final int dataType, final boolean pack, final boolean checkArgs) throws GLException {
+ if( checkArgs && ( 0 == dataFormat || 0 == dataType ) ) {
+ if( null == pixFmt || null == glp ) {
+ throw new GLException("Zero format and/or type w/o pixFmt or glp: "+this);
+ }
+ final int[] df = new int[1];
+ final int[] dt = new int[1];
+ if( 0 == convert(glp, pixFmt, pack, df, dt) ) {
+ throw new GLException("Could not find format and type for "+pixFmt+" and "+glp+", "+this);
+ }
+ this.format = df[0];
+ this.type = dt[0];
+ this.pfmt = pixFmt;
+ } else {
+ this.format = dataFormat;
+ this.type = dataType;
+ this.pfmt = null != pixFmt ? pixFmt : getPixelFormat(dataFormat, dataType);
+ if( null == this.pfmt ) {
+ throw new GLException("Could not find PixelFormat for format and/or type: "+this);
+ }
+ }
+ if( checkArgs ) {
+ final int bytesPerPixel = GLBuffers.bytesPerPixel(this.format, this.type);
+ if( 0 == bytesPerPixel ) {
+ throw new GLException("Zero bytesPerPixel: "+this);
+ }
}
- return pixFmt;
}
@Override
public String toString() {
- return "PixelAttributes[comp "+componentCount+", fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", bytesPerPixel "+bytesPerPixel+"]";
+ return "PixelAttributes[fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", "+pfmt+"]";
}
}
@@ -339,14 +526,18 @@ public class GLPixelBuffer {
public final int height;
/** Depth in pixels. */
public final int depth;
- /** Data packing direction. If <code>true</code> for read mode GPU -> CPU, <code>false</code> for write mode CPU -> GPU. */
+ /**
+ * Data packing direction.
+ * <p>{@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.</p>
+ * <p>{@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.</p>
+ */
public final boolean pack;
/** Byte size of the buffer. Actually the number of {@link Buffer#remaining()} bytes when passed in ctor. */
public final int byteSize;
/**
* Buffer holding the pixel data. If {@link #rewind()}, it holds <code>byteSize</code> {@link Buffer#remaining()} bytes.
* <p>
- * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)}.
+ * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int)}.
* However, other {@link GLPixelBufferProvider} may utilize different {@link Buffer} types.
* </p>
*/
@@ -375,14 +566,16 @@ public class GLPixelBuffer {
/**
* @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
* @param width in pixels
* @param height in pixels
* @param depth in pixels
- * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
* @param buffer the backing array
* @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
+ * @param hostPixelComp the host {@link PixelFormat.Composition}
*/
- public GLPixelBuffer(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final Buffer buffer, final boolean allowRowStride) {
+ public GLPixelBuffer(final GLPixelAttributes pixelAttributes, final boolean pack, final int width, final int height, final int depth, final Buffer buffer, final boolean allowRowStride) {
this.pixelAttributes = pixelAttributes;
this.width = width;
this.height = height;
@@ -462,7 +655,7 @@ public class GLPixelBuffer {
* @param newWidth new width in pixels
* @param newHeight new height in pixels
* @param newByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
- * @see GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)
+ * @see GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int)
*/
public boolean requiresNewBuffer(final GL gl, final int newWidth, final int newHeight, int newByteSize) {
if( !isValid() ) {
@@ -470,7 +663,7 @@ public class GLPixelBuffer {
}
if( 0 >= newByteSize ) {
final int[] tmp = { 0 };
- newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, newWidth, newHeight, 1, true);
+ newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.pfmt.comp.bytesPerPixel(), newWidth, newHeight, 1, true);
}
if( allowRowStride ) {
return byteSize < newByteSize;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
index 290033e99..3f52a0d3c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
@@ -28,13 +28,13 @@
package com.jogamp.opengl.util;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
/**
* Utility to safely set and restore the PACK and UNPACK pixel storage mode,
@@ -180,7 +180,7 @@ public class GLPixelStorageModes {
if( gl.isGL2GL3() ) {
gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, GL.GL_FALSE); // gl3
gl.glPixelStorei(GL2GL3.GL_PACK_LSB_FIRST, GL.GL_FALSE); // gl3
- if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 ) {
+ if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_2) >= 0 ) {
gl.glPixelStorei(GL2GL3.GL_PACK_IMAGE_HEIGHT, 0); // gl3, GL_VERSION_1_2
gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_IMAGES, 0); // gl3, GL_VERSION_1_2
}
@@ -251,7 +251,7 @@ public class GLPixelStorageModes {
gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, 0); // es3, gl3
gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0); // es3, gl3
if( gl.isGL2GL3() ) {
- if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 ) {
+ if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_2) >= 0 ) {
gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0); // es3, gl3, GL_VERSION_1_2
gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0); // es3, gl3, GL_VERSION_1_2
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index e84a1d874..c2067a9f2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -31,11 +31,12 @@ package com.jogamp.opengl.util;
import java.io.File;
import java.io.IOException;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLException;
+import com.jogamp.nativewindow.util.PixelFormat;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLException;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.texture.Texture;
@@ -51,10 +52,10 @@ import com.jogamp.opengl.util.texture.TextureIO;
*/
public class GLReadBufferUtil {
protected final GLPixelBufferProvider pixelBufferProvider;
- protected final int componentCount, alignment;
protected final Texture readTexture;
protected final GLPixelStorageModes psm;
+ protected boolean hasAlpha;
protected GLPixelBuffer readPixelBuffer = null;
protected TextureData readTextureData = null;
@@ -68,10 +69,9 @@ public class GLReadBufferUtil {
public GLReadBufferUtil(final GLPixelBufferProvider pixelBufferProvider, final boolean alpha, final boolean write2Texture) {
this.pixelBufferProvider = pixelBufferProvider;
- this.componentCount = alpha ? 4 : 3 ;
- this.alignment = alpha ? 4 : 1 ;
this.readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
this.psm = new GLPixelStorageModes();
+ this.hasAlpha = alpha; // preset
}
/** Returns the {@link GLPixelBufferProvider} used by this instance. */
@@ -81,7 +81,7 @@ public class GLReadBufferUtil {
return null!=readTextureData && null!=readPixelBuffer && readPixelBuffer.isValid();
}
- public boolean hasAlpha() { return 4 == componentCount ? true : false ; }
+ public boolean hasAlpha() { return hasAlpha; }
public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
@@ -173,13 +173,13 @@ public class GLReadBufferUtil {
if(GL.GL_NO_ERROR != glerr0) {
System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
}
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
- final int internalFormat;
- if(gl.isGL2GL3() && 3 == componentCount) {
- internalFormat = GL.GL_RGB;
- } else {
- internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
- }
+ final int reqCompCount = hasAlpha ? 4 : 3;
+ final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), reqCompCount);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, reqCompCount, true);
+ final int componentCount = pixelAttribs.pfmt.comp.componenCount();
+ hasAlpha = 0 <= pixelAttribs.pfmt.comp.find(PixelFormat.CType.A);
+ final int alignment = 4 == componentCount ? 4 : 1 ;
+ final int internalFormat = 4 == componentCount ? GL.GL_RGBA : GL.GL_RGB;
final boolean flipVertically;
if( drawable.isGLOriented() ) {
@@ -189,11 +189,11 @@ public class GLReadBufferUtil {
}
final int tmp[] = new int[1];
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, width, height, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), width, height, 1, true);
boolean newData = false;
if( null == readPixelBuffer || readPixelBuffer.requiresNewBuffer(gl, width, height, readPixelSize) ) {
- readPixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, width, height, 1, true, readPixelSize);
+ readPixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, width, height, 1, readPixelSize);
Buffers.rangeCheckBytes(readPixelBuffer.buffer, readPixelSize);
try {
readTextureData = new TextureData(
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java
index bab85e531..151c8255d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java
@@ -39,9 +39,9 @@
package com.jogamp.opengl.util;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -61,7 +61,7 @@ public class Gamma {
private Gamma() {}
/**
- * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(javax.media.nativewindow.NativeSurface, float, float, float)}.
+ * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(com.jogamp.nativewindow.NativeSurface, float, float, float)}.
* <p>
* Use {@link #setDisplayGamma(GLAutoDrawable, float, float, float)} in case of using an {#link GLAutoDrawable}.
* </p>
@@ -71,7 +71,7 @@ public class Gamma {
}
/**
- * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(javax.media.nativewindow.NativeSurface, float, float, float)}
+ * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(com.jogamp.nativewindow.NativeSurface, float, float, float)}
* locking {@link GLAutoDrawable#getUpstreamLock()} to ensure proper atomic operation.
*/
public static boolean setDisplayGamma(final GLAutoDrawable drawable, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException {
@@ -85,7 +85,7 @@ public class Gamma {
}
/**
- * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(javax.media.nativewindow.NativeSurface)}.
+ * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(com.jogamp.nativewindow.NativeSurface)}.
* <p>
* Use {@link #resetDisplayGamma(GLAutoDrawable)} in case of using an {#link GLAutoDrawable}.
* </p>
@@ -95,7 +95,7 @@ public class Gamma {
}
/**
- * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(javax.media.nativewindow.NativeSurface)}
+ * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(com.jogamp.nativewindow.NativeSurface)}
* locking {@link GLAutoDrawable#getUpstreamLock()} to ensure proper atomic operation.
*/
public static void resetDisplayGamma(final GLAutoDrawable drawable) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
index 150e92c2e..b627f244c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
@@ -8,14 +8,15 @@ import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Iterator;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLPointerFunc;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES1;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLPointerFunc;
import jogamp.opengl.Debug;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.PropertyAccess;
@@ -450,7 +451,7 @@ public class ImmModeSink {
this.nElems=0;
this.tElems=0;
- this.pageSize = Platform.getMachineDescription().pageSizeInBytes();
+ this.pageSize = Platform.getMachineDataInfo().pageSizeInBytes();
reallocateBuffer(initialElementCount);
rewind();
@@ -1376,7 +1377,7 @@ public class ImmModeSink {
if(DEBUG_BUFFER) {
System.err.println("ImmModeSink.realloc.X: "+this.toString());
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
return true;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index 11acb0c58..57f9301b8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -37,9 +37,9 @@ package com.jogamp.opengl.util;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import jogamp.common.os.PlatformPropsImpl;
@@ -660,8 +660,14 @@ public final class PMVMatrix implements GLMatrixFunc {
glMultMatrixf( FloatUtil.makeOrtho(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar), 0 );
}
+ /**
+ * {@inheritDoc}
+ *
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0,
+ * or if left == right, or bottom == top, or zNear == zFar.
+ */
@Override
- public final void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
+ public final void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) throws GLException {
glMultMatrixf( FloatUtil.makeFrustum(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar), 0 );
}
@@ -676,8 +682,9 @@ public final class PMVMatrix implements GLMatrixFunc {
* @param aspect aspect ratio width / height
* @param zNear
* @param zFar
+ * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0, or if zNear == zFar.
*/
- public final void gluPerspective(final float fovy_deg, final float aspect, final float zNear, final float zFar) {
+ public final void gluPerspective(final float fovy_deg, final float aspect, final float zNear, final float zFar) throws GLException {
glMultMatrixf( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0 );
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
index 64da547c2..f28774afa 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
@@ -34,11 +34,11 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.PixelFormat;
-import javax.media.nativewindow.util.PixelRectangle;
-import javax.media.nativewindow.util.PixelFormatUtil;
+import com.jogamp.nativewindow.util.Dimension;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.nativewindow.util.PixelFormat;
+import com.jogamp.nativewindow.util.PixelRectangle;
+import com.jogamp.nativewindow.util.PixelFormatUtil;
import jogamp.opengl.Debug;
import jogamp.opengl.util.pngj.ImageInfo;
@@ -137,7 +137,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
} else {
destFmt = ddestFmt; // user choice
}
- final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.bytesPerPixel() * width);
+ final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.comp.bytesPerPixel() * width);
final ByteBuffer destPixels = destDirectBuffer ? Buffers.newDirectByteBuffer(destStrideInBytes * height) :
ByteBuffer.allocate(destStrideInBytes * height);
{
@@ -153,7 +153,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
System.err.println("PNGPixelRect: indexed "+indexed+", alpha "+hasAlpha+", grayscale "+imgInfo.greyscale+", channels "+channels+"/"+imgInfo.channels+
", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+
", grayAlpha "+isGrayAlpha+", pixels "+width+"x"+height+", dpi "+dpiX+"x"+dpiY+", format "+srcFmt);
- System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", bytesPerPixel "+destFmt.bytesPerPixel()+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented);
+ System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented);
System.err.println("PNGPixelRect: destStrideInBytes "+destStrideInBytes+" (destMinStrideInBytes "+destMinStrideInBytes+")");
}
@@ -227,7 +227,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
(byte)scanline[lineOff+1], // G
(byte)scanline[lineOff+2], // B
srcHasAlpha ? (byte)scanline[lineOff+3] : (byte)0xff); // A
- final int dbpp = dest_fmt.bytesPerPixel();
+ final int dbpp = dest_fmt.comp.bytesPerPixel();
d.put(dOff++, (byte) ( p )); // 1
if( 1 < dbpp ) {
d.put(dOff++, (byte) ( p >>> 8 )); // 2
@@ -261,7 +261,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
if(hasAlpha) {
line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
}
- return srcOff + pixelformat.bytesPerPixel();
+ return srcOff + pixelformat.comp.bytesPerPixel();
}
private static void setPixelRGBA8(final PixelFormat pixelformat, final ImageLine line, final int lineOff, final int srcPix, final int bytesPerPixel, final boolean hasAlpha) {
@@ -304,7 +304,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
public void write(final OutputStream outstream, final boolean closeOutstream) throws IOException {
final int width = size.getWidth();
final int height = size.getHeight();
- final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final int bytesPerPixel = pixelformat.comp.bytesPerPixel();
final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
(4 == bytesPerPixel) ? true : false /* alpha */,
(1 == bytesPerPixel) ? true : false /* grayscale */,
@@ -349,7 +349,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
final OutputStream outstream, final boolean closeOutstream) throws IOException {
final int width = size.getWidth();
final int height = size.getHeight();
- final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final int bytesPerPixel = pixelformat.comp.bytesPerPixel();
final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
(4 == bytesPerPixel) ? true : false /* alpha */,
(1 == bytesPerPixel) ? true : false /* grayscale */,
diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
index 3b65b0824..94db6e9e4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
@@ -27,10 +27,10 @@
*/
package com.jogamp.opengl.util;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLException;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
@@ -176,7 +176,7 @@ public class RandomTileRenderer extends TileRendererBase {
final int srcY = 0;
final int srcWidth = currentTileWidth;
final int srcHeight = currentTileHeight;
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
tileBuffer.clear();
if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
throw new IndexOutOfBoundsException("Required " + readPixelSize + " bytes of buffer, only had " + tileBuffer);
@@ -200,9 +200,9 @@ public class RandomTileRenderer extends TileRendererBase {
psm.setPackRowLength(gl2es3, rowLength);
/* read the tile into the final image */
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
- final int ibPos = ( currentTileXPos + ( currentTileYPos * rowLength ) ) * pixelAttribs.bytesPerPixel; // skipPixels + skipRows
+ final int ibPos = ( currentTileXPos + ( currentTileYPos * rowLength ) ) * pixelAttribs.pfmt.comp.bytesPerPixel(); // skipPixels + skipRows
final int ibLim = ibPos + readPixelSize;
imageBuffer.clear();
if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
index d8410a102..b4ddd4ed0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
@@ -36,11 +36,11 @@
*/
package com.jogamp.opengl.util;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GLException;
+import com.jogamp.nativewindow.util.Dimension;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GLException;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
@@ -479,7 +479,7 @@ public class TileRenderer extends TileRendererBase {
final int srcY = tileBorder;
final int srcWidth = tileSizeNB.getWidth();
final int srcHeight = tileSizeNB.getHeight();
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
tileBuffer.clear();
if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
throw new IndexOutOfBoundsException("Required " + readPixelSize + " bytes of buffer, only had " + tileBuffer);
@@ -503,11 +503,11 @@ public class TileRenderer extends TileRendererBase {
psm.setPackRowLength(gl2es3, rowLength);
/* read the tile into the final image */
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
final int skipPixels = currentColumn * tileSizeNB.getWidth();
final int skipRows = currentRow * tileSizeNB.getHeight();
- final int ibPos = ( skipPixels + ( skipRows * rowLength ) ) * pixelAttribs.bytesPerPixel;
+ final int ibPos = ( skipPixels + ( skipRows * rowLength ) ) * pixelAttribs.pfmt.comp.bytesPerPixel();
final int ibLim = ibPos + readPixelSize;
imageBuffer.clear();
if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
index a1735766e..df73f6f3a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
@@ -36,15 +36,15 @@
*/
package com.jogamp.opengl.util;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES3;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
+import com.jogamp.nativewindow.util.Dimension;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES3;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
import jogamp.opengl.Debug;
/**
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
index 2ad102235..662cf74b7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -27,9 +27,9 @@
*/
package com.jogamp.opengl.util.av;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
import jogamp.opengl.Debug;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
index 04bc0a15d..6b0b3784d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
@@ -36,10 +36,14 @@ import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.nio.Buffer;
import java.nio.IntBuffer;
+import java.util.Iterator;
-import javax.media.opengl.GL;
+import com.jogamp.nativewindow.util.PixelFormat;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.opengl.util.GLPixelBuffer;
/**
@@ -50,7 +54,7 @@ import com.jogamp.opengl.util.GLPixelBuffer;
* </p>
* <p>
* {@link AWTGLPixelBuffer} can be produced via {@link AWTGLPixelBufferProvider}'s
- * {@link AWTGLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocate(..)}.
+ * {@link AWTGLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocate(..)}.
* </p>
* <p>
* See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)} for {@link #allowRowStride} details.
@@ -61,30 +65,49 @@ import com.jogamp.opengl.util.GLPixelBuffer;
* </p>
*/
public class AWTGLPixelBuffer extends GLPixelBuffer {
- public static final GLPixelAttributes awtPixelAttributesIntRGBA4 = new GLPixelAttributes(4, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
- public static final GLPixelAttributes awtPixelAttributesIntRGB3 = new GLPixelAttributes(3, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+ /**
+ * Ignoring componentCount, since otherwise no AWT/GL matching types are found.
+ * <p>
+ * Due to using RGBA and BGRA, pack/unpack usage has makes no difference.
+ * </p>
+ */
+ private static final GLPixelAttributes awtPixelAttributesIntBGRA = new GLPixelAttributes(GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+ private static final GLPixelAttributes awtPixelAttributesIntRGBA = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
/** The underlying {@link BufferedImage}. */
public final BufferedImage image;
+ private final PixelFormat.Composition hostPixelComp;
+ private final int awtFormat;
+
/**
- *
+ * @param hostPixelComp the host {@link PixelFormat.Composition}
* @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ * @param awtFormat the used AWT format, i.e. {@link AWTGLPixelBufferProvider#getAWTFormat(GLProfile, int)}
* @param width in pixels
* @param height in pixels
* @param depth in pixels
- * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
* @param image the AWT image
* @param buffer the backing array
* @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
* If <code>true</code>, user shall decide whether to use a {@link #getAlignedImage(int, int) width-aligned image}.
*/
- public AWTGLPixelBuffer(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final BufferedImage image,
- final Buffer buffer, final boolean allowRowStride) {
- super(pixelAttributes, width, height, depth, pack, buffer, allowRowStride);
+ public AWTGLPixelBuffer(final PixelFormat.Composition hostPixelComp,
+ final GLPixelAttributes pixelAttributes,
+ final boolean pack,
+ final int awtFormat, final int width, final int height, final int depth,
+ final BufferedImage image, final Buffer buffer, final boolean allowRowStride) {
+ super(pixelAttributes, pack, width, height, depth, buffer, allowRowStride);
this.image = image;
+ this.hostPixelComp = hostPixelComp;
+ this.awtFormat = awtFormat;
}
+ public final PixelFormat.Composition getHostPixelComp() { return hostPixelComp; }
+ public final int getAWTFormat() { return awtFormat; }
+
@Override
public void dispose() {
image.flush();
@@ -147,12 +170,57 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
public AWTGLPixelBufferProvider(final boolean allowRowStride) {
this.allowRowStride = allowRowStride;
}
+
@Override
public boolean getAllowRowStride() { return allowRowStride; }
@Override
- public GLPixelAttributes getAttributes(final GL gl, final int componentCount) {
- return 4 == componentCount ? awtPixelAttributesIntRGBA4 : awtPixelAttributesIntRGB3;
+ public GLPixelAttributes getAttributes(final GL gl, final int componentCount, final boolean pack) {
+ return gl.isGLES() ? awtPixelAttributesIntRGBA : awtPixelAttributesIntBGRA;
+ }
+
+ public GLPixelAttributes getAttributes(final GLProfile glp, final int componentCount) {
+ return glp.isGLES() ? awtPixelAttributesIntRGBA : awtPixelAttributesIntBGRA;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns a valid {@link PixelFormat.Composition} instance from {@link #getAWTPixelFormat(GLProfile, int)}.
+ * </p>
+ */
+ @Override
+ public PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount) {
+ return getAWTPixelFormat(glp, componentCount).comp;
+ }
+
+ /**
+ * Returns one of
+ * <ul>
+ * <li>GL__, 4c -> 4c: {@link BufferedImage#TYPE_INT_ARGB} <-> {@link GL#GL_BGRA}</li>
+ * <li>GLES, 4c -> 4c: {@link BufferedImage#TYPE_INT_BGR} <-> {@link GL#GL_RGBA}</li>
+ * <li>GL__, 3c -> 4c: {@link BufferedImage#TYPE_INT_RGB} <-> {@link GL#GL_BGRA}</li>
+ * <li>GLES, 3c -> 4c: {@link BufferedImage#TYPE_INT_BGR} <-> {@link GL#GL_RGBA}</li>
+ * </ul>
+ * @param glp
+ * @param componentCount
+ * @return
+ */
+ public int getAWTFormat(final GLProfile glp, final int componentCount) {
+ if( 4 == componentCount ) {
+ // FIXME: 4 component solution BufferedImage.TYPE_INT_ARGB: GLES format missing (i.e. GL_BGRA)
+ return glp.isGLES() ? BufferedImage.TYPE_INT_BGR : BufferedImage.TYPE_INT_ARGB;
+ } else {
+ return glp.isGLES() ? BufferedImage.TYPE_INT_BGR : BufferedImage.TYPE_INT_RGB;
+ }
+ }
+
+ public PixelFormat getAWTPixelFormat(final GLProfile glp, final int componentCount) {
+ if( 4 == componentCount ) {
+ return glp.isGLES() ? PixelFormat.RGBx8888 : PixelFormat.BGRA8888;
+ } else {
+ return glp.isGLES() ? PixelFormat.RGBx8888 : PixelFormat.BGRx8888;
+ }
}
/**
@@ -162,11 +230,17 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
* </p>
*/
@Override
- public AWTGLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
- final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ public AWTGLPixelBuffer allocate(final GL gl, final PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes, final boolean pack,
+ final int width, final int height, final int depth, final int minByteSize) {
+ if( null == hostPixComp ) {
+ throw new IllegalArgumentException("Null hostPixComp");
+ }
+ final int awtFormat = getAWTFormat(gl.getGLProfile(), hostPixComp.componenCount());
+ final BufferedImage image = new BufferedImage(width, height, awtFormat);
final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
- return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride);
+ return new AWTGLPixelBuffer(hostPixComp, pixelAttributes, pack,
+ awtFormat, width, height, depth, image, ibuffer, allowRowStride);
}
}
@@ -174,15 +248,22 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
* Provider for singleton {@link AWTGLPixelBuffer} instances.
* <p>
* Provider instance holds the last {@link AWTGLPixelBuffer} instance
- * {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
- * A new {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocation}
+ * {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
+ * A new {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocation}
* will return same instance, if a new buffer is not {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int) required}.
* The latter is true if size are compatible, hence <code>allowRowStride</code> should be enabled, if possible.
* </p>
*/
public static class SingleAWTGLPixelBufferProvider extends AWTGLPixelBufferProvider implements SingletonGLPixelBufferProvider {
- private AWTGLPixelBuffer singleRGBA4 = null;
- private AWTGLPixelBuffer singleRGB3 = null;
+ private final IntObjectHashMap bufferMap = new IntObjectHashMap(8);
+
+ private static int getHashCode(final PixelFormat.Composition hostPixelComp, final GLPixelAttributes pixelAttributes, final boolean pack) {
+ // 31 * x == (x << 5) - x
+ int hash = hostPixelComp.hashCode();
+ hash = ((hash << 5) - hash) + pixelAttributes.hashCode();
+ // hash = ((hash << 5) - hash) + (pack ? 100 : 0); // no difference due to RGBA/BGRA only modes.
+ return hash;
+ }
/**
* @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
@@ -198,52 +279,72 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
* </p>
*/
@Override
- public AWTGLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
- if( 4 == pixelAttributes.componentCount ) {
- if( null == singleRGBA4 || singleRGBA4.requiresNewBuffer(gl, width, height, minByteSize) ) {
- singleRGBA4 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
- }
- return singleRGBA4;
- } else {
- if( null == singleRGB3 || singleRGB3.requiresNewBuffer(gl, width, height, minByteSize) ) {
- singleRGB3 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
+ public AWTGLPixelBuffer allocate(final GL gl, PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes,
+ final boolean pack, final int width, final int height, final int depth, final int minByteSize) {
+ if( null == hostPixComp ) {
+ hostPixComp = pixelAttributes.pfmt.comp;
+ }
+ final int bufferKey = getHashCode(hostPixComp, pixelAttributes, pack);
+ AWTGLPixelBuffer r = (AWTGLPixelBuffer) bufferMap.get(bufferKey);
+ if( null == r || r.requiresNewBuffer(gl, width, height, minByteSize) ) {
+ if( null != r ) {
+ r.dispose();
}
- return singleRGB3;
+ r = allocateImpl(hostPixComp, pixelAttributes, pack,
+ getAWTFormat(gl.getGLProfile(), hostPixComp.componenCount()), width, height, depth, minByteSize);
+ bufferMap.put(bufferKey, r);
}
+ return r;
}
- private AWTGLPixelBuffer allocateImpl(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
- final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ private AWTGLPixelBuffer allocateImpl(final PixelFormat.Composition hostPixComp,
+ final GLPixelAttributes pixelAttributes,
+ final boolean pack,
+ final int awtFormat, final int width, final int height, final int depth,
+ final int minByteSize) {
+ final BufferedImage image = new BufferedImage(width, height, awtFormat);
final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
- return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, getAllowRowStride());
+ return new AWTGLPixelBuffer(hostPixComp, pixelAttributes, pack,
+ awtFormat, width, height, depth, image, ibuffer, getAllowRowStride());
}
- /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link AWTGLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */
+ /**
+ * Return the last {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}
+ * {@link AWTGLPixelBuffer}, if compatible w/ the given {@link PixelFormat.Composition} and {@link GLPixelAttributes}.
+ **/
@Override
- public AWTGLPixelBuffer getSingleBuffer(final GLPixelAttributes pixelAttributes) {
- return 4 == pixelAttributes.componentCount ? singleRGBA4 : singleRGB3;
+ public AWTGLPixelBuffer getSingleBuffer(final PixelFormat.Composition hostPixelComp, final GLPixelAttributes pixelAttributes, final boolean pack) {
+ return (AWTGLPixelBuffer) bufferMap.get(getHashCode(hostPixelComp, pixelAttributes, pack));
}
/**
- * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
* @return the newly initialized single {@link AWTGLPixelBuffer}, or null if already allocated.
*/
@Override
- public AWTGLPixelBuffer initSingleton(final int componentCount, final int width, final int height, final int depth, final boolean pack) {
- if( 4 == componentCount ) {
- if( null != singleRGBA4 ) {
- return null;
- }
- singleRGBA4 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGBA4, width, height, depth, pack, 0);
- return singleRGBA4;
- } else {
- if( null != singleRGB3 ) {
- return null;
- }
- singleRGB3 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGB3, width, height, depth, pack, 0);
- return singleRGB3;
+ public AWTGLPixelBuffer initSingleton(final GLProfile glp, final int componentCount,
+ final boolean pack, final int width, final int height, final int depth) {
+ final GLPixelAttributes pixelAttributes = getAttributes(glp, componentCount);
+ final PixelFormat awtPixelFormat = getAWTPixelFormat(glp, componentCount);
+ final int awtFormat = getAWTFormat(glp, componentCount);
+ final int bufferKey = getHashCode(awtPixelFormat.comp, pixelAttributes, pack);
+ AWTGLPixelBuffer r = (AWTGLPixelBuffer) bufferMap.get(bufferKey);
+ if( null != r ) {
+ return null;
+ }
+ r = allocateImpl(awtPixelFormat.comp, pixelAttributes, pack, awtFormat, width, height, depth, 0);
+ bufferMap.put(bufferKey, r);
+ return r;
+ }
+
+ @Override
+ public void dispose() {
+ for(final Iterator<IntObjectHashMap.Entry> i=bufferMap.iterator(); i.hasNext(); ) {
+ final AWTGLPixelBuffer b = (AWTGLPixelBuffer)i.next().value;
+ b.dispose();
}
+ bufferMap.clear();
}
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
index b75ad3b17..aad94aae6 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -29,9 +29,9 @@ package com.jogamp.opengl.util.awt;
import java.awt.image.BufferedImage;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.GLReadBufferUtil;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java
index a78bc9bb3..ee9e1314e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java
@@ -41,7 +41,7 @@ package com.jogamp.opengl.util.awt;
import java.awt.Graphics2D;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
/** Provides a Java 2D overlay on top of an arbitrary GLDrawable,
making it easier to do things like draw text and images on top of
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
index fc0861eaa..e6f5aaa2e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
@@ -64,10 +64,10 @@ import java.nio.*;
import java.text.*;
import java.util.*;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.GLPointerFunc;
-import javax.media.opengl.glu.*;
-import javax.media.opengl.awt.*;
+import com.jogamp.opengl.*;
+import com.jogamp.opengl.fixedfunc.GLPointerFunc;
+import com.jogamp.opengl.glu.*;
+import com.jogamp.opengl.awt.*;
import jogamp.opengl.Debug;
@@ -81,15 +81,15 @@ import jogamp.opengl.Debug;
Using the {@link TextRenderer TextRenderer} is simple. Add a
"<code>TextRenderer renderer;</code>" field to your {@link
- javax.media.opengl.GLEventListener GLEventListener}. In your {@link
- javax.media.opengl.GLEventListener#init init} method, add:
+ com.jogamp.opengl.GLEventListener GLEventListener}. In your {@link
+ com.jogamp.opengl.GLEventListener#init init} method, add:
<PRE>
renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 36));
</PRE>
- <P> In the {@link javax.media.opengl.GLEventListener#display display} method of your
- {@link javax.media.opengl.GLEventListener GLEventListener}, add:
+ <P> In the {@link com.jogamp.opengl.GLEventListener#display display} method of your
+ {@link com.jogamp.opengl.GLEventListener GLEventListener}, add:
<PRE>
renderer.beginRendering(drawable.getWidth(), drawable.getHeight());
// optionally set the color
@@ -381,7 +381,7 @@ public class TextRenderer {
@param width the width of the current on-screen OpenGL drawable
@param height the height of the current on-screen OpenGL drawable
- @throws javax.media.opengl.GLException If an OpenGL context is not current when this method is called
+ @throws com.jogamp.opengl.GLException If an OpenGL context is not current when this method is called
*/
public void beginRendering(final int width, final int height) throws GLException {
beginRendering(width, height, true);
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java
index ef59f9fa0..c8b365235 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java
@@ -47,10 +47,10 @@ import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.*;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.GLLightingFunc;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
-import javax.media.opengl.glu.gl2.*;
+import com.jogamp.opengl.*;
+import com.jogamp.opengl.fixedfunc.GLLightingFunc;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.opengl.glu.gl2.*;
import com.jogamp.opengl.util.texture.*;
import com.jogamp.opengl.util.texture.awt.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java
index 92cbd66da..752d56827 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java
@@ -39,10 +39,10 @@
package com.jogamp.opengl.util.gl2;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.GLLightingFunc;
-import javax.media.opengl.glu.*;
-import javax.media.opengl.glu.gl2.*;
+import com.jogamp.opengl.*;
+import com.jogamp.opengl.fixedfunc.GLLightingFunc;
+import com.jogamp.opengl.glu.*;
+import com.jogamp.opengl.glu.gl2.*;
/** Subset of the routines provided by the GLUT interface. Note the
signatures of many of the methods are necessarily different than
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
index 3b8706a24..bb1c5e9b1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
@@ -44,13 +44,13 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL3;
-import javax.media.opengl.GL4;
-import javax.media.opengl.GLES2;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL3;
+import com.jogamp.opengl.GL4;
+import com.jogamp.opengl.GLES2;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
import jogamp.opengl.Debug;
@@ -1049,7 +1049,7 @@ public class ShaderCode {
public static final boolean requiresGL3DefaultPrecision(final GL2ES2 gl) {
if( gl.isGL3() ) {
final VersionNumber glslVersion = gl.getContext().getGLSLVersionNumber();
- return glslVersion.compareTo(GLContext.Version130) >= 0 && glslVersion.compareTo(GLContext.Version150) < 0 ;
+ return glslVersion.compareTo(GLContext.Version1_30) >= 0 && glslVersion.compareTo(GLContext.Version1_50) < 0 ;
} else {
return false;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
index a9b0bddc6..63455ba51 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
@@ -28,7 +28,7 @@
package com.jogamp.opengl.util.glsl;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.os.Platform;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
index d758fc121..e06f7be00 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
@@ -32,14 +32,15 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLArrayData;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLUniformData;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLArrayData;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLUniformData;
import jogamp.opengl.Debug;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.util.GLArrayDataEditable;
@@ -161,7 +162,7 @@ public class ShaderState {
final int newId = (null!=prog)?prog.id():-1;
System.err.println("ShaderState: attachShaderProgram: "+curId+" -> "+newId+" (enable: "+enable+")\n\t"+shaderProgram+"\n\t"+prog);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
if(null!=shaderProgram) {
@@ -340,7 +341,7 @@ public class ShaderState {
* @throws GLException if no program is attached
* @throws GLException if the program is already linked
*
- * @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String)
+ * @see com.jogamp.opengl.GL2ES2#glBindAttribLocation(int, int, String)
* @see #getAttribLocation(GL2ES2, String)
* @see #getCachedAttribLocation(String)
*/
@@ -361,7 +362,7 @@ public class ShaderState {
* @throws GLException if no program is attached
* @throws GLException if the program is already linked
*
- * @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String)
+ * @see com.jogamp.opengl.GL2ES2#glBindAttribLocation(int, int, String)
* @see #getAttribLocation(GL2ES2, String)
* @see #getCachedAttribLocation(String)
* @see #getAttribute(String)
@@ -405,7 +406,7 @@ public class ShaderState {
} else if(verbose) {
System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
}
@@ -448,7 +449,7 @@ public class ShaderState {
} else if(verbose) {
System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
}
@@ -483,7 +484,7 @@ public class ShaderState {
if(verbose) {
System.err.println("ShaderState: glEnableVertexAttribArray failed, no index for: "+name);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
return false;
@@ -558,7 +559,7 @@ public class ShaderState {
if(verbose) {
System.err.println("ShaderState: glDisableVertexAttribArray failed, no index for: "+name);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
return false;
@@ -860,7 +861,7 @@ public class ShaderState {
* @throws GLException is the program is not linked
*
* @see #glGetUniformLocation
- * @see javax.media.opengl.GL2ES2#glGetUniformLocation
+ * @see com.jogamp.opengl.GL2ES2#glGetUniformLocation
* @see #getUniformLocation
* @see ShaderProgram#glReplaceShader
*/
@@ -875,7 +876,7 @@ public class ShaderState {
} else if(verbose) {
System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
}
@@ -898,7 +899,7 @@ public class ShaderState {
* @throws GLException is the program is not linked
*
* @see #glGetUniformLocation
- * @see javax.media.opengl.GL2ES2#glGetUniformLocation
+ * @see com.jogamp.opengl.GL2ES2#glGetUniformLocation
* @see #getUniformLocation
* @see ShaderProgram#glReplaceShader
*/
@@ -916,7 +917,7 @@ public class ShaderState {
} else if(verbose) {
System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location);
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
}
}
@@ -935,8 +936,8 @@ public class ShaderState {
* @return false, if the location could not be determined, otherwise true
*
* @see #glGetUniformLocation
- * @see javax.media.opengl.GL2ES2#glGetUniformLocation
- * @see javax.media.opengl.GL2ES2#glUniform
+ * @see com.jogamp.opengl.GL2ES2#glGetUniformLocation
+ * @see com.jogamp.opengl.GL2ES2#glUniform
* @see #getUniformLocation
* @see ShaderProgram#glReplaceShader
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
index 06f7d9268..165a5167a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
@@ -37,7 +37,7 @@ import java.io.PrintStream;
import java.nio.*;
import java.util.*;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GLExtensions;
@@ -221,7 +221,7 @@ public class ShaderUtil {
/** Returns true if GeometryShader is supported, i.e. whether GLContext is &ge; 3.2 or ARB_geometry_shader4 extension is available. */
public static boolean isGeometryShaderSupported(final GL _gl) {
final GLContext ctx = _gl.getContext();
- return ctx.getGLVersionNumber().compareTo(GLContext.Version320) >= 0 ||
+ return ctx.getGLVersionNumber().compareTo(GLContext.Version3_2) >= 0 ||
ctx.isExtensionAvailable(GLExtensions.ARB_geometry_shader4);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java
index 1ed875f27..37bca895a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java
@@ -4,12 +4,12 @@
package com.jogamp.opengl.util.glsl.fixedfunc;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES1;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.fixedfunc.GLPointerFuncUtil;
import jogamp.opengl.util.glsl.fixedfunc.FixedFuncHook;
import jogamp.opengl.util.glsl.fixedfunc.FixedFuncImpl;
@@ -77,18 +77,18 @@ public class FixedFuncUtil {
* Useful for uniq mapping of canonical array index names as listed.
*
* @see #mgl_Vertex
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_VERTEX_ARRAY
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#GL_VERTEX_ARRAY
* @see #mgl_Normal
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_NORMAL_ARRAY
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#GL_NORMAL_ARRAY
* @see #mgl_Color
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_COLOR_ARRAY
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#GL_COLOR_ARRAY
* @see #mgl_MultiTexCoord
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_TEXTURE_COORD_ARRAY
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#glEnableClientState
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#glVertexPointer
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#glColorPointer
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#glNormalPointer
- * @see javax.media.opengl.fixedfunc.GLPointerFunc#glTexCoordPointer
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#GL_TEXTURE_COORD_ARRAY
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#glEnableClientState
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#glVertexPointer
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#glColorPointer
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#glNormalPointer
+ * @see com.jogamp.opengl.fixedfunc.GLPointerFunc#glTexCoordPointer
*/
public static String getPredefinedArrayIndexName(final int glArrayIndex) {
return GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex);
@@ -96,25 +96,25 @@ public class FixedFuncUtil {
/**
* String name for
- * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY
+ * @see com.jogamp.opengl.GL2#GL_VERTEX_ARRAY
*/
public static final String mgl_Vertex = GLPointerFuncUtil.mgl_Vertex;
/**
* String name for
- * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY
+ * @see com.jogamp.opengl.GL2#GL_NORMAL_ARRAY
*/
public static final String mgl_Normal = GLPointerFuncUtil.mgl_Normal;
/**
* String name for
- * @see javax.media.opengl.GL2#GL_COLOR_ARRAY
+ * @see com.jogamp.opengl.GL2#GL_COLOR_ARRAY
*/
public static final String mgl_Color = GLPointerFuncUtil.mgl_Color;
/**
* String name for
- * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY
+ * @see com.jogamp.opengl.GL2#GL_TEXTURE_COORD_ARRAY
*/
public static final String mgl_MultiTexCoord = GLPointerFuncUtil.mgl_MultiTexCoord;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java
index 1d629131e..f5dec1cab 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java
@@ -2,7 +2,7 @@ package com.jogamp.opengl.util.glsl.sdk;
import com.jogamp.common.util.IOUtil;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.opengl.util.glsl.*;
import java.io.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java
index 9ff37c7ee..ae289acf7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java
@@ -1,6 +1,6 @@
package com.jogamp.opengl.util.glsl.sdk;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import java.io.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
index f70ebf928..fad07b026 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
@@ -27,12 +27,12 @@
*/
package com.jogamp.opengl.util.stereo;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.RectangleImmutable;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLEventListener;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.nativewindow.util.RectangleImmutable;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLEventListener;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableHelper.GLEventListenerAction;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
index d32c981a3..302e783a2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
@@ -27,8 +27,8 @@
*/
package com.jogamp.opengl.util.stereo;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.PointImmutable;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.nativewindow.util.PointImmutable;
import jogamp.opengl.Debug;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java
index ab9ba99a1..68ae3241b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java
@@ -27,9 +27,9 @@
*/
package com.jogamp.opengl.util.stereo;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.RectangleImmutable;
-import javax.media.opengl.GL;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.nativewindow.util.RectangleImmutable;
+import com.jogamp.opengl.GL;
import com.jogamp.opengl.math.FovHVHalves;
@@ -45,8 +45,8 @@ import com.jogamp.opengl.math.FovHVHalves;
* <li>device.{@link #updateEyePose(int)}</li>
* <li>if device.{@link #ppAvailable()}: Set the render target, e.g. FBO</li>
* <li>Set the viewport using {@link Eye#getViewport()}</li>
- * <li>{@link StereoGLEventListener#reshapeForEye(javax.media.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream.reshapeEye(..)}</li>
- * <li>{@link StereoGLEventListener#display(javax.media.opengl.GLAutoDrawable, int) upstream.display(..)}.</li>
+ * <li>{@link StereoGLEventListener#reshapeForEye(com.jogamp.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream.reshapeEye(..)}</li>
+ * <li>{@link StereoGLEventListener#display(com.jogamp.opengl.GLAutoDrawable, int) upstream.display(..)}.</li>
* </ul></li>
* <li>Reset the viewport</li>
* <li>If device.{@link #ppAvailable()}:<ul>
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java
index ec580cbf9..c1a06796c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java
@@ -27,8 +27,8 @@
*/
package com.jogamp.opengl.util.stereo;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLEventListener;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.util.CustomGLEventListener;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java
index 3031013b8..3e4e7ccd9 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java
@@ -75,7 +75,7 @@ public class StereoUtil {
* <p>
* This method merely exist as an example implementation to compute the matrices,
* which shall be adopted by the
- * {@link CustomGLEventListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream client code}.
+ * {@link CustomGLEventListener#reshape(com.jogamp.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream client code}.
* </p>
* @param eyeNum eye denominator
* @param zNear frustum near value
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java
index f5ef5672f..0f51c2e14 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java
@@ -32,9 +32,9 @@ import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.common.util.IOUtil;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
index e7693f4a6..18a7527b6 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
@@ -39,9 +39,9 @@ package com.jogamp.opengl.util.texture;
import java.nio.*;
-import javax.media.opengl.*;
-import javax.media.opengl.glu.*;
-import javax.media.nativewindow.NativeWindowFactory;
+import com.jogamp.opengl.*;
+import com.jogamp.opengl.glu.*;
+import com.jogamp.nativewindow.NativeWindowFactory;
import jogamp.opengl.*;
@@ -346,8 +346,8 @@ public class Texture {
* Returns the OpenGL "target" of this texture.
*
* @return the OpenGL target of this texture
- * @see javax.media.opengl.GL#GL_TEXTURE_2D
- * @see javax.media.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB
+ * @see com.jogamp.opengl.GL#GL_TEXTURE_2D
+ * @see com.jogamp.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB
*/
public int getTarget() {
return target;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
index 5b2e4fc00..ce1acc6d7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
@@ -39,7 +39,7 @@ package com.jogamp.opengl.util.texture;
import java.nio.Buffer;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.GLBuffers;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index 6011afe7b..27571ae0d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -55,15 +55,15 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.PixelFormat;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
+import com.jogamp.nativewindow.util.Dimension;
+import com.jogamp.nativewindow.util.DimensionImmutable;
+import com.jogamp.nativewindow.util.PixelFormat;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
import jogamp.opengl.Debug;
@@ -1125,12 +1125,12 @@ public class TextureIO {
final String fileSuffix) throws IOException {
if (PNG.equals(fileSuffix)) {
final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
- final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
+ final GLPixelAttributes glpa = new GLPixelAttributes(glp, image.getPixelformat(), false /* pack */);
if ( 0 == pixelFormat ) {
pixelFormat = glpa.format;
} // else FIXME: Actually not supported w/ preset pixelFormat!
if ( 0 == internalFormat ) {
- final boolean hasAlpha = 4 == glpa.bytesPerPixel;
+ final boolean hasAlpha = 4 == glpa.pfmt.comp.bytesPerPixel();
if(glp.isGL2ES3()) {
internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
} else {
@@ -1351,8 +1351,8 @@ public class TextureIO {
final GLPixelAttributes pixelAttribs = data.getPixelAttributes();
final int pixelFormat = pixelAttribs.format;
final int pixelType = pixelAttribs.type;
- final int bytesPerPixel = pixelAttribs.bytesPerPixel;
- final PixelFormat pixFmt = pixelAttribs.getPixelFormat();
+ final int bytesPerPixel = pixelAttribs.pfmt.comp.bytesPerPixel();
+ final PixelFormat pixFmt = pixelAttribs.pfmt;
if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) &&
( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
Buffer buf0 = data.getBuffer();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
index 5add4f695..7147fd61b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -27,10 +27,10 @@
*/
package com.jogamp.opengl.util.texture;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLRunnable;
-import javax.media.opengl.GLEventListener;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLRunnable;
+import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.util.TimeFrameI;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
index 467ab41c5..1866c5921 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
@@ -27,11 +27,11 @@
*/
package com.jogamp.opengl.util.texture;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GL3;
-import javax.media.opengl.GLException;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GL3;
+import com.jogamp.opengl.GLException;
/**
* Preserves a [ texture-unit, texture-target ] state.
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
index ccb3ecc3c..aa0be8e9b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
@@ -60,11 +60,11 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.texture.TextureData;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java
index c3b3adc75..2b21ef8e4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java
@@ -41,7 +41,7 @@ package com.jogamp.opengl.util.texture.awt;
import java.awt.image.*;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.opengl.util.texture.*;
public class AWTTextureIO extends TextureIO {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java
index 20fc92819..a71458837 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java
@@ -50,7 +50,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
-import javax.media.opengl.GL;
+import com.jogamp.opengl.GL;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
index 66a486f9b..0d82528a2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
@@ -31,7 +31,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
-import javax.media.opengl.GL;
+import com.jogamp.opengl.GL;
import jogamp.opengl.Debug;
import jogamp.opengl.util.jpeg.JPEGDecoder;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
index 461ddceb8..700de593f 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
@@ -43,7 +43,7 @@ import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.util.texture.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java
index 27549dfe3..9088dc48e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java
@@ -40,7 +40,7 @@
package com.jogamp.opengl.util.texture.spi;
import java.io.*;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.util.IOUtil;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java
index 28823abb3..bb872714c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java
@@ -42,7 +42,7 @@ package com.jogamp.opengl.util.texture.spi;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.util.IOUtil;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java
index 0299531b1..e84f300e2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java
@@ -41,7 +41,7 @@ package com.jogamp.opengl.util.texture.spi;
import java.io.*;
import java.net.*;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.texture.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java
index 4174adf52..ba762baf3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java
@@ -44,7 +44,7 @@ import java.awt.image.*;
import java.io.*;
import java.net.*;
import javax.imageio.*;
-import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.GLProfile;
import jogamp.opengl.Debug;
import com.jogamp.opengl.util.texture.*;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java
index 60ac5680e..35a2f8422 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java
@@ -45,7 +45,7 @@ import java.io.*;
import java.nio.*;
import javax.imageio.*;
-import javax.media.opengl.*;
+import com.jogamp.opengl.*;
import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.util.awt.*;