summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes
diff options
context:
space:
mode:
authorXerxes Rånby <[email protected]>2012-08-06 21:17:11 +0000
committerXerxes Rånby <[email protected]>2012-08-06 21:17:11 +0000
commitab671729fd4b50127d8dcb95bd5fd13ce0a4078b (patch)
tree3a3a4a73a3eda0531dc73f556587683b9c979e0e /src/jogl/classes
parent6e4051d8c9faeec003b15b68bd01e3caf22869fb (diff)
parent9e87acd921bcb357f1ec88d166bde672b54b02c8 (diff)
Merge remote-tracking branch 'github-sgothel/master' into armv6hf
Diffstat (limited to 'src/jogl/classes')
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java2
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java4
-rwxr-xr-xsrc/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java10
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java18
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java (renamed from src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java)3
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FBObject.java1943
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLExtensions.java81
-rw-r--r--src/jogl/classes/com/jogamp/opengl/JoglVersion.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java98
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java381
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FBObject.java483
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java179
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java12
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java25
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java3
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java3
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java25
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java1
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java6
-rw-r--r--src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java8
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawable.java48
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java70
-rw-r--r--src/jogl/classes/javax/media/opengl/GLBase.java55
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilities.java65
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java9
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java94
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawableFactory.java85
-rw-r--r--src/jogl/classes/javax/media/opengl/GLProfile.java63
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java333
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java7
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java278
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java191
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java240
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableImpl.java47
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java138
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java70
-rw-r--r--src/jogl/classes/jogamp/opengl/GLPbufferImpl.java39
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLContext.java76
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java100
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java226
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java318
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java123
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java56
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java153
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java109
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java130
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java102
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java11
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java156
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java110
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java130
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java6
82 files changed, 5161 insertions, 2197 deletions
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
index 1d9cf3668..5334d45cf 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -410,7 +410,7 @@ public class BuildComposablePipeline {
output.flush();
output.close();
- System.out.println("wrote to file: " + file); // JAU
+ System.out.println("wrote to file: " + file);
}
/** Get the name of the object through which API calls should be routed. */
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
index 87a734e1f..482d35cae 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -293,9 +293,9 @@ public class BuildStaticGLInfo {
output.println(" public static String getFunctionAssociation(String glFunctionName)");
output.println(" {");
output.println(" String mappedName = null;");
- output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);");
+ output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutationNumber(glFunctionName);");
output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {");
- output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);");
+ output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutation(glFunctionName, i);");
output.println(" try {");
output.println(" mappedName = (String)funcToAssocMap.get(tmp);");
output.println(" } catch (Exception e) { }");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
index c1a4facd2..ba025e18c 100755
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -43,7 +43,7 @@ import com.jogamp.gluegen.GlueEmitterControls;
import com.jogamp.gluegen.GlueGen;
import com.jogamp.gluegen.MethodBinding;
import com.jogamp.gluegen.procaddress.ProcAddressConfiguration;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -224,11 +224,11 @@ public class GLConfiguration extends ProcAddressConfiguration {
}
}
}
- boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol);
- boolean isGLFunc = GLExtensionNames.isGLFunction(symbol);
+ boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
+ boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
if (isGLFunc || isGLEnum) {
- if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) {
- String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc);
+ if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) {
+ String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc);
if (getDropUniqVendorExtensions(extSuffix)) {
if (DEBUG_IGNORES) {
System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix);
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index f4658ad7b..809c6783d 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -51,7 +51,7 @@ import com.jogamp.gluegen.SymbolFilter;
import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.procaddress.ProcAddressEmitter;
import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.IOException;
import java.io.PrintWriter;
@@ -110,13 +110,13 @@ public class GLEmitter extends ProcAddressEmitter {
if (declarations != null) {
for (Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) {
String decl = iterator.next();
- boolean isGLFunction = GLExtensionNames.isGLFunction(decl);
+ boolean isGLFunction = GLNameResolver.isGLFunction(decl);
boolean isGLEnumeration = false;
if (!isGLFunction) {
- isGLEnumeration = GLExtensionNames.isGLEnumeration(decl);
+ isGLEnumeration = GLNameResolver.isGLEnumeration(decl);
}
if (isGLFunction || isGLEnumeration) {
- String renamed = GLExtensionNames.normalize(decl, isGLFunction);
+ String renamed = GLNameResolver.normalize(decl, isGLFunction);
if (!renamed.equals(decl)) {
config.addJavaSymbolRename(decl, renamed);
}
@@ -181,7 +181,7 @@ public class GLEmitter extends ProcAddressEmitter {
String cause = null;
for (String decl : declarations) {
boolean isFunc = !decl.startsWith("GL_");
- if (!GLExtensionNames.isExtension(decl, isFunc)) {
+ if (!GLNameResolver.isExtension(decl, isFunc)) {
isExtension = false;
break;
}
@@ -199,7 +199,7 @@ public class GLEmitter extends ProcAddressEmitter {
}
}
cause = decl;
- String unifiedName = GLExtensionNames.normalize(decl, isFunc);
+ String unifiedName = GLNameResolver.normalize(decl, isFunc);
// NOTE that we look up the unified name in the
// BuildStaticGLInfo's notion of the APIs -- since
// we might not be emitting glue code for the
@@ -472,12 +472,12 @@ public class GLEmitter extends ProcAddressEmitter {
w.println(" * it was statically linked.");
w.println(" */");
w.println(" public long getAddressFor(String functionNameUsr) {");
- w.println(" String functionNameBase = "+GLExtensionNames.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLExtensionNames.normalizeARB(functionNameUsr, true), true);");
+ w.println(" String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
w.println(" String addressFieldNameBase = PROCADDRESS_VAR_PREFIX + functionNameBase;");
w.println(" java.lang.reflect.Field addressField = null;");
- w.println(" int funcNamePermNum = "+GLExtensionNames.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
w.println(" for(int i = 0; null==addressField && i < funcNamePermNum; i++) {");
- w.println(" String addressFieldName = "+GLExtensionNames.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
w.println(" try {");
w.println(" addressField = getClass().getField(addressFieldName);");
w.println(" } catch (Exception e) { }");
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
index 426333034..92554776a 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
@@ -37,7 +37,8 @@
*/
package com.jogamp.gluegen.runtime.opengl;
-public class GLExtensionNames {
+/** Runtime utility identify and resolve extension names, which may be subsumed to core. */
+public class GLNameResolver {
//GL_XYZ : GL_XYZ, GL_XYZ_GL2, GL_XYZ_ARB, GL_XYZ_OES, GL_XYZ_OML
//GL_XYZ : GL_XYZ, GL_GL2_XYZ, GL_ARB_XYZ, GL_OES_XYZ, GL_OML_XYZ
//
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 fe9efebc7..9775de491 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
@@ -45,10 +45,10 @@ public class GLProcAddressResolver implements FunctionAddressResolver {
public long resolve(String name, DynamicLookupHelper lookup) {
long newProcAddress = 0;
- int permutations = GLExtensionNames.getFuncNamePermutationNumber(name);
+ int permutations = GLNameResolver.getFuncNamePermutationNumber(name);
for (int i = 0; 0 == newProcAddress && i < permutations; i++) {
- String funcName = GLExtensionNames.getFuncNamePermutation(name, i);
+ String funcName = GLNameResolver.getFuncNamePermutation(name, i);
try {
newProcAddress = lookup.dynamicLookupFunction(funcName);
} catch (Exception e) {
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
new file mode 100644
index 000000000..644d87b1a
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -0,0 +1,1943 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLBase;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.opengl.FBObject.Attachment.Type;
+
+/**
+ * Core utility class simplifying usage of framebuffer objects (FBO)
+ * with all {@link GLProfile}s.
+ * <p>
+ * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int)}
+ * while preserving the {@link Attachment} references.
+ * </p>
+ * <p>
+ * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()},
+ * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (<code>zero</code>) framebuffer is selected.
+ * </p>
+ *
+ * <p>FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .</p>
+ */
+public class FBObject {
+ protected static final boolean DEBUG = Debug.debug("FBObject");
+
+ /**
+ * 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 >= core 3.0 or implements the extensions
+ * <code>ARB_ES2_compatibility</code>, <code>ARB_framebuffer_object</code>, <code>EXT_framebuffer_object</code> or <code>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#hasFBO()
+ */
+ public static final boolean supportsBasicFBO(GL gl) {
+ return gl.getContext().hasFBO();
+ }
+
+ /**
+ * 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 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 static final boolean supportsFullFBO(GL gl) {
+ return gl.isGL3() || // GL >= 3.0
+
+ gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
+
+ ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
+ gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+ gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+ gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ) ;
+ }
+
+ public static final int getMaxSamples(GL gl) {
+ if( supportsFullFBO(gl) ) {
+ int[] val = new int[] { 0 } ;
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ return val[0];
+ } else {
+ return 0;
+ }
+ }
+
+ /** Common super class of all attachments */
+ public static abstract class Attachment {
+ public enum Type {
+ NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE;
+
+ /**
+ * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL}
+ * @throws IllegalArgumentException if <code>format</code> cannot be handled.
+ */
+ public static Type determine(int format) throws IllegalArgumentException {
+ switch(format) {
+ case GL.GL_RGBA4:
+ case GL.GL_RGB5_A1:
+ case GL.GL_RGB565:
+ case GL.GL_RGB8:
+ case GL.GL_RGBA8:
+ return Type.COLOR;
+ case GL.GL_DEPTH_COMPONENT16:
+ case GL.GL_DEPTH_COMPONENT24:
+ case GL.GL_DEPTH_COMPONENT32:
+ return Type.DEPTH;
+ case GL.GL_STENCIL_INDEX1:
+ case GL.GL_STENCIL_INDEX4:
+ case GL.GL_STENCIL_INDEX8:
+ return Type.STENCIL;
+ case GL.GL_DEPTH24_STENCIL8:
+ return Type.DEPTH_STENCIL;
+ default:
+ throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ }
+ }
+ };
+
+ /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */
+ public final Type type;
+
+ /** immutable the internal format */
+ public final int format;
+
+ private int width, height;
+
+ private int name;
+
+ /** <code>true</code> if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */
+ protected boolean resourceOwner;
+
+ private int initCounter;
+
+ protected Attachment(Type type, int iFormat, int width, int height, int name) {
+ this.type = type;
+ this.format = iFormat;
+ this.width = width;
+ this.height = height;
+ this.name = name;
+ this.resourceOwner = false;
+ this.initCounter = 0;
+ }
+
+ /** width of attachment */
+ public final int getWidth() { return width; }
+ /** height of attachment */
+ public final int getHeight() { return height; }
+ /* pp */ final void setSize(int w, int h) { width = w; height = h; }
+
+ /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */
+ public final int getName() { return name; }
+ /* pp */ final void setName(int n) { name = n; }
+
+ public final int getInitCounter() { return initCounter; }
+
+ /**
+ * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
+ * <p>Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.</p>
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ */
+ public void initialize(GL gl) throws GLException {
+ initCounter++;
+ /*
+ super.initialize(gl);
+ if(1 == getInitCounter() && 0 == getName() ) {
+ do init ..
+ freeResources = true; // if all OK
+ }
+ */
+ }
+
+ /**
+ * Releases the attachment buffer if initialized, i.e. name is <code>zero</code>.
+ * <p>Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.</p>
+ * @throws GLException if buffer release fails.
+ */
+ public void free(GL gl) throws GLException {
+ /*
+ if(1 == getInitCounter() && freeResources && .. ) {
+ do free ..
+ }
+ super.free(gl);
+ */
+ initCounter--;
+ if(0 == initCounter) {
+ resourceOwner = false;
+ name = 0;
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.free: "+this);
+ }
+ }
+
+ /**
+ * <p>
+ * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if( this == o ) return true;
+ if( ! ( o instanceof Attachment ) ) return false;
+ final Attachment a = (Attachment)o;
+ return type == a.type &&
+ format == a.format ||
+ width == a.width ||
+ height== a.height ||
+ name == a.name ;
+ }
+
+ /**
+ * <p>
+ * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + type.ordinal();
+ hash = ((hash << 5) - hash) + format;
+ hash = ((hash << 5) - hash) + width;
+ hash = ((hash << 5) - hash) + height;
+ hash = ((hash << 5) - hash) + name;
+ return hash;
+ }
+
+ int objectHashCode() { return super.hashCode(); }
+
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+
+ ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+
+ ", resOwner "+resourceOwner+", initCount "+initCounter+"]";
+ }
+
+ public static Type getType(int attachmentPoint, int maxColorAttachments) {
+ if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) {
+ return Type.COLOR;
+ }
+ switch(attachmentPoint) {
+ case GL.GL_DEPTH_ATTACHMENT:
+ return Type.DEPTH;
+ case GL.GL_STENCIL_ATTACHMENT:
+ return Type.STENCIL;
+ default:
+ throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint));
+ }
+ }
+ }
+
+ /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */
+ public static class RenderAttachment extends Attachment {
+ private int samples;
+
+ /**
+ * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR}
+ * @param iFormat
+ * @param samples
+ * @param width
+ * @param height
+ * @param name
+ */
+ public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) {
+ super(validateType(type), iFormat, width, height, name);
+ this.samples = samples;
+ }
+
+ /** number of samples, or zero for no multisampling */
+ public final int getSamples() { return samples; }
+ /* pp */ final void setSamples(int s) { samples = s; }
+
+ private static Type validateType(Type type) {
+ switch(type) {
+ case DEPTH:
+ case STENCIL:
+ case COLOR:
+ return type;
+ default:
+ throw new IllegalArgumentException("Invalid type: "+type);
+ }
+ }
+
+ /**
+ * <p>
+ * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if( this == o ) return true;
+ if( ! ( o instanceof RenderAttachment ) ) return false;
+ return super.equals(o) &&
+ samples == ((RenderAttachment)o).samples;
+ }
+
+ /**
+ * <p>
+ * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = super.hashCode();
+ hash = ((hash << 5) - hash) + samples;
+ return hash;
+ }
+
+ @Override
+ public void initialize(GL gl) throws GLException {
+ super.initialize(gl);
+ if( 1 == getInitCounter() && 0 == getName() ) {
+ final int[] name = new int[] { -1 };
+ gl.glGenRenderbuffers(1, name, 0);
+ if( 0 == name[0] ) {
+ throw new GLException("null renderbuffer, "+this);
+ }
+ setName(name[0]);
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName());
+ if( samples > 0 ) {
+ ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight());
+ } else {
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
+ }
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteRenderbuffers(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ }
+ resourceOwner = true;
+ if(DEBUG) {
+ System.err.println("Attachment.init: "+this);
+ }
+ }
+ }
+
+ @Override
+ public void free(GL gl) {
+ if(1 == getInitCounter() && resourceOwner && 0 != getName() ) {
+ final int[] name = new int[] { getName() };
+ gl.glDeleteRenderbuffers(1, name, 0);
+ }
+ super.free(gl);
+ }
+
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+
+ ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+
+ ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]";
+ }
+ }
+
+ /**
+ * Marker interface, denotes a color buffer attachment.
+ * <p>Always an instance of {@link Attachment}.</p>
+ * <p>Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.</b>
+ */
+ public static interface Colorbuffer {
+ }
+
+ /** Color render buffer attachment */
+ public static class ColorAttachment extends RenderAttachment implements Colorbuffer {
+ public ColorAttachment(int iFormat, int samples, int width, int height, int name) {
+ super(Type.COLOR, iFormat, samples, width, height, name);
+ }
+ }
+
+ /** Texture attachment */
+ public static class TextureAttachment extends Attachment implements Colorbuffer {
+ /** details of the texture setup */
+ public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT;
+
+ /**
+ * @param type allowed types are [ {@link Type#COLOR_TEXTURE}, {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} ]
+ * @param iFormat
+ * @param width
+ * @param height
+ * @param dataFormat
+ * @param dataType
+ * @param magFilter
+ * @param minFilter
+ * @param wrapS
+ * @param wrapT
+ * @param name
+ */
+ public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT, int name) {
+ super(validateType(type), iFormat, width, height, name);
+ this.dataFormat = dataFormat;
+ this.dataType = dataType;
+ this.magFilter = magFilter;
+ this.minFilter = minFilter;
+ this.wrapS = wrapS;
+ this.wrapT = wrapT;
+ }
+
+ private static Type validateType(Type type) {
+ switch(type) {
+ case COLOR_TEXTURE:
+ case DEPTH_TEXTURE:
+ case STENCIL_TEXTURE:
+ return type;
+ default:
+ throw new IllegalArgumentException("Invalid type: "+type);
+ }
+ }
+
+ /**
+ * Initializes the texture and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
+ * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case.
+ */
+ @Override
+ public void initialize(GL gl) throws GLException {
+ super.initialize(gl);
+ if( 1 == getInitCounter() && 0 == getName() ) {
+ final int[] name = new int[] { -1 };
+ gl.glGenTextures(1, name, 0);
+ if(0 == name[0]) {
+ throw new GLException("null texture, "+this);
+ }
+ setName(name[0]);
+
+ gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]);
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ if( 0 < magFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
+ }
+ if( 0 < minFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
+ }
+ if( 0 < wrapS ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ }
+ if( 0 < wrapT ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ }
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteTextures(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ }
+ resourceOwner = true;
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.init: "+this);
+ }
+ }
+
+ @Override
+ public void free(GL gl) {
+ if(1 == getInitCounter() && resourceOwner && 0 != getName() ) {
+ final int[] name = new int[] { getName() };
+ gl.glDeleteTextures(1, name, 0);
+ }
+ super.free(gl);
+ }
+ }
+
+ private boolean initialized;
+ private boolean basicFBOSupport;
+ private boolean fullFBOSupport;
+ private boolean rgba8Avail;
+ private boolean depth24Avail;
+ private boolean depth32Avail;
+ private boolean stencil01Avail;
+ private boolean stencil04Avail;
+ private boolean stencil08Avail;
+ private boolean stencil16Avail;
+ private boolean packedDepthStencilAvail;
+ private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize;
+
+ private int width, height, samples;
+ private int vStatus;
+ private int fbName;
+ private boolean bound;
+
+ private int colorAttachmentCount;
+ private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points
+ private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
+
+ private final FBObject samplesSink; // MSAA sink
+ private TextureAttachment samplesSinkTexture;
+ private boolean samplesSinkDirty;
+
+ //
+ // ColorAttachment helper ..
+ //
+
+ private final void validateColorAttachmentPointRange(int point) {
+ if(maxColorAttachments != colorAttachmentPoints.length) {
+ throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
+ }
+ if(0 > point || point >= maxColorAttachments) {
+ throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]");
+ }
+ }
+
+ private final void validateAddColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ if( null != colorAttachmentPoints[point] ) {
+ throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]);
+ }
+ }
+
+ private final void addColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = ca;
+ colorAttachmentCount++;
+ }
+
+ private final void removeColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = null;
+ colorAttachmentCount--;
+ }
+
+ /**
+ * Return the {@link Colorbuffer} attachment at <code>attachmentPoint</code> if it is attached to this FBO, otherwise null.
+ *
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachTexture2D(GL, int, boolean, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ */
+ public final Colorbuffer getColorbuffer(int attachmentPoint) {
+ validateColorAttachmentPointRange(attachmentPoint);
+ return colorAttachmentPoints[attachmentPoint];
+ }
+
+ /**
+ * Finds the passed {@link Colorbuffer} within the valid range of attachment points
+ * using <i>reference</i> comparison only.
+ * <p>
+ * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap.
+ * </p>
+ * @param ca the {@link Colorbuffer} to look for.
+ * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1]
+ */
+ public final int getColorbufferAttachmentPoint(Colorbuffer ca) {
+ for(int i=0; i<colorAttachmentPoints.length; i++) {
+ if( colorAttachmentPoints[i] == ca ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the passed {@link Colorbuffer} if it is attached to this FBO, otherwise null.
+ * Implementation compares the <i>reference</i> only.
+ *
+ * <p>
+ * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point
+ * to be used for {@link #getColorbuffer(int)}
+ * </p>
+ *
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachTexture2D(GL, int, boolean, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ */
+ public final Colorbuffer getColorbuffer(Colorbuffer ca) {
+ final int p = getColorbufferAttachmentPoint(ca);
+ return p>=0 ? getColorbuffer(p) : null;
+ }
+
+ /**
+ * Creates an uninitialized FBObject instance.
+ * <p>
+ * Call {@link #init(GL, int, int, int)} .. etc to use it.
+ * </p>
+ */
+ public FBObject() {
+ this(false);
+ }
+ /* pp */ FBObject(boolean isSampleSink) {
+ this.initialized = false;
+
+ // TBD @ init
+ this.basicFBOSupport = false;
+ this.fullFBOSupport = false;
+ this.rgba8Avail = false;
+ this.depth24Avail = false;
+ this.depth32Avail = false;
+ this.stencil01Avail = false;
+ this.stencil04Avail = false;
+ this.stencil08Avail = false;
+ this.stencil16Avail = false;
+ this.packedDepthStencilAvail = false;
+ this.maxColorAttachments=-1;
+ this.maxSamples=-1;
+ this.maxTextureSize = 0;
+ this.maxRenderbufferSize = 0;
+
+ this.width = 0;
+ this.height = 0;
+ this.samples = 0;
+ this.vStatus = -1;
+ this.fbName = 0;
+ this.bound = false;
+
+ this.colorAttachmentPoints = null; // at init ..
+ this.colorAttachmentCount = 0;
+ this.depth = null;
+ this.stencil = null;
+
+ this.samplesSink = isSampleSink ? null : new FBObject(true);
+ this.samplesSinkTexture = null;
+ this.samplesSinkDirty = true;
+ }
+
+ private void init(GL gl, int width, int height, int samples) throws GLException {
+ if(initialized) {
+ throw new GLException("FBO already initialized");
+ }
+ fullFBOSupport = supportsFullFBO(gl);
+
+ if( !fullFBOSupport && !supportsBasicFBO(gl) ) {
+ throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this);
+ }
+
+ basicFBOSupport = true;
+
+ rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8);
+ depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24);
+ depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32);
+ stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1);
+ stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4);
+ stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8);
+ stencil16Avail = fullFBOSupport;
+
+ packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil);
+
+ final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments);
+
+ int val[] = new int[1];
+
+ int glerr = gl.glGetError();
+ if(DEBUG && GL.GL_NO_ERROR != glerr) {
+ System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr));
+ }
+
+ int realMaxColorAttachments = 1;
+ maxColorAttachments = 1;
+ if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) {
+ try {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0);
+ glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1
+ } else if(DEBUG) {
+ System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (GLException gle) {}
+ }
+ maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size
+
+ colorAttachmentPoints = new Colorbuffer[maxColorAttachments];
+ colorAttachmentCount = 0;
+
+ maxSamples = 0;
+ if(fullFBOSupport) {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ maxSamples = val[0];
+ } else if(DEBUG) {
+ System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ }
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
+ maxTextureSize = val[0];
+ gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
+ this.maxRenderbufferSize = val[0];
+
+ glerr = gl.glGetError();
+ if(DEBUG && GL.GL_NO_ERROR != glerr) {
+ System.err.println("FBObject.init-preexisting.1 GL Error 0x"+Integer.toHexString(glerr));
+ }
+
+ this.width = width;
+ this.height = height;
+ this.samples = samples <= maxSamples ? samples : maxSamples;
+
+ if(DEBUG) {
+ System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples");
+ System.err.println("basicFBOSupport: "+basicFBOSupport);
+ System.err.println("fullFBOSupport: "+fullFBOSupport);
+ System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments);
+ System.err.println("maxSamples: "+maxSamples);
+ System.err.println("maxTextureSize: "+maxTextureSize);
+ System.err.println("maxRenderbufferSize: "+maxRenderbufferSize);
+ System.err.println("rgba8: "+rgba8Avail);
+ System.err.println("depth24: "+depth24Avail);
+ System.err.println("depth32: "+depth32Avail);
+ System.err.println("stencil01: "+stencil01Avail);
+ System.err.println("stencil04: "+stencil04Avail);
+ System.err.println("stencil08: "+stencil08Avail);
+ System.err.println("stencil16: "+stencil16Avail);
+ System.err.println("packedDepthStencil: "+packedDepthStencilAvail);
+ System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments);
+ System.err.println(gl.getContext().getGLVersion());
+ System.err.println(JoglVersion.getGLStrings(gl, null).toString());
+ System.err.println(gl.getContext());
+ }
+
+ checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error
+
+ if(width > 2 + maxTextureSize || height> 2 + maxTextureSize ||
+ width > maxRenderbufferSize || height> maxRenderbufferSize ) {
+ throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
+ }
+
+ if(null != samplesSink) {
+ // init sampling sink
+ samplesSink.reset(gl, width, height);
+ resetMSAATexture2DSink(gl);
+ }
+
+ // generate fbo ..
+ gl.glGenFramebuffers(1, val, 0);
+ fbName = val[0];
+ if(0 == fbName) {
+ throw new GLException("null framebuffer");
+ }
+
+ // bind fbo ..
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName);
+ checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error
+ if(!gl.glIsFramebuffer(fbName)) {
+ checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
+ }
+ bound = true;
+ initialized = true;
+
+ updateStatus(gl);
+ if(DEBUG) {
+ System.err.println("FBObject.init(): "+this);
+ }
+ }
+
+ /**
+ * Initializes or resets this FBO's instance.
+ * <p>
+ * In case the new parameters are compatible with the current ones
+ * no action will be performed. Otherwise all attachments will be recreated
+ * to match the new given parameters.
+ * </p>
+ * <p>
+ * Currently incompatibility and hence recreation is given if
+ * the size or sample count doesn't match for subsequent calls.
+ * </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth
+ * @param newHeight
+ * @throws GLException in case of an error
+ */
+ public final void reset(GL gl, int newWidth, int newHeight) {
+ reset(gl, newWidth, newHeight, 0);
+ }
+
+ /**
+ * Initializes or resets this FBO's instance.
+ * <p>
+ * In case the new parameters are compatible with the current ones
+ * no action will be performed. Otherwise all attachments will be recreated
+ * to match the new given parameters.
+ * </p>
+ * <p>
+ * Currently incompatibility and hence recreation is given if
+ * the size or sample count doesn't match for subsequent calls.
+ * </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth
+ * @param newHeight
+ * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}.
+ * @throws GLException in case of an error
+ */
+ public final void reset(GL gl, int newWidth, int newHeight, int newSamples) {
+ if(!initialized) {
+ init(gl, newWidth, newHeight, newSamples);
+ return;
+ }
+ newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp
+
+ if( newWidth != width || newHeight != height || newSamples != samples ) {
+ if(DEBUG) {
+ System.err.println("FBObject.reset - START - "+this);
+ }
+
+ final boolean wasBound = isBound();
+
+ width = newWidth;
+ height = newHeight;
+ samples = newSamples;
+ detachAllImpl(gl, true , true);
+ resetMSAATexture2DSink(gl);
+
+ if(wasBound) {
+ bind(gl);
+ } else {
+ unbind(gl);
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.reset - END - "+this);
+ }
+ }
+ }
+
+ /**
+ * Note that the status may reflect an incomplete state during transition of attachments.
+ * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
+ * @see #validateStatus()
+ */
+ public final int getStatus() {
+ return vStatus;
+ }
+
+ /** return the {@link #getStatus()} as a string. */
+ public final String getStatusString() {
+ return getStatusString(vStatus);
+ }
+
+ public static final String getStatusString(int fbStatus) {
+ switch(fbStatus) {
+ case -1:
+ return "NOT A FBO";
+
+ case GL.GL_FRAMEBUFFER_COMPLETE:
+ return "OK";
+
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ return("GL FBO: incomplete, incomplete attachment\n");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ return("GL FBO: incomplete, missing attachment");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ return("GL FBO: incomplete, attached images must have same dimensions");
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
+ return("GL FBO: incomplete, attached images must have same format");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ return("GL FBO: incomplete, missing draw buffer");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ return("GL FBO: incomplete, missing read buffer");
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ return("GL FBO: incomplete, missing multisample buffer");
+ case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ return("GL FBO: incomplete, layer targets");
+
+ case GL.GL_FRAMEBUFFER_UNSUPPORTED:
+ return("GL FBO: Unsupported framebuffer format");
+ case GL2GL3.GL_FRAMEBUFFER_UNDEFINED:
+ return("GL FBO: framebuffer undefined");
+
+ case 0:
+ return("GL FBO: incomplete, implementation fault");
+ default:
+ return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus));
+ }
+ }
+
+ /**
+ * The status may even be valid if incomplete during transition of attachments.
+ * @see #getStatus()
+ */
+ public final boolean isStatusValid() {
+ switch(vStatus) {
+ case GL.GL_FRAMEBUFFER_COMPLETE:
+ return true;
+
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ if(0 == colorAttachmentCount || null == depth) {
+ // we are in transition
+ return true;
+ }
+
+ case GL.GL_FRAMEBUFFER_UNSUPPORTED:
+ case GL2GL3.GL_FRAMEBUFFER_UNDEFINED:
+
+ case 0:
+ default:
+ System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
+ " : " + getStatusString(vStatus));
+ return false;
+ }
+ }
+
+ private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException {
+ if(GL.GL_NO_ERROR != err) {
+ if(null != gl) {
+ destroy(gl);
+ }
+ if(null != exceptionMessage) {
+ throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private final void checkInitialized() throws GLException {
+ if(!initialized) {
+ throw new GLException("FBO not initialized, call init(GL) first.");
+ }
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the texture data type and format automatically.
+ *
+ * <p>Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.</p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the texture data type and format automatically.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
+ final int textureInternalFormat, textureDataFormat, textureDataType;
+ if(gl.isGLES()) {
+ textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint,
+ int internalFormat, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
+ return attachTexture2D(gl, attachmentPoint,
+ new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType,
+ magFilter, minFilter, wrapS, wrapT, 0 /* name */));
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>
+ * In case the passed TextureAttachment <code>texA</code> is uninitialized, i.e. it's texture name is <code>zero</code>,
+ * a new texture name is generated and setup w/ the texture parameter.<br/>
+ * Otherwise, i.e. texture name is not <code>zero</code>, the passed TextureAttachment <code>texA</code> is
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ * </p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above.
+ * @return the passed TextureAttachment <code>texA</code> instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException {
+ validateAddColorAttachment(attachmentPoint, texA);
+
+ if(samples>0) {
+ removeColorAttachment(attachmentPoint, texA);
+ 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).");
+ }
+
+ texA.initialize(gl);
+ addColorAttachment(attachmentPoint, texA);
+
+ bind(gl);
+
+ // Set up the color buffer for use as a renderable texture:
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_TEXTURE_2D, texA.getName(), 0);
+ updateStatus(gl);
+
+ if(!isStatusValid()) {
+ detachColorbuffer(gl, attachmentPoint);
+ throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.attachTexture2D: "+this);
+ }
+ return texA;
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the format automatically.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ final int internalFormat;
+ if( rgba8Avail ) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
+ }
+ return attachColorbuffer(gl, attachmentPoint, internalFormat);
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8}
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ * @throws IllegalArgumentException if <code>internalFormat</code> doesn't reflect a colorbuffer
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException {
+ final Attachment.Type atype = Attachment.Type.determine(internalFormat);
+ if( Attachment.Type.COLOR != atype ) {
+ throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+
+ return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0));
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl
+ * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
+ * @param colA the template for the new {@link ColorAttachment}
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException {
+ validateAddColorAttachment(attachmentPoint, colA);
+
+ colA.initialize(gl);
+ addColorAttachment(attachmentPoint, colA);
+
+ bind(gl);
+
+ // Attach the color buffer
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_RENDERBUFFER, colA.getName());
+
+ updateStatus(gl);
+ if(!isStatusValid()) {
+ detachColorbuffer(gl, attachmentPoint);
+ throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.attachColorbuffer: "+this);
+ }
+ return colA;
+ }
+
+
+ /**
+ * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance,
+ * selecting the internalFormat automatically.
+ * <p>
+ * Stencil and depth buffer can be attached only once.
+ * </p>
+ * <p>
+ * In case the desired type or bit-number is not supported, the next available one is chosen.
+ * </p>
+ * <p>
+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details
+ * about the attached buffer. The details cannot be returned, since it's possible 2 buffers
+ * are being created, depth and stencil.
+ * </p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl
+ * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL}
+ * @param reqBits desired bits for depth or -1 for default (24 bits)
+ * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached.
+ * @throws IllegalArgumentException
+ * @see #getDepthAttachment()
+ * @see #getStencilAttachment()
+ */
+ public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException {
+ if( 0 > reqBits ) {
+ reqBits = 24;
+ }
+ final int internalFormat;
+ int internalStencilFormat = -1;
+
+ switch ( atype ) {
+ case DEPTH:
+ if( 32 <= reqBits && depth32Avail ) {
+ internalFormat = GL.GL_DEPTH_COMPONENT32;
+ } else if( 24 <= reqBits && depth24Avail ) {
+ internalFormat = GL.GL_DEPTH_COMPONENT24;
+ } else {
+ internalFormat = GL.GL_DEPTH_COMPONENT16;
+ }
+ break;
+
+ case STENCIL:
+ if( 16 <= reqBits && stencil16Avail ) {
+ internalFormat = GL2GL3.GL_STENCIL_INDEX16;
+ } else if( 8 <= reqBits && stencil08Avail ) {
+ internalFormat = GL.GL_STENCIL_INDEX8;
+ } else if( 4 <= reqBits && stencil04Avail ) {
+ internalFormat = GL.GL_STENCIL_INDEX4;
+ } else if( 1 <= reqBits && stencil01Avail ) {
+ internalFormat = GL.GL_STENCIL_INDEX1;
+ } else {
+ throw new GLException("stencil buffer n/a");
+ }
+ break;
+
+ case DEPTH_STENCIL:
+ if( packedDepthStencilAvail ) {
+ internalFormat = GL.GL_DEPTH24_STENCIL8;
+ } else {
+ if( 24 <= reqBits && depth24Avail ) {
+ internalFormat = GL.GL_DEPTH_COMPONENT24;
+ } else {
+ internalFormat = GL.GL_DEPTH_COMPONENT16;
+ }
+ if( stencil08Avail ) {
+ internalStencilFormat = GL.GL_STENCIL_INDEX8;
+ } else if( stencil04Avail ) {
+ internalStencilFormat = GL.GL_STENCIL_INDEX4;
+ } else if( stencil01Avail ) {
+ internalStencilFormat = GL.GL_STENCIL_INDEX1;
+ } else {
+ throw new GLException("stencil buffer n/a");
+ }
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
+ }
+
+ attachRenderbufferImpl(gl, atype, internalFormat);
+
+ if(0<=internalStencilFormat) {
+ attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat);
+ }
+ }
+
+ /**
+ * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance,
+ * depending on the <code>internalFormat</code>.
+ * <p>
+ * Stencil and depth buffer can be attached only once.
+ * </p>
+ * <p>
+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details
+ * about the attached buffer. The details cannot be returned, since it's possible 2 buffers
+ * are being created, depth and stencil.
+ * </p>
+ *
+ * <p>Leaves the FBO bound.</p>
+ *
+ * @param gl the current GL context
+ * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32},
+ * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8}
+ * or {@link GL#GL_DEPTH24_STENCIL8}
+ * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached.
+ * @throws IllegalArgumentException
+ * @see #getDepthAttachment()
+ * @see #getStencilAttachment()
+ */
+ public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException {
+ final Attachment.Type atype = Attachment.Type.determine(internalFormat);
+ if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) {
+ throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+ attachRenderbufferImpl(gl, atype, internalFormat);
+ }
+
+ protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException {
+ if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) {
+ throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+ if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) {
+ throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+ attachRenderbufferImpl2(gl, atype, internalFormat);
+ }
+
+ private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException {
+ if( Attachment.Type.DEPTH == atype ) {
+ if(null == depth) {
+ depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0);
+ } else {
+ depth.setSize(width, height);
+ depth.setSamples(samples);
+ }
+ depth.initialize(gl);
+ } else if( Attachment.Type.STENCIL == atype ) {
+ if(null == stencil) {
+ stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0);
+ } else {
+ stencil.setSize(width, height);
+ stencil.setSamples(samples);
+ }
+ stencil.initialize(gl);
+ } else if( Attachment.Type.DEPTH_STENCIL == atype ) {
+ if(null == depth) {
+ depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0);
+ } else {
+ depth.setSize(width, height);
+ depth.setSamples(samples);
+ }
+ depth.initialize(gl);
+ if(null == stencil) {
+ stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName());
+ } else {
+ stencil.setName(depth.getName());
+ stencil.setSize(width, height);
+ stencil.setSamples(samples);
+ }
+ stencil.initialize(gl);
+ }
+
+ bind(gl);
+
+ // Attach the buffer
+ if( Attachment.Type.DEPTH == atype ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
+ } else if( Attachment.Type.STENCIL == atype ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
+ } else if( Attachment.Type.DEPTH_STENCIL == atype ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
+ }
+
+ updateStatus(gl);
+ if( !isStatusValid() ) {
+ detachRenderbuffer(gl, atype);
+ throw new GLException("renderbuffer attachment failed: "+this.getStatusString());
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.attachRenderbuffer: "+this);
+ }
+ }
+
+ /**
+ * <p>Leaves the FBO bound!</p>
+ * @param gl
+ * @param ca
+ * @throws IllegalArgumentException
+ */
+ public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException {
+ if(null == detachColorbufferImpl(gl, attachmentPoint, false)) {
+ throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.detachAll: "+this);
+ }
+ }
+
+ private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) {
+ final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here
+
+ if(null == colbuf) {
+ return null;
+ }
+
+ bind(gl);
+
+ if(colbuf instanceof TextureAttachment) {
+ final TextureAttachment texA = (TextureAttachment) colbuf;
+ if( 0 != texA.getName() ) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_TEXTURE_2D, 0, 0);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ }
+ texA.free(gl);
+ removeColorAttachment(attachmentPoint, texA);
+ if(recreate) {
+ texA.setSize(width, height);
+ attachTexture2D(gl, attachmentPoint, texA);
+ }
+ } else if(colbuf instanceof ColorAttachment) {
+ final ColorAttachment colA = (ColorAttachment) colbuf;
+ if( 0 != colA.getName() ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0+attachmentPoint,
+ GL.GL_RENDERBUFFER, 0);
+ }
+ colA.free(gl);
+ removeColorAttachment(attachmentPoint, colbuf);
+ if(recreate) {
+ colA.setSize(width, height);
+ colA.setSamples(samples);
+ attachColorbuffer(gl, attachmentPoint, colA);
+ }
+ }
+ return colbuf;
+ }
+
+ /**
+ *
+ * @param gl
+ * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL}
+ */
+ public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException {
+ detachRenderbufferImpl(gl, atype, false);
+ }
+
+ public final boolean isDepthStencilPackedFormat() {
+ final boolean res = null != depth && null != stencil &&
+ depth.format == stencil.format ;
+ if(res && depth.getName() != stencil.getName() ) {
+ throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil);
+ }
+ return res;
+ }
+
+ private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException {
+ switch ( atype ) {
+ case DEPTH:
+ case STENCIL:
+ case DEPTH_STENCIL:
+ break;
+ default:
+ throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
+ }
+ if( null == depth && null == stencil ) {
+ return ; // nop
+ }
+ // reduction of possible combinations, create unique atype command(s)
+ final ArrayList<Attachment.Type> actions = new ArrayList<Attachment.Type>(2);
+ if( isDepthStencilPackedFormat() ) {
+ // packed
+ actions.add(Attachment.Type.DEPTH_STENCIL);
+ } else {
+ // individual
+ switch ( atype ) {
+ case DEPTH:
+ if( null != depth ) { actions.add(Attachment.Type.DEPTH); }
+ break;
+ case STENCIL:
+ if( null != stencil ) { actions.add(Attachment.Type.STENCIL); }
+ break;
+ case DEPTH_STENCIL:
+ if( null != depth ) { actions.add(Attachment.Type.DEPTH); }
+ if( null != stencil ) { actions.add(Attachment.Type.STENCIL); }
+ break;
+ default: // handled
+ }
+ }
+
+ bind(gl);
+
+ for(int i = 0; i < actions.size(); i++) {
+ final int format;
+
+ Attachment.Type action = actions.get(i);
+ switch ( action ) {
+ case DEPTH:
+ format = depth.format;
+ if( 0 != depth.getName() ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ depth.free(gl);
+ if(!recreate) {
+ depth = null;
+ }
+ break;
+ case STENCIL:
+ format = stencil.format;
+ if(0 != stencil.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ stencil.free(gl);
+ if(!recreate) {
+ stencil = null;
+ }
+ break;
+ case DEPTH_STENCIL:
+ format = depth.format;
+ if(0 != depth.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ depth.free(gl);
+ stencil.free(gl);
+ if(!recreate) {
+ depth = null;
+ stencil = null;
+ }
+ break;
+ default:
+ throw new InternalError("XXX");
+ }
+ if(recreate) {
+ attachRenderbufferImpl2(gl, action, format);
+ }
+ }
+ }
+
+ /**
+ * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s.
+ * <p>Leaves the FBO bound!</p>
+ * <p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final void detachAll(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAll(gl);
+ }
+ detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */);
+ }
+
+ /**
+ * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s.
+ * <p>Leaves the FBO bound!</p>
+ * <p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final void detachAllColorbuffer(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAllColorbuffer(gl);
+ }
+ detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */);
+ }
+
+ /**
+ * Detaches all {@link TextureAttachment}s
+ * <p>Leaves the FBO bound!</p>
+ * <p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final void detachAllTexturebuffer(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAllTexturebuffer(gl);
+ }
+ for(int i=0; i<maxColorAttachments; i++) {
+ if(colorAttachmentPoints[i] instanceof TextureAttachment) {
+ detachColorbufferImpl(gl, i, false);
+ }
+ }
+ }
+
+ public final void detachAllRenderbuffer(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.detachAllRenderbuffer(gl);
+ }
+ detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, false);
+ }
+
+ private final void detachAllImpl(GL gl, boolean detachNonColorbuffer, boolean recreate) {
+ for(int i=0; i<maxColorAttachments; i++) {
+ detachColorbufferImpl(gl, i, recreate);
+ }
+ if( !recreate && colorAttachmentCount>0 ) {
+ throw new InternalError("Non zero ColorAttachments "+this);
+ }
+
+ if(detachNonColorbuffer) {
+ detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate);
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.detachAll: [resetNonColorbuffer "+detachNonColorbuffer+", recreate "+recreate+"]: "+this);
+ }
+ }
+
+ /**
+ * @param gl the current GL context
+ */
+ public final void destroy(GL gl) {
+ if(null != samplesSink) {
+ samplesSink.destroy(gl);
+ }
+
+ detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */);
+
+ // cache FB names, preset exposed to zero,
+ // braking ties w/ GL/GLContext link to getReadFramebuffer()/getWriteFramebuffer()
+ final int fb_cache = fbName;
+ fbName = 0;
+
+ int name[] = new int[1];
+ if(0!=fb_cache) {
+ name[0] = fb_cache;
+ gl.glDeleteFramebuffers(1, name, 0);
+ }
+ initialized = false;
+ bound = false;
+ if(DEBUG) {
+ System.err.println("FBObject.destroy: "+this);
+ }
+ }
+
+ private final boolean sampleSinkSizeMismatch() {
+ return samplesSink.getWidth() != width || samplesSink.getHeight() != height ;
+ }
+ private final boolean sampleSinkTexMismatch() {
+ return null == samplesSinkTexture || 0 == samplesSinkTexture.getName() ;
+ }
+ private final boolean sampleSinkDepthStencilMismatch() {
+ final boolean depthMismatch = ( null != depth && null == samplesSink.depth ) ||
+ ( null != depth && null != samplesSink.depth &&
+ depth.format != samplesSink.depth.format );
+
+ final boolean stencilMismatch = ( null != stencil && null == samplesSink.stencil ) ||
+ ( null != stencil && null != samplesSink.stencil &&
+ stencil.format != samplesSink.stencil.format );
+
+ return depthMismatch || stencilMismatch;
+ }
+
+ private final void resetMSAATexture2DSink(GL gl) throws GLException {
+ if(0 == samples) {
+ // MSAA off
+ if(null != samplesSink) {
+ samplesSink.detachAll(gl);
+ }
+ return;
+ }
+
+ boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch();
+ boolean sampleSinkTexMismatch = sampleSinkTexMismatch();
+ boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
+
+ /** if(DEBUG) {
+ System.err.println("FBObject.resetMSAATexture2DSink.0: \n\tTHIS "+this+",\n\tSINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ } */
+
+ if(!sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) {
+ // all properties match ..
+ return;
+ }
+
+ unbind(gl);
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetMSAATexture2DSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ }
+
+ if( sampleSinkDepthStencilMismatch ) {
+ samplesSink.detachAllRenderbuffer(gl);
+ }
+
+ if( sampleSinkSizeMismatch ) {
+ samplesSink.reset(gl, width, height);
+ }
+
+ if(null == samplesSinkTexture) {
+ samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true);
+ } else if( 0 == samplesSinkTexture.getName() ) {
+ samplesSinkTexture.setSize(width, height);
+ samplesSink.attachTexture2D(gl, 0, samplesSinkTexture);
+ }
+
+ if( sampleSinkDepthStencilMismatch ) {
+ samplesSink.attachRenderbuffer(gl, depth.format);
+ if( null != stencil && !isDepthStencilPackedFormat() ) {
+ samplesSink.attachRenderbuffer(gl, stencil.format);
+ }
+ }
+
+ sampleSinkSizeMismatch = sampleSinkSizeMismatch();
+ sampleSinkTexMismatch = sampleSinkTexMismatch();
+ sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
+ if(sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) {
+ throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ }
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetMSAATexture2DSink: END\n\tTHIS "+this+",\n\tSINK "+samplesSink+
+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ }
+ }
+
+ /**
+ * Bind this FBO, i.e. bind write framebuffer to {@link #getWriteFramebuffer()}.
+ *
+ * <p>If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()},
+ * if full FBO is supported.</p>
+ *
+ * <p>
+ * In case you have attached more than one color buffer,
+ * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.
+ * </p>
+ * @param gl the current GL context
+ * @throws GLException
+ */
+ public final void bind(GL gl) throws GLException {
+ if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) {
+ checkInitialized();
+ if(samples > 0 && fullFBOSupport) {
+ // draw to multisampling - read from samplesSink
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer());
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer());
+ } else {
+ // one for all
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer());
+ }
+
+ checkNoError(null, gl.glGetError(), "FBObject post-bind"); // throws GLException if error
+ bound = true;
+ samplesSinkDirty = true;
+ }
+ }
+
+ /**
+ * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}.
+ *
+ * <p>If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing
+ * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}</p>
+ *
+ * @param gl the current GL context
+ * @throws GLException
+ */
+ public final void unbind(GL gl) throws GLException {
+ if(bound) {
+ if(fullFBOSupport) {
+ // default read/draw buffers, may utilize GLContext/GLDrawable override of
+ // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer()
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ } else {
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
+ }
+ checkNoError(null, gl.glGetError(), "FBObject post-unbind"); // throws GLException if error
+ bound = false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>.
+ * <p>
+ * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}.
+ * </p>
+ * @param gl the current GL context
+ */
+ public final boolean isBound(GL gl) {
+ bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ;
+ return bound;
+ }
+
+ /** Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>. */
+ public final boolean isBound() { return bound; }
+
+ /**
+ * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}.
+ *
+ * <p>The operation is skipped, if no multisampling is used or
+ * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)},
+ * see {@link #isSamplingBufferDirty()} </p>
+ *
+ * <p>If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
+ * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}</p>
+ *
+ * <p>In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+ * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()});
+ * </p>
+ *
+ * <p>Leaves the FBO unbound.</p>
+ *
+ * @param gl the current GL context
+ * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)}
+ * @throws IllegalArgumentException
+ */
+ public final void syncSamplingBuffer(GL gl) {
+ unbind(gl);
+ if(samples>0 && samplesSinkDirty) {
+ samplesSinkDirty = false;
+ resetMSAATexture2DSink(gl);
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName);
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer());
+ ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK
+ GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST);
+ if(fullFBOSupport) {
+ // default read/draw buffers, may utilize GLContext/GLDrawable override of
+ // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer()
+ gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ } else {
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
+ }
+ }
+ }
+
+ /**
+ * Bind the given texture colorbuffer.
+ *
+ * <p>If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.</p>
+ *
+ * <p>Leaves the FBO unbound!</p>
+ *
+ * @param gl the current GL context
+ * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)}
+ * @throws IllegalArgumentException
+ */
+ public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException {
+ if(null == ta) { throw new IllegalArgumentException("null TextureAttachment"); }
+ if(samples > 0 && samplesSinkTexture == ta) {
+ syncSamplingBuffer(gl);
+ } else {
+ unbind(gl);
+ }
+ gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it ..
+ }
+
+ /**
+ * Unbind texture, ie bind 'non' texture 0
+ *
+ * <p>Leaves the FBO unbound.</p>
+ */
+ public final void unuse(GL gl) {
+ unbind(gl);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it
+ }
+
+ /**
+ * Returns <code>true</code> if <i>basic</i> or <i>full</i> FBO is supported, otherwise <code>false</code>.
+ * @param full <code>true</code> for <i>full</i> FBO supported query, otherwise <code>false</code> for <i>basic</i> FBO support query.
+ * @see #supportsFullFBO(GL)
+ * @see #supportsBasicFBO(GL)
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; }
+
+ /**
+ * Returns <code>true</code> if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise <code>false</code>.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; }
+
+ /**
+ * Returns <code>true</code> if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise <code>false</code>.
+ * @param bits 16, 24 or 32 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsDepth(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 16: return basicFBOSupport;
+ case 24: return depth24Avail;
+ case 32: return depth32Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise <code>false</code>.
+ * @param bits 1, 4, 8 or 16 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsStencil(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 1: return stencil01Avail;
+ case 4: return stencil04Avail;
+ case 8: return stencil08Avail;
+ case 16: return stencil16Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise <code>false</code>.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; }
+
+ /**
+ * Returns the maximum number of colorbuffer attachments.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
+
+ /**
+ * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; }
+
+ /**
+ * Returns <code>true</code> if this instance has been initialized with {@link #reset(GL, int, int)}
+ * or {@link #reset(GL, int, int, int)}, otherwise <code>false</code>
+ */
+ public final boolean isInitialized() { return initialized; }
+ /** Returns the width */
+ public final int getWidth() { return width; }
+ /** Returns the height */
+ public final int getHeight() { return height; }
+ /** Returns the number of samples for multisampling (MSAA). zero if no multisampling is used. */
+ public final int getNumSamples() { return samples; }
+ /** Returns the framebuffer name to render to. */
+ public final int getWriteFramebuffer() { return fbName; }
+ /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
+ public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; }
+ /** Return the number of color/texture attachments */
+ public final int getColorAttachmentCount() { return colorAttachmentCount; }
+ /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getStencilAttachment() { return stencil; }
+ /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getDepthAttachment() { return depth; }
+
+ /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */
+ public final FBObject getSamplingSinkFBO() { return samplesSink; }
+
+ /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */
+ public final TextureAttachment getSamplingSink() { return samplesSinkTexture; }
+ /**
+ * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer)
+ * has been flagged dirty by a previous call of {@link #bind(GL)},
+ * otherwise <code>false</code>.
+ */
+ public final boolean isSamplingBufferDirty() { return samplesSinkDirty; }
+
+ int objectHashCode() { return super.hashCode(); }
+
+ public final String toString() {
+ final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ;
+ return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+
+ ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+
+ ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+
+ ", obj 0x"+Integer.toHexString(objectHashCode())+"]";
+ }
+
+ private final void updateStatus(GL gl) {
+ if( 0 == fbName ) {
+ vStatus = -1;
+ } else {
+ vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
new file mode 100644
index 000000000..f7e25fa01
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -0,0 +1,81 @@
+/**
+ * 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;
+
+/**
+ * Class holding OpenGL extension strings, commonly used by JOGL's implementation.
+ */
+public class GLExtensions {
+ public static final String VERSION_1_2 = "GL_VERSION_1_2";
+ public static final String VERSION_1_4 = "GL_VERSION_1_4";
+ public static final String VERSION_1_5 = "GL_VERSION_1_5";
+ public static final String VERSION_2_0 = "GL_VERSION_2_0";
+
+ public static final String ARB_debug_output = "GL_ARB_debug_output";
+ public static final String AMD_debug_output = "GL_AMD_debug_output";
+
+ public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object";
+ public static final String OES_framebuffer_object = "GL_OES_framebuffer_object";
+ public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object";
+ public static final String EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
+ public static final String EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
+ public static final String EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
+ public static final String OES_depth24 = "GL_OES_depth24";
+ public static final String OES_depth32 = "GL_OES_depth32";
+ public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil";
+ public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments";
+
+ public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
+
+ public static final String EXT_abgr = "GL_EXT_abgr";
+ public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8";
+ public static final String OES_stencil1 = "GL_OES_stencil1";
+ public static final String OES_stencil4 = "GL_OES_stencil4";
+ public static final String OES_stencil8 = "GL_OES_stencil8";
+ public static final String APPLE_float_pixels = "GL_APPLE_float_pixels";
+
+ public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
+ public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle";
+ public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle";
+ public static final String NV_texture_rectangle = "GL_NV_texture_rectangle";
+ public static final String EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
+ public static final String IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
+ public static final String EXT_texture_compression_s3tc = "GL_EXT_texture_compression_s3tc";
+ public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc";
+ public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap";
+ public static final String OES_read_format = "GL_OES_read_format";
+
+ public static final String OES_EGL_image_external = "GL_OES_EGL_image_external";
+
+ //
+ // Aliased GLX/WGL/.. extensions
+ //
+
+ public static final String ARB_pixel_format = "GL_ARB_pixel_format";
+ public static final String ARB_pbuffer = "GL_ARB_pbuffer";
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 75785fd86..cdb4b82bb 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -93,11 +93,13 @@ public class JoglVersion extends JogampVersion {
return sb;
}
- public static StringBuilder getDefaultOpenGLInfo(StringBuilder sb, boolean withCapabilitiesInfo) {
+ public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) {
if(null==sb) {
sb = new StringBuilder();
}
- final AbstractGraphicsDevice device = GLProfile.getDefaultDevice();
+ if(null == device) {
+ device = GLProfile.getDefaultDevice();
+ }
sb.append("Default Profiles on device ").append(device).append(Platform.getNewline());
if(null!=device) {
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
@@ -120,13 +122,21 @@ public class JoglVersion extends JogampVersion {
if(null==sb) {
sb = new StringBuilder();
}
- GLContext ctx = gl.getContext();
-
+
sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline());
sb.append(device.getClass().getSimpleName()).append("[type ")
.append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline());
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
sb.append(Platform.getNewline());
+
+ return getGLStrings(gl, sb);
+ }
+
+ public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ final GLContext ctx = gl.getContext();
sb.append("Swap Interval ").append(gl.getSwapInterval());
sb.append(Platform.getNewline());
sb.append("GL Profile ").append(gl.getGLProfile());
diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
new file mode 100644
index 000000000..8450ffdb0
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
@@ -0,0 +1,98 @@
+/**
+ * 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 javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.opengl.GLAutoDrawableDelegate;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.GLFBODrawableImpl;
+
+/**
+ * Platform-independent class exposing FBO offscreen functionality to
+ * applications.
+ * <p>
+ * This class distinguishes itself from {@link GLAutoDrawableDelegate}
+ * with it's {@link #setSize(int, int)} functionality.
+ * </p>
+ */
+public class OffscreenAutoDrawable extends GLAutoDrawableDelegate {
+
+ /**
+ * @param drawable a valid {@link GLDrawable}, may not be realized yet.
+ * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass <code>false</code>. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) {
+ super(drawable, context, null, ownDevice);
+ }
+
+ /**
+ * Attempts to resize this offscreen auto drawable, if supported
+ * by the underlying {@link GLDrawable).
+ * @param newWidth
+ * @param newHeight
+ * @return <code>true</code> if resize was executed, otherwise <code>false</code>.
+ * @throws GLException in case of an error during the resize operation
+ */
+ public boolean setSize(int newWidth, int newHeight) throws GLException {
+ boolean done = false;
+ if(drawable instanceof GLFBODrawableImpl) {
+ context.makeCurrent();
+ try {
+ ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight);
+ done = true;
+ } finally {
+ context.release();
+ }
+ }
+ if(done) {
+ this.defaultWindowResizedOp();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * If the underlying {@link GLDrawable} is an FBO implementation
+ * and contains an {#link FBObject}, the same is returned.
+ * Otherwise returns <code>null</code>.
+ */
+ public FBObject getFBObject() {
+ if(drawable instanceof GLFBODrawableImpl) {
+ return ((GLFBODrawableImpl)drawable).getFBObject();
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 5ee58b78d..8d237162c 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -45,6 +45,7 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.Threading;
+import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
@@ -63,27 +64,19 @@ import org.eclipse.swt.widgets.Shell;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.JoglVersion;
/**
* Native SWT Canvas implementing GLAutoDrawable
- * <p>
- * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (impossible),
- * proper recursive locking is required for drawable/context @ destroy and display.
- * Recreation etc could pull those instances while animating!
- * Simply locking before using drawable/context offthread
- * would allow a deadlock situation!
- * </p>
- * <p>
- * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized.
- In case any of the methods are called outside of a locked state
- extra care should be added. Maybe we shall expose locking facilities to the user.
- However, since the user shall stick to the GLEventListener model while utilizing
- GLAutoDrawable implementations, she is safe due to the implicit locked state.
- * </p>
+ *
+ * <p>Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.</p>
+ *
*/
public class GLCanvas extends Canvas implements GLAutoDrawable {
+ private static final boolean DEBUG = Debug.debug("GLCanvas");
/*
* Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled
@@ -97,22 +90,25 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
//private static final boolean useSWTThread = ThreadingImpl.getMode() != ThreadingImpl.WORKER;
/* GL Stuff */
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
private final GLDrawableHelper helper = new GLDrawableHelper();
- private volatile GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display
+
+ private final GLContext shareWith;
+ private final GLCapabilitiesImmutable capsRequested;
+ private final GLCapabilitiesChooser capsChooser;
+
+ private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
private GLContext context;
/* Native window surface */
private AbstractGraphicsDevice device;
- private final long nativeWindowHandle;
- private final ProxySurface proxySurface;
/* Construction parameters stored for GLAutoDrawable accessor methods */
private int additionalCtxCreationFlags = 0;
- private final GLCapabilitiesImmutable glCapsRequested;
/* Flag indicating whether an unprocessed reshape is pending. */
- private volatile boolean sendReshape;
+ private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking
/*
* Invokes init(...) on all GLEventListeners. Assumes context is current when run.
@@ -141,10 +137,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Action to make specified context current prior to running displayAction */
- private final Runnable makeCurrentAndDisplayAction = new Runnable() {
+ private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, displayAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -157,10 +159,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Swaps buffers, making the GLContext current first */
- private final Runnable makeCurrentAndSwapBuffersAction = new Runnable() {
+ private final Runnable makeCurrentAndSwapBuffersOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -181,16 +189,33 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
private final Runnable disposeOnEDTGLAction = new Runnable() {
@Override
public void run() {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
- }
- };
-
- private final Runnable disposeGraphicsDeviceAction = new Runnable() {
- @Override
- public void run() {
- if (null != device) {
- device.close();
- device = null;
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if (null != drawable && null != context) {
+ boolean animatorPaused = false;
+ final GLAnimatorControl animator = getAnimator();
+ if (null != animator) {
+ animatorPaused = animator.pause();
+ }
+
+ if(context.isCreated()) {
+ helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
+ }
+
+ if (animatorPaused) {
+ animator.resume();
+ }
+ }
+ // SWT is owner of the device handle, not us.
+ // Hence close() operation is a NOP.
+ if (null != device) {
+ device.close();
+ device = null;
+ }
+ SWTAccessor.setRealized(GLCanvas.this, false); // unrealize ..
+ } finally {
+ _lock.unlock();
}
}
};
@@ -200,6 +225,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
*/
private volatile Rectangle clientArea;
+ /**
+ * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)}
+ * on the SWT thread.
+ *
+ * @param parent
+ * Required (non-null) parent Composite.
+ * @param style
+ * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
+ * Canvas constructor, so OpenGL handles the background.
+ * @param caps
+ * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
+ * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
+ * actually used may differ based on the capabilities of the graphics device.
+ * @param chooser
+ * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
+ * requested GLCapabilities, and the available capabilities of the graphics device.
+ * @param shareWith
+ * Optional GLContext to share state (textures, vbos, shaders, etc.) with.
+ * @return a new instance
+ */
+ public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps,
+ final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+ final GLCanvas[] res = new GLCanvas[] { null };
+ parent.getDisplay().syncExec(new Runnable() {
+ public void run() {
+ res[0] = new GLCanvas( parent, style, caps, chooser, shareWith );
+ }
+ });
+ return res[0];
+ }
+
/**
* Creates a new SWT GLCanvas.
*
@@ -229,35 +285,29 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
clientArea = GLCanvas.this.getClientArea();
- /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
device = SWTAccessor.getDevice(this);
- /* Native handle for the control, used to associate with GLContext */
- nativeWindowHandle = SWTAccessor.getWindowHandle(this);
/* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
if(null == caps) {
caps = new GLCapabilities(GLProfile.getDefault(device));
}
- glCapsRequested = caps;
-
- final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
-
- /* Create a NativeWindow proxy for the SWT canvas */
- proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, caps, chooser);
-
- /* Associate a GL surface with the proxy */
- drawable = glFactory.createGLDrawable(proxySurface);
- drawable.setRealized(true);
-
- context = drawable.createContext(shareWith);
-
+ this.capsRequested = caps;
+ this.capsChooser = chooser;
+ this.shareWith = shareWith;
+
+ // post create .. when ready
+ drawable = null;
+ context = null;
+
/* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
/* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
addPaintListener(new PaintListener() {
@Override
public void paintControl(final PaintEvent arg0) {
- if (!helper.isExternalAnimatorAnimating()) {
- display();
+ if ( !helper.isExternalAnimatorAnimating() ) {
+ display(); // checks: null != drawable
}
}
});
@@ -265,12 +315,112 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
addControlListener(new ControlAdapter() {
@Override
public void controlResized(final ControlEvent arg0) {
- clientArea = GLCanvas.this.getClientArea();
- /* Mark for OpenGL reshape next time the control is painted */
- sendReshape = true;
+ updateSizeCheck();
}
});
}
+ private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final void destroy(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return clientArea.width;
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return clientArea.height;
+ }
+
+ @Override
+ public String toString() {
+ return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]";
+ }
+ };
+
+ protected final void updateSizeCheck() {
+ final Rectangle oClientArea = clientArea;
+ final Rectangle nClientArea = GLCanvas.this.getClientArea();
+ if ( nClientArea != null &&
+ ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
+ ) {
+ clientArea = nClientArea; // write back new value
+ sendReshape = true; // Mark for OpenGL reshape next time the control is painted
+ }
+ }
+
+ @Override
+ public void display() {
+ if( null != drawable || validateDrawableAndContext() ) {
+ runInGLThread(makeCurrentAndDisplayOnEDTAction);
+ }
+ }
+
+
+ /** assumes drawable == null ! */
+ protected final boolean validateDrawableAndContext() {
+ if( GLCanvas.this.isDisposed() ) {
+ return false;
+ }
+ final Rectangle nClientArea = clientArea;
+ if(0 == nClientArea.width * nClientArea.height) {
+ return false;
+ }
+
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
+
+ /* Native handle for the control, used to associate with GLContext */
+ final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+
+ /* Create a NativeWindow proxy for the SWT canvas */
+ ProxySurface proxySurface = null;
+ try {
+ proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle,
+ capsRequested, capsChooser, swtCanvasUpStreamHook);
+ } catch (GLException gle) {
+ // not ready yet ..
+ if(DEBUG) { System.err.println(gle.getMessage()); }
+ }
+
+ if(null != proxySurface) {
+ /* Associate a GL surface with the proxy */
+ drawable = glFactory.createGLDrawable(proxySurface);
+ drawable.setRealized(true);
+
+ context = drawable.createContext(shareWith);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ final boolean res = null != drawable;
+ if(DEBUG && res) {
+ System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
+ Thread.dumpStack();
+ }
+ return res;
+ }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
@Override
public void addGLEventListener(final GLEventListener arg0) {
@@ -296,11 +446,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
- public void display() {
- runInGLThread(makeCurrentAndDisplayAction);
- }
-
- @Override
public GLAnimatorControl getAnimator() {
return helper.getAnimator();
}
@@ -312,7 +457,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext getContext() {
- return context;
+ return null != drawable ? context : null;
}
@Override
@@ -322,7 +467,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GL getGL() {
- return (null == context) ? null : context.getGL();
+ final GLContext _context = context;
+ return (null == _context) ? null : _context.getGL();
}
@Override
@@ -352,27 +498,35 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext setContext(GLContext newCtx) {
- final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
- context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ if(newCtxCurrent) {
+ context.makeCurrent();
+ }
+ return oldCtx;
+ } finally {
+ _lock.unlock();
}
- return oldCtx;
}
@Override
public void setContextCreationFlags(final int arg0) {
additionalCtxCreationFlags = arg0;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
}
}
@Override
public GL setGL(final GL arg0) {
- if (null != context) {
- context.setGL(arg0);
+ final GLContext _context = context;
+ if (null != _context) {
+ _context.setGL(arg0);
return arg0;
}
return null;
@@ -380,17 +534,24 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext createContext(final GLContext shareWith) {
- if(drawable != null) {
- final GLContext _ctx = drawable.createContext(shareWith);
- _ctx.setContextCreationFlags(additionalCtxCreationFlags);
- return _ctx;
+ 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();
}
- return null;
}
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null;
}
/**
@@ -399,46 +560,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @return Non-null GLCapabilities.
*/
public GLCapabilitiesImmutable getRequestedGLCapabilities() {
- return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null;
}
@Override
public GLDrawableFactory getFactory() {
- return (drawable != null) ? drawable.getFactory() : null;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.getFactory() : null;
}
@Override
public GLProfile getGLProfile() {
- return glCapsRequested.getGLProfile();
+ return capsRequested.getGLProfile();
}
@Override
public long getHandle() {
- return (drawable != null) ? drawable.getHandle() : 0;
- }
-
- @Override
- public int getHeight() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.height;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.getHandle() : 0;
}
@Override
public NativeSurface getNativeSurface() {
- return (drawable != null) ? drawable.getNativeSurface() : null;
- }
-
- @Override
- public int getWidth() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.width;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.getNativeSurface() : null;
}
@Override
public boolean isRealized() {
- return (drawable != null) ? drawable.isRealized() : false;
+ final GLDrawable _drawable = drawable;
+ return (_drawable != null) ? _drawable.isRealized() : false;
}
@Override
@@ -448,41 +600,18 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public void swapBuffers() throws GLException {
- runInGLThread(makeCurrentAndSwapBuffersAction);
+ runInGLThread(makeCurrentAndSwapBuffersOnEDTAction);
}
- // FIXME: API of update() method ?
@Override
public void update() {
- // FIXME: display();
+ // don't paint background etc .. nop avoids flickering
}
@Override
public void dispose() {
- if (null != drawable && null != context) { // drawable is volatile!
- boolean animatorPaused = false;
- final GLAnimatorControl animator = getAnimator();
- if (null != animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
-
- if(context.isCreated()) {
- runInGLThread(disposeOnEDTGLAction);
- }
-
- if (animatorPaused) {
- animator.resume();
- }
- }
- final Display display = getDisplay();
-
- if (display.getThread() == Thread.currentThread()) {
- disposeGraphicsDeviceAction.run();
- } else {
- display.syncExec(disposeGraphicsDeviceAction);
- }
- super.dispose();
+ runInGLThread(disposeOnEDTGLAction);
+ super.dispose();
}
/**
@@ -501,7 +630,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @see Platform#AWT_AVAILABLE
* @see Platform#getOSType()
*/
- private void runInGLThread(final Runnable action) {
+ private static void runInGLThread(final Runnable action) {
if(Platform.OSType.MACOS == Platform.OS_TYPE) {
SWTAccessor.invoke(true, action);
} else {
@@ -515,7 +644,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Display display = new Display();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
deleted file mode 100644
index 3e049a334..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 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:
- *
- * - 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.
- *
- */
-
-package com.jogamp.opengl.util;
-
-import javax.media.opengl.*;
-
-public class FBObject {
- static final int MAX_FBO_TEXTURES = 32; // just for our impl .. not the real 'max' FBO color attachments
- private int[] fbo_tex_names;
- private int[] fbo_tex_units;
- private int fbo_tex_num;
- private int colorattachment_num;
-
- private boolean initialized;
- private int width, height;
- private int fb, depth_rb, stencil_rb, vStatus;
- private boolean bound;
-
- public FBObject(int width, int height) {
- this.fbo_tex_names = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_units = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_num = 0;
- this.colorattachment_num = 0;
- this.initialized = false;
- this.width = width;
- this.height = height;
- this.fb = 0;
- this.depth_rb = 0;
- this.stencil_rb = 0;
- this.bound = false;
- }
-
- /**
- * @return true if the FB status is valid, otherwise false
- * @see #getStatus()
- */
- public boolean isStatusValid() {
- switch(vStatus) {
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return true;
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
- case 0:
- default:
- System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
- " : " + getStatusString(vStatus));
- return false;
- }
- }
-
- /**
- * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
- * @see #validateStatus()
- */
- public int getStatus() {
- return vStatus;
- }
-
- public String getStatusString() {
- return getStatusString(vStatus);
- }
-
- public static final String getStatusString(int fbStatus) {
- switch(fbStatus) {
- case -1:
- return "NOT A FBO";
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return "OK";
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- return("GL FBO: Unsupported framebuffer format");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- return("GL FBO: incomplete, incomplete attachment\n");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- return("GL FBO: incomplete, missing attachment");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- return("GL FBO: incomplete, attached images must have same dimensions");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- return("GL FBO: incomplete, attached images must have same format");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- return("GL FBO: incomplete, missing draw buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- return("GL FBO: incomplete, missing read buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- return("GL FBO: incomplete, missing multisample buffer");
- case 0:
- return("GL FBO: incomplete, implementation fault");
- default:
- return("GL FBO: incomplete, implementation ERROR");
- }
- }
-
- private boolean checkNoError(GL gl, int err, String exceptionMessage) {
- if(GL.GL_NO_ERROR != err) {
- if(null != gl) {
- destroy(gl);
- }
- if(null != exceptionMessage) {
- throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
- }
- return false;
- }
- return true;
- }
-
- private final void checkInitialized() {
- if(!initialized) {
- throw new GLException("FBO not initialized, call init(GL) first.");
- }
- }
-
- private final void checkBound(GL gl, boolean shallBeBound) {
- checkInitialized();
- if(bound != shallBeBound) {
- final String s0 = shallBeBound ? "not" : "already" ;
- throw new GLException("FBO "+s0+" bound "+toString());
- }
- checkNoError(null, gl.glGetError(), "FBObject pre"); // throws GLException if error
- }
-
- /**
- * Initializes this FBO's instance with it's texture.
- *
- * <p>Leaves the FBO bound!</p>
- *
- * @param gl the current GL context
- * @throws GLException in case of an error
- */
- public void init(GL gl) throws GLException {
- if(initialized) {
- throw new GLException("FBO already initialized");
- }
- checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error
-
- // generate fbo ..
- int name[] = new int[1];
-
- gl.glGenFramebuffers(1, name, 0);
- fb = name[0];
- if(fb==0) {
- throw new GLException("null generated framebuffer");
- }
-
- // bind fbo ..
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb);
- checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error
- if(!gl.glIsFramebuffer(fb)) {
- checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
- }
- bound = true;
- initialized = true;
-
- updateStatus(gl);
- }
-
- /**
- * Attaches a[nother] Texture2D Color Buffer to this FBO's instance,
- * selecting the texture data type and format automatically.
- * <p>This may be done as many times as many color attachments are supported,
- * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- *
- * @param gl the current GL context
- * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)}
- * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
- * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
- * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
- * @return idx of the new attached texture, otherwise -1
- * @throws GLException in case of an error
- */
- public int attachTexture2D(GL gl, int texUnit, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
- final int textureInternalFormat, textureDataFormat, textureDataType;
- if(gl.isGLES()) {
- textureInternalFormat=GL.GL_RGBA;
- textureDataFormat=GL.GL_RGBA;
- textureDataType=GL.GL_UNSIGNED_BYTE;
- } else {
- textureInternalFormat=GL.GL_RGBA8;
- textureDataFormat=GL.GL_BGRA;
- textureDataType=GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
- }
- return attachTexture2D(gl, texUnit, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
- }
-
- /**
- * Attaches a[nother] Texture2D Color Buffer to this FBO's instance,
- * selecting the texture data type and format automatically.
- * <p>This may be done as many times as many color attachments are supported,
- * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- *
- * @param gl the current GL context
- * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)}
- * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param textureDataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
- * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
- * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
- * @return index of the texture colorbuffer if bound and configured successfully, otherwise -1
- * @throws GLException in case the texture colorbuffer couldn't be allocated
- */
- public int attachTexture2D(GL gl, int texUnit,
- int textureInternalFormat, int textureDataFormat, int textureDataType,
- int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
- checkBound(gl, true);
- final int fbo_tex_idx = fbo_tex_num;
- gl.glGenTextures(1, fbo_tex_names, fbo_tex_num);
- if(fbo_tex_names[fbo_tex_idx]==0) {
- throw new GLException("null generated texture");
- }
- fbo_tex_units[fbo_tex_idx] = texUnit;
- fbo_tex_num++;
- if(0<=texUnit) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
- }
- gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx]);
- checkNoError(gl, gl.glGetError(), "FBObject Init.bindTex"); // throws GLException if error
- gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, textureInternalFormat, width, height, 0,
- textureDataFormat, textureDataType, null);
- int glerr = gl.glGetError();
- if(GL.GL_NO_ERROR != glerr) {
- int[] sz = new int[1];
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0);
- // throws GLException if error
- checkNoError(gl, glerr, "FBObject Init.texImage2D: "+
- " int-fmt 0x"+Integer.toHexString(textureInternalFormat)+
- ", "+width+"x"+height+
- ", data-fmt 0x"+Integer.toHexString(textureDataFormat)+
- ", data-type 0x"+Integer.toHexString(textureDataType)+
- ", max tex-sz "+sz[0]);
- }
- if( 0 < magFilter ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
- }
- if( 0 < minFilter ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
- }
- if( 0 < wrapS ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
- }
- if( 0 < wrapT ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
- }
-
- // Set up the color buffer for use as a renderable texture:
- gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0 + colorattachment_num++,
- GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx], 0);
-
- updateStatus(gl);
- return isStatusValid() ? fbo_tex_idx : -1;
- }
-
- /**
- * Attaches one Depth Buffer to this FBO's instance.
- * <p>This may be done only one time.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- * @param gl the current GL context
- * @param depthComponentType {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32}
- * @return true if the depth renderbuffer could be bound and configured, otherwise false
- * @throws GLException in case the depth renderbuffer couldn't be allocated or one is already attached.
- */
- public boolean attachDepthBuffer(GL gl, int depthComponentType) throws GLException {
- checkBound(gl, true);
- if(depth_rb != 0) {
- throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")");
- }
- int name[] = new int[1];
- gl.glGenRenderbuffers(1, name, 0);
- depth_rb = name[0];
- if(depth_rb==0) {
- throw new GLException("null generated renderbuffer");
- }
- // Initialize the depth buffer:
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb);
- if(!gl.glIsRenderbuffer(depth_rb)) {
- System.err.println("not a depthbuffer: "+ depth_rb);
- name[0] = depth_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- depth_rb=0;
- return false;
- }
-
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height);
- // Set up the depth buffer attachment:
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
- GL.GL_DEPTH_ATTACHMENT,
- GL.GL_RENDERBUFFER, depth_rb);
- updateStatus(gl);
- return isStatusValid();
- }
-
- /**
- * Attaches one Stencil Buffer to this FBO's instance.
- * <p>This may be done only one time.</p>
- *
- * <p>Assumes a bound FBO</p>
- * <p>Leaves the FBO bound!</p>
- * @param gl the current GL context
- * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8}
- * @return true if the stencil renderbuffer could be bound and configured, otherwise false
- * @throws GLException in case the stencil renderbuffer couldn't be allocated or one is already attached.
- */
- public boolean attachStencilBuffer(GL gl, int stencilComponentType) throws GLException {
- checkBound(gl, true);
- if(stencil_rb != 0) {
- throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")");
- }
- int name[] = new int[1];
- gl.glGenRenderbuffers(1, name, 0);
- stencil_rb = name[0];
- if(stencil_rb==0) {
- throw new GLException("null generated stencilbuffer");
- }
- // Initialize the stencil buffer:
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb);
- if(!gl.glIsRenderbuffer(stencil_rb)) {
- System.err.println("not a stencilbuffer: "+ stencil_rb);
- name[0] = stencil_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- stencil_rb=0;
- return false;
- }
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height);
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
- GL.GL_STENCIL_ATTACHMENT,
- GL.GL_RENDERBUFFER, stencil_rb);
- updateStatus(gl);
- return isStatusValid();
- }
-
- /**
- * @param gl the current GL context
- */
- public void destroy(GL gl) {
- if(bound) {
- unbind(gl);
- }
-
- int name[] = new int[1];
-
- if(0!=stencil_rb) {
- name[0] = stencil_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- stencil_rb = 0;
- }
- if(0!=depth_rb) {
- name[0] = depth_rb;
- gl.glDeleteRenderbuffers(1, name, 0);
- depth_rb=0;
- }
- if(null!=fbo_tex_names && fbo_tex_num>0) {
- gl.glDeleteTextures(1, fbo_tex_names, fbo_tex_num);
- fbo_tex_names = new int[MAX_FBO_TEXTURES];
- fbo_tex_units = new int[MAX_FBO_TEXTURES];
- fbo_tex_num = 0;
- }
- colorattachment_num = 0;
- if(0!=fb) {
- name[0] = fb;
- gl.glDeleteFramebuffers(1, name, 0);
- fb = 0;
- }
- initialized = false;
- }
-
- /**
- * Bind this FBO
- * <p>In case you have attached more than one color buffer,
- * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.</p>
- * @param gl the current GL context
- */
- public void bind(GL gl) {
- checkBound(gl, false);
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb);
- bound = true;
- }
-
- /**
- * Unbind FBO, ie bind 'non' FBO 0
- * @param gl the current GL context
- */
- public void unbind(GL gl) {
- checkBound(gl, true);
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
- bound = false;
- }
-
- /**
- * Bind the texture with given index.
- *
- * <p>If a valid texture unit was named via {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)},
- * the unit is activated via {@link GL#glActiveTexture(int) glActiveTexture(GL.GL_TEXTURE0 + unit)}.</p>
- * @param gl the current GL context
- * @param texIdx index of the texture to use, prev. attached w/ {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)}
- */
- public void use(GL gl, int texIdx) {
- checkBound(gl, false);
- if(texIdx >= fbo_tex_num) {
- throw new GLException("Invalid texId, only "+fbo_tex_num+" textures are attached");
- }
- if(0<=fbo_tex_units[texIdx]) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + fbo_tex_units[texIdx]);
- }
- gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[texIdx]); // use it ..
- }
-
- /** Unbind texture, ie bind 'non' texture 0 */
- public void unuse(GL gl) {
- checkBound(gl, false);
- gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it
- }
-
- public final boolean isBound() { return bound; }
- public final int getWidth() { return width; }
- public final int getHeight() { return height; }
- public final int getFBName() { return fb; }
- public final int getTextureNumber() { return fbo_tex_num; }
- public final int getTextureName(int idx) { return fbo_tex_names[idx]; }
-
- /** @return the named texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit was desired. */
- public final int getTextureUnit(int idx) { return fbo_tex_units[idx]; }
- public final int getColorAttachmentNumber() { return colorattachment_num; }
- public final int getStencilBuffer() { return stencil_rb; }
- public final int getDepthBuffer() { return depth_rb; }
- public final String toString() {
- return "FBO[name "+fb+", size "+width+"x"+height+", color num "+colorattachment_num+", tex num "+fbo_tex_num+", depth "+depth_rb+", stencil "+stencil_rb+"]";
- }
-
- private void updateStatus(GL gl) {
- if(!gl.glIsFramebuffer(fb)) {
- vStatus = -1;
- } else {
- vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
- }
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index 8401b9cd2..331d6fa4e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -39,6 +39,7 @@
package com.jogamp.opengl.util;
import com.jogamp.common.nio.Buffers;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
@@ -56,22 +57,32 @@ import java.nio.*;
public class GLBuffers extends Buffers {
/**
- * @param glType shall be one of
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27)
+ * @param glType shall be one of (29) <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL.GL_HALF_FLOAT, GLES2.GL_HALF_FLOAT_OES: <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
* @return -1 if glType is unhandled, otherwise the actual value > 0
*/
public static final int sizeOfGLType(int glType) {
- switch (glType) { // 25
+ switch (glType) { // 29
+ // case GL2.GL_BITMAP:
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
@@ -86,6 +97,8 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
return SIZEOF_SHORT;
case GL.GL_FIXED:
@@ -108,29 +121,38 @@ public class GLBuffers extends Buffers {
case GL.GL_FLOAT:
return SIZEOF_FLOAT;
- case GL2.GL_DOUBLE:
+ case GL2GL3.GL_DOUBLE:
return SIZEOF_DOUBLE;
}
return -1;
}
/**
- * @param glType shall be one of
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27)
+ * @param glType shall be one of (29) <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
* @return null if glType is unhandled, otherwise the new Buffer object
*/
public static final Buffer newDirectGLBuffer(int glType, int numElements) {
- switch (glType) {
+ switch (glType) { // 29
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
@@ -145,6 +167,8 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
return newDirectShortBuffer(numElements);
case GL.GL_FIXED:
@@ -174,18 +198,26 @@ public class GLBuffers extends Buffers {
}
/**
- * @param glType shall be one of
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27)
+ * @param glType shall be one of (29) <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
* @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object
*/
public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) {
@@ -195,7 +227,7 @@ public class GLBuffers extends Buffers {
parent.position(bytePos);
parent.limit(bytePos + byteLen);
- switch (glType) {
+ switch (glType) { // 29
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
@@ -210,6 +242,8 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
return parent.asShortBuffer();
case GL.GL_FIXED:
@@ -362,28 +396,46 @@ public class GLBuffers extends Buffers {
*
* @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
*
- * @param format must be one of
- * GL_COLOR_INDEX, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
- * GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE,
- * GL_RG, GL_LUMINANCE_ALPHA,
- * GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_ABGR_EXT,
- * GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER,
- * GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER,
- * GL_RGBA_INTEGER, GL_BGRA_INTEGER, GL_HILO_NV, GL_SIGNED_HILO_NV (26)
+ * @param format must be one of (26) <br/>
+ * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
+ * GL_RED GL_RED_INTEGER <br/>
+ * GL_GREEN GL_GREEN_INTEGER <br/>
+ * GL_BLUE GL_BLUE_INTEGER <br/>
+ * GL_ALPHA GL_LUMINANCE (12) <br/>
+ * <br/>
+ * GL_LUMINANCE_ALPHA GL_RG <br/>
+ * GL_RG_INTEGER GL_HILO_NV <br/>
+ * GL_SIGNED_HILO_NV (5) <br/>
+ * <br/>
+ * GL_RGB GL_RGB_INTEGER <br/>
+ * GL_BGR GL_BGR_INTEGER (4)<br/>
+ * <br/>
+ * GL_RGBA GL_RGBA_INTEGER <br/>
+ * GL_BGRA GL_BGRA_INTEGER <br/>
+ * GL_ABGR_EXT (5)<br/>
*
- * @param type must be one of
- * GL_BITMAP,
- * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
- * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
- * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
- * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
- * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
- * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
- * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
- * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
- * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
- * GL_HILO16_NV, GL_SIGNED_HILO16_NV (28)
+ * @param type must be one of (30) <br/>
+ * GL_BITMAP, <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
*
* @param width in pixels
* @param height in pixels
@@ -402,7 +454,7 @@ public class GLBuffers extends Buffers {
if (height < 0) return 0;
if (depth < 0) return 0;
- switch (format) /* 24 */ {
+ switch (format) /* 26 */ {
case GL2.GL_COLOR_INDEX:
case GL2GL3.GL_STENCIL_INDEX:
case GL2GL3.GL_DEPTH_COMPONENT:
@@ -445,7 +497,7 @@ public class GLBuffers extends Buffers {
throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
}
- switch (type) /* 26 */ {
+ switch (type) /* 30 */ {
case GL2.GL_BITMAP:
if (GL2.GL_COLOR_INDEX == format || GL2GL3.GL_STENCIL_INDEX == format) {
return (depth * (height * ((width+7)/8)));
@@ -460,6 +512,7 @@ public class GLBuffers extends Buffers {
case GLES2.GL_HALF_FLOAT_OES:
esize = 2;
break;
+ case GL.GL_FIXED:
case GL2ES2.GL_INT:
case GL.GL_UNSIGNED_INT:
case GL.GL_FLOAT:
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index 368cbc0a2..b0fae8a6d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -35,6 +35,7 @@ import java.io.IOException;
import java.nio.*;
import javax.media.opengl.*;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
@@ -67,6 +68,10 @@ public class GLReadBufferUtil {
return null!=readTextureData && null!=readPixelBuffer ;
}
+ public boolean hasAlpha() { return 4 == components ? true : false ; }
+
+ public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
+
/**
* @return the raw pixel ByteBuffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}
*/
@@ -104,13 +109,14 @@ public class GLReadBufferUtil {
/**
* Read the drawable's pixels to TextureData and Texture, if requested at construction
*
- * @param gl the current GL object
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
* @param drawable the drawable to read from
* @param flip weather to flip the data vertically or not
*
* @see #GLReadBufferUtil(boolean, boolean)
*/
- public boolean readPixels(GL gl, GLDrawable drawable, boolean flip) {
+ public boolean readPixels(GL gl, boolean flip) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
final int textureInternalFormat, textureDataFormat, textureDataType;
final int[] glImplColorReadVals = new int[] { 0, 0 };
@@ -118,7 +124,7 @@ public class GLReadBufferUtil {
textureInternalFormat=GL.GL_RGB;
textureDataFormat=GL.GL_RGB;
textureDataType = GL.GL_UNSIGNED_BYTE;
- } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable("GL_OES_read_format")) {
+ } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable(GLExtensions.OES_read_format)) {
gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
index 3b817afcf..cf0373044 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
@@ -1,15 +1,20 @@
package com.jogamp.opengl.util;
-import com.jogamp.common.util.*;
-import com.jogamp.opengl.util.glsl.ShaderState;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.*;
+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 java.nio.*;
-import java.util.Iterator;
-import java.util.ArrayList;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.util.glsl.ShaderState;
public class ImmModeSink {
@@ -337,10 +342,8 @@ public class ImmModeSink {
enableBuffer(gl, true);
if (buffer!=null) {
- GL2ES1 glf = gl.getGL2ES1();
-
if(null==indices) {
- glf.glDrawArrays(mode, 0, count);
+ gl.glDrawArrays(mode, 0, count);
} else {
Class<?> clazz = indices.getClass();
int type=-1;
@@ -352,7 +355,7 @@ public class ImmModeSink {
if(0>type) {
throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this);
}
- glf.glDrawElements(mode, indices.remaining(), type, indices);
+ gl.glDrawElements(mode, indices.remaining(), type, indices);
// GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
index fa66673fd..0022d5c2d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
@@ -48,6 +48,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.glu.gl2.GLUgl2;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.GLPixelStorageModes;
import com.jogamp.opengl.util.TGAWriter;
@@ -392,7 +393,7 @@ public class Screenshot {
private static void checkExtABGR() {
GL2 gl = GLUgl2.getCurrentGL2();
- if (!gl.isExtensionAvailable("GL_EXT_abgr")) {
+ if (!gl.isExtensionAvailable(GLExtensions.EXT_abgr)) {
throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr");
}
}
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 622ee1b79..1735fcddd 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
@@ -41,6 +41,7 @@ package com.jogamp.opengl.util.awt;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.*;
import com.jogamp.opengl.util.packrect.*;
import com.jogamp.opengl.util.texture.*;
@@ -1976,7 +1977,7 @@ public class TextRenderer {
private final boolean is15Available(GL gl) {
if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) {
- isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5");
+ isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable(GLExtensions.VERSION_1_5);
checkFor_isExtensionAvailable_GL_VERSION_1_5 = true;
}
return isExtensionAvailable_GL_VERSION_1_5;
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 49d4add5f..e7bf87a36 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
@@ -44,6 +44,7 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.opengl.*;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.texture.spi.*;
/**
@@ -262,8 +263,8 @@ public class Texture {
*
* See the <a href="#perftips">performance tips</a> above for hints
* on how to maximize performance when using many Texture objects.
- * @param gl TODO
- *
+ *
+ * @param gl the current GL context
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
@@ -448,12 +449,12 @@ public class Texture {
// See whether we have automatic mipmap generation support
boolean haveAutoMipmapGeneration =
- (gl.isExtensionAvailable("GL_VERSION_1_4") ||
- gl.isExtensionAvailable("GL_SGIS_generate_mipmap"));
+ (gl.isExtensionAvailable(GLExtensions.VERSION_1_4) ||
+ gl.isExtensionAvailable(GLExtensions.SGIS_generate_mipmap));
// Indicate to the TextureData what functionality is available
- data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr"));
- data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2"));
+ data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr));
+ data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2));
// Indicates whether both width and height are power of two
boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight);
@@ -646,7 +647,7 @@ public class Texture {
int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR);
int magFilter = GL.GL_LINEAR;
- int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
+ int wrapMode = (gl.isExtensionAvailable(GLExtensions.VERSION_1_2) || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
// REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB
if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) {
@@ -925,8 +926,8 @@ public class Texture {
private void updateSubImageImpl(GL gl, TextureData data, int newTarget, int mipmapLevel,
int dstx, int dsty,
int srcx, int srcy, int width, int height) throws GLException {
- data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr"));
- data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2"));
+ data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr));
+ data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2));
Buffer buffer = data.getBuffer();
if (buffer == null && data.getMipmapData() == null) {
@@ -1044,8 +1045,8 @@ public class Texture {
case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc") &&
- !gl.isExtensionAvailable("GL_NV_texture_compression_vtc")) {
+ if (!gl.isExtensionAvailable(GLExtensions.EXT_texture_compression_s3tc) &&
+ !gl.isExtensionAvailable(GLExtensions.NV_texture_compression_vtc)) {
throw new GLException("DXTn compressed textures not supported by this graphics card");
}
break;
@@ -1081,7 +1082,7 @@ public class Texture {
private static boolean haveTexRect(GL gl) {
return (!disableTexRect &&
TextureIO.isTexRectEnabled() &&
- gl.isExtensionAvailable("GL_ARB_texture_rectangle"));
+ gl.isExtensionAvailable(GLExtensions.ARB_texture_rectangle));
}
private static boolean preferTexRect(GL gl) {
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 ca97cdc4b..b878c6002 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -155,6 +155,14 @@ public class TextureIO {
file. */
public static final String TIFF = "tiff";
+ /** Constant which can be used as a file suffix to indicate a PAM
+ file, NetPbm magic 7 - binary RGB and RGBA. Write support only. */
+ public static final String PAM = "pam";
+
+ /** Constant which can be used as a file suffix to indicate a PAM
+ file, NetPbm magic 6 - binary RGB. Write support only. */
+ public static final String PPM = "ppm";
+
private static final boolean DEBUG = Debug.debug("TextureIO");
// For manually disabling the use of the texture rectangle
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 5ee2104a3..6b41c0bc8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -102,7 +102,6 @@ import javax.media.opengl.GL;
*/
public interface TextureSequence {
public static final String GL_OES_EGL_image_external_Required_Prelude = "#extension GL_OES_EGL_image_external : enable\n";
- public static final String GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
public static final String samplerExternalOES = "samplerExternalOES";
public static final String sampler2D = "sampler2D";
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 c2b131b97..cd42a1157 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
@@ -77,8 +77,10 @@ public class NetPbmTextureWriter implements TextureWriter {
public int getMagic() { return magic; }
- public static final String PPM = "ppm";
- public static final String PAM = "pam";
+ /** @see TextureIO#PPM */
+ public static final String PPM = TextureIO.PPM;
+ /** @see TextureIO#PAM */
+ public static final String PAM = TextureIO.PAM;
public String getSuffix() { return (magic==6)?PPM:PAM; }
diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
index b57b85e5c..5fa8ce32d 100644
--- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
+++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
@@ -117,6 +117,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
final int availnum = available.size();
if (DEBUG) {
+ Thread.dumpStack();
System.err.println("Desired: " + gldes);
System.err.println("Available: " + availnum);
for (int i = 0; i < available.size(); i++) {
@@ -141,7 +142,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
for (int i = 0; i < scores.length; i++) {
scores[i] = NO_SCORE;
}
- final int gldes_samples = gldes.getSampleBuffers() ? gldes.getNumSamples() : 0;
+ final int gldes_samples = gldes.getNumSamples();
// Compute score for each
for (int i = 0; i < availnum; i++) {
@@ -158,8 +159,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
if (gldes.getStereo() != cur.getStereo()) {
continue;
}
- final int cur_samples =
- cur.getSampleBuffers() ? cur.getNumSamples() : 0;
+ final int cur_samples = cur.getNumSamples() ;
int score = 0;
// Compute difference in color depth
@@ -242,7 +242,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
if (i > 0) {
System.err.print(",");
}
- System.err.print(" " + scores[i]);
+ System.err.print(" " + i +": " + scores[i]);
}
System.err.println(" ]");
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 80d4f796c..0b2c664fe 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -51,8 +51,8 @@ import jogamp.opengl.Debug;
calls to {@link GLContext#makeCurrent makeCurrent} will block if
the context is current on another thread. This allows the internal
GLContext for the GLAutoDrawable to be used both by the event
- based rendering mechanism as well by end users directly.<P>
-
+ based rendering mechanism as well by end users directly.
+ <p>
The implementation shall initialize itself as soon as possible,
ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized.
The following protocol shall be satisfied:
@@ -64,18 +64,18 @@ import jogamp.opengl.Debug;
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><P>
-
+ </ul></P>
+ <p>
Another implementation detail is the drawable 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 javax.media.nativewindow.NativeSurface NativeSurface}.<br>
+ shall be able to detect such cases in conjunction with the associated {@link javax.media.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 javax.media.opengl.awt.GLCanvas}'s
and NEWT's <code>AWTCanvas</code> {@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()}
specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow}
- implementation on the Windows platform, which utilizes the native platform's <i>MonitorFromWindow(HWND)</i> function.<br>
+ 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 choosen again. The following protocol shall be satisfied.
+ to be chosen again. The following protocol shall be satisfied.
<ul>
<li> Controlled disposal:</li>
<ul>
@@ -97,16 +97,16 @@ import jogamp.opengl.Debug;
</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>
-
- However, to not introduce to much breakage with older applications and because of the situation
+ 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>
-
+ screen change action as follows:<br/>
<PRE>
-Djogl.screenchange.action=false Disable the drawable reconfiguration (the default)
-Djogl.screenchange.action=true Enable the drawable reconfiguration
</PRE>
+ </p>
*/
public interface GLAutoDrawable extends GLDrawable {
/** Flag reflecting wheather the drawable reconfiguration will be issued in
@@ -362,5 +362,29 @@ public interface GLAutoDrawable extends GLDrawable {
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 javax.media.opengl.awt.GLCanvas}</td> <td>is a</td> <td>{@link java.awt.Canvas}</td</tr>
+ * <tr><td>AWT</td> <td>{@link javax.media.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>
+ * @return
+ */
+ public Object getUpstreamWidget();
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
index 89d5cc4cb..67e81270d 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
@@ -28,6 +28,8 @@
package javax.media.opengl;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -56,23 +58,33 @@ import jogamp.opengl.GLDrawableImpl;
public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate");
- public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context) {
- super((GLDrawableImpl)drawable, (GLContextImpl)context);
+ /**
+ * @param drawable a valid {@link GLDrawable}, may not be realized yet.
+ * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
+ * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass <code>false</code>. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) {
+ super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
+ this.upstreamWidget = null;
}
//
- // make protected methods accessible
+ // expose default methods
//
- public void defaultWindowRepaintOp() {
+ public final void windowRepaintOp() {
super.defaultWindowRepaintOp();
}
- public void defaultWindowResizedOp() {
+ public final void windowResizedOp() {
super.defaultWindowResizedOp();
}
- public void defaultWindowDestroyNotifyOp() {
+ public final void windowDestroyNotifyOp() {
super.defaultWindowDestroyNotifyOp();
}
@@ -80,44 +92,35 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
// Complete GLAutoDrawable
//
- private RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
-
+ private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
+ private final Object upstreamWidget;
+
+ @Override
+ protected final RecursiveLock getLock() { return lock; }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return upstreamWidget;
+ }
+
/**
* {@inheritDoc}
* <p>
- * This implementation calls {@link #defaultDestroyOp()}.
+ * This implementation calls {@link #defaultDestroy()}.
* </p>
* <p>
* User still needs to destroy the upstream window, which details are hidden from this aspect.
+ * This can be performed by overriding {@link #destroyImplInLock()}.
* </p>
*/
@Override
- public void destroy() {
- lock.lock();
- try {
- defaultDestroyOp();
- } finally {
- lock.unlock();
- }
+ public final void destroy() {
+ defaultDestroy();
}
@Override
public void display() {
- if( sendDestroy ) {
- sendDestroy=false;
- destroy();
- return;
- }
-
- lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
- try {
- if( null != drawable && drawable.isRealized() && null != context ) {
- // surface is locked/unlocked implicit by context's makeCurrent/release
- helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
- }
- } finally {
- lock.unlock();
- }
+ defaultDisplay();
}
//
@@ -133,4 +136,9 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
public final void setRealized(boolean realized) {
}
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
+ }
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index bd24b15bc..f5831a72d 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -340,5 +340,60 @@ public interface GLBase {
* 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 (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ */
+ public int glGetBoundBuffer(int target);
+
+ /**
+ * @param buffer a GL buffer name, generated with {@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)} for example.
+ * @return the size of the given GL buffer
+ */
+ public long glGetBufferSize(int buffer);
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOArrayEnabled();
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOElementArrayEnabled();
+
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ 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 FBObject}) based drawable
+ * is being used.
+ * </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 FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public int getDefaultReadFramebuffer();
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
index 61ab2e58d..8845ec665 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
@@ -55,8 +55,9 @@ import javax.media.nativewindow.CapabilitiesImmutable;
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 pbuffer = false;
+ private GLProfile glProfile = null;
+ private boolean isPBuffer = false;
+ private boolean isFBO = false;
private boolean doubleBuffered = true;
private boolean stereo = false;
private boolean hardwareAccelerated = true;
@@ -105,7 +106,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
public int hashCode() {
// 31 * x == (x << 5) - x
int hash = 31 + this.glProfile.hashCode() ;
- hash = ((hash << 5) - hash) + ( this.pbuffer ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isFBO ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isPBuffer ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 );
hash = ((hash << 5) - hash) + this.depthBits;
@@ -132,7 +134,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
GLCapabilitiesImmutable other = (GLCapabilitiesImmutable)obj;
boolean res = super.equals(obj) &&
other.getGLProfile()==glProfile &&
- other.isPBuffer()==pbuffer &&
+ other.isPBuffer()==isPBuffer &&
+ other.isFBO()==isFBO &&
other.getStereo()==stereo &&
other.getHardwareAccelerated()==hardwareAccelerated &&
other.getDepthBits()==depthBits &&
@@ -180,8 +183,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return -1;
}
- final int ms = sampleBuffers ? numSamples : 0;
- final int xms = caps.getSampleBuffers() ? caps.getNumSamples() : 0;
+ final int ms = getNumSamples();
+ final int xms = caps.getNumSamples() ;
if(ms > xms) {
return 1;
@@ -222,30 +225,53 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
@Override
public final boolean isPBuffer() {
- return pbuffer;
+ return isPBuffer;
}
/**
- * Enables or disables pbuffer usage.<br>
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}<br>
+ * Enables or disables pbuffer usage.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * </p>
* Defaults to false.
*/
public void setPBuffer(boolean enable) {
if(enable) {
setOnscreen(false);
}
- pbuffer = enable;
+ isPBuffer = enable;
+ }
+
+ @Override
+ public final boolean isFBO() {
+ return isFBO;
+ }
+
+ /**
+ * Enables or disables FBO usage.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * </p>
+ * Defaults to false.
+ */
+ public void setFBO(boolean enable) {
+ if(enable) {
+ setOnscreen(false);
+ }
+ isFBO = enable;
}
/**
* Sets whether the drawable surface supports onscreen.<br>
- * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)}<br>
+ * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)}
+ * and {@link #setFBO(int) setFBO(false)}<br>
* Defaults to true.
*/
@Override
public void setOnscreen(boolean onscreen) {
if(onscreen) {
setPBuffer(false);
+ setFBO(false);
}
super.setOnscreen(onscreen);
}
@@ -385,15 +411,18 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return sampleBuffers;
}
- /** If sample buffers are enabled, indicates the number of buffers
- to be allocated. Defaults to 2. */
+ /**
+ * If sample buffers are enabled, indicates the number of buffers
+ * to be allocated. Defaults to 2.
+ * @see #getNumSamples()
+ */
public void setNumSamples(int numSamples) {
this.numSamples = numSamples;
}
@Override
public final int getNumSamples() {
- return numSamples;
+ return sampleBuffers ? numSamples : 0;
}
/** For pbuffers only, indicates whether floating-point buffers
@@ -462,12 +491,16 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
sink.append(glProfile);
if(!isOnscreen()) {
- if(pbuffer) {
+ if(isFBO) {
+ sink.append(", fbo");
+ }
+ if(isPBuffer) {
sink.append(", pbuffer [r2t ").append(pbufferRenderToTexture?1:0)
.append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0)
.append(", float ").append(pbufferFloatingPointBuffers?1:0)
.append("]");
- } else {
+ }
+ if(!isFBO && !isPBuffer) {
sink.append(", pixmap");
}
}
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
index 5f8795edc..7e0459b2d 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
@@ -111,7 +111,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
/**
* Returns the number of sample buffers to be allocated if sample
- * buffers are enabled. Defaults to 2.
+ * buffers are enabled, otherwise returns 0. Defaults to 2.
*/
int getNumSamples();
@@ -144,10 +144,15 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
boolean getStereo();
/**
- * Indicates whether pbuffer is used/requested.
+ * Indicates whether pbuffer offscreen is used/requested.
*/
boolean isPBuffer();
+ /**
+ * Indicates whether FBO offscreen is used/requested.
+ */
+ boolean isFBO();
+
@Override
boolean equals(Object obj);
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 351f90027..63a02ad9c 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -55,6 +55,7 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.GLExtensions;
/** Abstraction for an OpenGL rendering context. In order to perform
OpenGL rendering, a context must be "made current" on the current
@@ -69,6 +70,7 @@ import com.jogamp.common.util.locks.RecursiveLock;
abstraction provides a stable object which clients can use to
refer to a given context. */
public abstract class GLContext {
+
/**
* If <code>true</code> (default), bootstrapping the available GL profiles
* will use the highest compatible GL context for each profile,
@@ -120,13 +122,13 @@ public abstract class GLContext {
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. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ /** <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;
/** <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 << 8;
- /** Context supports FBO, details see {@link #hasFBO()}.
+ /** Context supports basic FBO, details see {@link #hasFBO()}.
* Not a cache key.
* @see #hasFBO()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
@@ -136,16 +138,6 @@ public abstract class GLContext {
/** 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 << 15;
- protected static final String GL_ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
- protected static final String GL_ARB_framebuffer_object = "GL_ARB_framebuffer_object";
- protected static final String GL_EXT_framebuffer_object = "GL_EXT_framebuffer_object";
- protected static final String GL_EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
- protected static final String GL_EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
- protected static final String GL_EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
- protected static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
- protected static final String GL_EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
- protected static final String GL_IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
-
private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
private final HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>();
@@ -639,11 +631,19 @@ public abstract class GLContext {
return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
}
- /** Returns whether the context supports FBO, hence is either GL-ES >= 2.0, >= core GL 3.0 or implements the extensions
- * <code>GL_ARB_ES2_compatibility</code>, <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>.
+ /**
+ * 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 >= core 3.0 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
+ * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL)
+ * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL)
*/
public final boolean hasFBO() {
return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
@@ -659,13 +659,13 @@ public abstract class GLContext {
/** 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(GL_ARB_texture_non_power_of_two);
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
}
public boolean isTextureFormatBGRA8888Available() {
return isGL2GL3() ||
- isExtensionAvailable(GL_EXT_texture_format_BGRA8888) ||
- isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ;
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
/** @see GLProfile#isGL4bc() */
@@ -798,7 +798,32 @@ public abstract class GLContext {
}
protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; }
-
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ 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 FBObject}) based drawable
+ * is being used.
+ * </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 FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public abstract int getDefaultReadFramebuffer();
+
/**
* @return The extension implementing the GLDebugOutput feature,
* either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>.
@@ -984,6 +1009,7 @@ public abstract class GLContext {
deviceVersionsAvailableSet.add(devKey);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
+ System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
}
}
}
@@ -1010,6 +1036,10 @@ public abstract class GLContext {
validateProfileBits(profile, "profile");
validateProfileBits(resCtp, "resCtp");
+ if(DEBUG) {
+ System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
+ // Thread.dumpStack();
+ }
final String key = getDeviceVersionAvailableKey(device, reqMajor, profile);
final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
synchronized(deviceVersionAvailable) {
@@ -1122,7 +1152,9 @@ public abstract class GLContext {
} else /* if (glpImpl.isGL2()) */ {
reqMajorCTP[0]=2;
}
- if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc
+ 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;
@@ -1141,8 +1173,7 @@ public abstract class GLContext {
int _major[] = { 0 };
int _minor[] = { 0 };
int _ctp[] = { 0 };
- if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1],
- _major, _minor, _ctp)) {
+ if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) {
return _ctp[0];
}
return 0; // n/a
@@ -1181,6 +1212,23 @@ public abstract class GLContext {
}
/**
+ * 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 #hasFBO()}.
+ * </p>
+ *
+ * @param device the device to request whether FBO is available for
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasFBO()
+ */
+ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) {
+ return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
+ }
+
+ /**
* @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}
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index d6480e7aa..9a0d2cb99 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -50,9 +50,11 @@ import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GLProfile.ShutdownType;
import jogamp.opengl.Debug;
@@ -398,9 +400,18 @@ public abstract class GLDrawableFactory {
/**
* Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
* <p>
- * A Pbuffer drawable/surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.<br>
- * Otherwise a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.<br>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below.
+ * </p>
+ * <p>
+ * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#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 javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
+ * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * </p>
+ * <p>
+ * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
* </p>
*
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
@@ -421,42 +432,32 @@ public abstract class GLDrawableFactory {
throws GLException;
/**
- * Creates an offscreen NativeSurface.<br>
- * A Pbuffer surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.<br>
- * Otherwise a simple pixmap/bitmap surface is created. The latter is unlikely to be hardware accelerated.<br>
- *
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, 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 offscreen native surface
- *
- * @throws GLException if any window system-specific errors caused
- * the creation of the GLDrawable to fail.
- */
- public abstract NativeSurface createOffscreenSurface(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser,
- int width, int height);
-
- /**
- * Highly experimental API entry, allowing developer of new windowing system bindings
- * to leverage the native window handle to produce a NativeSurface implementation (ProxySurface), having the required GLCapabilities.<br>
- * Such surface can be used to instantiate a GLDrawable and hence test your new binding w/o the
- * costs of providing a full set of abstraction like the AWT GLCanvas or even the native NEWT bindings.
+ * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link 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 (destruction) of the given surface handle shall be handled by the caller.
+ * </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>
*
- * @param device the platform's target device, shall not be <code>null</code>
+ * @param device which {@link javax.media.nativewindow.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
- * @return The proxy surface wrapping the windowHandle on the device
+ * @param upstream optional {@link ProxySurface.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,
+ public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ int screenIdx,
long windowHandle,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser);
+ GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
/**
* Returns true if it is possible to create a GLPbuffer. Some older
@@ -492,23 +493,7 @@ public abstract class GLDrawableFactory {
GLContext shareWith)
throws GLException;
- /**
- * 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#hasFBO()}.
- * </p>
- *
- * @param device which {@link javax.media.nativewindow.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#hasFBO()
- */
- public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) {
- return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) );
- }
-
+
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index a7200b560..1e10dc9a6 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -86,7 +86,14 @@ public class GLProfile {
* </p>
*/
private static final boolean enableANGLE = Debug.isPropertyDefined("jogl.enable.ANGLE", true);
-
+
+ /**
+ * In case no OpenGL ES implementation is required
+ * and if the running platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.opengles</code> disables querying a possible existing OpenGL ES implementation.
+ */
+ private static final boolean disableOpenGLES = Debug.isPropertyDefined("jogl.disable.opengles", true);
+
static {
// Also initializes TempJarCache if shall be used.
Platform.initSingleton();
@@ -117,10 +124,12 @@ public class GLProfile {
* @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
+ final boolean justInitialized;
initLock.lock();
try {
if(!initialized) { // volatile: ok
initialized = true;
+ justInitialized = true;
if(DEBUG) {
System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName());
Thread.dumpStack();
@@ -166,10 +175,17 @@ public class GLProfile {
return null;
}
});
+ } else {
+ justInitialized = false;
}
} finally {
initLock.unlock();
}
+ if(DEBUG) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
+ }
+ }
}
/**
@@ -1466,7 +1482,7 @@ public class GLProfile {
}
}
- if ( ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
+ if ( !disableOpenGLES && ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
t=null;
try {
eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
@@ -1532,18 +1548,17 @@ public class GLProfile {
if(DEBUG) {
// System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
- 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 hasGLES2Impl "+hasGLES2Impl);
- System.err.println("GLProfile.init defaultDevice "+defaultDevice);
- System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
- if(hasGL234Impl || hasGLES1Impl || hasGLES2Impl) { // avoid deadlock
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true));
- }
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ 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 hasGLES2Impl "+hasGLES2Impl);
+ 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));
}
}
@@ -1642,24 +1657,6 @@ public class GLProfile {
if (DEBUG) {
System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail);
}
- if( hasGLES2Impl ) {
- // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile
- GLContext.mapAvailableGLVersion(device,
- 2, GLContext.CTX_PROFILE_ES,
- 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0");
- }
- }
- if( hasGLES1Impl ) {
- // Always favor the native ES1 impl.
- GLContext.mapAvailableGLVersion(device,
- 1, GLContext.CTX_PROFILE_ES,
- 1, 0, GLContext.CTX_PROFILE_ES);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0");
- }
- }
addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
}
@@ -1767,7 +1764,7 @@ public class GLProfile {
}
_mappedProfiles.put(profile, glProfile);
if (DEBUG) {
- System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection());
+ System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
}
if(null==defaultGLProfileHW && isHardwareRasterizer[0]) {
defaultGLProfileHW=glProfile;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 48f7ea24a..03fd78ac7 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -60,6 +60,7 @@ import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.OffscreenLayerOption;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -84,6 +85,8 @@ import javax.media.opengl.Threading;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
+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;
@@ -132,20 +135,6 @@ import jogamp.opengl.GLDrawableHelper;
* <ul>
* <li><pre>sun.awt.noerasebackground=true</pre></li>
* </ul>
- * <p>
- * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (default: single-thread),
- * proper recursive locking is required for drawable/context @ destroy and display.
- * Recreation etc could pull those instances while animating!
- * Simply locking before using drawable/context offthread
- * would allow a deadlock situation!
- * </p>
- * <p>
- * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized.
- In case any of the methods are called outside of a locked state
- extra care should be added. Maybe we shall expose locking facilities to the user.
- However, since the user shall stick to the GLEventListener model while utilizing
- GLAutoDrawable implementations, she is safe due to the implicit locked state.
- * </p>
*/
@SuppressWarnings("serial")
@@ -153,11 +142,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
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 GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display
+ private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
private GLContextImpl context;
- private boolean sendReshape = false;
+ private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
// copy of the cstr args, mainly for recreation
private GLCapabilitiesImmutable capsReqUser;
@@ -262,6 +252,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
public void setShallUseOffscreenLayer(boolean v) {
shallUseOffscreenLayer = v;
}
@@ -273,8 +268,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public final boolean isOffscreenLayerSurfaceEnabled() {
- if(null != drawable) {
- return ((JAWTWindow)drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled();
+ final GLDrawable _drawable = drawable;
+ if(null != _drawable) {
+ return ((JAWTWindow)_drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled();
}
return false;
}
@@ -393,12 +389,18 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public GLContext createContext(final GLContext shareWith) {
- if(drawable != null) {
- final GLContext _ctx = drawable.createContext(shareWith);
- _ctx.setContextCreationFlags(additionalCtxCreationFlags);
- return _ctx;
+ 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();
}
- return null;
}
@Override
@@ -407,7 +409,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public boolean isRealized() {
- return (null != drawable) ? drawable.isRealized() : false;
+ final GLDrawable _drawable = drawable;
+ return ( null != _drawable ) ? _drawable.isRealized() : false;
}
@Override
@@ -422,50 +425,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@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 ..
- }
Threading.invoke(true, displayOnEDTAction, getTreeLock());
-
awtWindowClosingProtocol.addClosingListenerOneShot();
}
private void dispose(boolean regenerate) {
- final GLAnimatorControl animator = getAnimator();
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: dispose("+regenerate+") - START, hasContext " +
- (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
- Thread.dumpStack();
- }
-
- if(null!=drawable && null!=context) { // drawable is volatile!
- boolean animatorPaused = false;
- if(null!=animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
-
- disposeRegenerate=regenerate;
-
- if(context.isCreated()) {
- Threading.invoke(true, disposeOnEDTAction, getTreeLock());
- }
-
- if(animatorPaused) {
- animator.resume();
- }
- }
-
- if(!regenerate) {
- disposeAbstractGraphicsDevice();
- }
-
- if(DEBUG) {
- System.err.println(getThreadName()+": dispose("+regenerate+") - END, "+animator);
- }
+ disposeRegenerate=regenerate;
+ Threading.invoke(true, disposeOnEDTAction, getTreeLock());
}
/**
@@ -525,43 +491,49 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@SuppressWarnings("deprecation")
@Override
public void addNotify() {
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds());
- Thread.dumpStack();
- }
-
- /**
- * '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();
-
- if (!Beans.isDesignTime()) {
- createDrawableAndContext();
- }
-
- // init drawable by paint/display makes the init sequence more equal
- // for all launch flavors (applet/javaws/..)
- // validateGLDrawable();
-
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds());
+ Thread.dumpStack();
+ }
+
+ /**
+ * '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();
+
+ if (!Beans.isDesignTime()) {
+ createDrawableAndContext();
+ }
+
+ // init drawable by paint/display makes the init sequence more equal
+ // for all launch flavors (applet/javaws/..)
+ // validateGLDrawable();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
+ }
+ } finally {
+ _lock.unlock();
}
}
@@ -580,23 +552,24 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
private boolean validateGLDrawable() {
- boolean realized = false;
- if (!Beans.isDesignTime()) {
- if ( null != drawable ) { // OK: drawable is volatile
- realized = drawable.isRealized();
- if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) {
- // make sure drawable realization happens on AWT EDT, due to AWTTree lock
- AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction);
- realized = true;
- sendReshape=true; // ensure a reshape is being send ..
- if(DEBUG) {
- System.err.println(getThreadName()+": Realized Drawable: "+drawable.toString());
- Thread.dumpStack();
- }
+ final GLDrawable _drawable = drawable;
+ if ( null != _drawable ) {
+ if( _drawable.isRealized() ) {
+ return true;
+ }
+ if (!Beans.isDesignTime() &&
+ 0 < _drawable.getWidth() * _drawable.getHeight() ) {
+ // make sure drawable realization happens on AWT EDT, due to AWTTree lock
+ AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction);
+ sendReshape=true; // ensure a reshape is being send ..
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString());
+ Thread.dumpStack();
}
+ return true;
}
}
- return realized;
+ return false;
}
private Runnable setRealizedOnEDTAction = new Runnable() {
@Override
@@ -628,9 +601,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
try {
dispose(false);
} finally {
- context=null;
- drawable=null;
- awtConfig=null;
super.removeNotify();
}
}
@@ -650,7 +620,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void reshape(int x, int y, int width, int height) {
super.reshape(x, y, width, height);
- if(null != drawable && drawable.isRealized() && !drawable.getChosenGLCapabilities().isOnscreen()) {
+ final GLDrawable _drawable = drawable;
+ if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) {
dispose(true);
} else {
sendReshape = true;
@@ -705,13 +676,19 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public GLContext setContext(GLContext newCtx) {
- final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
- context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ if(newCtxCurrent) {
+ context.makeCurrent();
+ }
+ return oldCtx;
+ } finally {
+ _lock.unlock();
}
- return oldCtx;
}
@Override
@@ -724,15 +701,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if (Beans.isDesignTime()) {
return null;
}
- GLContext ctx = getContext();
- return (ctx == null) ? null : ctx.getGL();
+ final GLContext _context = context;
+ return (_context == null) ? null : _context.getGL();
}
@Override
public GL setGL(GL gl) {
- GLContext ctx = getContext();
- if (ctx != null) {
- ctx.setGL(gl);
+ final GLContext _context = context;
+ if (_context != null) {
+ _context.setGL(gl);
return gl;
}
return null;
@@ -757,8 +734,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void setContextCreationFlags(int flags) {
additionalCtxCreationFlags = flags;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
}
}
@@ -791,26 +769,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public NativeSurface getNativeSurface() {
- return (null != drawable) ? drawable.getNativeSurface() : null;
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getNativeSurface() : null;
}
@Override
public long getHandle() {
- return (null != drawable) ? drawable.getHandle() : 0;
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getHandle() : 0;
}
@Override
public GLDrawableFactory getFactory() {
- return (null != drawable) ? drawable.getFactory() : null;
+ final GLDrawable _drawable = drawable;
+ return (null != _drawable) ? _drawable.getFactory() : null;
}
@Override
public String toString() {
- final int dw = (null!=drawable) ? drawable.getWidth() : -1;
- final int dh = (null!=drawable) ? drawable.getHeight() : -1;
+ final GLDrawable _drawable = drawable;
+ final int dw = (null!=_drawable) ? _drawable.getWidth() : -1;
+ final int dh = (null!=_drawable) ? _drawable.getHeight() : -1;
return "AWT-GLCanvas[Realized "+isRealized()+
- ",\n\t"+((null!=drawable)?drawable.getClass().getName():"null-drawable")+
+ ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
",\n\tFactory "+getFactory()+
",\n\thandle 0x"+Long.toHexString(getHandle())+
",\n\tDrawable size "+dw+"x"+dh+
@@ -824,7 +806,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
//
private boolean disposeRegenerate;
- private final Runnable postDisposeAction = new Runnable() {
+ private final Runnable postDisposeOnEDTAction = new Runnable() {
@Override
public void run() {
context=null;
@@ -854,7 +836,47 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private final Runnable disposeOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLAnimatorControl animator = getAnimator();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: dispose("+disposeRegenerate+") - START, hasContext " +
+ (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
+ Thread.dumpStack();
+ }
+
+ if(null!=drawable && null!=context) {
+ boolean animatorPaused = false;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ }
+
+ if(context.isCreated()) {
+ helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction);
+ }
+
+ if(animatorPaused) {
+ animator.resume();
+ }
+ }
+
+ if(!disposeRegenerate) {
+ if(null != awtConfig) {
+ disposeAbstractGraphicsDevice();
+ }
+ awtConfig=null;
+ }
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator);
+ }
+
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -874,7 +896,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if(DEBUG) {
System.err.println(getThreadName()+": GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
}
- awtConfig=null;
}
}
};
@@ -885,7 +906,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
*
* @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
*/
- void disposeAbstractGraphicsDevice() {
+ private void disposeAbstractGraphicsDevice() {
if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
disposeAbstractGraphicsDeviceAction.run();
} else {
@@ -936,14 +957,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private final Runnable displayOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, displayAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( validateGLDrawable() ) {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ } else if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
+ }
+ } finally {
+ _lock.unlock();
+ }
}
};
private final Runnable swapBuffersOnEDTAction = new Runnable() {
@Override
public void run() {
- helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -1026,9 +1063,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
config = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
} else {
try {
final ArrayList<AWTGraphicsConfiguration> bucket = new ArrayList<AWTGraphicsConfiguration>(1);
@@ -1036,9 +1073,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public void run() {
AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
bucket.add(c);
}
});
@@ -1070,7 +1107,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ 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");
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index cd18c5098..acb8f2183 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -87,7 +87,7 @@ import jogamp.opengl.awt.Java2D;
import jogamp.opengl.awt.Java2DGLContext;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLBuffers;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
@@ -251,6 +251,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
public void display() {
if (EventQueue.isDispatchThread()) {
// Want display() to be synchronous, so call paintImmediately()
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
index 804e9ee14..aabef29b0 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
@@ -32,7 +32,6 @@ import java.nio.FloatBuffer;
import javax.media.opengl.GL2ES2;
// FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER !
import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
@@ -45,7 +44,9 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderState;
@@ -60,6 +61,7 @@ public class VBORegion2PES2 extends GLRegion {
private FBObject fbo;
+ private TextureAttachment texA;
private PMVMatrix fboPMVMatrix;
GLUniformData mgl_fboPMVMatrix;
@@ -72,7 +74,7 @@ public class VBORegion2PES2 extends GLRegion {
super(renderModes);
fboPMVMatrix = new PMVMatrix();
mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf());
- mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
+ mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
}
public void update(GL2ES2 gl, RenderState rs) {
@@ -214,8 +216,9 @@ public class VBORegion2PES2 extends GLRegion {
final ShaderState st = rs.getShaderState();
gl.glViewport(0, 0, width, hight);
- st.uniform(gl, mgl_ActiveTexture);
- fbo.use(gl, 0);
+ st.uniform(gl, mgl_ActiveTexture);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue());
+ fbo.use(gl, texA);
verticeFboAttr.enableBuffer(gl, true);
texCoordFboAttr.enableBuffer(gl, true);
indicesFbo.enableBuffer(gl, true);
@@ -244,20 +247,16 @@ public class VBORegion2PES2 extends GLRegion {
// System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5));
if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) {
- fbo.destroy(gl);
- fbo = null;
+ fbo.reset(gl, tex_width_c, tex_height_c);
}
- if(null == fbo) {
- fbo = new FBObject(tex_width_c, tex_height_c);
- fbo.init(gl);
+ if(null == fbo) {
+ fbo = new FBObject();
+ fbo.reset(gl, tex_width_c, tex_height_c);
// FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth
- fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- // fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- fbo.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16); // FIXME: or shall we use 24 or 32 bit depth ?
- if(!fbo.isStatusValid()) {
- throw new GLException("FBO invalid: "+fbo);
- }
+ texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
} else {
fbo.bind(gl);
}
@@ -305,6 +304,7 @@ public class VBORegion2PES2 extends GLRegion {
if(null != fbo) {
fbo.destroy(gl);
fbo = null;
+ texA = null;
}
if(null != verticeTxtAttr) {
st.ownAttribute(verticeTxtAttr, false);
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index 5c6d7446a..cc4e1b434 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -30,6 +30,8 @@ package jogamp.opengl;
import java.io.PrintStream;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
@@ -46,6 +48,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.opengl.util.Animator;
@@ -63,43 +66,69 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
protected final GLDrawableHelper helper = new GLDrawableHelper();
protected final FPSCounterImpl fpsCounter = new FPSCounterImpl();
- protected GLDrawableImpl drawable;
+ protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
protected GLContextImpl context;
+ protected final boolean ownDevice;
protected int additionalCtxCreationFlags = 0;
- protected boolean sendReshape = false;
- protected boolean sendDestroy = false;
+ protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking
+ protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking
- public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context) {
+ /**
+ * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet.
+ * @param context a valid {@link GLContextImpl}, may not be made current (created) yet.
+ * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass <code>false</code>. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ */
+ public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) {
this.drawable = drawable;
this.context = context;
+ this.ownDevice = ownDevice;
resetFPSCounter();
}
+ protected abstract RecursiveLock getLock();
+
/** Returns the delegated GLDrawable */
public final GLDrawable getDelegatedDrawable() { return drawable; }
/** Default implementation to handle repaint events from the windowing system */
- protected void defaultWindowRepaintOp() {
- if( null != drawable && drawable.isRealized() ) {
- if( !drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
+ protected final void defaultWindowRepaintOp() {
+ final GLDrawable _drawable = drawable;
+ if( null != _drawable && _drawable.isRealized() ) {
+ if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
display();
}
- }
+ }
}
/** Default implementation to handle resize events from the windowing system */
- protected void defaultWindowResizedOp() {
- if( null!=drawable ) {
+ protected final void defaultWindowResizedOp() {
+ final GLDrawable _drawable = drawable;
+ if( null!=_drawable ) {
if(DEBUG) {
System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
}
- sendReshape = true;
- defaultWindowRepaintOp();
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+ if( _drawable.isRealized() ) {
+ if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
+ display();
+ }
+ }
}
}
- /** Default implementation to handle destroy notifications from the windowing system */
- protected void defaultWindowDestroyNotifyOp() {
+ /**
+ * Default implementation to handle destroy notifications from the windowing system.
+ *
+ * <p>
+ * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol}
+ * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default),
+ * {@link #defaultDestroy()} is being called.
+ * </p>
+ */
+ protected final void defaultWindowDestroyNotifyOp() {
final NativeSurface ns = getNativeSurface();
final boolean shallClose;
if(ns instanceof WindowClosingProtocol) {
@@ -108,27 +137,66 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
shallClose = true;
}
if( shallClose ) {
- // Is an animator thread perform rendering?
- if (helper.isExternalAnimatorRunning()) {
- // Pause animations before initiating safe destroy.
- final GLAnimatorControl ctrl = helper.getAnimator();
- final boolean isPaused = ctrl.pause();
- destroy();
- if(isPaused) {
- ctrl.resume();
- }
- } else if (null != ns && ns.isSurfaceLockedByOtherThread()) {
- // surface is locked by another thread
- // Flag that destroy should be performed on the next
- // attempt to display.
- sendDestroy = true;
- } else {
- // Without an external thread animating or locking the
- // surface, we are safe.
- destroy ();
- }
+ destroyAvoidAwareOfLocking();
}
}
+
+ /**
+ * Calls {@link #destroy()}
+ * directly if the following requirements are met:
+ * <ul>
+ * <li>An {@link GLAnimatorControl} is bound (see {@link #getAnimator()}) and running on another thread.
+ * Here we pause the animation while issuing the destruction.</li>
+ * <li>Surface is not locked by another thread (considered anonymous).</li>
+ * </ul>
+ * <p>
+ * Otherwise destroy is being flagged to be called within the next
+ * call of display().
+ * </p>
+ * <p>
+ * This method is being used to avoid deadlock if
+ * destruction is desired by <i>other</i> threads, e.g. the window manager.
+ * </p>
+ * @see #defaultWindowDestroyNotifyOp()
+ * @see #defaultDisplay()
+ */
+ protected final void destroyAvoidAwareOfLocking() {
+ final NativeSurface ns = getNativeSurface();
+
+ final GLAnimatorControl ctrl = helper.getAnimator();
+
+ // Is an animator thread perform rendering?
+ if ( helper.isAnimatorRunningOnOtherThread() ) {
+ // Pause animations before initiating safe destroy.
+ final boolean isPaused = ctrl.pause();
+ destroy();
+ if(isPaused) {
+ ctrl.resume();
+ }
+ } else if (null != ns && ns.isSurfaceLockedByOtherThread()) {
+ // surface is locked by another thread
+ // Flag that destroy should be performed on the next
+ // attempt to display.
+ sendDestroy = true; // async, but avoiding deadlock
+ } else {
+ // Without an external thread animating or locking the
+ // surface, we are safe.
+ destroy();
+ }
+ }
+
+ /**
+ * Calls {@link #destroyImplInLock()} while claiming the lock.
+ */
+ protected final void defaultDestroy() {
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ destroyImplInLock();
+ } finally {
+ lock.unlock();
+ }
+ }
/**
* Default implementation to destroys the drawable and context of this GLAutoDrawable:
@@ -137,24 +205,47 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
* <li>destroys the GLContext, if valid</li>
* <li>destroys the GLDrawable, if valid</li>
* </ul>
+ * <p>Method assumes the lock is being hold.</p>
+ * <p>Override it to extend it to destroy your resources, i.e. the actual window.
+ * In such case call <code>super.destroyImplInLock</code> first.</p>
*/
- protected void defaultDestroyOp() {
- if( null != drawable && drawable.isRealized() ) {
- if( null != context && context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
- try {
- helper.disposeGL(this, drawable, context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
+ protected void destroyImplInLock() {
+ final GLContext _context = context;
+ final GLDrawable _drawable = drawable;
+ if( null != _drawable ) {
+ if( _drawable.isRealized() ) {
+ if( null != _context && _context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(this, _drawable, _context, null);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
}
+ _drawable.setRealized(false);
+ }
+ if( ownDevice ) {
+ _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close();
}
- drawable.setRealized(false);
}
context = null;
drawable = null;
}
+ public final void defaultSwapBuffers() throws GLException {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ if(drawable!=null && context != null) {
+ drawable.swapBuffers();
+ helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
//
// GLAutoDrawable
//
@@ -179,6 +270,30 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
fpsCounter.tickFPS();
} };
+ protected final void defaultDisplay() {
+ if( sendDestroy ) {
+ sendDestroy=false;
+ destroy();
+ return;
+ }
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ if( null != context ) {
+ // surface is locked/unlocked implicit by context's makeCurrent/release
+ helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ protected final Runnable defaultSwapAction = new Runnable() {
+ @Override
+ public final void run() {
+ drawable.swapBuffers();
+ } } ;
+
@Override
public final GLContext getContext() {
return context;
@@ -186,27 +301,35 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
@Override
public final GLContext setContext(GLContext newCtx) {
- final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
- context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ if(newCtxCurrent) {
+ context.makeCurrent();
+ }
+ return oldCtx;
+ } finally {
+ lock.unlock();
}
- return oldCtx;
}
@Override
public final GL getGL() {
- if (context == null) {
+ final GLContext _context = context;
+ if (_context == null) {
return null;
}
- return context.getGL();
+ return _context.getGL();
}
@Override
public final GL setGL(GL gl) {
- if (context != null) {
- context.setGL(gl);
+ final GLContext _context = context;
+ if (_context != null) {
+ _context.setGL(gl);
return gl;
}
return null;
@@ -261,8 +384,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
@Override
public final void setContextCreationFlags(int flags) {
additionalCtxCreationFlags = flags;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
}
}
@@ -331,27 +455,36 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
@Override
public final GLContext createContext(final GLContext shareWith) {
- if(drawable != null) {
- final GLContext _ctx = drawable.createContext(shareWith);
- _ctx.setContextCreationFlags(additionalCtxCreationFlags);
- return _ctx;
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ if(drawable != null) {
+ final GLContext _ctx = drawable.createContext(shareWith);
+ _ctx.setContextCreationFlags(additionalCtxCreationFlags);
+ return _ctx;
+ }
+ return null;
+ } finally {
+ lock.unlock();
}
- return null;
}
@Override
public final boolean isRealized() {
- return null != drawable ? drawable.isRealized() : false;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isRealized() : false;
}
@Override
public int getWidth() {
- return null != drawable ? drawable.getWidth() : 0;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getWidth() : 0;
}
@Override
public int getHeight() {
- return null != drawable ? drawable.getHeight() : 0;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getHeight() : 0;
}
/**
@@ -374,29 +507,26 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final void swapBuffers() throws GLException {
- if(drawable!=null && context != null) {
- drawable.swapBuffers();
- }
- }
-
- @Override
public final GLCapabilitiesImmutable getChosenGLCapabilities() {
- return null != drawable ? drawable.getChosenGLCapabilities() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getChosenGLCapabilities() : null;
}
@Override
public final GLProfile getGLProfile() {
- return null != drawable ? drawable.getGLProfile() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getGLProfile() : null;
}
@Override
public final NativeSurface getNativeSurface() {
- return null != drawable ? drawable.getNativeSurface() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getNativeSurface() : null;
}
@Override
public final long getHandle() {
- return null != drawable ? drawable.getHandle() : 0;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getHandle() : 0;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 4dd8806fa..bf6a0ee6e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -49,8 +49,9 @@ import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.gluegen.runtime.ProcAddressTable;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -88,13 +89,14 @@ public abstract class GLContextImpl extends GLContext {
// Tracks creation and initialization of buffer objects to avoid
// repeated glGet calls upon glMapBuffer operations
private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet
- private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
- private GLStateTracker glStateTracker = new GLStateTracker();
+ private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
+ private final GLStateTracker glStateTracker = new GLStateTracker();
private GLDebugMessageHandler glDebugHandler = null;
+ private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
-
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -140,11 +142,11 @@ public abstract class GLContextImpl extends GLContext {
bufferSizeTracker.clearCachedBufferSizes();
}
- if (bufferStateTracker != null) {
+ if (bufferStateTracker != null) { // <init>
bufferStateTracker.clearBufferObjectState();
}
- if (glStateTracker != null) {
+ if (glStateTracker != null) { // <init>
glStateTracker.clearStates(false);
}
@@ -156,6 +158,11 @@ public abstract class GLContextImpl extends GLContext {
glRenderer = "";
glRendererLowerCase = glRenderer;
+
+ if (boundFBOTarget != null) { // <init>
+ boundFBOTarget[0] = 0; // draw
+ boundFBOTarget[1] = 0; // read
+ }
super.resetStates();
}
@@ -199,7 +206,7 @@ public abstract class GLContextImpl extends GLContext {
drawableRead = (GLDrawableImpl) readWrite;
}
final GLDrawable old = drawable;
- drawable = ( null != readWrite ) ? (GLDrawableImpl) readWrite : null;
+ drawable = (GLDrawableImpl) readWrite ;
if(lockHeld) {
makeCurrent();
}
@@ -252,16 +259,19 @@ public abstract class GLContextImpl extends GLContext {
public void release() throws GLException {
release(false);
}
- private void release(boolean force) throws GLException {
+ private void release(boolean inDestruction) throws GLException {
if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+force+", "+lock);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+inDestruction+", "+lock);
}
if ( !lock.isOwner(Thread.currentThread()) ) {
throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this);
}
- final boolean actualRelease = ( force || lock.getHoldCount() == 1 ) && 0 != contextHandle;
+ final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
try {
if( actualRelease ) {
+ if( !inDestruction ) {
+ drawable.contextMadeCurrent(this, false);
+ }
releaseImpl();
}
} finally {
@@ -306,13 +316,12 @@ public abstract class GLContextImpl extends GLContext {
}
try {
// release current context
- if(null != glDebugHandler) {
- if(lock.getHoldCount() == 1) {
- // needs current context to disable debug handler
- makeCurrent();
- }
- glDebugHandler.enable(false);
+ if(lock.getHoldCount() == 1) {
+ // needs current context to disable debug handler
+ makeCurrent();
}
+ drawable.contextRealized(this, false);
+ glDebugHandler.enable(false);
if(lock.getHoldCount() > 1) {
// pending release() after makeCurrent()
release(true);
@@ -329,7 +338,6 @@ public abstract class GLContextImpl extends GLContext {
if (TRACE_SWITCH) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
- Thread.dumpStack(); // JAU
}
}
} finally {
@@ -488,11 +496,18 @@ public abstract class GLContextImpl extends GLContext {
if(TRACE_GL) {
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
}
+
+ drawable.contextRealized(this, true);
+
if(DEBUG || TRACE_SWITCH) {
System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock);
}
- } else if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock);
+ } else {
+ drawable.contextMadeCurrent(this, true);
+
+ if(TRACE_SWITCH) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock);
+ }
}
/* FIXME: refactor dependence on Java 2D / JOGL bridge
@@ -543,14 +558,11 @@ public abstract class GLContextImpl extends GLContext {
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- if( !GLContext.getAvailableGLVersionsSet(device) ) {
- final int reqMajor;
- final int reqProfile;
- if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES) ) {
- // ES1 or ES2
- reqMajor = ctxMajorVersion;
- reqProfile = GLContext.CTX_PROFILE_ES;
- } else {
+ // Non ARB desktop profiles may not have been registered
+ if( !GLContext.getAvailableGLVersionsSet(device) ) { // not yet set
+ if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile
+ final int reqMajor;
+ final int reqProfile;
if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) {
reqMajor = 2;
} else {
@@ -561,12 +573,13 @@ public abstract class GLContextImpl extends GLContext {
} else {
reqProfile = GLContext.CTX_PROFILE_COMPAT;
}
- }
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
- ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.setAvailableGLVersionsSet(device);
- if (DEBUG) {
- System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
+ ctxMajorVersion, ctxMinorVersion, ctxOptions);
+ GLContext.setAvailableGLVersionsSet(device);
+
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
+ }
}
}
}
@@ -776,7 +789,7 @@ public abstract class GLContextImpl extends GLContext {
}
/**
- * Note: Since context creation is temproary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true.
+ * Note: Since context creation is temporary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true.
* This method does not reset the states, allowing the caller to utilize the state variables.
**/
private final boolean createContextARBMapVersionsAvailable(int reqMajor, int reqProfile) {
@@ -1034,22 +1047,29 @@ public abstract class GLContextImpl extends GLContext {
table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
}
- private final void initGLRendererStrings() {
+ private final boolean initGLRendererStrings() {
final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString");
if(0 == _glGetString) {
// FIXME
System.err.println("Warning: Entry point to 'glGetString' is NULL.");
- Thread.dumpStack();
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
} else {
final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString);
if(null == _glRenderer) {
// FIXME
- System.err.println("Warning: GL_RENDERER is NULL.");
- Thread.dumpStack();
+ if(DEBUG) {
+ System.err.println("Warning: GL_RENDERER is NULL.");
+ Thread.dumpStack();
+ }
+ return false;
} else {
glRenderer = _glRenderer;
glRendererLowerCase = glRenderer.toLowerCase();
+ return true;
}
}
}
@@ -1088,17 +1108,20 @@ public abstract class GLContextImpl extends GLContext {
}
updateGLXProcAddressTable();
- initGLRendererStrings();
+ final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
+
+ if( !initGLRendererStrings() && DEBUG) {
+ System.err.println("Warning: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ }
if(!isCurrentContextHardwareRasterizer()) {
ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
}
- final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
- final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
- System.err.println(getThreadName() + ": Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
}
//
@@ -1154,11 +1177,10 @@ public abstract class GLContextImpl extends GLContext {
}
}
- if( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && ctxMajorVersion >= 2 ||
- isExtensionAvailable(GL_ARB_ES2_compatibility) ) {
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && major >= 2 ) || isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) ) {
ctxProfileBits |= CTX_IMPL_ES2_COMPAT;
ctxProfileBits |= CTX_IMPL_FBO;
- } else if( hasFBOImpl(ctxMajorVersion, ctxProfileBits, extensionAvailability) ) {
+ } else if( hasFBOImpl(major, ctxProfileBits, extensionAvailability) ) {
ctxProfileBits |= CTX_IMPL_FBO;
}
@@ -1168,23 +1190,26 @@ public abstract class GLContextImpl extends GLContext {
setContextVersion(major, minor, ctxProfileBits, true);
setDefaultSwapInterval();
+
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null));
+ }
}
- protected static final boolean hasFBOImpl(int ctxMajorVersion, int ctxProfileBits, ExtensionAvailabilityCache extCache) {
- return ( ctxMajorVersion >= 3 ) || // any >= 3.0 GL ctx
+ protected static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) {
+ return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) || // ES >= 2.0
- ( 0 != (ctxProfileBits & CTX_PROFILE_ES) && ctxMajorVersion >= 2 ) || // ES >= 2.0
+ major >= 3 || // any >= 3.0 GL ctx
( null != extCache &&
- ( extCache.isExtensionAvailable(GL_ARB_ES2_compatibility) ) || // ES 2.0 compatible
+ extCache.isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) || // ES 2.0 compatible
- ( extCache.isExtensionAvailable(GL_ARB_framebuffer_object) ) || // ARB_framebuffer_object
+ extCache.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
- ( extCache.isExtensionAvailable(GL_EXT_framebuffer_object) && // EXT_framebuffer_object*
- extCache.isExtensionAvailable(GL_EXT_framebuffer_multisample) &&
- extCache.isExtensionAvailable(GL_EXT_framebuffer_blit) &&
- extCache.isExtensionAvailable(GL_EXT_packed_depth_stencil) ) );
+ extCache.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) || // EXT_framebuffer_object
+
+ extCache.isExtensionAvailable(GLExtensions.OES_framebuffer_object) ) ; // OES_framebuffer_object excluded
}
protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) {
@@ -1259,11 +1284,11 @@ public abstract class GLContextImpl extends GLContext {
// dynamic function lookup at last incl name aliasing (not cached)
DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
- String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true);
+ String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
long addr = 0;
- int variants = GLExtensionNames.getFuncNamePermutationNumber(tmpBase);
+ int variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
for(int i = 0; 0==addr && i < variants; i++) {
- String tmp = GLExtensionNames.getFuncNamePermutation(tmpBase, i);
+ String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
try {
addr = dynLookup.dynamicLookupFunction(tmp);
} catch (Exception e) { }
@@ -1317,7 +1342,7 @@ public abstract class GLContextImpl extends GLContext {
protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctxProfileBits) {
// remove non-key values
- ctxProfileBits &= ~( GLContext.CTX_OPTION_DEBUG | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ;
+ ctxProfileBits &= ~( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ;
return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits));
}
@@ -1372,6 +1397,56 @@ public abstract class GLContextImpl extends GLContext {
}
//---------------------------------------------------------------------------
+ // Special FBO hook
+ //
+
+ /**
+ * Tracks {@link GL#GL_FRAMEBUFFER}, {@link GL2GL3#GL_DRAW_FRAMEBUFFER} and {@link GL2GL3#GL_READ_FRAMEBUFFER}
+ * to be returned via {@link #getBoundFramebuffer(int)}.
+ *
+ * <p>Invoked by {@link GL#glBindFramebuffer(int, int)}. </p>
+ *
+ * <p>Assumes valid <code>framebufferName</code> range of [0..{@link Integer#MAX_VALUE}]</p>
+ *
+ * <p>Does not throw an exception if <code>target</code> is unknown or <code>framebufferName</code> invalid.</p>
+ */
+ public final void setBoundFramebuffer(int target, int framebufferName) {
+ if(0 > framebufferName) {
+ return; // ignore invalid name
+ }
+ switch(target) {
+ case GL.GL_FRAMEBUFFER:
+ boundFBOTarget[0] = framebufferName; // draw
+ boundFBOTarget[1] = framebufferName; // read
+ break;
+ case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ boundFBOTarget[0] = framebufferName; // draw
+ break;
+ case GL2GL3.GL_READ_FRAMEBUFFER:
+ boundFBOTarget[1] = framebufferName; // read
+ break;
+ default: // ignore untracked target
+ }
+ }
+ @Override
+ public final int getBoundFramebuffer(int target) {
+ switch(target) {
+ case GL.GL_FRAMEBUFFER:
+ case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ return boundFBOTarget[0]; // draw
+ case GL2GL3.GL_READ_FRAMEBUFFER:
+ return boundFBOTarget[1]; // read
+ default:
+ throw new InternalError("Invalid FBO target name: "+toHexString(target));
+ }
+ }
+
+ @Override
+ public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); }
+ @Override
+ public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
+
+ //---------------------------------------------------------------------------
// GL_ARB_debug_output, GL_AMD_debug_output helpers
//
diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
index b950c2fdf..0000e6199 100644
--- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
+++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
@@ -37,6 +37,8 @@ import javax.media.opengl.GLException;
import com.jogamp.common.os.Platform;
import com.jogamp.gluegen.runtime.ProcAddressTable;
+import com.jogamp.opengl.GLExtensions;
+
import jogamp.opengl.gl4.GL4bcProcAddressTable;
/**
@@ -54,12 +56,6 @@ import jogamp.opengl.gl4.GL4bcProcAddressTable;
* the messages are translated to <i>ARB</i> {@link GLDebugMessage}, using {@link GLDebugMessage#translateAMDEvent(javax.media.opengl.GLContext, long, int, int, int, String)}.</p>
*/
public class GLDebugMessageHandler {
- /** Extension <i>GL_ARB_debug_output</i> implementing GLDebugMessage */
- public static final String GL_ARB_debug_output = "GL_ARB_debug_output".intern();
-
- /** Extension <i>GL_AMD_debug_output</i> implementing GLDebugMessage */
- public static final String GL_AMD_debug_output = "GL_AMD_debug_output".intern();
-
private static final boolean DEBUG = Debug.debug("GLDebugMessageHandler");
private static final int EXT_ARB = 1;
@@ -131,11 +127,11 @@ public class GLDebugMessageHandler {
}
return;
}
- if( ctx.isExtensionAvailable(GL_ARB_debug_output) ) {
- extName = GL_ARB_debug_output;
+ if( ctx.isExtensionAvailable(GLExtensions.ARB_debug_output) ) {
+ extName = GLExtensions.ARB_debug_output;
extType = EXT_ARB;
- } else if( ctx.isExtensionAvailable(GL_AMD_debug_output) ) {
- extName = GL_AMD_debug_output;
+ } else if( ctx.isExtensionAvailable(GLExtensions.AMD_debug_output) ) {
+ extName = GLExtensions.AMD_debug_output;
extType = EXT_AMD;
}
if(DEBUG) {
@@ -145,6 +141,8 @@ public class GLDebugMessageHandler {
if(0 == extType) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler: No extension available! "+ctx.getGLVersion());
+ System.err.println("GL_EXTENSIONS "+ctx.getGLExtensionCount());
+ System.err.println(ctx.getGLExtensionsString());
}
return;
}
@@ -190,11 +188,11 @@ public class GLDebugMessageHandler {
}
public final boolean isExtensionARB() {
- return extName == GL_ARB_debug_output;
+ return extName == GLExtensions.ARB_debug_output;
}
public final boolean isExtensionAMD() {
- return extName == GL_AMD_debug_output;
+ return extName == GLExtensions.AMD_debug_output;
}
/**
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index e5c44a8d4..f7808294b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -1,22 +1,22 @@
/*
* 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
@@ -29,11 +29,11 @@
* 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.
*/
@@ -47,7 +47,8 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -88,7 +89,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
return null;
}
protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device);
-
+
/**
* Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
* either a preexisting or newly created, or <code>null</code> if creation failed or not supported.<br>
@@ -115,7 +116,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
}
protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
- /**
+ /**
* Returns the GLDynamicLookupHelper
* @param profile if EGL/ES, profile <code>1</code> refers to ES1 and <code>2</code> to ES2,
* otherwise the profile is ignored.
@@ -125,6 +126,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
// Dispatching GLDrawable construction in respect to the NativeSurface Capabilities
//
+ @Override
public GLDrawable createGLDrawable(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -132,23 +134,38 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final AbstractGraphicsDevice adevice = config.getScreen().getDevice();
+ final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile());
GLDrawable result = null;
adevice.lock();
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
- // layered surface -> Offscreen/PBuffer
+ // layered surface -> Offscreen/[FBO|PBuffer]
final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
chosenCapsMod.setOnscreen(false);
- chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice));
+ /* if( isFBOAvailable ) { // FIXME JAU: FBO n/a yet
+ chosenCapsMod.setFBO(true);
+ } else */
+ if( canCreateGLPbuffer(adevice) ) {
+ chosenCapsMod.setPBuffer(true);
+ } else {
+ chosenCapsMod.setFBO(false);
+ chosenCapsMod.setPBuffer(false);
+ }
config.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
+ }
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
}
- result = createOffscreenDrawableImpl(target);
} else if(chosenCaps.isOnscreen()) {
// onscreen
if(DEBUG) {
@@ -158,12 +175,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
} else {
// offscreen
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO-chosen(-avail)/PBuffer: "+chosenCaps.isFBO()+"("+isFBOAvailable+")/"+chosenCaps.isPBuffer()+": "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target);
}
- result = createOffscreenDrawableImpl(target);
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
+ }
}
} finally {
adevice.unlock();
@@ -176,43 +199,42 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Onscreen GLDrawable construction
+ // Onscreen GLDrawable construction
//
protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target);
//---------------------------------------------------------------------------
//
- // PBuffer Offscreen GLDrawable construction
+ // PBuffer Offscreen GLDrawable construction
//
-
+
+ @Override
public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ @Override
public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
int width,
int height,
GLContext shareWith) {
- if(height<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ if(width<=0 || height<=0) {
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
-
AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
-
- if (!canCreateGLPbuffer(device)) {
- throw new GLException("Pbuffer support not available with device: "+device);
+ if ( !canCreateGLPbuffer(device) ) {
+ throw new GLException("Pbuffer not available with device: "+device);
}
-
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
GLDrawableImpl drawable = null;
device.lock();
try {
- drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
if(null != drawable) {
drawable.setRealized(true);
}
@@ -223,80 +245,163 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if(null==drawable) {
throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height);
}
- return new GLPbufferImpl( drawable, shareWith);
+ return new GLPbufferImpl( drawable, shareWith, true);
}
//---------------------------------------------------------------------------
//
- // Offscreen GLDrawable construction
+ // Offscreen GLDrawable construction
//
- protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
-
+ @Override
public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
- int width,
- int height) {
+ int width, int height) {
if(width<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
+
+ if( capsRequested.isFBO() && GLContext.isFBOAvailable(device, capsRequested.getGLProfile()) ) {
+ device.lock();
+ try {
+ return createFBODrawableImpl(device, capsRequested, chooser, width, height);
+ } finally {
+ device.unlock();
+ }
+ }
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, false, canCreateGLPbuffer(device));
device.lock();
try {
- return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
} finally {
device.unlock();
}
}
- public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ /** Creates a platform independent offscreen FBO GLDrawable implementation */
+ protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int initialWidth, int initialHeight) {
+ final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64);
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+
+ return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */);
+ }
+
+ /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */
+ protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
+
+ /**
+ * Creates a mutable {@link ProxySurface} w/o defined surface handle.
+ * <p>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}.
+ * </p>
+ * <p>
+ * Lifecycle (destruction) of the TBD surface handle shall be handled by the caller.
+ * </p>
+ * @param device a valid platform dependent target device.
+ * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details,
+ * otherwise <code>device</code> instance is used as-is.
+ * @param capsChosen
+ * @param capsRequested
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @param lifecycleHook optional control of the surface's lifecycle
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook);
+
+ /**
+ * A dummy surface 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 GLDrawable} and {@link GLContext} to query information.
+ * It also allows creation of framebuffer objects which are used for rendering.
+ * </p>
+ * @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ *
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int width, int height) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
device.lock();
try {
- return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height);
+ return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height);
} finally {
device.unlock();
}
}
-
+
/**
- * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well,
- * so the windowing system related implementation is able to set the surface handle.
+ * A dummy surface 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 GLDrawable} and {@link GLContext} to query information.
+ * It also allows creation of framebuffer objects which are used for rendering.
+ * </p>
+ * @param device a valid platform dependent target device.
+ * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details,
+ * otherwise <code>device</code> instance is used as-is.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
*/
- protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height);
+ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
- public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ //---------------------------------------------------------------------------
+ //
+ // ProxySurface (Wrapped pre-existing native surface) construction
+ //
+
+ @Override
+ public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
- throw new GLException("No shared device for requested: "+device);
+ throw new GLException("No shared device for requested: "+deviceReq);
+ }
+ if(0 == windowHandle) {
+ throw new IllegalArgumentException("Null windowHandle");
}
device.lock();
try {
- return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser);
+ return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream);
} finally {
device.unlock();
}
- }
-
- protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+ }
+
+ /**
+ * Creates a {@link ProxySurface} with a set surface handle.
+ * <p>
+ * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance.
+ * </p>
+ * @param upstream TODO
+ */
+ protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
//---------------------------------------------------------------------------
//
@@ -304,7 +409,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
protected abstract GLContext createExternalGLContextImpl();
-
+
+ @Override
public GLContext createExternalGLContext() {
NativeWindowFactory.getDefaultToolkitLock().lock();
try {
@@ -316,6 +422,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
protected abstract GLDrawable createExternalGLDrawableImpl();
+ @Override
public GLDrawable createExternalGLDrawable() {
NativeWindowFactory.getDefaultToolkitLock().lock();
try {
@@ -398,7 +505,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* normal ahead of time, use resetDisplayGamma(). Throws
* IllegalArgumentException if any of the parameters were
* out-of-bounds.
- *
+ *
* @param gamma The gamma value, typically > 1.0 (default value is
* 1.0)
* @param brightness The brightness value between -1.0 and 1.0,
@@ -484,7 +591,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
return;
if (gammaShutdownHook == null) {
gammaShutdownHook = new Thread(new Runnable() {
- public void run() {
+ @Override
+ public void run() {
synchronized (GLDrawableFactoryImpl.this) {
resetGammaRamp(originalGammaRamp);
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 0c01aa676..090c5fe69 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -189,8 +189,9 @@ public class GLDrawableHelper {
*/
public final void dispose(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- listeners.get(i).dispose(drawable);
+ final ArrayList<GLEventListener> _listeners = listeners;
+ for (int i=0; i < _listeners.size(); i++) {
+ _listeners.get(i).dispose(drawable);
}
}
}
@@ -209,8 +210,9 @@ public class GLDrawableHelper {
/** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */
public final void init(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- final GLEventListener listener = listeners.get(i) ;
+ final ArrayList<GLEventListener> _listeners = listeners;
+ for (int i=0; i < _listeners.size(); i++) {
+ final GLEventListener listener = _listeners.get(i) ;
// If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called.
// This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window),
@@ -232,8 +234,9 @@ public class GLDrawableHelper {
}
private final void displayImpl(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- final GLEventListener listener = listeners.get(i) ;
+ final ArrayList<GLEventListener> _listeners = listeners;
+ for (int i=0; i < _listeners.size(); i++) {
+ final GLEventListener listener = _listeners.get(i) ;
// GLEventListener may need to be init,
// in case this one is added after the realization of the GLAutoDrawable
init( listener, drawable, true /* sendReshape */) ;
@@ -324,7 +327,7 @@ public class GLDrawableHelper {
}
}
- public final boolean isExternalAnimatorRunning() {
+ public final boolean isAnimatorRunningOnOtherThread() {
return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 58a4ac6b4..abf2bf557 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -42,6 +42,7 @@ package jogamp.opengl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
@@ -75,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
if( !realized ) {
return; // destroyed already
}
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
if ( caps.getDoubleBuffered() ) {
if(!surface.surfaceSwap()) {
int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
@@ -149,6 +150,9 @@ public abstract class GLDrawableImpl implements GLDrawable {
realized = realizedArg;
AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
if(realizedArg) {
+ if(surface instanceof ProxySurface) {
+ ((ProxySurface)surface).createNotify();
+ }
if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)");
}
@@ -156,17 +160,21 @@ public abstract class GLDrawableImpl implements GLDrawable {
aDevice.lock();
}
try {
- setRealizedImpl();
if(realizedArg) {
+ setRealizedImpl();
updateHandle();
} else {
destroyHandle();
+ setRealizedImpl();
}
} finally {
if(realizedArg) {
unlockSurface();
} else {
aDevice.unlock();
+ if(surface instanceof ProxySurface) {
+ ((ProxySurface)surface).destroyNotify();
+ }
}
}
} else if(DEBUG) {
@@ -175,6 +183,39 @@ public abstract class GLDrawableImpl implements GLDrawable {
}
protected abstract void setRealizedImpl();
+ /**
+ * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>construct</code>, <code>destroy</code>.
+ * <p>
+ * If <code>realized</code> is <code>true</code>, the context has just been created and made current.
+ * </p>
+ * <p>
+ * If <code>realized</code> is <code>false</code>, the context is still current and will be release and destroyed after this method returns.
+ * </p>
+ * <p>
+ * @see #contextMadeCurrent(GLContext, boolean)
+ */
+ protected void contextRealized(GLContext glc, boolean realized) {}
+
+ /**
+ * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>makeCurrent</code>, <code>release</code>.
+ * <p>
+ * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered.
+ * </p>
+ * <p>
+ * If <code>current</code> is <code>true</code>, the context has just been made current.
+ * </p>
+ * <p>
+ * If <code>current</code> is <code>false</code>, the context is still current and will be release after this method returns.
+ * </p>
+ * @see #contextRealized(GLContext, boolean)
+ */
+ protected void contextMadeCurrent(GLContext glc, boolean current) { }
+
+ /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
+ protected int getDefaultDrawFramebuffer() { return 0; }
+ /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
+ protected int getDefaultReadFramebuffer() { return 0; }
+
@Override
public final synchronized boolean isRealized() {
return realized;
@@ -190,10 +231,12 @@ public abstract class GLDrawableImpl implements GLDrawable {
return surface.getHeight();
}
+ /** @see NativeSurface#lockSurface() */
public final int lockSurface() throws GLException {
return surface.lockSurface();
}
+ /** @see NativeSurface#unlockSurface() */
public final void unlockSurface() {
surface.unlockSurface();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
new file mode 100644
index 000000000..b7ea4f826
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -0,0 +1,138 @@
+package jogamp.opengl;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+
+/**
+ * Offscreen GLDrawable implementation using framebuffer object (FBO)
+ * as it's offscreen rendering mechanism.
+ *
+ * @see GLDrawableImpl#contextRealized(GLContext, boolean)
+ * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean)
+ * @see GLDrawableImpl#getDefaultDrawFramebuffer()
+ * @see GLDrawableImpl#getDefaultReadFramebuffer()
+ */
+public class GLFBODrawableImpl extends GLDrawableImpl {
+ final GLDrawableImpl parent;
+ final FBObject fbo;
+ int texUnit;
+ int samplesTexUnit = 0;
+ int width=0, height=0, samples=0;
+
+ protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent,
+ NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) {
+ super(factory, surface, false);
+ this.parent = parent;
+ this.texUnit = textureUnit;
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
+ this.width = initialWidth;
+ this.height = initialHeight;
+ this.samples = caps.getNumSamples();
+ this.fbo = new FBObject();
+ }
+
+ @Override
+ protected void contextRealized(GLContext glc, boolean realized) {
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
+ final GL gl = glc.getGL();
+ if(realized) {
+ fbo.reset(gl, width, height, samples);
+ samples = fbo.getNumSamples(); // update, maybe capped
+ if(samples > 0) {
+ fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0);
+ } else {
+ fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0);
+ }
+ if( caps.getStencilBits() > 0 ) {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
+ } else {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ }
+ } else if(null != fbo) {
+ fbo.destroy(gl);
+ }
+ }
+
+ @Override
+ protected void contextMadeCurrent(GLContext glc, boolean current) {
+ final GL gl = glc.getGL();
+ if(current) {
+ fbo.bind(gl);
+ } else {
+ fbo.unbind(gl);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
+ fbo.use(gl, samples > 0 ? fbo.getSamplingSink() : (TextureAttachment) fbo.getColorbuffer(0) );
+ if( samples > 0) {
+ gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbo.getReadFramebuffer());
+ }
+ }
+ }
+
+ @Override
+ protected int getDefaultDrawFramebuffer() { return fbo.getWriteFramebuffer(); }
+
+ @Override
+ protected int getDefaultReadFramebuffer() { return fbo.getReadFramebuffer(); }
+
+ public FBObject getFBObject() { return fbo; }
+
+ public void setSize(GL gl, int newWidth, int newHeight) throws GLException {
+ width = newWidth;
+ height = newHeight;
+ fbo.reset(gl, width, height, samples);
+ samples = fbo.getNumSamples(); // update, maybe capped
+ }
+
+ public void setSamples(GL gl, int newSamples) throws GLException {
+ samples = newSamples;
+ fbo.reset(gl, width, height, samples);
+ samples = fbo.getNumSamples(); // update, maybe capped
+ }
+
+
+ @Override
+ public GLContext createContext(GLContext shareWith) {
+ final GLContext ctx = parent.createContext(shareWith);
+ ctx.setGLDrawable(this, false);
+ return ctx;
+ }
+
+ @Override
+ public GLDynamicLookupHelper getGLDynamicLookupHelper() {
+ return parent.getGLDynamicLookupHelper();
+ }
+
+ @Override
+ protected void swapBuffersImpl() {
+ }
+
+ @Override
+ protected void setRealizedImpl() {
+ parent.setRealized(realized);
+ if(realized) {
+ final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) msConfig.getChosenCapabilities();
+ final GLCapabilitiesImmutable chosenFBOCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, true /*FBO*/, false /*PBO*/);
+ msConfig.setChosenCapabilities(chosenFBOCaps);
+ }
+ }
+
+ @Override
+ public int getWidth() {
+ return width;
+ }
+
+ @Override
+ public int getHeight() {
+ return height;
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index b7c15bfda..3f38f33bc 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -38,7 +38,8 @@ public class GLGraphicsConfigurationUtil {
public static final int WINDOW_BIT = 1 << 0;
public static final int BITMAP_BIT = 1 << 1;
public static final int PBUFFER_BIT = 1 << 2;
- public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT ;
+ public static final int FBO_BIT = 1 << 3;
+ public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT | FBO_BIT ;
public static final StringBuilder winAttributeBits2String(StringBuilder sb, int winattrbits) {
if(null==sb) {
@@ -61,30 +62,43 @@ public class GLGraphicsConfigurationUtil {
sb.append(", ");
}
sb.append("PBUFFER");
+ seperator=true;
+ }
+ if( 0 != ( FBO_BIT & winattrbits ) ) {
+ if(seperator) {
+ sb.append(", ");
+ }
+ sb.append("FBO");
}
return sb;
}
/**
+ * @param isFBO TODO
* @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set
*/
- public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer) {
+ public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer, boolean isFBO) {
int winattrbits = 0;
if(isOnscreen) {
winattrbits |= WINDOW_BIT;
- } else if (!isPBuffer) {
- winattrbits |= BITMAP_BIT;
} else {
- winattrbits |= PBUFFER_BIT;
+ if(isFBO) {
+ winattrbits |= FBO_BIT;
+ }
+ if (!isPBuffer) {
+ winattrbits |= BITMAP_BIT;
+ } else {
+ winattrbits |= PBUFFER_BIT;
+ }
}
return winattrbits;
}
/**
- * @see #getWinAttributeBits(boolean, boolean)
+ * @see #getWinAttributeBits(boolean, boolean, boolean)
*/
public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) {
- return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer());
+ return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer(), false);
}
public static final boolean addGLCapabilitiesPermutations(List<GLCapabilitiesImmutable> capsBucket, GLCapabilitiesImmutable temp, int winattrbits) {
@@ -92,43 +106,58 @@ public class GLGraphicsConfigurationUtil {
if( 0 != ( WINDOW_BIT & winattrbits ) ) {
GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
cpy.setOnscreen(true);
+ cpy.setPBuffer(false);
+ cpy.setFBO(false);
capsBucket.add(cpy);
}
- if( 0 != ( PBUFFER_BIT & winattrbits ) ) {
+ if( 0 != ( PBUFFER_BIT & winattrbits ) || 0 != ( FBO_BIT & winattrbits ) ) {
GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
- cpy.setPBuffer(true);
+ cpy.setFBO(0 != ( FBO_BIT & winattrbits ));
+ cpy.setPBuffer(0 != ( PBUFFER_BIT & winattrbits ));
capsBucket.add(cpy);
}
if( 0 != ( BITMAP_BIT & winattrbits ) ) {
GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
cpy.setOnscreen(false);
cpy.setPBuffer(false);
+ cpy.setFBO(false);
capsBucket.add(cpy);
}
return capsBucket.size() > preSize;
}
- public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable)
+ public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
{
if( !capsRequested.isOnscreen() ) {
- return fixOffScreenGLCapabilities(capsRequested, pbufferAvailable);
+ return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable);
}
- return capsRequested;
+ return fixOnscreenGLCapabilities(capsRequested);
}
- public static GLCapabilitiesImmutable fixOffScreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable)
+ public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested)
+ {
+ if( !capsRequested.isOnscreen() ) {
+ // fix caps ..
+ GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
+ caps2.setOnscreen(true);
+ return caps2;
+ }
+ return capsRequested;
+ }
+
+ public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
{
if( capsRequested.getDoubleBuffered() ||
capsRequested.isOnscreen() ||
- ( !pbufferAvailable && capsRequested.isPBuffer() ) )
+ ( fboAvailable != capsRequested.isFBO() ) ||
+ ( pbufferAvailable != capsRequested.isPBuffer() ) )
{
// fix caps ..
GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN
caps2.setOnscreen(false);
- if(caps2.isPBuffer() && !pbufferAvailable) {
- caps2.setPBuffer(false);
- }
+ caps2.setFBO( fboAvailable );
+ caps2.setPBuffer( pbufferAvailable );
return caps2;
}
return capsRequested;
@@ -136,25 +165,28 @@ public class GLGraphicsConfigurationUtil {
public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(GLCapabilitiesImmutable capsRequested)
{
- if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer()) {
+ if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer() || capsRequested.isFBO() ) {
// fix caps ..
GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - we don't need to be single buffered ..
caps2.setOnscreen(false);
caps2.setPBuffer(true);
+ caps2.setFBO(false);
return caps2;
}
return capsRequested;
}
+ /** Fix opaque setting while preserve alpha bits */
public static GLCapabilitiesImmutable fixOpaqueGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean isOpaque)
{
GLCapabilities caps2 = null;
if( capsRequested.isBackgroundOpaque() != isOpaque) {
- // fix caps ..
+ final int alphaBits = capsRequested.getAlphaBits();
caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setBackgroundOpaque(isOpaque);
+ caps2.setAlphaBits(alphaBits);
return caps2;
}
return capsRequested;
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index a8277fd71..32f4cb696 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -42,10 +42,14 @@ package jogamp.opengl;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLPbuffer;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
/** Platform-independent class exposing pbuffer functionality to
applications. This class is not exposed in the public API as it
would probably add no value; however it implements the GLDrawable
@@ -54,9 +58,8 @@ import javax.media.opengl.GLPbuffer;
public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
private int floatMode;
- public GLPbufferImpl(GLDrawableImpl pbufferDrawable,
- GLContext sharedContext) {
- super(pbufferDrawable, null); // drawable := pbufferDrawable
+ public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext, boolean ownDevice) {
+ super(pbufferDrawable, null, ownDevice); // drawable := pbufferDrawable
GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)
drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
@@ -102,7 +105,7 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
//
// GLDrawable delegation
//
-
+
@Override
public final void setRealized(boolean realized) {
}
@@ -110,10 +113,19 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
//
// GLAutoDrawable completion
//
+ private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
+
+ @Override
+ protected final RecursiveLock getLock() { return lock; }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return null;
+ }
@Override
public void destroy() {
- defaultDestroyOp();
+ defaultDestroy();
}
@Override
@@ -122,12 +134,23 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
}
@Override
- public void display() {
- if( null != drawable && drawable.isRealized() && null != context ) {
- helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
+ public final void display() {
+ final RecursiveLock _lock = lock;
+ _lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
+ try {
+ if( null != context ) {
+ helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
+ }
+ } finally {
+ _lock.unlock();
}
}
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 65a4c3ece..c5d0df645 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -110,14 +110,8 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void makeCurrentImpl() throws GLException {
- if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) {
- throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable);
- }
if (EGL.eglGetCurrentContext() != contextHandle) {
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- drawable.getHandle(),
- drawableRead.getHandle(),
- contextHandle)) {
+ if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
throw new GLException("Error making context 0x" +
Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError()));
}
@@ -126,10 +120,7 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void releaseImpl() throws GLException {
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- EGL.EGL_NO_SURFACE,
- EGL.EGL_NO_SURFACE,
- EGL.EGL_NO_CONTEXT)) {
+ if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) {
throw new GLException("Error freeing OpenGL context 0x" +
Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError()));
}
@@ -137,7 +128,7 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void destroyImpl() throws GLException {
- if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), contextHandle)) {
+ if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle)) {
final int eglError = EGL.eglGetError();
if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
throw new GLException("Error destroying OpenGL context 0x" +
@@ -158,16 +149,16 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected boolean createImpl(GLContextImpl shareWith) throws GLException {
- long eglDisplay = ((EGLDrawable)drawable).getDisplay();
- EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration();
- GLProfile glProfile = drawable.getGLProfile();
- long eglConfig = config.getNativeConfig();
+ final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+ final long eglDisplay = config.getScreen().getDevice().getHandle();
+ final GLProfile glProfile = drawable.getGLProfile();
+ final long eglConfig = config.getNativeConfig();
long shareWithHandle = EGL.EGL_NO_CONTEXT;
- if (eglDisplay == 0) {
+ if ( 0 == eglDisplay ) {
throw new GLException("Error: attempted to create an OpenGL context without a display connection");
}
- if (eglConfig == 0) {
+ if ( 0 == eglConfig ) {
throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration");
}
@@ -217,10 +208,7 @@ public abstract class EGLContext extends GLContextImpl {
",\n\t"+this+
",\n\tsharing with 0x" + Long.toHexString(shareWithHandle));
}
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- drawable.getHandle(),
- drawableRead.getHandle(),
- contextHandle)) {
+ if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
throw new GLException("Error making context 0x" +
Long.toHexString(contextHandle) + " current: error code " + EGL.eglGetError());
}
@@ -269,8 +257,7 @@ public abstract class EGLContext extends GLContextImpl {
eglQueryStringInitialized = true;
}
if (eglQueryStringAvailable) {
- final String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(),
- EGL.EGL_EXTENSIONS);
+ final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS);
if (DEBUG) {
System.err.println("EGL extensions: " + ret);
}
@@ -291,7 +278,7 @@ public abstract class EGLContext extends GLContextImpl {
}
return false;
}
- return EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval);
+ return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval);
}
@Override
@@ -300,6 +287,45 @@ public abstract class EGLContext extends GLContextImpl {
@Override
public abstract void releasePbufferFromTexture();
+ //
+ // Accessible ..
+ //
+
+ /**
+ * If context is an ES profile, map it to the given device
+ * via {@link GLContext#mapAvailableGLVersion(AbstractGraphicsDevice, int, int, int, int, int)}.
+ * <p>
+ * We intentionally override a non native EGL device ES profile mapping,
+ * i.e. this will override/modify an already 'set' X11/WGL/.. mapping.
+ * </p>
+ *
+ * @param device
+ */
+ protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) {
+ mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions);
+ }
+
+ protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) {
+ int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES );
+ mapCurrentAvailableGLVersionImpl(device, major, 0, ctp);
+ }
+ private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) {
+ if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) {
+ // ES1 or ES2
+ final int reqMajor = major;
+ final int reqProfile = GLContext.CTX_PROFILE_ES;
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
+ major, minor, ctp);
+ }
+ }
+
+ protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ return GLContext.getAvailableGLVersionsSet(device);
+ }
+ protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ GLContext.setAvailableGLVersionsSet(device);
+ }
+
protected static String toHexString(int hex) {
return GLContext.toHexString(hex);
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
index e09400c09..432010f49 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
@@ -30,12 +30,15 @@ package jogamp.opengl.egl;
import java.nio.IntBuffer;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
import com.jogamp.common.util.LongIntHashMap;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
/**
* This implementation provides recursive calls to
@@ -67,23 +70,6 @@ public class EGLDisplayUtil {
return eglDisplay;
}
- public static long eglGetDisplay(NativeSurface surface, boolean allowFallBackToDefault) {
- final long nDisplay;
- if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) {
- nDisplay = surface.getSurfaceHandle(); // don't even ask ..
- } else {
- nDisplay = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
- }
- long eglDisplay = EGLDisplayUtil.eglGetDisplay(nDisplay);
- if (eglDisplay == EGL.EGL_NO_DISPLAY && nDisplay != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) {
- if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY");
- }
- eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- }
- return eglDisplay;
- }
-
public static synchronized boolean eglInitialize(long eglDisplay, int[] major, int major_offset, int[] minor, int minor_offset) {
final boolean res;
final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
@@ -99,7 +85,19 @@ public class EGLDisplayUtil {
return res;
}
+ /**
+ *
+ * @param eglDisplay
+ * @param major
+ * @param minor
+ * @return true if the eglDisplay is valid and it's reference counter becomes one and {@link EGL#eglTerminate(long)} was successful, otherwise false
+ *
+ * @see EGL#eglInitialize(long, int[], int, int[], int)}
+ */
public static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
+ if( EGL.EGL_NO_DISPLAY == eglDisplay) {
+ return false;
+ }
final boolean res;
final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
if(1==refCnt) { // only initialize once
@@ -114,7 +112,14 @@ public class EGLDisplayUtil {
return res;
}
+ /**
+ * @param eglDisplay the EGL display handle
+ * @return true if the eglDisplay is valid and it's reference counter becomes zero and {@link EGL#eglTerminate(long)} was successful, otherwise false
+ */
public static synchronized boolean eglTerminate(long eglDisplay) {
+ if( EGL.EGL_NO_DISPLAY == eglDisplay) {
+ return false;
+ }
final boolean res;
final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate
if(0==refCnt) { // no terminate if still in use or already terminated
@@ -130,4 +135,65 @@ public class EGLDisplayUtil {
}
return res;
}
+
+ public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
+ public long eglGetAndInitDisplay(long nativeDisplayID) {
+ long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+ if (eglDisplay == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
+ throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ return eglDisplay;
+ }
+ public void eglTerminate(long eglDisplayHandle) {
+ EGLDisplayUtil.eglTerminate(eglDisplayHandle);
+ }
+ };
+
+ /**
+ * @param nativeDisplayID
+ * @param connection
+ * @param unitID
+ * @return an initialized EGLGraphicsDevice
+ * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails
+ * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback)
+ */
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) {
+ final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback);
+ eglDisplay.open();
+ return eglDisplay;
+ }
+
+ /**
+ * @param surface
+ * @param allowFallBackToDefault
+ * @return an initialized EGLGraphicsDevice
+ * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails
+ */
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(NativeSurface surface, boolean allowFallBackToDefault) {
+ long nativeDisplayID;
+ if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) {
+ nativeDisplayID = surface.getSurfaceHandle(); // don't even ask ..
+ } else {
+ nativeDisplayID = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
+ }
+ long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+ if (eglDisplay == EGL.EGL_NO_DISPLAY && nativeDisplayID != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) {
+ if(DEBUG) {
+ System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY");
+ }
+ nativeDisplayID = EGL.EGL_DEFAULT_DISPLAY;
+ eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+ }
+ if (eglDisplay == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Failed to created EGL display: "+surface+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
+ throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ }
+ final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice();
+ return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback);
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
index 491f22119..383b61f88 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
@@ -36,82 +36,65 @@
package jogamp.opengl.egl;
-import jogamp.opengl.GLDynamicLookupHelper;
-import jogamp.opengl.GLDrawableImpl;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.VisualIDHolder.VIDType;
-import javax.media.opengl.*;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLDynamicLookupHelper;
-import com.jogamp.nativewindow.egl.*;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
public abstract class EGLDrawable extends GLDrawableImpl {
- protected boolean ownEGLDisplay = false; // for destruction
- protected boolean ownEGLSurface = false; // for destruction
- private EGLGraphicsConfiguration eglConfig;
- protected long eglDisplay;
- protected long eglSurface;
+ private boolean ownEGLSurface = false; // for destruction
- protected EGLDrawable(EGLDrawableFactory factory,
- NativeSurface component) throws GLException {
+ protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException {
super(factory, component, false);
- eglSurface=EGL.EGL_NO_SURFACE;
- eglDisplay=0;
- }
-
- public long getDisplay() {
- return eglDisplay;
- }
-
- @Override
- public long getHandle() {
- return eglSurface;
- }
-
- public EGLGraphicsConfiguration getGraphicsConfiguration() {
- return eglConfig;
- }
-
- @Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities();
}
@Override
public abstract GLContext createContext(GLContext shareWith);
- protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle);
-
- private void recreateSurface() {
- // create a new EGLSurface ..
- if(EGL.EGL_NO_SURFACE!=eglSurface) {
- EGL.eglDestroySurface(eglDisplay, eglSurface);
- }
+ protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle);
+ private final void recreateSurface() {
+ final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice();
if(DEBUG) {
- System.err.println(getThreadName() + ": createSurface using eglDisplay "+toHexString(eglDisplay)+", "+eglConfig);
+ System.err.println(getThreadName() + ": createSurface using "+eglConfig);
+ }
+ if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) {
+ EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle());
}
-
- eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), surface.getSurfaceHandle());
- int eglError0 = EGL.EGL_SUCCESS;
+
+ final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook();
+ final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface();
+ long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle());
+
+ int eglError0;
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) {
// Try window handle if available and differs (Windows HDC / HWND).
// ANGLE impl. required HWND on Windows.
- if(surface instanceof NativeWindow) {
- final NativeWindow nw = (NativeWindow) surface;
+ if(upstreamSurface instanceof NativeWindow) {
+ final NativeWindow nw = (NativeWindow) upstreamSurface;
if(nw.getWindowHandle() != nw.getSurfaceHandle()) {
if(DEBUG) {
System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle");
}
- eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), nw.getWindowHandle());
+ eglSurface = createSurface(eglConfig, nw.getWindowHandle());
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
}
}
}
}
+ } else {
+ eglError0 = EGL.EGL_SUCCESS;
}
if (EGL.EGL_NO_SURFACE == eglSurface) {
throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0));
@@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl {
if(DEBUG) {
System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface));
}
+
+ ((MutableSurface)surface).setSurfaceHandle(eglSurface);
}
@Override
@@ -130,131 +115,72 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
@Override
- protected void setRealizedImpl() {
+ protected final void setRealizedImpl() {
+ final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice();
if (realized) {
- AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
- AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
- if(aDevice instanceof EGLGraphicsDevice) {
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START");
- }
- // just fetch the data .. trust but verify ..
- eglDisplay = aDevice.getHandle();
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice);
+ final long eglDisplayHandle = eglDevice.getHandle();
+ if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) {
+ throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice);
+ }
+ int[] tmp = new int[1];
+ boolean eglSurfaceValid = 0 != surface.getSurfaceHandle();
+ if(eglSurfaceValid) {
+ eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0);
+ if(!eglSurfaceValid) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface);
+ }
}
- if(aConfig instanceof EGLGraphicsConfiguration) {
- eglConfig = (EGLGraphicsConfiguration) aConfig; // done ..
- if (null == eglConfig) {
- throw new GLException("Null EGLGraphicsConfiguration from "+aConfig);
- }
-
- int[] tmp = new int[1];
- if ( 0 != surface.getSurfaceHandle() &&
- EGL.eglQuerySurface(eglDisplay, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) {
- // surface holds static EGLSurface
- eglSurface = surface.getSurfaceHandle();
- if(DEBUG) {
- System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface));
- }
- } else {
- // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
- ownEGLSurface=true;
- }
- } else {
- throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig);
+ }
+ if(eglSurfaceValid) {
+ // surface holds valid EGLSurface
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle()));
}
+ ownEGLSurface=false;
} else {
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START");
+ // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
+ // However .. let's validate the surface object first
+ if( ! (surface instanceof ProxySurface) ) {
+ throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface);
}
- // create a new EGL config ..
- ownEGLDisplay=true;
- // EGLSurface is ours ..
- ownEGLSurface=true;
-
- eglDisplay = EGLDisplayUtil.eglGetDisplay(surface, true);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL display: "+surface+", "+aDevice+", error "+toHexString(EGL.eglGetError()));
+ final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook();
+ if( null == upstreamHook ) {
+ throw new InternalError("null upstreamHook of: "+surface);
}
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed"+", error "+Integer.toHexString(EGL.eglGetError()));
+ if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) {
+ throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook);
}
- EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
- AbstractGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex());
- final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
- if(aConfig instanceof EGLGraphicsConfiguration) {
- final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
- if(0 == capsChosen.getEGLConfig()) {
- // 'refresh' the native EGLConfig handle
- capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDisplay, capsChosen.getEGLConfigID()));
- if(0 == capsChosen.getEGLConfig()) {
- throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
- }
- }
- eglConfig = new EGLGraphicsConfiguration(s, capsChosen, capsRequested, null);
- if(DEBUG) {
- System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig);
- }
- } else {
- eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsRequested, capsRequested, null, s, aConfig.getVisualID(VIDType.NATIVE), false);
-
- if (null == eglConfig) {
- throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s);
- } else if(DEBUG) {
- System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig);
- }
+ if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) {
+ throw new InternalError("null upstream surface");
+ }
+ ownEGLSurface=true;
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface");
}
- // subsequent updateHandle() will issue recreateSurface();
- }
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface);
}
- } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) {
+ } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) {
if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", eglDisplay: "+toHexString(eglDisplay)+", eglSurface: "+toHexString(eglSurface));
+ System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle()));
}
// Destroy the window surface
- if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) {
+ if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) {
throw new GLException("Error destroying window surface (eglDestroySurface)");
}
- eglSurface = EGL.EGL_NO_SURFACE;
- if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) {
- EGLDisplayUtil.eglTerminate(eglDisplay);
- }
- eglDisplay=EGL.EGL_NO_DISPLAY;
- eglConfig=null;
+ ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE);
}
}
@Override
protected final void swapBuffersImpl() {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
// single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
- if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) {
+ if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) {
throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this);
}
}
- /**
- * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable.
- * Leave it here for later impl. of an EGLExternalDrawable.
- public int getWidth() {
- int[] tmp = new int[1];
- if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) {
- throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError()));
- }
- return tmp[0];
- }
-
- public int getHeight() {
- int[] tmp = new int[1];
- if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) {
- throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError()));
- }
- return tmp[0];
- } */
-
@Override
public GLDynamicLookupHelper getGLDynamicLookupHelper() {
if (getGLProfile().usesNativeGLES2()) {
@@ -271,8 +197,8 @@ public abstract class EGLDrawable extends GLDrawableImpl {
return getClass().getName()+"[realized "+isRealized()+
",\n\tfactory "+getFactory()+
",\n\tsurface "+getNativeSurface()+
- ",\n\teglSurface "+toHexString(eglSurface)+
- ",\n\teglConfig "+eglConfig+
+ ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+
+ ",\n\teglConfig "+surface.getGraphicsConfiguration()+
",\n\trequested "+getRequestedGLCapabilities()+
",\n\tchosen "+getChosenGLCapabilities()+"]";
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index e4f6f0ef8..c848e3e5c 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GL;
+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.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLProfile.ShutdownType;
+import jogamp.opengl.Debug;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.os.Platform;
@@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
public class EGLDrawableFactory extends GLDrawableFactoryImpl {
+ /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true);
+ /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
+
private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null;
private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null;
private static boolean isANGLE = false;
@@ -184,10 +195,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if(DEBUG) {
System.err.println("EGLDrawableFactory.destroy("+shutdownType+"): "+sr.device.toString());
}
- final long eglDisplay = sr.device.getHandle();
- if(EGL.EGL_NO_DISPLAY != eglDisplay) {
- EGLDisplayUtil.eglTerminate(eglDisplay);
- }
+ sr.device.close();
}
sharedMap.clear();
sharedMap = null;
@@ -234,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
// final EGLContext getContextES1() { return contextES1; }
// final EGLContext getContextES2() { return contextES2; }
final boolean wasES1ContextAvailable() { return wasES1ContextCreated; }
- final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
+ final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
}
@Override
@@ -248,66 +256,144 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper;
}
- /**
- private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) {
- boolean madeCurrent = false;
- final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile));
- caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
- caps.setDoubleBuffered(false);
- caps.setOnscreen(false);
- caps.setPBuffer(true);
- final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
- if(null!=drawable) {
+ private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) {
+ if( !GLProfile.isAvailable(adevice, profileString) ) {
+ return false;
+ }
+ final GLProfile glp = GLProfile.get(adevice, profileString) ;
+ final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
+ EGLGraphicsDevice eglDevice = null;
+ NativeSurface surface = null;
+ ProxySurface upstreamSurface = null; // X11, GLX, ..
+ boolean success = false;
+ boolean deviceFromUpstreamSurface = false;
+ try {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
+ if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) {
+ eglDevice = sharedEGLDevice; // reuse
+ surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen
+ upstreamSurface = (ProxySurface)surface;
+ upstreamSurface.createNotify();
+ deviceFromUpstreamSurface = false;
+ } else {
+ surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window
+ upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ;
+ if(null != upstreamSurface) {
+ upstreamSurface.createNotify();
+ }
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
+ deviceFromUpstreamSurface = true;
+ }
+
+ final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface );
+ drawable.setRealized(true);
final EGLContext context = (EGLContext) drawable.createContext(null);
if (null != context) {
- context.setSynchronized(true);
try {
context.makeCurrent(); // could cause exception
- madeCurrent = context.isCurrent();
+ success = context.isCurrent();
+ if(success) {
+ final String glVersion = context.getGL().glGetString(GL.GL_VERSION);
+ if(null == glVersion) {
+ // Oops .. something is wrong
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
+ }
+ success = false;
+ }
+ }
+ if(success) {
+ context.mapCurrentAvailableGLVersion(eglDevice);
+ if(eglDevice != adevice) {
+ context.mapCurrentAvailableGLVersion(adevice);
+ }
+ }
} catch (GLException gle) {
if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed");
+ System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed");
gle.printStackTrace();
}
} finally {
context.destroy();
}
}
- drawable.destroy();
+ drawable.setRealized(false);
+ } catch (Throwable t) {
+ if(DEBUG) {
+ System.err.println("Catched Exception:");
+ t.printStackTrace();
+ }
+ success = false;
+ } finally {
+ if(eglDevice == sharedEGLDevice) {
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
+ } else if( deviceFromUpstreamSurface ) {
+ if(null != eglDevice) {
+ eglDevice.close();
+ }
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
+ } else {
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
+ if(null != eglDevice) {
+ eglDevice.close();
+ }
+ }
}
- return madeCurrent;
- } */
+ return success;
+ }
/* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) {
return null;
}
- String connection = adevice.getConnection();
+ final String connection = adevice.getConnection();
SharedResource sr;
synchronized(sharedMap) {
sr = sharedMap.get(connection);
}
if(null==sr) {
- long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError()));
- } else if(DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay));
+ final boolean madeCurrentES1;
+ final boolean madeCurrentES2;
+ final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+
+ if(QUERY_EGL_ES) {
+ madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1);
+ madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2);
+ } else {
+ madeCurrentES1 = true;
+ madeCurrentES2 = true;
+ EGLContext.mapStaticGLESVersion(sharedDevice, 1);
+ if(sharedDevice != adevice) {
+ EGLContext.mapStaticGLESVersion(adevice, 1);
+ }
+ EGLContext.mapStaticGLESVersion(sharedDevice, 2);
+ if(sharedDevice != adevice) {
+ EGLContext.mapStaticGLESVersion(adevice, 2);
+ }
}
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+
+ if( !EGLContext.getAvailableGLVersionsSet(adevice) ) {
+ // Even though we override the non EGL native mapping intentionally,
+ // avoid exception due to double 'set' - carefull exception of the rule.
+ EGLContext.setAvailableGLVersionsSet(adevice);
}
- final EGLGraphicsDevice sharedDevice = new EGLGraphicsDevice(eglDisplay, connection, adevice.getUnitID());
- // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1);
- // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2);
- final boolean madeCurrentES1 = true; // FIXME
- final boolean madeCurrentES2 = true; // FIXME
sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2);
+
synchronized(sharedMap) {
sharedMap.put(connection, sr);
+ if(adevice != sharedDevice) {
+ sharedMap.put(sharedDevice.getConnection(), sr);
+ }
}
if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice);
+ System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice);
System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1);
System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2);
}
@@ -378,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- return new EGLOnscreenDrawable(this, target);
+ return new EGLOnscreenDrawable(this, getEGLSurface(target));
+ }
+
+ protected static NativeSurface getEGLSurface(NativeSurface surface) {
+ AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
+ AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
+ if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) {
+ // already in native EGL format
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig);
+ }
+ return surface;
+ }
+ // create EGL instance out of platform native types
+ final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
+ final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
+ final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
+ final EGLGraphicsConfiguration eglConfig;
+ if( aConfig instanceof EGLGraphicsConfiguration ) {
+ // Config is already in EGL type - reuse ..
+ final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
+ if( 0 == capsChosen.getEGLConfig() ) {
+ // 'refresh' the native EGLConfig handle
+ capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID()));
+ if( 0 == capsChosen.getEGLConfig() ) {
+ throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
+ }
+ }
+ eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null);
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig);
+ }
+ } else {
+ eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
+ capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false);
+
+ if (null == eglConfig) {
+ throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen);
+ } else if(DEBUG) {
+ System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig);
+ }
+ }
+ return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface));
}
+ static String getThreadName() { return Thread.currentThread().getName(); }
@Override
protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
@@ -401,20 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser));
- ns.surfaceSizeChanged(width, height);
- return ns;
+ protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final EGLGraphicsDevice device;
+ if(createNewDevice) {
+ final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
+ device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (EGLGraphicsDevice) deviceReq;
+ }
+ final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, width, height, lifecycleHook);
+ }
+
+ @Override
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq));
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) {
+ if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
+ if(0 == eglDevice.getHandle()) {
+ eglDevice.open();
+ s.setImplBitfield(ProxySurface.OWN_DEVICE);
+ }
+ createPBufferSurfaceImpl(s, false);
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) {
+ final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+ EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(EGL.EGL_NO_SURFACE);
+ if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) {
+ eglDevice.close();
+ }
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+ @Override
+ public String toString() {
+ return "EGLSurfaceLifecycleHook[]";
+ }
+
+ };
+
+ /**
+ * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface.
+ * It will also hold the resulting pbuffer surface handle.
+ * @param useTexture
+ * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle
+ */
+ protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) {
+ final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final int texFormat;
+
+ if(useTexture) {
+ texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
+ } else {
+ texFormat = EGL.EGL_NO_TEXTURE;
+ }
+
+ if (DEBUG) {
+ System.out.println("Pbuffer config: " + config);
+ }
+
+ final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat);
+ final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0);
+ if (EGL.EGL_NO_SURFACE==surf) {
+ throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ } else if(DEBUG) {
+ System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+ }
+ ms.setSurfaceHandle(surf);
+ return ms;
}
@Override
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- EGLGraphicsDevice device = (EGLGraphicsDevice) adevice;
- DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
- WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
- return ns;
+ protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
+ final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+ final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
+ return new WrappedSurface(cfg, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 56e7a4d22..716a6e6f1 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
@@ -42,6 +42,7 @@ import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
@@ -96,9 +97,10 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
}
void updateGraphicsConfiguration() {
+ CapabilitiesImmutable capsChosen = getChosenCapabilities();
EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(
- getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen());
+ GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), capsChosen).chooseGraphicsConfiguration(
+ capsChosen, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
if(null!=newConfig) {
// FIXME: setScreen( ... );
setChosenCapabilities(newConfig.getChosenCapabilities());
@@ -151,7 +153,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config,
boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) {
List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask, forceTransparentFlag) ) {
return (EGLGLCapabilities) bucket.get(0);
} else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag) ) {
@@ -209,24 +211,6 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
return false;
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) {
- caps.setRedBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) {
- caps.setGreenBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) {
- caps.setBlueBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) {
- caps.setAlphaBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) {
- caps.setStencilBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) {
- caps.setDepthBits(val.get(0));
- }
if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val)) {
caps.setSampleBuffers(val.get(0)>0?true:false);
caps.setNumSamples(val.get(0));
@@ -262,6 +246,25 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
caps.setTransparentAlphaValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0));
} */
}
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) {
+ caps.setRedBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) {
+ caps.setGreenBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) {
+ caps.setBlueBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) {
+ caps.setAlphaBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) {
+ caps.setStencilBits(val.get(0));
+ }
+ if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) {
+ caps.setDepthBits(val.get(0));
+ }
return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, caps, drawableTypeBits );
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
index 5ab2632c6..0b21d2054 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
@@ -38,7 +38,6 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.VisualIDHolder.VIDType;
@@ -47,6 +46,7 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLDrawableFactory;
@@ -81,27 +81,27 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
// become the pre-selector for X11/.. to match the native visual id w/ EGL, if native ES is selected
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
- nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, eglFactory);
+ nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, eglFactory);
} else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
// become the selector for KD/EGL ..
- kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, eglFactory);
+ kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
}
static void unregisterFactory() {
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, nativeGraphicsConfigurationFactory);
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory);
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, nativeGraphicsConfigurationFactory);
} else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
nativeGraphicsConfigurationFactory = null;
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, kdeglGraphicsConfigurationFactory);
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, kdeglGraphicsConfigurationFactory);
kdeglGraphicsConfigurationFactory = null;
}
@@ -110,7 +110,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl (
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (absScreen == null) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects");
}
@@ -140,7 +140,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
- absScreen, VisualIDHolder.VID_UNDEFINED, false);
+ absScreen, nativeVisualID, false);
} else {
// handle non native cases (X11, ..)
if(null == nativeGraphicsConfigurationFactory) {
@@ -154,7 +154,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
- absScreen, VisualIDHolder.VID_UNDEFINED, false);
+ absScreen, nativeVisualID, false);
if(null == cfg || VisualIDHolder.VID_UNDEFINED == cfg.getVisualID(VIDType.NATIVE)) {
cfg = null;
if(DEBUG) {
@@ -167,7 +167,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(DEBUG) {
System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+nativeGraphicsConfigurationFactory.getClass().getSimpleName());
}
- cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen);
+ cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, nativeVisualID);
}
}
return cfg;
@@ -180,6 +180,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
}
EGLGraphicsDevice eglDevice = sharedResource.getDevice();
long eglDisplay = eglDevice.getHandle();
+ if(0 == eglDisplay) {
+ throw new GLException("null eglDisplay");
+ }
List<GLCapabilitiesImmutable> availableCaps = null;
IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
@@ -223,32 +226,24 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("Null AbstractGraphicsDevice");
}
- final long eglDisplay;
+ final EGLGraphicsDevice eglDevice;
final boolean ownEGLDisplay;
- if( !(absDevice instanceof EGLGraphicsDevice) ) {
- eglDisplay = EGLDisplayUtil.eglGetDisplay(absDevice.getHandle());
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Could not get EGL display from: "+absDevice);
- }
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+absDevice+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- ownEGLDisplay = true;
- } else {
- eglDisplay = absDevice.getHandle();
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Invalid EGL display: "+absDevice);
+ if( absDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) absDevice;
+ if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Invalid EGL display: "+eglDevice);
}
ownEGLDisplay = false;
+ } else {
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID());
+ ownEGLDisplay = true;
}
- EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) );
-
- GLProfile glp = capsChosen.getGLProfile();
- GLCapabilities fixedCaps;
+ final GLProfile glp = capsChosen.getGLProfile();
+ final EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(absDevice, glp), factory.canCreateGLPbuffer(absDevice) );
- EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
+ EGLGraphicsConfiguration res = eglChooseConfig(eglDevice.getHandle(), capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
if(null==res) {
if(DEBUG) {
System.err.println("eglChooseConfig failed with given capabilities "+capsChosen);
@@ -257,52 +252,67 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
// Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..]
//
// rgb888 - d16, s4
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
+ fixedCaps.setSampleBuffers(true);
+ fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(8);
fixedCaps.setGreenBits(8);
fixedCaps.setBlueBits(8);
fixedCaps.setDepthBits(16);
- fixedCaps.setSampleBuffers(true);
- fixedCaps.setNumSamples(4);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (1): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s0
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (2): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s4
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
+ fixedCaps.setSampleBuffers(true);
+ fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
- fixedCaps.setSampleBuffers(true);
- fixedCaps.setNumSamples(4);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (3): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]");
}
if(ownEGLDisplay) {
- ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
- EGLDisplayUtil.eglTerminate(eglDisplay);
+ ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
+ eglDevice.close();
}
return res;
}
@@ -315,7 +325,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
final GLProfile glp = capsChosen.getGLProfile();
final boolean onscreen = capsChosen.isOnscreen();
final boolean usePBuffer = capsChosen.isPBuffer();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
List<GLCapabilitiesImmutable> availableCaps = null;
int recommendedIndex = -1;
long recommendedEGLConfig = -1;
@@ -328,8 +338,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs");
}
if (DEBUG) {
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig maxConfigs: "+numConfigs.get(0));
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglDisplay "+toHexString(eglDisplay)+", "+capsChosen+", nativeVisualID "+toHexString(nativeVisualID));
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+", nativeVisualID "+toHexString(nativeVisualID)+", onscreen "+onscreen+", usePBuffer "+usePBuffer+", "+capsChosen+", numConfigs "+numConfigs.get(0));
}
final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen));
@@ -368,7 +377,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
+ availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
}
}
@@ -376,6 +385,8 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(DEBUG) {
// FIXME: this happens on a ATI PC Emulation ..
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs");
+ availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag);
+ printCaps("AllCaps", availableCaps, System.err);
}
return null;
}
@@ -434,27 +445,5 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
out.println(prefix+"["+i+"] "+caps.get(i));
}
}
-
- static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser) {
- if(capsChosen.isOnscreen()) {
- throw new GLException("Error: Onscreen set: "+capsChosen);
- }
-
- if(capsChosen.getDoubleBuffered()) {
- // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN
- GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable();
- caps2.setDoubleBuffered(false);
- capsChosen = caps2;
- }
-
- DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(capsChosen, capsReq, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
- if (null == eglConfig) {
- throw new GLException("Couldn't create EGLGraphicsConfiguration from "+screen);
- } else if(DEBUG) {
- System.err.println("Chosen eglConfig: "+eglConfig);
- }
- return eglConfig;
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 3768f1588..d54057775 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
@@ -54,8 +54,8 @@ public class EGLOnscreenDrawable extends EGLDrawable {
}
@Override
- protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
- return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null);
+ protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) {
+ return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index b2217c095..4a36625bd 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
@@ -40,15 +40,11 @@
package jogamp.opengl.egl;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
-import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
public class EGLPbufferDrawable extends EGLDrawable {
- private int texFormat;
protected static final boolean useTexture = false; // No yet ..
protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) {
@@ -56,30 +52,12 @@ public class EGLPbufferDrawable extends EGLDrawable {
}
@Override
- protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
- final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration();
- final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
-
- if(useTexture) {
- texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
- } else {
- texFormat = EGL.EGL_NO_TEXTURE;
- }
-
- if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
- }
-
- NativeSurface nw = getNativeSurface();
- int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat);
- long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0);
- if (EGL.EGL_NO_SURFACE==surf) {
- throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- } else if(DEBUG) {
- System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+ protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) {
+ final MutableSurface ms = (MutableSurface)getNativeSurface();
+ if(config != ms.getGraphicsConfiguration()) {
+ throw new InternalError("Not same: "+config.hashCode()+", "+ms.getGraphicsConfiguration()+": "+config+", "+ms.getGraphicsConfiguration());
}
- ((SurfaceChangeable)nw).setSurfaceHandle(surf);
- return surf;
+ return EGLDrawableFactory.createPBufferSurfaceImpl(ms, useTexture).getSurfaceHandle();
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
new file mode 100644
index 000000000..42c6e100e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -0,0 +1,56 @@
+package jogamp.opengl.egl;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLException;
+
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+
+public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook {
+ private final NativeSurface upstreamSurface;
+
+ public EGLUpstreamSurfaceHook(NativeSurface upstream) {
+ upstreamSurface = upstream;
+ }
+
+ public final NativeSurface getUpstreamSurface() { return upstreamSurface; }
+
+ @Override
+ public final void create(ProxySurface surface) {
+ if(upstreamSurface instanceof ProxySurface) {
+ ((ProxySurface)upstreamSurface).createNotify();
+ if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) {
+ throw new GLException("Could not lock: "+upstreamSurface);
+ }
+ }
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+ eglDevice.open();
+ }
+
+ @Override
+ public final void destroy(ProxySurface surface) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+ eglDevice.close();
+ if(upstreamSurface instanceof ProxySurface) {
+ upstreamSurface.unlockSurface();
+ ((ProxySurface)upstreamSurface).destroyNotify();
+ }
+ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return upstreamSurface.getWidth();
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return upstreamSurface.getHeight();
+ }
+
+ @Override
+ public String toString() {
+ final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": " + upstreamSurface ) : "nil";
+ return "EGLUpstreamSurfaceHook[upstream: "+us_s+"]";
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index aa66aa9d1..82525cfde 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -48,11 +48,13 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
+import javax.media.nativewindow.ProxySurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
@@ -63,6 +65,7 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
public abstract class MacOSXCGLContext extends GLContextImpl
{
@@ -252,9 +255,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
protected void makeCurrentImpl() throws GLException {
+ /** FIXME: won't work w/ special drawables (like FBO) - check for CGL mode regressions!
+ *
if (getOpenGLMode() != ((MacOSXCGLDrawable)drawable).getOpenGLMode()) {
setOpenGLMode(((MacOSXCGLDrawable)drawable).getOpenGLMode());
- }
+ } */
if (!impl.makeCurrent(contextHandle)) {
throw new GLException("Error making Context current: "+this);
}
@@ -338,8 +343,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
+ if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
+ glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
return true;
}
return super.isExtensionAvailable(glExtensionName);
@@ -426,10 +431,27 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public long create(long share, int ctp, int major, int minor) {
long ctx = 0;
- final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) MacOSXCGLContext.this.drawable;
- final NativeSurface surface = drawable.getNativeSurface();
+ final long nsViewHandle;
+ if(drawable instanceof MacOSXCGLDrawable) {
+ // we allow null here! (special pbuffer case)
+ nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle();
+ } else {
+ // we only allow a valid NSView here
+ final long aHandle = drawable.getHandle();
+ if( OSXUtil.isNSView(aHandle) ) {
+ nsViewHandle = aHandle;
+ } else {
+ throw new RuntimeException("Anonymous drawable instance's handle not of type NSView: "+drawable.getClass().getName()+", "+drawable);
+ }
+ }
+ final NativeSurface surface = drawable.getNativeSurface();
final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
+
+ boolean allowIncompleteView = null != backingLayerHost;
+ if( !allowIncompleteView && surface instanceof ProxySurface ) {
+ allowIncompleteView = 0 != ( ProxySurface.INVISIBLE_WINDOW & ((ProxySurface)surface).getImplBitfield() ) ;
+ }
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor);
if (pixelFormat == 0) {
@@ -443,13 +465,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl
screenVSyncTimeout = 1000000f / sRefreshRate;
if(DEBUG) {
System.err.println("NS create OSX>=lion "+isLionOrLater);
- System.err.println("NS create backendType: "+drawable.getOpenGLMode());
+ System.err.println("NS create allowIncompleteView: "+allowIncompleteView);
System.err.println("NS create backingLayerHost: "+backingLayerHost);
System.err.println("NS create share: "+share);
System.err.println("NS create chosenCaps: "+chosenCaps);
System.err.println("NS create pixelFormat: "+toHexString(pixelFormat));
System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle()));
- System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle()));
+ System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle));
System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros");
// Thread.dumpStack();
}
@@ -457,7 +479,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
int[] viewNotReady = new int[1];
// Try to allocate a context with this
ctx = CGL.createContext(share,
- drawable.getNSViewHandle(), null!=backingLayerHost,
+ nsViewHandle, allowIncompleteView,
pixelFormat,
chosenCaps.isBackgroundOpaque(),
viewNotReady, 0);
@@ -473,10 +495,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
CGL.setContextOpacity(ctx, 0);
}
- if(DEBUG) {
- GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(null, pixelFormat);
- System.err.println("NS create pixelformat2GLCaps: "+caps0);
- }
GLCapabilitiesImmutable fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
config.setChosenCapabilities(fixedCaps);
@@ -502,10 +520,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl
texWidth = drawable.getWidth();
texHeight = drawable.getHeight();
}
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight);
if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) {
throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable);
}
+ nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight);
if (DEBUG) {
System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable);
}
@@ -528,11 +546,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer));
}
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
- if(null == ols) {
- throw new InternalError("XXX: "+ols);
+ if(null != ols && ols.isSurfaceLayerAttached()) {
+ // still having a valid OLS attached to surface (parent OLS could have been removed)
+ ols.detachSurfaceLayer();
}
- CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
- ols.detachSurfaceLayer(nsOpenGLLayer);
+ CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
CGL.deletePixelFormat(nsOpenGLLayerPFmt);
nsOpenGLLayerPFmt = 0;
nsOpenGLLayer = 0;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index 257635b8c..af767f0c3 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -105,7 +105,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
@Override
protected void setRealizedImpl() {
}
-
+
protected long getNSViewHandle() {
return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0;
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 4e9d18fed..9689d9f64 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -50,8 +50,8 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
@@ -62,15 +62,19 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLProfile.ShutdownType;
+import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.opengl.GLExtensions;
public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper = null;
@@ -214,44 +218,39 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- final GLCapabilities caps = new GLCapabilities(glp);
- caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
- caps.setDepthBits(5);
- caps.setDoubleBuffered(false);
- caps.setOnscreen(false);
- caps.setPBuffer(true);
- final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
- if(null!=drawable) {
- drawable.setRealized(true);
- final GLContext context = drawable.createContext(null);
- if (null != context) {
- try {
- context.makeCurrent(); // could cause exception
- madeCurrent = context.isCurrent();
- if(madeCurrent) {
- GL gl = context.getGL();
- hasNPOTTextures = gl.isNPOTTextureAvailable();
- hasRECTTextures = gl.isExtensionAvailable("GL_EXT_texture_rectangle");
- hasAppleFloatPixels = gl.isExtensionAvailable("GL_APPLE_float_pixels");
- }
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
- gle.printStackTrace();
- }
- } finally {
- try {
- context.destroy();
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
- gle.printStackTrace();
- }
- }
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
+ if (null == sharedContext) {
+ throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
+ }
+
+ try {
+ sharedContext.makeCurrent(); // could cause exception
+ madeCurrent = sharedContext.isCurrent();
+ if(madeCurrent) {
+ GL gl = sharedContext.getGL();
+ hasNPOTTextures = gl.isNPOTTextureAvailable();
+ hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle);
+ hasAppleFloatPixels = gl.isExtensionAvailable(GLExtensions.APPLE_float_pixels);
+ }
+ } catch (GLException gle) {
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
+ gle.printStackTrace();
+ }
+ } finally {
+ try {
+ sharedContext.destroy();
+ } catch (GLException gle) {
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
+ gle.printStackTrace();
}
}
- drawable.setRealized(false);
}
+ sharedDrawable.setRealized(false);
}
sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels);
synchronized(sharedMap) {
@@ -332,18 +331,82 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX);
- WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true));
- ns.surfaceSizeChanged(width, height);
- return ns;
+ protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final MacOSXGraphicsDevice device;
+ if(createNewDevice) {
+ device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
+ } else {
+ device = (MacOSXGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, width, height, lifecycleHook);
}
@Override
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true), windowHandle);
- return ns;
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ long nsWindow = 0;
+ @Override
+ public final void create(ProxySurface s) {
+ if(0 == nsWindow && 0 == s.getSurfaceHandle()) {
+ nsWindow = OSXUtil.CreateNSWindow(0, 0, s.getWidth(), s.getHeight());
+ if(0 == nsWindow) {
+ throw new GLException("Error NS window 0");
+ }
+ long nsView = OSXUtil.GetNSView(nsWindow);
+ if(0 == nsView) {
+ throw new GLException("Error NS view 0");
+ }
+ s.setSurfaceHandle(nsView);
+ s.setImplBitfield(ProxySurface.INVISIBLE_WINDOW);
+ if(DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ if(0 != nsWindow && 0 != s.getSurfaceHandle()) {
+ OSXUtil.DestroyNSWindow(nsWindow);
+ nsWindow = 0;
+ s.setSurfaceHandle(0);
+ if(DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+
+ @Override
+ public String toString() {
+ return "MacOSXLSurfaceLifecycleHook[]";
+ }
+
+ };
+
+ @Override
+ protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true);
+ return new WrappedSurface(config, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
index 8393a688e..202644bb3 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
@@ -154,7 +154,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.NSOpenGLPFASamples:
- ivalues[idx] = caps.getSampleBuffers() ? ivalues[idx] = caps.getNumSamples() : 0;
+ ivalues[idx] = caps.getNumSamples() ;
break;
default:
@@ -233,7 +233,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
return fmt.get(0);
}
- static GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) {
+ static GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) {
return PixelFormat2GLCapabilities(null, pixelFormat, false);
}
@@ -281,6 +281,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
glp = GLProfile.get(GLProfile.GL2);
}
GLCapabilities caps = new GLCapabilities(glp);
+ int alphaBits = 0;
for (int i = 0; i < len; i++) {
int attr = cglInternalAttributeToken[i+off];
switch (attr) {
@@ -317,7 +318,8 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.NSOpenGLPFAAlphaSize:
- caps.setAlphaBits(ivalues[i]);
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
+ alphaBits = ivalues[i];
break;
case CGL.NSOpenGLPFADepthSize:
@@ -350,6 +352,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
}
}
+ caps.setAlphaBits(alphaBits);
return caps;
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
index 1a9070aef..f138e7557 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
@@ -50,14 +50,14 @@ import javax.media.opengl.GLCapabilitiesImmutable;
public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, new MacOSXCGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXCGLGraphicsConfigurationFactory());
}
private MacOSXCGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, absScreen, false);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
index ad4c06af2..6be9e386d 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
@@ -114,8 +114,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
// set a fake marker stating a valid drawable
currentDrawable = 1;
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(currentDrawable);
+ WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, null);
return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 242cea068..8f2f386af 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -42,7 +42,7 @@ package jogamp.opengl.macosx.cgl;
import javax.media.nativewindow.DefaultGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2GL3;
@@ -94,11 +94,11 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
registerContext(ctx);
return ctx;
}
-
+
@Override
protected long getNSViewHandle() {
- // pbuffer handle is NSOpenGLPixelBuffer
- return 0;
+ // pbuffer handle is NSOpenGLPixelBuffer
+ return 0;
}
@Override
@@ -115,7 +115,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
NativeSurface ns = getNativeSurface();
impl.destroy(pBuffer);
this.pBuffer = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
}
@@ -174,7 +174,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
}
- ((SurfaceChangeable)ns).setSurfaceHandle(pBuffer);
+ ((MutableSurface)ns).setSurfaceHandle(pBuffer);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
index a6fa01bad..edf9b7c84 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
@@ -58,14 +58,14 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLGraphicsConfiguration;
public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new MacOSXAWTCGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXAWTCGLGraphicsConfigurationFactory());
}
private MacOSXAWTCGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -103,9 +103,9 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur
GraphicsConfiguration gc = device.getDefaultConfiguration();
MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(macDevice).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(macDevice, capsChosen).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, macScreen);
+ chooser, macScreen, nativeVisualID);
if (macConfig == null) {
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+macScreen);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
index 31f13297b..6bf8839af 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
@@ -113,7 +113,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
// create EGLImage from texture
clientBuffer = null; // FIXME
nioTmp.put(0, EGL.EGL_NONE);
- image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(),
+ image = eglExt.eglCreateImageKHR( eglDrawable.getNativeSurface().getDisplayHandle(), eglCtx.getHandle(),
EGLExt.EGL_GL_TEXTURE_2D_KHR,
clientBuffer, nioTmp);
if (0==image) {
@@ -130,7 +130,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
// rendering the EGLImage texture before we tell OpenMAX to fill
// it with a new frame.
tmp[0] = EGL.EGL_NONE;
- sync = eglExt.eglCreateSyncKHR(eglDrawable.getDisplay(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0);
+ sync = eglExt.eglCreateSyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0);
if (0==sync) {
throw new RuntimeException("EGLSync creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", err "+toHexString(EGL.eglGetError()));
}
@@ -159,10 +159,10 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex;
if(0!=eglTex.getImage()) {
- eglExt.eglDestroyImageKHR(eglDrawable.getDisplay(), eglTex.getImage());
+ eglExt.eglDestroyImageKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getImage());
}
if(0!=eglTex.getSync()) {
- eglExt.eglDestroySyncKHR(eglDrawable.getDisplay(), eglTex.getSync());
+ eglExt.eglDestroySyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getSync());
}
super.destroyTexImage(gl, imgTex);
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index e255a0672..6a4ce5a4e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
@@ -52,10 +52,11 @@ public class WGLGLCapabilities extends GLCapabilities {
public boolean setValuesByGDI() {
arb_pixelformat = -1;
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
setRedBits(pfd.getCRedBits());
setGreenBits(pfd.getCGreenBits());
setBlueBits(pfd.getCBlueBits());
- setAlphaBits(pfd.getCAlphaBits());
+ setAlphaBits(pfd.getCAlphaBits());
setAccumRedBits(pfd.getCAccumRedBits());
setAccumGreenBits(pfd.getCAccumGreenBits());
setAccumBlueBits(pfd.getCAccumBlueBits());
@@ -77,6 +78,7 @@ public class WGLGLCapabilities extends GLCapabilities {
public boolean setValuesByARB(final int[] iattribs, final int niattribs, final int[] iresults) {
arb_pixelformat = 1;
+ int alphaBits = 0;
for (int i = 0; i < niattribs; i++) {
int attr = iattribs[i];
switch (attr) {
@@ -143,7 +145,8 @@ public class WGLGLCapabilities extends GLCapabilities {
break;
case WGLExt.WGL_ALPHA_BITS_ARB:
- setAlphaBits(iresults[i]);
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
+ alphaBits = iresults[i];
break;
case WGLExt.WGL_ACCUM_RED_BITS_ARB:
@@ -174,6 +177,7 @@ public class WGLGLCapabilities extends GLCapabilities {
throw new GLException("Unknown pixel format attribute " + iattribs[i]);
}
}
+ setAlphaBits(alphaBits);
return true;
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
index 296d53ce3..cf6f43b1c 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
@@ -41,7 +41,7 @@
package jogamp.opengl.windows.wgl;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -139,7 +139,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
hbitmap = 0;
throw new GLException("Error creating device context for offscreen OpenGL context, werr "+werr);
}
- ((SurfaceChangeable)ns).setSurfaceHandle(hdc);
+ ((MutableSurface)ns).setSurfaceHandle(hdc);
if(DEBUG) {
System.err.println("WindowsBitmapWGLDrawable (2): "+ns);
}
@@ -164,7 +164,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
GDI.DeleteDC(ns.getSurfaceHandle());
origbitmap = 0;
hbitmap = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java
deleted file mode 100644
index 05d6d9862..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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 jogamp.opengl.windows.wgl;
-
-import javax.media.nativewindow.AbstractGraphicsScreen;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
-
-import jogamp.nativewindow.windows.GDI;
-import jogamp.nativewindow.windows.GDISurface;
-import jogamp.nativewindow.windows.GDIUtil;
-
-public class WindowsDummyWGLDrawable extends WindowsWGLDrawable {
- private long hwnd;
- private boolean handleHwndLifecycle;
-
- private WindowsDummyWGLDrawable(GLDrawableFactory factory, GDISurface ns, boolean handleHwndLifecycle) {
- super(factory, ns, true);
- this.handleHwndLifecycle = handleHwndLifecycle;
-
- if(NativeSurface.LOCK_SURFACE_NOT_READY >= ns.lockSurface()) {
- throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)");
- }
- try {
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
- config.updateGraphicsConfiguration(factory, ns, null);
- if (DEBUG) {
- System.err.println("WindowsDummyWGLDrawable: "+config);
- }
- } catch (Throwable t) {
- setRealized(false);
- throw new GLException(t);
- } finally {
- unlockSurface();
- }
- }
-
- public static WindowsDummyWGLDrawable create(GLDrawableFactory factory, GLProfile glp, AbstractGraphicsScreen absScreen,
- long windowHandle, int width, int height, boolean handleWindowLifecycle) {
- if(0 == windowHandle) {
- throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError());
- }
- GLCapabilities caps = new GLCapabilities(glp);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen);
- GDISurface ns = new GDISurface(cfg, windowHandle);
- ns.surfaceSizeChanged(width, height);
- return new WindowsDummyWGLDrawable(factory, ns, handleWindowLifecycle);
- }
-
- @Override
- public GLContext createContext(GLContext shareWith) {
- // FIXME: figure out how to hook back in the Java 2D / JOGL bridge
- return new WindowsWGLContext(this, shareWith);
- }
-
- @Override
- protected void setRealizedImpl() {
- super.setRealizedImpl();
- if(!realized) {
- if (handleHwndLifecycle && hwnd != 0) {
- GDI.ShowWindow(hwnd, GDI.SW_HIDE);
- GDIUtil.DestroyDummyWindow(hwnd);
- hwnd = 0;
- }
- }
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
index 86441c688..96c1187d3 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
@@ -55,7 +55,6 @@ import com.jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextShareSet;
-
public class WindowsExternalWGLContext extends WindowsWGLContext {
private GLContext lastContext;
@@ -103,7 +102,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
System.err.println("WindowsExternalWGLContext valid hdc/pfd, retrieved cfg: " + cfg);
}
}
- return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc)), ctx, cfg);
+ return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null)), ctx, cfg);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
index 8f22aa60e..15bd005dc 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
@@ -50,6 +50,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import jogamp.nativewindow.windows.GDI;
+import jogamp.nativewindow.windows.GDIUtil;
import com.jogamp.nativewindow.WrappedSurface;
@@ -69,9 +70,9 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable {
throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError());
}
- AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true);
- return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc));
+ final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
+ final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true);
+ return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null));
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
index a11d6e78e..7dda6a1f1 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
@@ -42,6 +42,8 @@ package jogamp.opengl.windows.wgl;
import javax.media.opengl.*;
+import com.jogamp.opengl.GLExtensions;
+
import jogamp.opengl.GLContextImpl;
public class WindowsPbufferWGLContext extends WindowsWGLContext {
@@ -112,7 +114,7 @@ public class WindowsPbufferWGLContext extends WindowsWGLContext {
} else {
hasRTT = true;
- if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) {
+ if (rect && !gl.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " +
"supported; skipping requested render_to_texture_rectangle support for pbuffer");
rect = false;
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
index b00c796ec..175622343 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
@@ -42,7 +42,7 @@ package jogamp.opengl.windows.wgl;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -92,7 +92,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
if (wglExt.wglReleasePbufferDCARB(buffer, ns.getSurfaceHandle()) == 0) {
throw new GLException("Error releasing pbuffer device context: error code " + GDI.GetLastError());
}
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
if (!wglExt.wglDestroyPbufferARB(buffer)) {
throw new GLException("Error destroying pbuffer: error code " + GDI.GetLastError());
@@ -121,7 +121,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
try {
long sharedHdc = sharedSurface.getSurfaceHandle();
- WGLExt wglExt = sharedResource.getContext().getWGLExt();
+ WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
if (DEBUG) {
System.out.println("Pbuffer config: " + config);
@@ -131,7 +131,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
float[] fattributes = new float[1];
int[] floatModeTmp = new int[1];
int niattribs = 0;
- int width, height;
GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
GLProfile glProfile = chosenCaps.getGLProfile();
@@ -206,7 +205,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB;
iattributes[niattribs++] = GL.GL_FALSE;
- iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB;
+ iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; // exact
iattributes[niattribs++] = GL.GL_FALSE;
}
@@ -235,7 +234,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
NativeSurface ns = getNativeSurface();
// Set up instance variables
buffer = tmpBuffer;
- ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc);
+ ((MutableSurface)ns).setSurfaceHandle(tmpHdc);
cachedWGLExt = wglExt;
// Re-query chosen pixel format
@@ -249,14 +248,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
config.setCapsPFD(newCaps);
}
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 );
- width = tmp[0];
- wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 );
- height = tmp[0];
- ((SurfaceChangeable)ns).surfaceSizeChanged(width, height);
} finally {
sharedSurface.unlockSurface();
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index f143c158b..8825bad0a 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -53,6 +53,8 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
@@ -77,8 +79,8 @@ public class WindowsWGLContext extends GLContextImpl {
functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV");
extensionNameMap = new HashMap<String, String>();
- extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer");
- extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format");
+ extensionNameMap.put(GLExtensions.ARB_pbuffer, WindowsWGLDrawableFactory.WGL_ARB_pbuffer);
+ extensionNameMap.put(GLExtensions.ARB_pixel_format, WindowsWGLDrawableFactory.WGL_ARB_pixel_format);
}
// FIXME: figure out how to hook back in the Java 2D / JOGL bridge
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 176d27a71..09e97ff79 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -51,9 +51,10 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -67,9 +68,11 @@ import jogamp.nativewindow.windows.GDISurface;
import jogamp.nativewindow.windows.GDIUtil;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.JogampRuntimeException;
@@ -79,6 +82,7 @@ import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.opengl.GLExtensions;
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
@@ -203,8 +207,8 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
static class SharedResource implements SharedResourceRunner.Resource {
private WindowsGraphicsDevice device;
private AbstractGraphicsScreen screen;
- private WindowsDummyWGLDrawable drawable;
- private WindowsWGLContext context;
+ private GLDrawableImpl drawable;
+ private GLContextImpl context;
private boolean hasARBPixelFormat;
private boolean hasARBMultisample;
private boolean hasARBPBuffer;
@@ -214,7 +218,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private boolean isVendorNVIDIA;
private boolean needsCurrenContext4ARBPFDQueries;
- SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx,
+ SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx,
boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) {
device = dev;
screen = scrn;
@@ -250,9 +254,9 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
@Override
final public AbstractGraphicsScreen getScreen() { return screen; }
@Override
- final public WindowsWGLDrawable getDrawable() { return drawable; }
+ final public GLDrawableImpl getDrawable() { return drawable; }
@Override
- final public WindowsWGLContext getContext() { return context; }
+ final public GLContextImpl getContext() { return context; }
final boolean hasARBPixelFormat() { return hasARBPixelFormat; }
final boolean hasARBMultisample() { return hasARBMultisample; }
@@ -302,21 +306,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
@Override
public SharedResourceRunner.Resource createSharedResource(String connection) {
- WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
+ final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
sharedDevice.lock();
try {
- AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0);
- GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
+ final AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0);
+ final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- final int f_dim = 64;
- long hwnd = GDIUtil.CreateDummyWindow(0, 0, f_dim, f_dim);
- WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen, hwnd, f_dim, f_dim, true);
- if (null == sharedDrawable) {
- throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp);
- }
- WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null);
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
@@ -329,7 +330,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
try {
hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format);
hasARBMultisample = sharedContext.isExtensionAvailable(WGL_ARB_multisample);
- hasARBPBuffer = sharedContext.isExtensionAvailable(GL_ARB_pbuffer);
+ hasARBPBuffer = sharedContext.isExtensionAvailable(GLExtensions.ARB_pbuffer);
hasARBReadDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) &&
sharedContext.isFunctionAvailable(wglMakeContextCurrent);
vendor = sharedContext.getGL().glGetString(GL.GL_VENDOR);
@@ -401,7 +402,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
- final static String GL_ARB_pbuffer = "GL_ARB_pbuffer";
+ final static String WGL_ARB_pbuffer = "WGL_ARB_pbuffer";
final static String WGL_ARB_pixel_format = "WGL_ARB_pixel_format";
final static String WGL_ARB_multisample = "WGL_ARB_multisample";
final static String WGL_NV_float_buffer = "WGL_NV_float_buffer";
@@ -534,22 +535,89 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
- WrappedSurface ns = new WrappedSurface(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsChosen, capsRequested, chooser, screen) );
- ns.surfaceSizeChanged(width, height);
- return ns;
+ protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final WindowsGraphicsDevice device;
+ if(createNewDevice) {
+ device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (WindowsGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, width, height, lifecycleHook);
}
@Override
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- WindowsGraphicsDevice device = (WindowsGraphicsDevice) adevice;
- AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
- GDISurface ns = new GDISurface(cfg, windowHandle);
- return ns;
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final WindowsGraphicsDevice device;
+ if(createNewDevice) {
+ device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (WindowsGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(chosenCaps, requestedCaps, chooser, screen);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+requestedCaps+" on "+screen);
+ }
+ return new GDISurface(config, 0, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if(0 == ms.getWindowHandle()) {
+ final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, s.getWidth(), s.getHeight());
+ if(0 == windowHandle) {
+ throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError());
+ }
+ ms.setWindowHandle(windowHandle);
+ if(DEBUG) {
+ System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.create: "+ms);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if(0 != ms.getWindowHandle()) {
+ GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE);
+ GDIUtil.DestroyDummyWindow(ms.getWindowHandle());
+ ms.setWindowHandle(0);
+ if(DEBUG) {
+ System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+ms);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+
+ @Override
+ public String toString() {
+ return "GDISurfaceLifecycleHook[]";
+ }
+ };
+
+
+ @Override
+ protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
+ return new GDISurface(cfg, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index 408d8b074..209589b29 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
@@ -48,11 +48,13 @@ import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.opengl.GLExtensions;
import jogamp.nativewindow.windows.DWM_BLURBEHIND;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.MARGINS;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
@@ -160,7 +162,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
if (!WGLUtil.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) {
- throw new GLException("Unable to set pixel format " + caps +
+ throw new GLException("Unable to set pixel format " + caps.getPFDID() + " of " + caps +
" for device context " + toHexString(hdc) +
": error code " + GDI.GetLastError());
}
@@ -250,7 +252,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
if(sharedResource.hasARBPBuffer()) {
- WindowsWGLContext sharedCtx = sharedResource.getContext();
+ GLContextImpl sharedCtx = sharedResource.getContext();
if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) {
// pbo float buffer
iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia
@@ -313,12 +315,12 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
- if (!sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) {
+ if (!((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) {
throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID +
" of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError());
}
List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(1);
- final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
if(AttribList2GLCapabilities(bucket, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits)) {
return (WGLGLCapabilities) bucket.get(0);
}
@@ -342,7 +344,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS];
int[] numFormatsTmp = new int[1];
- if ( !sharedResource.getContext().getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0,
+ if ( !((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0,
fattributes, 0,
WindowsWGLGraphicsConfiguration.MAX_PFORMATS,
pformatsTmp, 0, numFormatsTmp, 0))
@@ -374,7 +376,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
static List<GLCapabilitiesImmutable> wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
long hdc, int[] pfdIDs, GLProfile glp, boolean onscreen, boolean usePBuffer) {
- final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+ final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, winattrbits);
}
@@ -398,7 +400,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
for(int i = 0; i<numFormats; i++) {
if ( pfdIDs[i] >= 1 &&
- sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) {
+ ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) {
AttribList2GLCapabilities(bucket, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits);
} else if (DEBUG) {
System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " +
@@ -507,9 +509,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
}
- WindowsWGLContext sharedCtx = sharedResource.getContext();
+ GLContextImpl sharedCtx = sharedResource.getContext();
if (rect) {
- if (!sharedCtx.isExtensionAvailable("GL_NV_texture_rectangle")) {
+ if (!sharedCtx.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
}
}
@@ -658,7 +660,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
static WGLGLCapabilities PFD2GLCapabilities(GLProfile glp, long hdc, int pfdID, boolean onscreen) {
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false, false);
List<GLCapabilitiesImmutable> capsBucket = new ArrayList<GLCapabilitiesImmutable>(1);
if( PFD2GLCapabilities(capsBucket, glp, hdc, pfdID, winattrmask) ) {
return (WGLGLCapabilities) capsBucket.get(0);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
index 850b64aa8..00ed91bb4 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
@@ -52,6 +52,7 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
+import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
@@ -68,13 +69,13 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
static VisualIDHolder.VIDComparator PfdIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.WIN32_PFD);
static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, new WindowsWGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsWGLGraphicsConfigurationFactory());
}
private WindowsWGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (! (capsChosen instanceof GLCapabilitiesImmutable) ) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen");
@@ -99,10 +100,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if(null==absScreen) {
absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
}
- AbstractGraphicsDevice absDevice = absScreen.getDevice();
-
+ final AbstractGraphicsDevice absDevice = absScreen.getDevice();
+ final GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory();
capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities(
- capsChosen, GLDrawableFactory.getDesktopFactory().canCreateGLPbuffer(absDevice) );
+ capsChosen, GLContext.isFBOAvailable(absDevice, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(absDevice) );
return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser );
}
@@ -112,9 +113,9 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
- WindowsWGLDrawable sharedDrawable = sharedResource.getDrawable();
+ GLDrawableImpl sharedDrawable = sharedResource.getDrawable();
GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities();
- WindowsWGLContext sharedContext = sharedResource.getContext();
+ GLContext sharedContext = sharedResource.getContext();
List<GLCapabilitiesImmutable> availableCaps = null;
if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
@@ -150,7 +151,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(long hdc, WindowsWGLDrawableFactory.SharedResource sharedResource, GLProfile glProfile) {
- int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc);
+ int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs((WindowsWGLContext)sharedResource.getContext(), hdc);
return WindowsWGLGraphicsConfiguration.wglARBPFIDs2AllGLCapabilities(sharedResource, hdc, pformats, glProfile);
}
@@ -265,7 +266,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
AbstractGraphicsDevice device = config.getScreen().getDevice();
WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(device);
- WindowsWGLContext sharedContext = null;
+ GLContext sharedContext = null;
if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) {
sharedContext = sharedResource.getContext();
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
@@ -355,7 +356,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed with: "+capsChosen);
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
- pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc);
+ pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs((WindowsWGLContext)sharedResource.getContext(), hdc);
if (DEBUG) {
final int len = ( null != pformats ) ? pformats.length : 0;
System.err.println("updateGraphicsConfigurationARB: NumFormats (wglAllARBPFIDs) " + len);
@@ -451,7 +452,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if(null == pformats) {
pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
}
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false, false);
for (int i = 0; i < pformats.length; i++) {
WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(availableCaps, glProfile, hdc, pformats[i], winattrmask);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
index bd64b58a4..3b2ff133a 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
@@ -63,14 +63,14 @@ import javax.media.opengl.GLDrawableFactory;
public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new WindowsAWTWGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsAWTWGLGraphicsConfigurationFactory());
}
private WindowsAWTWGLGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -105,11 +105,11 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex());
- GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice);
+ GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice, capsChosen);
WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration)
configFactory.chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, winScreen);
+ chooser, winScreen, nativeVisualID);
if (winConfig == null) {
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java
deleted file mode 100644
index 8914e2db9..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * 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 jogamp.opengl.x11.glx;
-
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLProfile;
-
-import jogamp.nativewindow.x11.X11Lib;
-
-import com.jogamp.nativewindow.WrappedSurface;
-import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-
-public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable {
- private static final int f_dim = 64;
- private long dummyWindow = 0;
-
- /**
- * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
- * we cannot switch the Display as we please,
- * hence we reuse the target's screen configuration.
- */
- public X11DummyGLXDrawable(X11GraphicsScreen screen, GLDrawableFactory factory, GLCapabilitiesImmutable caps) {
- super(factory,
- new WrappedSurface(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- caps, caps, null, screen)));
- this.realized = true;
-
- WrappedSurface ns = (WrappedSurface) getNativeSurface();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)ns.getGraphicsConfiguration();
-
- X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
- long dpy = device.getHandle();
- int scrn = screen.getIndex();
- int visualID = config.getXVisualID();
-
- dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID, f_dim, f_dim);
- ns.setSurfaceHandle( dummyWindow );
- ns.surfaceSizeChanged(f_dim, f_dim);
-
- updateHandle();
- }
-
- public static X11DummyGLXDrawable create(X11GraphicsScreen screen, GLDrawableFactory factory, GLProfile glp) {
- GLCapabilities caps = new GLCapabilities(glp);
- return new X11DummyGLXDrawable(screen, factory, caps);
- }
-
- public void setSize(int width, int height) {
- }
-
- @Override
- public int getWidth() {
- return 1;
- }
-
- @Override
- public int getHeight() {
- return 1;
- }
-
-
- @Override
- protected void setRealizedImpl() {
- super.setRealizedImpl();
- if(!realized) {
- if(0!=dummyWindow) {
- destroyHandle();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
- X11Lib.DestroyDummyWindow(config.getScreen().getDevice().getHandle(), dummyWindow);
- }
- }
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
index 53776386c..1f3edbd8a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
@@ -41,6 +41,7 @@
package jogamp.opengl.x11.glx;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -76,8 +77,15 @@ public class X11ExternalGLXContext extends X11GLXContext {
long drawable = GLX.glXGetCurrentDrawable();
if (drawable == 0) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current");
- }
+ }
int[] val = new int[1];
+
+ int w, h;
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0);
+ w=val[0];
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0);
+ h=val[0];
+
GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val, 0);
X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false);
@@ -87,9 +95,9 @@ public class X11ExternalGLXContext extends X11GLXContext {
// of 0, which doesn't work in a subsequent call to glXChooseFBConfig; if this happens,
// create and use a default config (this has been observed when running on CentOS 5.5 inside
// of VMWare Server 2.0 with the Mesa 6.5.1 drivers)
- if( X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) {
+ if( VisualIDHolder.VID_UNDEFINED == val[0] || !X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) {
GLCapabilities glcapsDefault = new GLCapabilities(GLProfile.getDefault());
- cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen);
+ cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen, VisualIDHolder.VID_UNDEFINED);
if(DEBUG) {
System.err.println("X11ExternalGLXContext invalid FBCONFIG_ID "+val[0]+", using default cfg: " + cfg);
}
@@ -97,8 +105,7 @@ public class X11ExternalGLXContext extends X11GLXContext {
cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]);
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(drawable);
+ final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, null);
return new X11ExternalGLXContext(new Drawable(factory, ns), ctx);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
index 3fabe7a13..8652e2d4a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
@@ -87,10 +87,7 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable {
System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")");
}
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(drawable);
- ns.surfaceSizeChanged(w, h);
- return new X11ExternalGLXDrawable(factory, ns);
+ return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, null));
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 0afadc677..e1e25be67 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -61,6 +61,7 @@ import jogamp.opengl.GLDrawableImpl;
import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
public abstract class X11GLXContext extends GLContextImpl {
private static final Map<String, String> functionNameMap;
@@ -83,8 +84,8 @@ public abstract class X11GLXContext extends GLContextImpl {
functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV");
extensionNameMap = new HashMap<String, String>();
- extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer");
- extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough
+ extensionNameMap.put(GLExtensions.ARB_pbuffer, X11GLXDrawableFactory.GLX_SGIX_pbuffer);
+ extensionNameMap.put(GLExtensions.ARB_pixel_format, X11GLXDrawableFactory.GLX_SGIX_pbuffer); // good enough
}
X11GLXContext(GLDrawableImpl drawable,
@@ -151,7 +152,7 @@ public abstract class X11GLXContext extends GLContextImpl {
throw new InternalError("Given readDrawable but no driver support");
}
} catch (RuntimeException re) {
- if(TRACE_SWITCH) {
+ if(DEBUG || TRACE_SWITCH) {
System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
"dpy "+toHexString(dpy)+
", write "+toHexString(writeDrawable)+
@@ -508,8 +509,8 @@ public abstract class X11GLXContext extends GLContextImpl {
@Override
public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
+ if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
+ glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
return getGLDrawable().getFactory().canCreateGLPbuffer(
drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice() );
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 9a563bdb8..b2e74f9d4 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -49,6 +49,9 @@ import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -64,6 +67,7 @@ import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.util.VersionNumber;
@@ -79,6 +83,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0);
public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0);
+ static final String GLX_SGIX_pbuffer = "GLX_SGIX_pbuffer";
+
private static DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper = null;
public X11GLXDrawableFactory() {
@@ -153,8 +159,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
static class SharedResource implements SharedResourceRunner.Resource {
X11GraphicsDevice device;
X11GraphicsScreen screen;
- X11DummyGLXDrawable drawable;
- X11GLXContext context;
+ GLDrawableImpl drawable;
+ GLContextImpl context;
String glXServerVendorName;
boolean isGLXServerVendorATI;
boolean isGLXServerVendorNVIDIA;
@@ -164,7 +170,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
boolean glXMultisampleAvailable;
SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn,
- X11DummyGLXDrawable draw, X11GLXContext ctx,
+ GLDrawableImpl draw, GLContextImpl ctx,
VersionNumber glXServerVer, String glXServerVendor, boolean glXServerMultisampleAvail) {
device = dev;
screen = scrn;
@@ -224,13 +230,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
@Override
public SharedResourceRunner.Resource createSharedResource(String connection) {
- X11GraphicsDevice sharedDevice =
+ final X11GraphicsDevice sharedDevice =
new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- true); // own non-shared display connection, no locking
+ true); // own non-shared display connection, w/ locking
// new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, no locking
+ // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, w/o locking
sharedDevice.lock();
try {
+ final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0);
+
if(!GLXUtil.isGLXAvailableOnServer(sharedDevice)) {
throw new GLException("GLX not available on device/server: "+sharedDevice);
}
@@ -242,20 +250,20 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
X11Util.setMarkAllDisplaysUnclosable(true);
X11Util.markDisplayUncloseable(sharedDevice.getHandle());
}
- X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0);
-
- GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
+
+ final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, glp);
- if (null == sharedDrawable) {
- throw new GLException("Couldn't create shared drawable for screen: "+sharedScreen+", "+glp);
- }
- X11GLXContext sharedContext = (X11GLXContext) sharedDrawable.createContext(null);
+
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
+
boolean madeCurrent = false;
sharedContext.makeCurrent();
try {
@@ -298,7 +306,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (null != sr.context) {
// may cause JVM SIGSEGV:
- sr.context.destroy();
+ sr.context.destroy(); // will also pull the dummy MutuableSurface
sr.context = null;
}
@@ -394,7 +402,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- return new X11OnscreenGLXDrawable(this, target);
+ return new X11OnscreenGLXDrawable(this, target, false);
}
@Override
@@ -495,40 +503,98 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- if(null == deviceReq) {
- throw new InternalError("deviceReq is null");
- }
- final SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(deviceReq);
- if(null==sr) {
- throw new InternalError("No SharedResource for: "+deviceReq);
+ protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+ final X11GraphicsDevice device;
+ if(createNewDevice) {
+ // Null X11 locking, due to private non-shared Display handle
+ device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true);
+ } else {
+ device = (X11GraphicsDevice)deviceReq;
}
- final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sr.getScreen();
- final AbstractGraphicsDevice sharedDevice = sharedScreen.getDevice(); // should be same ..
-
- // create screen/device pair - Null X11 locking, due to private non-shared Display handle
- final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(sharedDevice.getConnection()), AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), true);
- final X11GraphicsScreen screen = new X11GraphicsScreen(device, sharedScreen.getIndex());
-
- WrappedSurface ns = new WrappedSurface(
- X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen) );
- if(ns != null) {
- ns.surfaceSizeChanged(width, height);
+ final X11GraphicsScreen screen = new X11GraphicsScreen(device, 0);
+ final X11GLXGraphicsConfiguration config = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
}
- return ns;
+ return new WrappedSurface( config, 0, width, height, lifecycleHook);
}
@Override
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- X11GraphicsDevice device = (X11GraphicsDevice) adevice;
- X11GraphicsScreen screen = new X11GraphicsScreen(device, 0);
- X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
- WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
- return ns;
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+ }
+ private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) {
+ if( 0 == s.getSurfaceHandle() ) {
+ final X11GLXGraphicsConfiguration cfg = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration();
+ final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen();
+ final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
+ if(0 == device.getHandle()) {
+ device.open();
+ s.setImplBitfield(ProxySurface.OWN_DEVICE);
+ }
+ final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), s.getWidth(), s.getHeight());
+ if(0 == windowHandle) {
+ throw new GLException("Creating dummy window failed w/ "+cfg+", "+s.getWidth()+"x"+s.getHeight());
+ }
+ s.setSurfaceHandle(windowHandle);
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+ }
+ }
+ }
+ @Override
+ public final void destroy(ProxySurface s) {
+ if(0 != s.getSurfaceHandle()) {
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration();
+ final X11GraphicsDevice device = (X11GraphicsDevice) config.getScreen().getDevice();
+ X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(0);
+ if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) {
+ device.close();
+ }
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s);
+ }
+ }
+ }
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return s.initialWidth;
+ }
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return s.initialHeight;
+ }
+ @Override
+ public String toString() {
+ return "X11SurfaceLifecycleHook[]";
+ }
+ };
+
+
+ @Override
+ protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true);
+ final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx);
+ final int xvisualID = X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
+ if(VisualIDHolder.VID_UNDEFINED == xvisualID) {
+ throw new GLException("Undefined VisualID of window 0x"+Long.toHexString(windowHandle)+", window probably invalid");
+ }
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": visualID 0x"+Integer.toHexString(xvisualID));
+ }
+ final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, xvisualID);
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": "+cfg);
+ }
+ return new WrappedSurface(cfg, windowHandle, 0, 0, upstream);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index b54b5150c..b458fffe1 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -36,12 +36,16 @@ package jogamp.opengl.x11.glx;
import java.util.ArrayList;
import java.util.List;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -67,7 +71,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) {
- final long display = x11Screen.getDevice().getHandle();
+ final AbstractGraphicsDevice device = x11Screen.getDevice();
+ final long display = device.getHandle();
if(0==display) {
throw new GLException("Display null of "+x11Screen);
}
@@ -80,7 +85,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
glp = GLProfile.getDefault(x11Screen.getDevice());
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(x11Screen.getDevice()));
+ final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, device, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(device));
if(null==caps) {
throw new GLException("GLCapabilities null of "+toHexString(fbcfg));
}
@@ -99,16 +104,25 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
void updateGraphicsConfiguration() {
- X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(
- getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen());
- if(null!=newConfig) {
- // FIXME: setScreen( ... );
- setXVisualInfo(newConfig.getXVisualInfo());
- setChosenCapabilities(newConfig.getChosenCapabilities());
- if(DEBUG) {
- System.err.println("updateGraphicsConfiguration: "+this);
+ final CapabilitiesImmutable aChosenCaps = getChosenCapabilities();
+ if( !(aChosenCaps instanceof X11GLCapabilities) || VisualIDHolder.VID_UNDEFINED == aChosenCaps.getVisualID(VIDType.X11_XVISUAL) ) {
+ // This case is actually quite impossible, since on X11 the visualID and hence GraphicsConfiguration
+ // must be determined _before_ window creation!
+ final X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
+ GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), aChosenCaps).chooseGraphicsConfiguration(
+ aChosenCaps, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
+ if(null!=newConfig) {
+ // FIXME: setScreen( ... );
+ setXVisualInfo(newConfig.getXVisualInfo());
+ setChosenCapabilities(newConfig.getChosenCapabilities());
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration updated:"+this);
+ }
+ } else {
+ throw new GLException("No native VisualID pre-chosen and update failed: "+this);
}
+ } else if (DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration kept:"+this);
}
}
@@ -233,11 +247,11 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return true;
}
- static int FBCfgDrawableTypeBits(final long display, final long fbcfg) {
+ static int FBCfgDrawableTypeBits(final AbstractGraphicsDevice device, GLProfile glp, final long fbcfg) {
int val = 0;
int[] tmp = new int[1];
- int fbtype = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0);
+ int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0);
if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT;
@@ -248,17 +262,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
if ( 0 != ( fbtype & GLX.GLX_PBUFFER_BIT ) ) {
val |= GLGraphicsConfigurationUtil.PBUFFER_BIT;
}
+ if ( GLContext.isFBOAvailable(device, glp) ) {
+ val |= GLGraphicsConfigurationUtil.FBO_BIT;
+ }
return val;
}
- static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg,
+ static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, AbstractGraphicsDevice device, long fbcfg,
boolean relaxed, boolean onscreen, boolean usePBuffer,
boolean isMultisampleAvailable) {
ArrayList<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- if( GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, winattrmask, isMultisampleAvailable) ) {
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
+ if( GLXFBConfig2GLCapabilities(bucket, glp, device, fbcfg, winattrmask, isMultisampleAvailable) ) {
return (X11GLCapabilities) bucket.get(0);
- } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
+ } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, device, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
return (X11GLCapabilities) bucket.get(0);
}
return null;
@@ -273,11 +290,12 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
static boolean GLXFBConfig2GLCapabilities(List<GLCapabilitiesImmutable> capsBucket,
- GLProfile glp, long display, long fbcfg,
+ GLProfile glp, AbstractGraphicsDevice device, long fbcfg,
int winattrmask, boolean isMultisampleAvailable) {
- final int allDrawableTypeBits = FBCfgDrawableTypeBits(display, fbcfg);
+ final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, glp, fbcfg);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
-
+
+ final long display = device.getHandle();
int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
if(null == visualInfo) {
@@ -301,19 +319,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
- res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0);
- res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0);
- res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG);
- res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0));
- res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0));
- res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0));
- res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0));
- res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0));
- res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
- res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
- res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
- res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
if (isMultisampleAvailable) {
res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0));
@@ -329,6 +334,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.setTransparentBlueValue(xrmask.getBlueMask());
res.setTransparentAlphaValue(alphaMask);
}
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0);
+ res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0);
+ res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG);
+ res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0));
+ res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0));
+ res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0));
+ res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0));
+ res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
+ res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
+ res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
+ res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
+ res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0));
+ res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0));
try {
res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE);
@@ -422,18 +441,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
// Note: use of hardware acceleration is determined by
// glXCreateContext, not by the XVisualInfo. Optimistically claim
// that all GLCapabilities have the capability to be hardware
- // accelerated.
- res.setHardwareAccelerated(true);
- res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0));
- res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0));
- res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0));
- res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0));
- res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0));
- res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
- res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
- res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
- res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
+ // accelerated.
if (isMultisampleEnabled) {
res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0));
@@ -449,6 +457,18 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.setTransparentBlueValue(xrmask.getBlueMask());
res.setTransparentAlphaValue(alphaMask);
}
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ res.setHardwareAccelerated(true);
+ res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0));
+ res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0));
+ res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0));
+ res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0));
+ res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0));
+ res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0));
+ res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
+ res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
+ res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
+ res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index 8377d2453..234b06bdb 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -40,10 +40,12 @@ import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -73,20 +75,24 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static GraphicsConfigurationFactory fallbackX11GraphicsConfigurationFactory = null;
static void registerFactory() {
final GraphicsConfigurationFactory newFactory = new X11GLXGraphicsConfigurationFactory();
- final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, newFactory);
+ final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, newFactory);
if(oldFactory == newFactory) {
throw new InternalError("GraphicsConfigurationFactory lifecycle impl. error");
}
- if(null == oldFactory) {
- throw new InternalError("Missing fallback GraphicsConfigurationFactory");
+ if(null != oldFactory) {
+ fallbackX11GraphicsConfigurationFactory = oldFactory;
+ } else {
+ fallbackX11GraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class);
+ if( null == fallbackX11GraphicsConfigurationFactory ) {
+ throw new InternalError("Missing fallback GraphicsConfigurationFactory");
+ }
}
- fallbackX11GraphicsConfigurationFactory = oldFactory;
}
private X11GLXGraphicsConfigurationFactory() {
}
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (!(absScreen instanceof X11GraphicsScreen)) {
throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here");
}
@@ -108,12 +114,12 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
if(DEBUG) {
System.err.println("No GLX available, fallback to "+fallbackX11GraphicsConfigurationFactory.getClass().getSimpleName()+" for: "+absScreen);
}
- return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen);
+ return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, VisualIDHolder.VID_UNDEFINED);
}
throw new InternalError("No GLX and no fallback GraphicsConfigurationFactory available for: "+absScreen);
}
return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested,
- (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen);
+ (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen, nativeVisualID);
}
protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) {
@@ -161,7 +167,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return null;
}
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
+ if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
@@ -198,7 +204,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
if (x11Screen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
@@ -209,24 +215,24 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(x11Device) );
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(x11Device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(x11Device) );
boolean usePBuffer = capsChosen.isPBuffer();
X11GLXGraphicsConfiguration res = null;
if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) {
- res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen);
+ res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen, xvisualID);
}
if(null==res) {
if(usePBuffer) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+capsChosen);
+ throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for visualID "+toHexString(xvisualID)+", "+capsChosen);
}
- res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen);
+ res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen, xvisualID);
}
if(null==res) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+capsChosen);
+ throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for visualID "+toHexString(xvisualID)+", "+x11Screen+", "+capsChosen);
}
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+capsChosen+"): "+res);
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic(visualID "+toHexString(xvisualID)+", "+x11Screen+","+capsChosen+"): "+res);
}
return res;
}
@@ -245,19 +251,20 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice));
+ final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, absDevice, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice));
return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
}
private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
int recommendedIndex = -1;
PointerBuffer fbcfgsL = null;
GLProfile glProfile = capsChosen.getGLProfile();
boolean onscreen = capsChosen.isOnscreen();
boolean usePBuffer = capsChosen.isPBuffer();
+ boolean useFBO = capsChosen.isFBO();
// Utilizing FBConfig
//
@@ -270,13 +277,15 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen);
int[] count = { -1 };
List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
-
- // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
- fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, useFBO);
+ // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice,
+ // skipped if xvisualID is given
+ if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
+ fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
+ }
if (fbcfgsL != null && fbcfgsL.limit()>0) {
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
+ if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
@@ -309,13 +318,40 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
+ if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
}
}
}
+
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: got configs: "+availableCaps.size());
+ for(int i=0; i<availableCaps.size(); i++) {
+ System.err.println(i+": "+availableCaps.get(i));
+ }
+ }
+
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+ for(int i=0; i<availableCaps.size(); ) {
+ VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
+ if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
+ availableCaps.remove(i);
+ } else {
+ i++;
+ }
+ }
+ if(0==availableCaps.size()) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
+ }
+ return null;
+ } else if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: post filter visualID "+toHexString(xvisualID)+" got configs: "+availableCaps.size());
+ }
+ }
+
int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
if ( 0 > chosenIndex ) {
if (DEBUG) {
@@ -332,13 +368,13 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
if (chooser == null) {
chooser = new DefaultGLCapabilitiesChooser();
}
GLProfile glProfile = capsChosen.getGLProfile();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */);
+ final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */, false);
List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
int recommendedIndex = -1;
@@ -350,14 +386,18 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen);
+ XVisualInfo recommendedVis = null;
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
- XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
- if (DEBUG) {
- System.err.print("glXChooseVisual recommended ");
- if (recommendedVis == null) {
- System.err.println("null visual");
- } else {
- System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
+ // skipped if xvisualID is given
+ if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
+ recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
+ if (DEBUG) {
+ System.err.print("glXChooseVisual recommended ");
+ if (recommendedVis == null) {
+ System.err.println("null visual");
+ } else {
+ System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
+ }
}
}
@@ -383,6 +423,32 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
}
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: got configs: "+availableCaps.size());
+ for(int i=0; i<availableCaps.size(); i++) {
+ System.err.println(i+": "+availableCaps.get(i));
+ }
+ }
+
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+ for(int i=0; i<availableCaps.size(); ) {
+ VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
+ if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
+ availableCaps.remove(i);
+ } else {
+ i++;
+ }
+ }
+ if(0==availableCaps.size()) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
+ }
+ return null;
+ } else if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID)+" got configs: "+availableCaps.size());
+ }
+ }
+
int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
if ( 0 > chosenIndex ) {
if (DEBUG) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
index 9e22afa6d..363299321 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
@@ -51,10 +51,13 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
long glXWindow; // GLXWindow, a GLXDrawable representation
boolean useGLXWindow;
- protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component) {
- super(factory, component, false);
+ protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component, boolean realized) {
+ super(factory, component, realized);
glXWindow=0;
useGLXWindow=false;
+ if(realized) {
+ updateHandle();
+ }
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
index cdf81ebd3..e1fe2f27e 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
@@ -43,7 +43,7 @@ package jogamp.opengl.x11.glx;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -77,7 +77,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
if (ns.getSurfaceHandle() != 0) {
GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle());
}
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
private void createPbuffer() {
@@ -108,12 +108,14 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
// Create the p-buffer.
int niattribs = 0;
- int[] iattributes = new int[5];
+ int[] iattributes = new int[7];
iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH;
iattributes[niattribs++] = ns.getWidth();
iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT;
iattributes[niattribs++] = ns.getHeight();
+ iattributes[niattribs++] = GLX.GLX_LARGEST_PBUFFER; // exact
+ iattributes[niattribs++] = 0;
iattributes[niattribs++] = 0;
long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes, 0);
@@ -123,15 +125,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
}
// Set up instance variables
- ((SurfaceChangeable)ns).setSurfaceHandle(pbuffer);
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_WIDTH, tmp, 0);
- int width = tmp[0];
- GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0);
- int height = tmp[0];
- ((SurfaceChangeable)ns).surfaceSizeChanged(width, height);
+ ((MutableSurface)ns).setSurfaceHandle(pbuffer);
if (DEBUG) {
System.err.println("Created pbuffer " + this);
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
index 1e7b89828..04627724c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
@@ -43,7 +43,7 @@ package jogamp.opengl.x11.glx;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
@@ -93,7 +93,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
pixmap = 0;
throw new GLException("glXCreateGLXPixmap failed");
}
- ((SurfaceChangeable)ns).setSurfaceHandle(drawable);
+ ((MutableSurface)ns).setSurfaceHandle(drawable);
if (DEBUG) {
System.err.println("Created pixmap " + toHexString(pixmap) +
", GLXPixmap " + toHexString(drawable) +
@@ -133,7 +133,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
X11Lib.XFreePixmap(display, pixmap);
drawable = 0;
pixmap = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
display = 0;
}
}