aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorPetr Skramovsky <[email protected]>2013-07-17 09:20:46 +0200
committerPetr Skramovsky <[email protected]>2013-07-17 09:20:46 +0200
commit9fce91044649c9f97bd94c5791a10270afad7570 (patch)
treea69fa244ddeb78e52248d4306a4ecc6b27e924da /src/jogl
parent5116d72f0150bdd6353ee664ef76e414bd61f87e (diff)
parentbfb10d309d97c19a33f9b6758f647186f8e0ddd6 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java171
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java79
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java61
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java83
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java8
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/FontFactory.java29
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLExtensions.java3
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java15
-rw-r--r--src/jogl/classes/com/jogamp/opengl/JoglVersion.java26
-rw-r--r--src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java51
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Quaternion.java72
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java52
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java13
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java24
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java7
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java9
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java90
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java4
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java3
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL2.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL3.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL3bc.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL4.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGLES2.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java7
-rw-r--r--src/jogl/classes/javax/media/opengl/GLBase.java138
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java452
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDebugMessage.java74
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawableFactory.java82
-rw-r--r--src/jogl/classes/javax/media/opengl/GLPipelineFactory.java20
-rw-r--r--src/jogl/classes/javax/media/opengl/GLProfile.java370
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL2.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL3.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL3bc.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL4.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGLES2.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java77
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp1
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp1
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/Debug.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java227
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java28
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java47
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java74
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableImpl.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java25
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java37
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/GLVersionNumber.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLContext.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java129
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java78
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java55
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java72
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java42
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java1940
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java74
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java550
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java11
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java53
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java284
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java31
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java35
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java13
-rw-r--r--src/jogl/native/GLDebugMessageHandler.c8
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m63
-rw-r--r--src/jogl/native/timespec.c5
-rw-r--r--src/jogl/native/timespec.h3
115 files changed, 4212 insertions, 2578 deletions
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
index 5334d45cf..262fed934 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -57,10 +57,31 @@ import java.util.Set;
public class BuildComposablePipeline {
- public static final int GEN_DEBUG = 1 << 0; // default
- public static final int GEN_TRACE = 1 << 1; // default
+ /** <p>Default: true</p>. */
+ public static final int GEN_DEBUG = 1 << 0;
+ /** <p>Default: true</p>. */
+ public static final int GEN_TRACE = 1 << 1;
+ /** <p>Default: false</p>. */
public static final int GEN_CUSTOM = 1 << 2;
+ /**
+ * By extra command-line argument: <code>prolog_xor_downstream</code>.
+ * <p>
+ * If true, either prolog (if exist) is called or downstream's method, but not both.
+ * By default, both methods would be called.
+ * </p>
+ * <p>Default: false</p>
+ */
public static final int GEN_PROLOG_XOR_DOWNSTREAM = 1 << 3;
+ /**
+ * By extra command-line argument: <code>gl_identity_by_assignable_class</code>.
+ * <p>
+ * If true, implementation does not utilize downstream's <code>isGL*()</code>
+ * implementation, but determines whether the GL profile is matched by interface inheritance.
+ * </p>
+ * <p>Default: false</p>
+ */
+ public static final int GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS = 1 << 4;
+
int mode;
private String outputDir;
private String outputPackage;
@@ -71,7 +92,7 @@ public class BuildComposablePipeline {
// Only desktop OpenGL has immediate mode glBegin / glEnd
private boolean hasImmediateMode;
// Desktop OpenGL and GLES1 have GL_STACK_OVERFLOW and GL_STACK_UNDERFLOW errors
- private boolean hasStackOverflow;
+ private boolean hasGL2ES1StackOverflow;
public static Class<?> getClass(String name) {
Class<?> clazz = null;
@@ -110,8 +131,12 @@ public class BuildComposablePipeline {
classDownstream = getClass(args[4]);
mode = GEN_CUSTOM;
if (args.length > 5) {
- if (args[5].equals("prolog_xor_downstream")) {
- mode |= GEN_PROLOG_XOR_DOWNSTREAM;
+ for(int i=5; i<args.length; i++) {
+ if (args[i].equals("prolog_xor_downstream")) {
+ mode |= GEN_PROLOG_XOR_DOWNSTREAM;
+ } else if (args[i].equals("gl_identity_by_assignable_class")) {
+ mode |= GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS;
+ }
}
}
} else {
@@ -119,7 +144,7 @@ public class BuildComposablePipeline {
outputName = null; // TBD ..
classPrologOpt = null;
classDownstream = classToComposeAround;
- mode = GEN_DEBUG | GEN_TRACE;
+ mode = GEN_DEBUG | GEN_TRACE ;
}
BuildComposablePipeline composer =
@@ -155,7 +180,7 @@ public class BuildComposablePipeline {
}
try {
- hasStackOverflow =
+ hasGL2ES1StackOverflow = hasImmediateMode &&
(classToComposeAround.getField("GL_STACK_OVERFLOW") != null);
} catch (Exception e) {
}
@@ -167,16 +192,16 @@ public class BuildComposablePipeline {
*/
public void emit() throws IOException {
- List<Method> publicMethodsRaw = Arrays.asList(classToComposeAround.getMethods());
+ final List<Method> publicMethodsRaw = Arrays.asList(classToComposeAround.getMethods());
- Set<PlainMethod> publicMethodsPlain = new HashSet<PlainMethod>();
+ final Set<PlainMethod> publicMethodsPlain = new HashSet<PlainMethod>();
for (Iterator<Method> iter = publicMethodsRaw.iterator(); iter.hasNext();) {
- Method method = iter.next();
+ final Method method = iter.next();
// Don't hook methods which aren't real GL methods,
// such as the synthetic "isGL2ES2" "getGL2ES2"
- String name = method.getName();
+ final String name = method.getName();
boolean runHooks = name.startsWith("gl");
- if (!name.startsWith("getGL") && !name.startsWith("isGL") && !name.equals("toString")) {
+ if ( !name.startsWith("getGL") && !name.startsWith("isGL") && !name.equals("getDownstreamGL") && !name.equals("toString") ) {
publicMethodsPlain.add(new PlainMethod(method, runHooks));
}
}
@@ -602,12 +627,17 @@ public class BuildComposablePipeline {
* Emits one of the isGL* methods.
*/
protected void emitGLIsMethod(PrintWriter output, String type) {
- output.println(" public boolean is" + type + "() {");
- Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
- if (clazz.isAssignableFrom(baseInterfaceClass)) {
- output.println(" return true;");
+ output.println(" @Override");
+ output.println(" public final boolean is" + type + "() {");
+ if( 0 != (GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS & getMode() ) ) {
+ final Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ output.println(" return true;");
+ } else {
+ output.println(" return false;");
+ }
} else {
- output.println(" return false;");
+ output.println(" return " + getDownstreamObjectName() + ".is" + type + "();");
}
output.println(" }");
}
@@ -624,27 +654,57 @@ public class BuildComposablePipeline {
emitGLIsMethod(output, "GL2");
emitGLIsMethod(output, "GLES1");
emitGLIsMethod(output, "GLES2");
+ emitGLIsMethod(output, "GLES3");
emitGLIsMethod(output, "GL2ES1");
emitGLIsMethod(output, "GL2ES2");
+ emitGLIsMethod(output, "GL3ES3");
+ emitGLIsMethod(output, "GL4ES3");
emitGLIsMethod(output, "GL2GL3");
- output.println(" public boolean isGLES() {");
- output.println(" return isGLES2() || isGLES1();");
+ if( 0 != (GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS & getMode() ) ) {
+ output.println(" @Override");
+ output.println(" public final boolean isGLES() {");
+ output.println(" return isGLES2() || isGLES1();");
+ output.println(" }");
+ } else {
+ emitGLIsMethod(output, "GLES");
+ }
+ output.println(" @Override");
+ output.println(" public final boolean isGL4core() {");
+ output.println(" return " + getDownstreamObjectName() + ".isGL4core();");
+ output.println(" }");
+ output.println(" @Override");
+ output.println(" public final boolean isGL3core() {");
+ output.println(" return " + getDownstreamObjectName() + ".isGL3core();");
output.println(" }");
- output.println(" public boolean isGLES2Compatible() {");
+ output.println(" @Override");
+ output.println(" public final boolean isGLcore() {");
+ output.println(" return " + getDownstreamObjectName() + ".isGLcore();");
+ output.println(" }");
+ output.println(" @Override");
+ output.println(" public final boolean isGLES2Compatible() {");
output.println(" return " + getDownstreamObjectName() + ".isGLES2Compatible();");
output.println(" }");
+ output.println(" @Override");
+ output.println(" public final boolean isGLES3Compatible() {");
+ output.println(" return " + getDownstreamObjectName() + ".isGLES3Compatible();");
+ output.println(" }");
}
/**
* Emits one of the getGL* methods.
*/
protected void emitGLGetMethod(PrintWriter output, String type) {
- output.println(" public javax.media.opengl." + type + " get" + type + "() {");
- Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
- if (clazz.isAssignableFrom(baseInterfaceClass)) {
- output.println(" return this;");
+ output.println(" @Override");
+ output.println(" public final javax.media.opengl." + type + " get" + type + "() {");
+ if( 0 != (GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS & getMode() ) ) {
+ final Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ output.println(" return this;");
+ } else {
+ output.println(" throw new GLException(\"Not a " + type + " implementation\");");
+ }
} else {
- output.println(" throw new GLException(\"Not a " + type + " implementation\");");
+ output.println(" return " + getDownstreamObjectName() + ".get" + type + "();");
}
output.println(" }");
}
@@ -661,10 +721,18 @@ public class BuildComposablePipeline {
emitGLGetMethod(output, "GL2");
emitGLGetMethod(output, "GLES1");
emitGLGetMethod(output, "GLES2");
+ emitGLGetMethod(output, "GLES3");
emitGLGetMethod(output, "GL2ES1");
emitGLGetMethod(output, "GL2ES2");
+ emitGLGetMethod(output, "GL3ES3");
+ emitGLGetMethod(output, "GL4ES3");
emitGLGetMethod(output, "GL2GL3");
- output.println(" public GLProfile getGLProfile() {");
+ output.println(" @Override");
+ output.println(" public final GL getDownstreamGL() throws GLException {");
+ output.println(" return " + getDownstreamObjectName() + ";");
+ output.println(" }");
+ output.println(" @Override");
+ output.println(" public final GLProfile getGLProfile() {");
output.println(" return " + getDownstreamObjectName() + ".getGLProfile();");
output.println(" }");
}
@@ -870,9 +938,9 @@ public class BuildComposablePipeline {
output.println(" case GL_INVALID_ENUM: buf.append(\"GL_INVALID_ENUM \"); break;");
output.println(" case GL_INVALID_VALUE: buf.append(\"GL_INVALID_VALUE \"); break;");
output.println(" case GL_INVALID_OPERATION: buf.append(\"GL_INVALID_OPERATION \"); break;");
- if (hasStackOverflow) {
- output.println(" case GL_STACK_OVERFLOW: buf.append(\"GL_STACK_OVERFLOW \"); break;");
- output.println(" case GL_STACK_UNDERFLOW: buf.append(\"GL_STACK_UNDERFLOW \"); break;");
+ if (hasGL2ES1StackOverflow) {
+ output.println(" case GL2ES1.GL_STACK_OVERFLOW: buf.append(\"GL_STACK_OVERFLOW \"); break;");
+ output.println(" case GL2ES1.GL_STACK_UNDERFLOW: buf.append(\"GL_STACK_UNDERFLOW \"); break;");
}
output.println(" case GL_OUT_OF_MEMORY: buf.append(\"GL_OUT_OF_MEMORY \"); break;");
output.println(" case GL_NO_ERROR: throw new InternalError(\"Should not be treating GL_NO_ERROR as error\");");
@@ -902,15 +970,20 @@ public class BuildComposablePipeline {
}
protected void emitClassDocComment(PrintWriter output) {
- output.println("/** <P> Composable pipeline which wraps an underlying {@link GL} implementation,");
- output.println(" providing error checking after each OpenGL method call. If an error occurs,");
- output.println(" causes a {@link GLException} to be thrown at exactly the point of failure.");
- output.println(" Sample code which installs this pipeline: </P>");
- output.println();
- output.println("<PRE>");
- output.println(" GL gl = drawable.setGL(new DebugGL(drawable.getGL()));");
- output.println("</PRE>");
- output.println("*/");
+ output.println("/**");
+ output.println(" * <p>");
+ output.println(" * Composable pipeline which wraps an underlying {@link GL} implementation,");
+ output.println(" * providing error checking after each OpenGL method call. If an error occurs,");
+ output.println(" * causes a {@link GLException} to be thrown at exactly the point of failure.");
+ output.println(" * </p>");
+ output.println(" * <p>");
+ output.println(" * Sample code which installs this pipeline:");
+ output.println(" * <pre>");
+ output.println(" * gl = drawable.setGL(new DebugGL(drawable.getGL()));");
+ output.println(" * </pre>");
+ output.println(" * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}");
+ output.println(" * </p>");
+ output.println(" */");
}
protected boolean hasPreDownstreamCallHook(Method m) {
@@ -1038,14 +1111,20 @@ public class BuildComposablePipeline {
}
protected void emitClassDocComment(PrintWriter output) {
- output.println("/** <P> Composable pipeline which wraps an underlying {@link GL} implementation,");
- output.println(" providing tracing information to a user-specified {@link java.io.PrintStream}");
- output.println(" before and after each OpenGL method call. Sample code which installs this pipeline: </P>");
- output.println();
- output.println("<PRE>");
- output.println(" GL gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
- output.println("</PRE>");
- output.println("*/");
+ output.println("/**");
+ output.println(" * <p>");
+ output.println(" * Composable pipeline which wraps an underlying {@link GL} implementation,");
+ output.println(" * providing tracing information to a user-specified {@link java.io.PrintStream}");
+ output.println(" * before and after each OpenGL method call.");
+ output.println(" * </p>");
+ output.println(" * <p>");
+ output.println(" * Sample code which installs this pipeline:");
+ output.println(" * <pre>");
+ output.println(" * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
+ output.println(" * </pre>");
+ output.println(" * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}");
+ output.println(" * </p>");
+ output.println(" */");
}
protected boolean hasPreDownstreamCallHook(Method m) {
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
index 482d35cae..5298cc357 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -106,14 +106,21 @@ import java.util.regex.Pattern;
public class BuildStaticGLInfo {
// Handles function pointer
- protected static int funcIdentifierGroup = 10;
+ protected static final int funcIdentifierGroup = 9;
protected static Pattern funcPattern =
- Pattern.compile("^(GLAPI|GL_API|GL_APICALL|EGLAPI|extern)?(\\s*)((unsigned|const)\\s+)?(\\w+)(\\s*\\*)?(\\s+)(GLAPIENTRY|GL_APIENTRY|APIENTRY|EGLAPIENTRY|WINAPI)?(\\s*)([ew]?gl\\w+)\\s?(\\(.*)");
+ Pattern.compile("^(GLAPI|GL_API|GL_APICALL|EGLAPI|extern)?(\\s*)((unsigned|const)\\s+)?(\\w+)(\\s+\\*\\s*|\\s*\\*\\s+|\\s+)?(GLAPIENTRY|GL_APIENTRY|APIENTRY|EGLAPIENTRY|WINAPI)?(\\s*)([ew]?gl\\w+)\\s?(\\(.*)");
protected static Pattern associationPattern =
Pattern.compile("\\#ifndef ([CEW]?GL[XU]?_[A-Za-z0-9_]+)(.*)");
- protected static int defineIdentifierGroup = 1;
+ protected static Pattern ifPattern =
+ Pattern.compile("\\#if(.*)");
+ protected static Pattern elsePattern =
+ Pattern.compile("\\#(elif|else)(.*)");
+ protected static Pattern endifPattern =
+ Pattern.compile("\\#endif(.*)");
+
+ protected static final int defineIdentifierGroup = 1;
protected static Pattern definePattern =
Pattern.compile("\\#define ([CEW]?GL[XU]?_[A-Za-z0-9_]+)\\s*([A-Za-z0-9_]+)(.*)");
@@ -194,38 +201,62 @@ public class BuildStaticGLInfo {
BufferedReader reader = new BufferedReader(new FileReader(cHeaderFilePath));
String line, activeAssociation = null;
Matcher m = null;
+ int block = 0;
while ((line = reader.readLine()) != null) {
- int type = 0; // 1-define, 2-function
- // see if we're inside a #ifndef GL_XXX block and matching a function
- if (activeAssociation != null) {
+ int type = 0; // 1-define, 2-function
+ if ( 0 < block ) { // inside a #ifndef GL_XXX block and matching a function, if block > 0
String identifier = null;
- if ((m = funcPattern.matcher(line)).matches()) {
- identifier = m.group(funcIdentifierGroup).trim();
- type = 2;
- } else if ((m = definePattern.matcher(line)).matches()) {
- identifier = m.group(defineIdentifierGroup).trim();
- type = 1;
- } else if (line.startsWith("#endif")) {
- if (DEBUG) {
- System.err.println("END ASSOCIATION BLOCK: <" + activeAssociation + ">");
+ if( 2 >= block ) { // not within sub-blocks > 2, i.e. further typedefs
+ if ((m = funcPattern.matcher(line)).matches()) {
+ identifier = m.group(funcIdentifierGroup).trim();
+ type = 2;
+ } else if ((m = definePattern.matcher(line)).matches()) {
+ identifier = m.group(defineIdentifierGroup).trim();
+ type = 1;
}
- activeAssociation = null;
}
- if ((identifier != null)
- && (activeAssociation != null)
- && // Handles #ifndef GL_... #define GL_...
- !identifier.equals(activeAssociation)) {
+ if ( identifier != null &&
+ activeAssociation != null &&
+ !identifier.equals(activeAssociation) // Handles #ifndef GL_... #define GL_...
+ )
+ {
addAssociation(identifier, activeAssociation);
if (DEBUG) {
- System.err.println(" ADDING ASSOCIATION: <" + identifier + "> <" + activeAssociation + "> ; type " + type);
+ System.err.println("<"+block+"> ADDING ASSOCIATION: <" + identifier + "> <" + activeAssociation + "> ; type " + type);
+ }
+ } else {
+ if ((m = ifPattern.matcher(line)).matches()) {
+ final String comment = m.group(1).trim();
+ block++;
+ if (DEBUG) {
+ System.err.println("<"+block+"> BEGIN IF BLOCK: <" + comment + ">");
+ }
+ } else if ((m = elsePattern.matcher(line)).matches()) {
+ final String comment = m.group(1).trim();
+ if (DEBUG) {
+ System.err.println("<"+block+"> ELSE BLOCK: <" + comment + ">");
+ }
+ } else if ((m = endifPattern.matcher(line)).matches()) {
+ final String comment = m.group(1).trim();
+ block--;
+ if( 0 == block ) {
+ if (DEBUG) {
+ System.err.println("<"+block+"> END ASSOCIATION BLOCK: <" + activeAssociation + " <-> " + comment + ">");
+ }
+ activeAssociation = null;
+ } else {
+ if (DEBUG) {
+ System.err.println("<"+block+"> END IF BLOCK: <" + comment + ">");
+ }
+ }
}
}
- } else if ((m = associationPattern.matcher(line)).matches()) {
+ } else if ((m = associationPattern.matcher(line)).matches()) {
// found a new #ifndef GL_XXX block
activeAssociation = m.group(1).trim();
-
+ block++;
if (DEBUG) {
- System.err.println("BEGIN ASSOCIATION BLOCK: <" + activeAssociation + ">");
+ System.err.println("<"+block+"> BEGIN ASSOCIATION BLOCK: <" + activeAssociation + ">");
}
}
}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
index ba025e18c..d4dca715b 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -61,6 +61,7 @@ public class GLConfiguration extends ProcAddressConfiguration {
// The following data members support ignoring an entire extension at a time
private List<String> glHeaders = new ArrayList<String>();
private Set<String> ignoredExtensions = new HashSet<String>();
+ private Set<String> forcedExtensions = new HashSet<String>();
private Set<String> extensionsRenamedIntoCore = new HashSet<String>();
private BuildStaticGLInfo glInfo;
@@ -90,6 +91,9 @@ public class GLConfiguration extends ProcAddressConfiguration {
if (cmd.equalsIgnoreCase("IgnoreExtension")) {
String sym = readString("IgnoreExtension", tok, filename, lineNo);
ignoredExtensions.add(sym);
+ } else if (cmd.equalsIgnoreCase("ForceExtension")) {
+ String sym = readString("ForceExtension", tok, filename, lineNo);
+ forcedExtensions.add(sym);
} else if (cmd.equalsIgnoreCase("RenameExtensionIntoCore")) {
String sym = readString("RenameExtensionIntoCore", tok, filename, lineNo);
extensionsRenamedIntoCore.add(sym);
@@ -202,16 +206,21 @@ public class GLConfiguration extends ProcAddressConfiguration {
for (String str : ignoredExtensions) {
System.err.println("\t" + str);
}
+ System.err.println("GL Forced extensions: ");
+ for (String str : forcedExtensions) {
+ System.err.println("\t" + str);
+ }
super.dumpIgnores();
}
protected boolean shouldIgnoreExtension(String symbol, boolean criteria) {
if (criteria && glInfo != null) {
- Set<String> extensionNames = glInfo.getExtension(symbol);
- if(null!=extensionNames) {
- for(Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
- String extensionName = i.next();
- if (extensionName != null && ignoredExtensions.contains(extensionName)) {
+ final Set<String> extensionNames = glInfo.getExtension(symbol);
+ if( null != extensionNames ) {
+ boolean ignoredExtension = false;
+ for(Iterator<String> i=extensionNames.iterator(); !ignoredExtension && i.hasNext(); ) {
+ final String extensionName = i.next();
+ if ( extensionName != null && ignoredExtensions.contains(extensionName) ) {
if (DEBUG_IGNORES) {
System.err.print("Ignore symbol <" + symbol + "> of extension <" + extensionName + ">");
if(extensionNames.size()==1) {
@@ -220,9 +229,26 @@ public class GLConfiguration extends ProcAddressConfiguration {
System.err.println(", WARNING MULTIPLE OCCURENCE: "+extensionNames);
}
}
- return true;
+ ignoredExtension = true;
+ }
+ }
+ if( ignoredExtension ) {
+ ignoredExtension = !shouldForceExtension( symbol, true, symbol );
+ if( ignoredExtension ) {
+ final Set<String> origSymbols = getRenamedJavaSymbols( symbol );
+ if(null != origSymbols) {
+ for(String origSymbol : origSymbols) {
+ if( shouldForceExtension( origSymbol, true, symbol ) ) {
+ ignoredExtension = false;
+ break;
+ }
+ }
+ }
}
}
+ if( ignoredExtension ) {
+ return true;
+ }
}
boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
@@ -240,6 +266,29 @@ public class GLConfiguration extends ProcAddressConfiguration {
}
return false;
}
+
+ public boolean shouldForceExtension(final String symbol, final boolean criteria, final String renamedSymbol) {
+ if (criteria && glInfo != null) {
+ final Set<String> extensionNames = glInfo.getExtension(symbol);
+ if( null != extensionNames ) {
+ for(Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
+ final String extensionName = i.next();
+ if ( extensionName != null && forcedExtensions.contains(extensionName) ) {
+ if (DEBUG_IGNORES) {
+ System.err.print("Not Ignore symbol <" + symbol + " -> " + renamedSymbol + "> of extension <" + extensionName + ">");
+ if(extensionNames.size()==1) {
+ System.err.println(", single .");
+ } else {
+ System.err.println(", WARNING MULTIPLE OCCURENCE: "+extensionNames);
+ }
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
@Override
public boolean shouldIgnoreInInterface(String symbol) {
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index 809c6783d..075c8bfd8 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -454,34 +454,69 @@ public class GLEmitter extends ProcAddressEmitter {
return (GLConfiguration) getConfig();
}
+ /**
+ * {@inheritDoc}
+ */
@Override
protected void endProcAddressTable() throws Exception {
PrintWriter w = tableWriter;
-
- w.println(" /**");
- w.println(" * This is a convenience method to get (by name) the native function");
- w.println(" * pointer for a given function. It lets you avoid having to");
- w.println(" * manually compute the &quot;" + PROCADDRESS_VAR_PREFIX + " + ");
- w.println(" * &lt;functionName&gt;&quot; member variable name and look it up via");
- w.println(" * reflection; it also will throw an exception if you try to get the");
- w.println(" * address of an unknown function, or one that is statically linked");
- w.println(" * and therefore does not have a function pointer in this table.");
- w.println(" *");
- w.println(" * @throws RuntimeException if the function pointer was not found in");
- w.println(" * this table, either because the function was unknown or because");
- w.println(" * it was statically linked.");
- w.println(" */");
- w.println(" public long getAddressFor(String functionNameUsr) {");
- 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 = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
- w.println(" for(int i = 0; null==addressField && i < funcNamePermNum; 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) { }");
+
+ w.println(" @Override");
+ w.println(" protected boolean isFunctionAvailableImpl(String functionNameUsr) throws IllegalArgumentException {");
+ w.println(" final String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
+ w.println(" final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX + "\" + functionNameBase;");
+ w.println(" final int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" final java.lang.reflect.Field addressField = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
+ w.println(" public final java.lang.reflect.Field run() {");
+ w.println(" java.lang.reflect.Field addressField = null;");
+ w.println(" for(int i = 0; i < funcNamePermNum; i++) {");
+ w.println(" final String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" try {");
+ w.println(" addressField = "+tableClassName+".class.getDeclaredField( addressFieldName );");
+ w.println(" addressField.setAccessible(true); // we need to read the protected value!");
+ w.println(" return addressField;");
+ w.println(" } catch (NoSuchFieldException ex) { }");
+ w.println(" }");
+ w.println(" return null;");
+ w.println(" } } );");
+ w.println();
+ w.println(" if(null==addressField) {");
+ w.println(" // The user is calling a bogus function or one which is not");
+ w.println(" // runtime linked");
+ w.println(" throw new RuntimeException(");
+ w.println(" \"WARNING: Address field query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+ w.println(" \"\\\"; it's either statically linked or address field is not a known \" +");
+ w.println(" \"function\");");
+ w.println(" } ");
+ w.println(" try {");
+ w.println(" return 0 != addressField.getLong(this);");
+ w.println(" } catch (Exception e) {");
+ w.println(" throw new RuntimeException(");
+ w.println(" \"WARNING: Address query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+ w.println(" \"\\\"; it's either statically linked or is not a known \" +");
+ w.println(" \"function\", e);");
w.println(" }");
+ w.println(" }");
+
+ w.println(" @Override");
+ w.println(" public long getAddressFor(String functionNameUsr) throws SecurityException, IllegalArgumentException {");
+ w.println(" SecurityUtil.checkAllLinkPermission();");
+ w.println(" final String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
+ w.println(" final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX + "\" + functionNameBase;");
+ w.println(" final int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" final java.lang.reflect.Field addressField = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
+ w.println(" public final java.lang.reflect.Field run() {");
+ w.println(" java.lang.reflect.Field addressField = null;");
+ w.println(" for(int i = 0; i < funcNamePermNum; i++) {");
+ w.println(" final String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" try {");
+ w.println(" addressField = "+tableClassName+".class.getDeclaredField( addressFieldName );");
+ w.println(" addressField.setAccessible(true); // we need to read the protected value!");
+ w.println(" return addressField;");
+ w.println(" } catch (NoSuchFieldException ex) { }");
+ w.println(" }");
+ w.println(" return null;");
+ w.println(" } } );");
w.println();
w.println(" if(null==addressField) {");
w.println(" // The user is calling a bogus function or one which is not");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
index 016674338..fdfaee8a6 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
@@ -43,6 +43,7 @@ import com.jogamp.gluegen.CommentEmitter;
import com.jogamp.gluegen.JavaEmitter;
import com.jogamp.gluegen.JavaMethodBindingEmitter;
import com.jogamp.gluegen.MethodBinding;
+import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.cgram.types.Type;
import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
@@ -103,11 +104,14 @@ public class GLJavaMethodBindingEmitter extends ProcAddressJavaMethodBindingEmit
@Override
protected void emitBindingCSignature(MethodBinding binding, PrintWriter writer) {
- super.emitBindingCSignature(binding, writer);
-
String symbolRenamed = binding.getName();
StringBuilder newComment = new StringBuilder();
+ final FunctionSymbol funcSym = binding.getCSymbol();
+ writer.print("<code> ");
+ writer.print(funcSym.getType().toString(symbolRenamed, tagNativeBinding));
+ writer.print(" </code> ");
+
newComment.append("<br>Part of ");
if (0 == glEmitter.addExtensionsOfSymbols2Buffer(newComment, ", ", "; ", symbolRenamed, binding.getAliasedNames())) {
if (glEmitter.getGLConfig().getAllowNonGLExtensions()) {
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
index 33d487355..d2824b9dc 100644
--- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
+++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
@@ -33,13 +33,23 @@ import java.net.URLConnection;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.SecurityUtil;
import jogamp.graph.font.FontConstructor;
import jogamp.graph.font.JavaFontLoader;
import jogamp.graph.font.UbuntuFontLoader;
+/**
+ * The optional property <i>jogamp.graph.font.ctor</i>
+ * allows user to specify the {@link FontConstructor} implementation.
+ * <p>
+ * Default {@link FontConstructor} is {@link jogamp.graph.font.typecast.TypecastFontConstructor},
+ * i.e. using our internal <i>typecast</i> branch.
+ * </p>
+ */
public class FontFactory {
+ private static final String FontConstructorPropKey = "jogamp.graph.font.ctor";
+ private static final String DefaultFontConstructor = "jogamp.graph.font.typecast.TypecastFontConstructor";
+
/** Ubuntu is the default font family */
public static final int UBUNTU = 0;
@@ -54,9 +64,9 @@ public class FontFactory {
* "jogamp.graph.font.typecast.TypecastFontFactory" (default)
* "jogamp.graph.font.ttf.TTFFontImpl"
*/
- String fontImplName = PropertyAccess.getProperty("FontImpl", true, SecurityUtil.getCommonAccessControlContext(FontFactory.class));
+ String fontImplName = PropertyAccess.getProperty(FontConstructorPropKey, true);
if(null == fontImplName) {
- fontImplName = "jogamp.graph.font.typecast.TypecastFontConstructor";
+ fontImplName = DefaultFontConstructor;
}
fontConstr = (FontConstructor) ReflectionUtil.createInstance(fontImplName, FontFactory.class.getClassLoader());
}
@@ -83,10 +93,13 @@ public class FontFactory {
}
public static boolean isPrintableChar( char c ) {
- Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
- return (!Character.isISOControl(c)) &&
- c != 0 &&
- block != null &&
- block != Character.UnicodeBlock.SPECIALS;
+ if( Character.isWhitespace(c) ) {
+ return true;
+ }
+ if( 0 == c || Character.isISOControl(c) ) {
+ return false;
+ }
+ final Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
+ return block != null && block != Character.UnicodeBlock.SPECIALS;
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
index c0666d153..14f4be96a 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -51,6 +51,7 @@ public class GLExtensions {
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 ARB_ES3_compatibility = "GL_ARB_ES3_compatibility";
public static final String EXT_abgr = "GL_EXT_abgr";
public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8";
@@ -69,7 +70,7 @@ public class GLExtensions {
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_single_precision = "GL_OES_single_precision";
public static final String OES_EGL_image_external = "GL_OES_EGL_image_external";
public static final String ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64";
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 36893f5ec..023a8a1aa 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -71,11 +71,18 @@ public class GLRendererQuirks {
/**
* Non compliant GL context due to a buggy implementation not suitable for use.
* <p>
- * Mesa >= 9.0 (?), Intel driver, OpenGL 3.1 compatibility context is not compliant:
- * <pre>
- * GL_RENDERER: Mesa DRI Intel(R) Sandybridge Desktop
- * </pre>
+ * Currently, Mesa >= 9.1.3 (may extend back as far as 9.0) OpenGL 3.1 compatibility
+ * context is not compliant. Most programs will give completely broken output (or no
+ * output at all. For now, this context is not trusted.
* </p>
+ * The above has been confirmed for the following Mesa 9.* GL_RENDERER strings:
+ * <ul>
+ * <li>Mesa .* Intel(R) Sandybridge Desktop</li>
+ * <li>Gallium 0.4 on AMD RS880</li>
+ * </ul>
+ * </p>
+ * <p>
+ * It still has to be verified whether the AMD OpenGL 3.1 core driver is compliant enought.
*/
public static final int GLNonCompliant = 6;
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 6cd02b749..1f0189aa3 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -130,7 +130,7 @@ public class JoglVersion extends JogampVersion {
public static StringBuilder getGLInfo(GL gl, StringBuilder sb) {
return getGLInfo(gl, sb, false);
}
- public static StringBuilder getGLInfo(GL gl, StringBuilder sb, boolean withCapabilitiesInfo) {
+ public static StringBuilder getGLInfo(GL gl, StringBuilder sb, boolean withCapabilitiesAndExtensionInfo) {
AbstractGraphicsDevice device = gl.getContext().getGLDrawable().getNativeSurface()
.getGraphicsConfiguration().getScreen().getDevice();
if(null==sb) {
@@ -143,15 +143,19 @@ public class JoglVersion extends JogampVersion {
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
sb.append(Platform.getNewline());
- sb = getGLStrings(gl, sb);
+ sb = getGLStrings(gl, sb, withCapabilitiesAndExtensionInfo);
- if( withCapabilitiesInfo ) {
+ if( withCapabilitiesAndExtensionInfo ) {
sb = getAllAvailableCapabilitiesInfo(device, sb);
}
return sb;
}
- public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+ public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+ return getGLStrings(gl, sb, true);
+ }
+
+ public static StringBuilder getGLStrings(GL gl, StringBuilder sb, boolean withExtensions) {
if(null==sb) {
sb = new StringBuilder();
}
@@ -177,14 +181,20 @@ public class JoglVersion extends JogampVersion {
sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION)).append(" / ").append(ctx.getGLSLVersionNumber());
}
sb.append(Platform.getNewline());
- sb.append("GL_EXTENSIONS ").append(ctx.getGLExtensionCount());
+ sb.append("GL FBO: basic ").append(gl.hasBasicFBOSupport()).append(", full ").append(gl.hasFullFBOSupport());
sb.append(Platform.getNewline());
- sb.append(" ").append(ctx.getGLExtensionsString());
+ sb.append("GL_EXTENSIONS ").append(ctx.getGLExtensionCount());
sb.append(Platform.getNewline());
+ if( withExtensions ) {
+ sb.append(" ").append(ctx.getGLExtensionsString());
+ sb.append(Platform.getNewline());
+ }
sb.append("GLX_EXTENSIONS ").append(ctx.getPlatformExtensionCount());
sb.append(Platform.getNewline());
- sb.append(" ").append(ctx.getPlatformExtensionsString());
- sb.append(Platform.getNewline());
+ if( withExtensions ) {
+ sb.append(" ").append(ctx.getPlatformExtensionsString());
+ sb.append(Platform.getNewline());
+ }
sb.append(VersionUtil.SEPERATOR);
return sb;
diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
index d160eccff..ca4846939 100644
--- a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
@@ -39,8 +39,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
- private static List<String> glueLibNames;
+public final class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
+ private static final List<String> glueLibNames;
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
@@ -69,11 +69,16 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
/** Make Cg symbols available to CgGL */
@Override
- public boolean shallLinkGlobal() { return true; }
+ public final boolean shallLinkGlobal() { return true; }
- /** default **/
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>false</code>.
+ * </p>
+ */
@Override
- public boolean shallLookupGlobal() { return false; }
+ public final boolean shallLookupGlobal() { return false; }
/** Tool has none **/
@Override
@@ -88,12 +93,12 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(String funcName) {
return false;
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsCg = new ArrayList<String>();
libsCg.add("Cg");
@@ -112,7 +117,7 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public RunnableExecutor getLibLoaderExecutor() {
+ public final RunnableExecutor getLibLoaderExecutor() {
return DynamicLibraryBundle.getDefaultRunnableExecutor();
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
index 9a51c32b3..f3f44f15a 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -113,6 +113,22 @@ public class FloatUtil {
}
/**
+ * @param a 4x4 matrix in column-major order (also result)
+ * @param b 4x4 matrix in column-major order
+ */
+ public static final void multMatrixf(final float[] a, int a_off, final float[] b, int b_off) {
+ for (int i = 0; i < 4; i++) {
+ // one row in column-major order
+ final int a_off_i = a_off+i;
+ final float ai0=a[a_off_i+0*4], ai1=a[a_off_i+1*4], ai2=a[a_off_i+2*4], ai3=a[a_off_i+3*4]; // row-i of a
+ a[a_off_i+0*4] = ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] ;
+ a[a_off_i+1*4] = ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] ;
+ a[a_off_i+2*4] = ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] ;
+ a[a_off_i+3*4] = ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ;
+ }
+ }
+
+ /**
* @param a 4x4 matrix in column-major order
* @param b 4x4 matrix in column-major order
* @param d result a*b in column-major order
@@ -146,6 +162,23 @@ public class FloatUtil {
d.put(dP+i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] );
}
}
+
+ /**
+ * @param a 4x4 matrix in column-major order (also result)
+ * @param b 4x4 matrix in column-major order
+ */
+ public static final void multMatrixf(final FloatBuffer a, final float[] b, int b_off) {
+ final int aP = a.position();
+ for (int i = 0; i < 4; i++) {
+ // one row in column-major order
+ final int aP_i = aP+i;
+ final float ai0=a.get(aP_i+0*4), ai1=a.get(aP_i+1*4), ai2=a.get(aP_i+2*4), ai3=a.get(aP_i+3*4); // row-i of a
+ a.put(aP_i+0*4 , ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] );
+ a.put(aP_i+1*4 , ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] );
+ a.put(aP_i+2*4 , ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] );
+ a.put(aP_i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] );
+ }
+ }
/**
* @param a 4x4 matrix in column-major order
@@ -167,6 +200,24 @@ public class FloatUtil {
}
/**
+ * @param a 4x4 matrix in column-major order (also result)
+ * @param b 4x4 matrix in column-major order
+ */
+ public static final void multMatrixf(final FloatBuffer a, final FloatBuffer b) {
+ final int aP = a.position();
+ final int bP = b.position();
+ for (int i = 0; i < 4; i++) {
+ // one row in column-major order
+ final int aP_i = aP+i;
+ final float ai0=a.get(aP_i+0*4), ai1=a.get(aP_i+1*4), ai2=a.get(aP_i+2*4), ai3=a.get(aP_i+3*4); // row-i of a
+ a.put(aP_i+0*4 , ai0 * b.get(bP+0+0*4) + ai1 * b.get(bP+1+0*4) + ai2 * b.get(bP+2+0*4) + ai3 * b.get(bP+3+0*4) );
+ a.put(aP_i+1*4 , ai0 * b.get(bP+0+1*4) + ai1 * b.get(bP+1+1*4) + ai2 * b.get(bP+2+1*4) + ai3 * b.get(bP+3+1*4) );
+ a.put(aP_i+2*4 , ai0 * b.get(bP+0+2*4) + ai1 * b.get(bP+1+2*4) + ai2 * b.get(bP+2+2*4) + ai3 * b.get(bP+3+2*4) );
+ a.put(aP_i+3*4 , ai0 * b.get(bP+0+3*4) + ai1 * b.get(bP+1+3*4) + ai2 * b.get(bP+2+3*4) + ai3 * b.get(bP+3+3*4) );
+ }
+ }
+
+ /**
* @param a 4x4 matrix in column-major order
* @param b 4x4 matrix in column-major order
* @param d result a*b in column-major order
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
index 409176101..c6bf44f6d 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
@@ -55,8 +55,8 @@ public class Quaternion {
* @param vector2
*/
public Quaternion(float[] vector1, float[] vector2) {
- float theta = FloatUtil.acos(VectorUtil.dot(vector1, vector2));
- float[] cross = VectorUtil.cross(vector1, vector2);
+ final float theta = FloatUtil.acos(VectorUtil.dot(vector1, vector2));
+ final float[] cross = VectorUtil.cross(vector1, vector2);
fromAxis(cross, theta);
}
@@ -77,9 +77,9 @@ public class Quaternion {
* @param angle rotation angle (rads)
*/
public void fromAxis(float[] vector, float angle) {
- float halfangle = angle * 0.5f;
- float sin = FloatUtil.sin(halfangle);
- float[] nv = VectorUtil.normalize(vector);
+ final float halfangle = angle * 0.5f;
+ final float sin = FloatUtil.sin(halfangle);
+ final float[] nv = VectorUtil.normalize(vector);
x = (nv[0] * sin);
y = (nv[1] * sin);
z = (nv[2] * sin);
@@ -92,8 +92,8 @@ public class Quaternion {
* @return new float[4] with ,theta,Rx,Ry,Rz
*/
public float[] toAxis() {
- float[] vec = new float[4];
- float scale = FloatUtil.sqrt(x * x + y * y + z * z);
+ final float[] vec = new float[4];
+ final float scale = FloatUtil.sqrt(x * x + y * y + z * z);
vec[0] = FloatUtil.acos(w) * 2.0f;
vec[1] = x / scale;
vec[2] = y / scale;
@@ -172,11 +172,11 @@ public class Quaternion {
* @param q a quaternion to multiply with
*/
public void mult(Quaternion q) {
- float w1 = w * q.w - x * q.x - y * q.y - z * q.z;
+ final float w1 = w * q.w - x * q.x - y * q.y - z * q.z;
- float x1 = w * q.x + x * q.w + y * q.z - z * q.y;
- float y1 = w * q.y - x * q.z + y * q.w + z * q.x;
- float z1 = w * q.z + x * q.y - y * q.x + z * q.w;
+ final float x1 = w * q.x + x * q.w + y * q.z - z * q.y;
+ final float y1 = w * q.y - x * q.z + y * q.w + z * q.x;
+ final float z1 = w * q.z + x * q.y - y * q.x + z * q.w;
w = w1;
x = x1;
@@ -202,11 +202,11 @@ public class Quaternion {
* @return rotated vector
*/
public float[] mult(float[] vector) {
- // TODO : optimalize
- float[] res = new float[3];
- Quaternion a = new Quaternion(vector[0], vector[1], vector[2], 0.0f);
- Quaternion b = new Quaternion(this);
- Quaternion c = new Quaternion(this);
+ // TODO : optimize
+ final float[] res = new float[3];
+ final Quaternion a = new Quaternion(vector[0], vector[1], vector[2], 0.0f);
+ final Quaternion b = new Quaternion(this);
+ final Quaternion c = new Quaternion(this);
b.inverse();
a.mult(b);
c.mult(a);
@@ -220,11 +220,11 @@ public class Quaternion {
* Normalize a quaternion required if to be used as a rotational quaternion
*/
public void normalize() {
- float norme = (float) FloatUtil.sqrt(w * w + x * x + y * y + z * z);
+ final float norme = (float) FloatUtil.sqrt(w * w + x * x + y * y + z * z);
if (norme == 0.0f) {
setIdentity();
} else {
- float recip = 1.0f / norme;
+ final float recip = 1.0f / norme;
w *= recip;
x *= recip;
@@ -237,9 +237,9 @@ public class Quaternion {
* Invert the quaternion If rotational, will produce a the inverse rotation
*/
public void inverse() {
- float norm = w * w + x * x + y * y + z * z;
+ final float norm = w * w + x * x + y * y + z * z;
- float recip = 1.0f / norm;
+ final float recip = 1.0f / norm;
w *= recip;
x = -1 * x * recip;
@@ -254,7 +254,7 @@ public class Quaternion {
* @return new float[16] column matrix 4x4
*/
public float[] toMatrix() {
- float[] matrix = new float[16];
+ final float[] matrix = new float[16];
matrix[0] = 1.0f - 2 * y * y - 2 * z * z;
matrix[1] = 2 * x * y + 2 * w * z;
matrix[2] = 2 * x * z - 2 * w * y;
@@ -330,20 +330,8 @@ public class Quaternion {
}
/**
- * Check if this quaternion is empty, ie (0,0,0,1)
- *
- * @return true if empty, false otherwise
- * @deprecated use {@link #isIdentity()} instead
- */
- @Deprecated
- public boolean isEmpty() {
- if (w == 1 && x == 0 && y == 0 && z == 0)
- return true;
- return false;
- }
-
- /**
- * Check if this quaternion represents an identity matrix, for rotation.
+ * Check if this quaternion represents an identity matrix for rotation,
+ * , ie (0,0,0,1).
*
* @return true if it is an identity rep., false otherwise
*/
@@ -365,28 +353,28 @@ public class Quaternion {
* @param m 3x3 column matrix
*/
public void setFromMatrix(float[] m) {
- float T = m[0] + m[4] + m[8] + 1;
+ final float T = m[0] + m[4] + m[8] + 1;
if (T > 0) {
- float S = 0.5f / (float) FloatUtil.sqrt(T);
+ final float S = 0.5f / (float) FloatUtil.sqrt(T);
w = 0.25f / S;
x = (m[5] - m[7]) * S;
y = (m[6] - m[2]) * S;
z = (m[1] - m[3]) * S;
} else {
if ((m[0] > m[4]) & (m[0] > m[8])) {
- float S = FloatUtil.sqrt(1.0f + m[0] - m[4] - m[8]) * 2f; // S=4*qx
+ final float S = FloatUtil.sqrt(1.0f + m[0] - m[4] - m[8]) * 2f; // S=4*qx
w = (m[7] - m[5]) / S;
x = 0.25f * S;
y = (m[3] + m[1]) / S;
z = (m[6] + m[2]) / S;
} else if (m[4] > m[8]) {
- float S = FloatUtil.sqrt(1.0f + m[4] - m[0] - m[8]) * 2f; // S=4*qy
+ final float S = FloatUtil.sqrt(1.0f + m[4] - m[0] - m[8]) * 2f; // S=4*qy
w = (m[6] - m[2]) / S;
x = (m[3] + m[1]) / S;
y = 0.25f * S;
z = (m[7] + m[5]) / S;
} else {
- float S = FloatUtil.sqrt(1.0f + m[8] - m[0] - m[4]) * 2f; // S=4*qz
+ final float S = FloatUtil.sqrt(1.0f + m[8] - m[0] - m[4]) * 2f; // S=4*qz
w = (m[3] - m[1]) / S;
x = (m[6] + m[2]) / S;
y = (m[7] + m[5]) / S;
@@ -403,7 +391,7 @@ public class Quaternion {
* @return true if representing a rotational matrix, false otherwise
*/
public boolean isRotationMatrix(float[] m) {
- double epsilon = 0.01; // margin to allow for rounding errors
+ final float epsilon = 0.01f; // margin to allow for rounding errors
if (FloatUtil.abs(m[0] * m[3] + m[3] * m[4] + m[6] * m[7]) > epsilon)
return false;
if (FloatUtil.abs(m[0] * m[2] + m[3] * m[5] + m[6] * m[8]) > epsilon)
@@ -421,6 +409,6 @@ public class Quaternion {
private float determinant(float[] m) {
return m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5]
- - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2];
+ - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2];
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
index 5a75d016a..0033afeaa 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -292,21 +292,21 @@ public class VectorUtil {
*/
public static boolean vertexInTriangle(float[] a, float[] b, float[] c, float[] p){
// Compute vectors
- float[] ac = computeVector(a, c); //v0
- float[] ab = computeVector(a, b); //v1
- float[] ap = computeVector(a, p); //v2
+ final float[] ac = computeVector(a, c); //v0
+ final float[] ab = computeVector(a, b); //v1
+ final float[] ap = computeVector(a, p); //v2
// Compute dot products
- float dot00 = dot(ac, ac);
- float dot01 = dot(ac, ab);
- float dot02 = dot(ac, ap);
- float dot11 = dot(ab, ab);
- float dot12 = dot(ab, ap);
+ final float dot00 = dot(ac, ac);
+ final float dot01 = dot(ac, ab);
+ final float dot02 = dot(ac, ap);
+ final float dot11 = dot(ab, ab);
+ final float dot12 = dot(ab, ap);
// Compute barycentric coordinates
- float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
- float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
- float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+ final float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ final float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+ final float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
// Check if point is in triangle
return (u >= 0) && (v >= 0) && (u + v < 1);
@@ -337,12 +337,12 @@ public class VectorUtil {
* @return positive area if ccw else negative area value
*/
public static float area(ArrayList<? extends Vert2fImmutable> vertices) {
- int n = vertices.size();
+ final int n = vertices.size();
float area = 0.0f;
for (int p = n - 1, q = 0; q < n; p = q++)
{
- float[] pCoord = vertices.get(p).getCoord();
- float[] qCoord = vertices.get(q).getCoord();
+ final float[] pCoord = vertices.get(p).getCoord();
+ final float[] qCoord = vertices.get(q).getCoord();
area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
}
return area;
@@ -366,18 +366,18 @@ public class VectorUtil {
* returns null
*/
public static float[] seg2SegIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
- float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
+ final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
if (determinant == 0)
return null;
- float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
- float beta = (c.getX()*d.getY()-c.getY()*d.getY());
- float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
- float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
+ final float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
+ final float beta = (c.getX()*d.getY()-c.getY()*d.getY());
+ final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
+ final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
- float gamma = (xi - a.getX())/(b.getX() - a.getX());
- float gamma1 = (xi - c.getX())/(d.getX() - c.getX());
+ final float gamma = (xi - a.getX())/(b.getX() - a.getX());
+ final float gamma1 = (xi - c.getX())/(d.getX() - c.getX());
if(gamma <= 0 || gamma >= 1) return null;
if(gamma1 <= 0 || gamma1 >= 1) return null;
@@ -393,15 +393,15 @@ public class VectorUtil {
* returns null
*/
public static float[] line2lineIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
- float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
+ final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
if (determinant == 0)
return null;
- float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
- float beta = (c.getX()*d.getY()-c.getY()*d.getY());
- float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
- float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
+ final float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
+ final float beta = (c.getX()*d.getY()-c.getY()*d.getY());
+ final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
+ final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
return new float[]{xi,yi,0};
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
index 26d299663..8de178e49 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
@@ -165,6 +165,6 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
};
public boolean blockUntilDone(Thread thread) {
- return ((Thread.currentThread() != thread) && !EventQueue.isDispatchThread());
+ return Thread.currentThread() != thread && !EventQueue.isDispatchThread();
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
index 837fc84bd..ef92100ad 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -115,6 +115,10 @@ public abstract class AnimatorBase implements GLAnimatorControl {
drawablesEmpty = true;
}
+ private static final boolean useAWTAnimatorImpl(int modeBits) {
+ return 0 != ( MODE_EXPECT_AWT_RENDERING_THREAD & modeBits ) && null != awtAnimatorImplClazz;
+ }
+
/**
* Initializes implementation details post setup,
* invoked at {@link #add(GLAutoDrawable)}, {@link #start()}, ..
@@ -125,9 +129,9 @@ public abstract class AnimatorBase implements GLAnimatorControl {
*
* @throws GLException if Animator is {@link #isStarted()}
*/
- protected void initImpl(boolean force) {
+ protected synchronized void initImpl(boolean force) {
if( force || null == impl ) {
- if( 0 != ( MODE_EXPECT_AWT_RENDERING_THREAD & modeBits ) && null != awtAnimatorImplClazz ) {
+ if( useAWTAnimatorImpl( modeBits ) ) {
try {
impl = (AnimatorImpl) awtAnimatorImplClazz.newInstance();
baseName = getBaseName("AWT");
@@ -150,20 +154,20 @@ public abstract class AnimatorBase implements GLAnimatorControl {
* @param enable
* @param bitValues
*
- * @throws GLException if Animator is {@link #isStarted()}
+ * @throws GLException if Animator is {@link #isStarted()} and {@link #MODE_EXPECT_AWT_RENDERING_THREAD} about to change
* @see AnimatorBase#MODE_EXPECT_AWT_RENDERING_THREAD
*/
public synchronized void setModeBits(boolean enable, int bitValues) throws GLException {
- if( isStarted() ) {
- throw new GLException("Animator already started");
- }
final int _oldModeBits = modeBits;
if(enable) {
modeBits |= bitValues;
} else {
modeBits &= ~bitValues;
}
- if( _oldModeBits != modeBits ) {
+ if( useAWTAnimatorImpl( _oldModeBits ) != useAWTAnimatorImpl( modeBits ) ) {
+ if( isStarted() ) {
+ throw new GLException("Animator already started");
+ }
initImpl(true);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
index 23b0845ee..bbd2951b9 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
@@ -61,6 +61,6 @@ class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl {
}
public boolean blockUntilDone(Thread thread) {
- return (Thread.currentThread() != thread);
+ return Thread.currentThread() != thread;
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
index b0fc7f332..2bd45e3e4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -189,9 +189,9 @@ public class GLPixelBuffer {
private boolean disposed = false;
- public StringBuffer toString(StringBuffer sb) {
+ public StringBuilder toString(StringBuilder sb) {
if(null == sb) {
- sb = new StringBuffer();
+ sb = new StringBuilder();
}
sb.append(pixelAttributes).append(", dim ").append(width).append("x").append(height).append("x").append(depth).append(", pack ").append(pack)
.append(", disposed ").append(disposed).append(", valid ").append(isValid()).append(", buffer[sz [bytes ").append(byteSize).append(", elemSize ").append(bufferElemSize).append(", ").append(buffer).append("]");
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
index 27ce7d8ec..dc96cb5f2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
@@ -48,9 +48,16 @@ import com.jogamp.opengl.util.glsl.ShaderState;
* </p>
*/
public class ImmModeSink {
- protected static final boolean DEBUG_BEGIN_END = Debug.isPropertyDefined("jogl.debug.ImmModeSink.BeginEnd", true);
- protected static final boolean DEBUG_DRAW = Debug.isPropertyDefined("jogl.debug.ImmModeSink.Draw", true);
- protected static final boolean DEBUG_BUFFER = Debug.isPropertyDefined("jogl.debug.ImmModeSink.Buffer", true);
+ protected static final boolean DEBUG_BEGIN_END;
+ protected static final boolean DEBUG_DRAW;
+ protected static final boolean DEBUG_BUFFER;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_BEGIN_END = Debug.isPropertyDefined("jogl.debug.ImmModeSink.BeginEnd", true);
+ DEBUG_DRAW = Debug.isPropertyDefined("jogl.debug.ImmModeSink.Draw", true);
+ DEBUG_BUFFER = Debug.isPropertyDefined("jogl.debug.ImmModeSink.Buffer", true);
+ }
public static final int GL_QUADS = 0x0007; // Needs data manipulation on ES1/ES2
public static final int GL_QUAD_STRIP = 0x0008;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index bfc03d019..58151856f 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -488,7 +488,7 @@ public class PMVMatrix implements GLMatrixFunc {
if(matrixGetName==GL_MATRIX_MODE) {
params.put((float)matrixMode);
} else {
- FloatBuffer matrix = glGetMatrixf(matrixGetName);
+ final FloatBuffer matrix = glGetMatrixf(matrixGetName);
params.put(matrix); // matrix -> params
matrix.reset();
}
@@ -500,7 +500,7 @@ public class PMVMatrix implements GLMatrixFunc {
if(matrixGetName==GL_MATRIX_MODE) {
params[params_offset]=(float)matrixMode;
} else {
- FloatBuffer matrix = glGetMatrixf(matrixGetName);
+ final FloatBuffer matrix = glGetMatrixf(matrixGetName);
matrix.get(params, params_offset, 16); // matrix -> params
matrix.reset();
}
@@ -619,15 +619,15 @@ public class PMVMatrix implements GLMatrixFunc {
@Override
public final void glMultMatrixf(final FloatBuffer m) {
if(matrixMode==GL_MODELVIEW) {
- FloatUtil.multMatrixf(matrixMv, m, matrixMv);
+ FloatUtil.multMatrixf(matrixMv, m);
dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
- FloatUtil.multMatrixf(matrixP, m, matrixP);
+ FloatUtil.multMatrixf(matrixP, m);
dirtyBits |= DIRTY_FRUSTUM ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
- FloatUtil.multMatrixf(matrixTex, m, matrixTex);
+ FloatUtil.multMatrixf(matrixTex, m);
modifiedBits |= MODIFIED_TEXTURE;
}
}
@@ -635,15 +635,15 @@ public class PMVMatrix implements GLMatrixFunc {
@Override
public final void glMultMatrixf(float[] m, int m_offset) {
if(matrixMode==GL_MODELVIEW) {
- FloatUtil.multMatrixf(matrixMv, m, m_offset, matrixMv);
+ FloatUtil.multMatrixf(matrixMv, m, m_offset);
dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
- FloatUtil.multMatrixf(matrixP, m, m_offset, matrixP);
+ FloatUtil.multMatrixf(matrixP, m, m_offset);
dirtyBits |= DIRTY_FRUSTUM ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
- FloatUtil.multMatrixf(matrixTex, m, m_offset, matrixTex);
+ FloatUtil.multMatrixf(matrixTex, m, m_offset);
modifiedBits |= MODIFIED_TEXTURE;
}
}
@@ -813,8 +813,8 @@ public class PMVMatrix implements GLMatrixFunc {
float[] win_pos, int win_pos_offset ) {
if(usesBackingArray) {
return projectFloat.gluProject(objx, objy, objz,
- matrixMv.array(), 0,
- matrixP.array(), 0,
+ matrixMv.array(), matrixMv.position(),
+ matrixP.array(), matrixP.position(),
viewport, viewport_offset,
win_pos, win_pos_offset);
} else {
@@ -843,8 +843,8 @@ public class PMVMatrix implements GLMatrixFunc {
float[] obj_pos, int obj_pos_offset) {
if(usesBackingArray) {
return projectFloat.gluUnProject(winx, winy, winz,
- matrixMv.array(), 0,
- matrixP.array(), 0,
+ matrixMv.array(), matrixMv.position(),
+ matrixP.array(), matrixP.position(),
viewport, viewport_offset,
obj_pos, obj_pos_offset);
} else {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
index aceb609a1..df1bbdf26 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
@@ -109,7 +109,7 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
super.dispose();
}
- public StringBuffer toString(StringBuffer sb) {
+ public StringBuilder toString(StringBuilder sb) {
sb = super.toString(sb);
sb.append(", allowRowStride ").append(allowRowStride).append(", image [").append(image.getWidth()).append("x").append(image.getHeight()).append(", ").append(image.toString()).append("]");
return sb;
@@ -225,4 +225,4 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
}
}
}
-} \ No newline at end of file
+}
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 1735fcddd..c67141525 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
@@ -128,7 +128,12 @@ import jogamp.opengl.Debug;
@author Kenneth Russell
*/
public class TextRenderer {
- private static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.TextRenderer", true);
+ private static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.isPropertyDefined("jogl.debug.TextRenderer", true);
+ }
// These are occasionally useful for more in-depth debugging
private static final boolean DISABLE_GLYPH_CACHE = false;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
index 968391976..8e7781f07 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
@@ -55,8 +55,13 @@ import com.jogamp.opengl.util.GLArrayDataEditable;
* and can be retrieved via {@link #getShaderState(GL)}.
* </p>
*/
-public class ShaderState {
- public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true);
+public class ShaderState {
+ public static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true);
+ }
public ShaderState() {
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
index 7d110659a..d18fd4bae 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
@@ -221,7 +221,7 @@ public class ShaderUtil {
/** Returns true if GeometryShader is supported, i.e. whether GLContext is &ge; 3.2 or ARB_geometry_shader4 extension is available. */
public static boolean isGeometryShaderSupported(GL _gl) {
final GLContext ctx = _gl.getContext();
- return ctx.getGLVersionNumber().compareTo(GLContext.Version32) >= 0 ||
+ return ctx.getGLVersionNumber().compareTo(GLContext.Version320) >= 0 ||
ctx.isExtensionAvailable(GLExtensions.ARB_geometry_shader4);
}
@@ -249,10 +249,10 @@ public class ShaderUtil {
for(int i = source.length - 1; i>=0; i--) {
final CharSequence csq = source[i];
if(csq instanceof String) {
- // if ShaderCode.create(.. mutableStringBuffer == false )
+ // if ShaderCode.create(.. mutableStringBuilder == false )
tmp[i] = (String) csq;
} else {
- // if ShaderCode.create(.. mutableStringBuffer == true )
+ // if ShaderCode.create(.. mutableStringBuilder == true )
tmp[i] = source[i].toString();
}
}
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 bf85bea87..f2ef3ac25 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
@@ -52,18 +52,32 @@ import com.jogamp.opengl.util.texture.spi.*;
* Represents an OpenGL texture object. Contains convenience routines
* for enabling/disabling OpenGL texture state, binding this texture,
* and computing texture coordinates for both the entire image as well
- * as a sub-image.
+ * as a sub-image.
+ *
+ * <a name="textureCallOrder"><h5>Order of Texture Commands</h5></a>
+ * <p>
+ * Due to many confusions w/ texture usage, following list described the order
+ * and semantics of texture unit selection, binding and enabling.
+ * <ul>
+ * <li><i>Optional:</i> Set active textureUnit via <code>gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit)</code>, <code>0</code> is default.</li>
+ * <li>Bind <code>textureId</code> -> active <code>textureUnit</code>'s <code>textureTarget</code> via <code>gl.glBindTexture(textureTarget, textureId)</code></li>
+ * <li><i>Compatible Context Only:</i> Enable active <code>textureUnit</code>'s <code>textureTarget</code> via <code>glEnable(textureTarget)</code>.
+ * <li><i>Optional:</i> Fiddle with the texture parameters and/or environment settings.</li>
+ * <li>GLSL: Use <code>textureUnit</code> in your shader program, enable shader program.</li>
+ * <li>Issue draw commands</li>
+ * </ul>
+ * </p>
*
* <p><a name="nonpow2"><b>Non-power-of-two restrictions</b></a>
* <br> When creating an OpenGL texture object, the Texture class will
- * attempt to leverage the <a
- * href="http://www.opengl.org/registry/specs/ARB/texture_non_power_of_two.txt">GL_ARB_texture_non_power_of_two</a>
- * and <a
- * href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a>
- * extensions (in that order) whenever possible. If neither extension
- * is available, the Texture class will simply upload a non-pow2-sized
+ * attempt to use <i>non-power-of-two textures</i> (NPOT) if available, see {@link GL#isNPOTTextureAvailable()}.
+ * Further more,
+ * <a href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a>
+ * (RECT) will be attempted on OSX w/ ATI drivers.
+ * If NPOT is not available or RECT not chosen, the Texture class will simply upload a non-pow2-sized
* image into a standard pow2-sized texture (without any special
- * scaling). Since the choice of extension (or whether one is used at
+ * scaling).
+ * Since the choice of extension (or whether one is used at
* all) depends on the user's machine configuration, developers are
* recommended to use {@link #getImageTexCoords} and {@link
* #getSubImageTexCoords}, as those methods will calculate the
@@ -91,16 +105,24 @@ import com.jogamp.opengl.util.texture.spi.*;
* when switching between textures it is necessary to call {@link
* #bind}, but when drawing many triangles all using the same texture,
* for best performance only one call to {@link #bind} should be made.
+ * User may also utilize multiple texture units,
+ * see <a href="#textureCallOrder"> order of texture commands above</a>.
*
* <p><a name="premult"><b>Alpha premultiplication and blending</b></a>
- * <br> The mathematically correct way to perform blending in OpenGL
- * (with the SrcOver "source over destination" mode, or any other
- * Porter-Duff rule) is to use "premultiplied color components", which
- * means the R/G/ B color components have already been multiplied by
- * the alpha value. To make things easier for developers, the Texture
- * class will automatically convert non-premultiplied image data into
- * premultiplied data when storing it into an OpenGL texture. As a
- * result, it is important to use the correct blending function; for
+ * <p>
+ * <i>Disclaimer: Consider performing alpha premultiplication in shader code, if really desired! Otherwise use RGBA.</i><br/>
+ * </p>
+ * <p>
+ * The Texture class does not convert RGBA image data into
+ * premultiplied data when storing it into an OpenGL texture.
+ * </p>
+ * <p>
+ * The mathematically correct way to perform blending in OpenGL
+ * with the SrcOver "source over destination" mode, or any other
+ * Porter-Duff rule, is to use <i>premultiplied color components</i>,
+ * which means the R/G/ B color components must have been multiplied by
+ * the alpha value. If using <i>premultiplied color components</i>
+ * it is important to use the correct blending function; for
* example, the SrcOver rule is expressed as:
<pre>
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
@@ -138,9 +160,7 @@ import com.jogamp.opengl.util.texture.spi.*;
<TR> <TD> AlphaXor <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA
</TABLE>
</CENTER>
- *
- * @author Chris Campbell
- * @author Kenneth Russell
+ * @author Chris Campbell, Kenneth Russell, et.al.
*/
public class Texture {
/** The GL target type. */
@@ -207,12 +227,13 @@ public class Texture {
* Enables this texture's target (e.g., GL_TEXTURE_2D) in the
* given GL context's state. This method is a shorthand equivalent
* of the following OpenGL code:
- <pre>
- gl.glEnable(texture.getTarget());
- </pre>
- *
+ * <pre>
+ * gl.glEnable(texture.getTarget());
+ * </pre>
* <p>
- * Call is ignored if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
+ * Call is ignored if the {@link GL} object's context
+ * is using a core profile, see {@link GL#isGLcore()},
+ * or if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
* </p>
* <p>
* See the <a href="#perftips">performance tips</a> above for hints
@@ -224,7 +245,7 @@ public class Texture {
* OpenGL-related errors occurred
*/
public void enable(GL gl) throws GLException {
- if(GLES2.GL_TEXTURE_EXTERNAL_OES != target) {
+ if( !gl.isGLcore() && GLES2.GL_TEXTURE_EXTERNAL_OES != target) {
gl.glEnable(target);
}
}
@@ -233,12 +254,13 @@ public class Texture {
* Disables this texture's target (e.g., GL_TEXTURE_2D) in the
* given GL state. This method is a shorthand equivalent
* of the following OpenGL code:
- <pre>
- gl.glDisable(texture.getTarget());
- </pre>
- *
+ * <pre>
+ * gl.glDisable(texture.getTarget());
+ * </pre>
* <p>
- * Call is ignored if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
+ * Call is ignored if the {@link GL} object's context
+ * is using a core profile, see {@link GL#isGLcore()},
+ * or if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
* </p>
* <p>
* See the <a href="#perftips">performance tips</a> above for hints
@@ -250,7 +272,7 @@ public class Texture {
* OpenGL-related errors occurred
*/
public void disable(GL gl) throws GLException {
- if(GLES2.GL_TEXTURE_EXTERNAL_OES != target) {
+ if( !gl.isGLcore() && GLES2.GL_TEXTURE_EXTERNAL_OES != target ) {
gl.glDisable(target);
}
}
@@ -275,12 +297,6 @@ public class Texture {
}
/**
- * @deprecated use {@link #destroy(GL)}
- */
- public final void dispose(GL gl) throws GLException {
- destroy(gl);
- }
- /**
* Destroys the native resources used by this texture object.
*
* @throws GLException if any OpenGL-related errors occurred
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 6b41c0bc8..9f951d5da 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -75,7 +75,7 @@ import javax.media.opengl.GL;
// in case a fixed lookup function is being chosen, replace the name in our code
rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
- // Cache the TextureSequence shader details in StringBuffer:
+ // Cache the TextureSequence shader details in StringBuilder:
final StringBuilder sFpIns = new StringBuilder();
// .. declaration of the texture sampler using the implementation specific type
@@ -217,4 +217,4 @@ public interface TextureSequence {
* @throws IllegalStateException if instance is not initialized
*/
public String getTextureLookupFragmentShaderImpl() throws IllegalStateException ;
-} \ No newline at end of file
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
index b4b00e744..93d37029e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
@@ -177,7 +177,8 @@ public class PNGImage {
}
if(DEBUG) {
System.err.println("PNGImage: "+imgInfo);
- System.err.println("PNGImage: indexed "+indexed+", alpha "+hasAlpha+", channels "+channels+", bytesPerPixel "+bytesPerPixel+
+ System.err.println("PNGImage: indexed "+indexed+", alpha "+hasAlpha+", channels "+channels+"/"+imgInfo.channels+
+ ", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+
", pixels "+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+"x"+dpi[1]+", glFormat 0x"+Integer.toHexString(glFormat));
}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL2.java b/src/jogl/classes/javax/media/opengl/DebugGL2.java
new file mode 100644
index 000000000..05bcf3d5e
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL2.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL2 extends DebugGL4bc {
+ public DebugGL2(GL2 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL3.java b/src/jogl/classes/javax/media/opengl/DebugGL3.java
new file mode 100644
index 000000000..c17f90667
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL3.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL3 extends DebugGL4bc {
+ public DebugGL3(GL3 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL3bc.java b/src/jogl/classes/javax/media/opengl/DebugGL3bc.java
new file mode 100644
index 000000000..6e294d42b
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL3bc.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL3bc extends DebugGL4bc {
+ public DebugGL3bc(GL3bc downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL4.java b/src/jogl/classes/javax/media/opengl/DebugGL4.java
new file mode 100644
index 000000000..d21d39390
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL4.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL4 extends DebugGL4bc {
+ public DebugGL4(GL4 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGLES2.java b/src/jogl/classes/javax/media/opengl/DebugGLES2.java
new file mode 100644
index 000000000..dee363c1b
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGLES2.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGLES2 extends DebugGLES3 {
+ public DebugGLES2(GLES2 downstream) {
+ super((GLES3)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
index b052769ca..b0f3da8e4 100644
--- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
+++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
@@ -85,8 +85,13 @@ import jogamp.opengl.Debug;
*/
public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
- private static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.CapabilitiesChooser", true);
+ private static final boolean DEBUG;
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.isPropertyDefined("jogl.debug.CapabilitiesChooser", true);
+ }
+
private final static int NO_SCORE = -9999999;
private final static int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000;
private final static int OPAQUE_MISMATCH_PENALTY = 750;
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index 74c1b9609..f1853351f 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -88,35 +88,41 @@ public interface GLBase {
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 4.0 compatibility profile.
* The GL4 compatibility profile includes the GL2, GL2ES1, GL2ES2, GL3, GL3bc and GL4 profile.
+ * @see GLContext#isGL4bc()
*/
public boolean isGL4bc();
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 4.0 core profile.
* The GL4 core profile includes the GL2ES2, and GL3 profile.
+ * @see GLContext#isGL4()
*/
public boolean isGL4();
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 3.1 compatibility profile.
* The GL3 compatibility profile includes the GL2, GL2ES1, GL2ES2 and GL3 profile.
+ * @see GLContext#isGL3bc()
*/
public boolean isGL3bc();
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 3.1 core profile.
* The GL3 core profile includes the GL2ES2 profile.
+ * @see GLContext#isGL3()
*/
public boolean isGL3();
/**
* Indicates whether this GL object conforms to the OpenGL &le; 3.0 profile.
* The GL2 profile includes the GL2ES1 and GL2ES2 profile.
+ * @see GLContext#isGL2()
*/
public boolean isGL2();
/**
* Indicates whether this GL object conforms to the OpenGL ES1 &ge; 1.0 profile.
+ * @see GLContext#isGLES1()
*/
public boolean isGLES1();
@@ -127,103 +133,205 @@ public interface GLBase {
* To query whether core ES2 functionality is provided, use {@link #isGLES2Compatible()}.
* </p>
* @see #isGLES2Compatible()
+ * @see GLContext#isGLES2()
*/
public boolean isGLES2();
/**
+ * Indicates whether this GL object conforms to the OpenGL ES2 &ge; 3.0 profile.
+ * <p>
+ * Remark: ES3 compatible desktop profiles are not included.
+ * To query whether core ES3 functionality is provided, use {@link #isGLES3Compatible()}.
+ * </p>
+ * @see #isGLES3Compatible()
+ * @see GLContext#isGLES3()
+ */
+ public boolean isGLES3();
+
+ /**
* Indicates whether this GL object conforms to one of the OpenGL ES profiles,
* see {@link #isGLES1()} and {@link #isGLES2()}.
+ * @see GLContext#isGLES()
*/
public boolean isGLES();
/**
* Indicates whether this GL object conforms to a GL2ES1 compatible profile.
+ * @see GLContext#isGL2ES1()
*/
public boolean isGL2ES1();
/**
* Indicates whether this GL object conforms to a GL2ES2 compatible profile.
+ * @see GLContext#isGL2ES2()
*/
public boolean isGL2ES2();
/**
+ * Indicates whether this GL object conforms to a GL3ES3 compatible profile.
+ * @see GLContext#isGL3ES3()
+ */
+ public boolean isGL3ES3();
+
+ /**
+ * Returns true if this GL object conforms to a GL4ES3 compatible profile, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLContext#isGL4ES3()
+ */
+ public boolean isGL4ES3();
+
+ /**
+ * Indicates whether this GL object conforms to a GL2GL3 compatible profile.
+ * @see GLContext#isGL2GL3()
+ */
+ public boolean isGL2GL3();
+
+ /**
+ * Indicates whether this GL object uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ * @see GLContext#isGL4core()
+ */
+ public boolean isGL4core();
+
+ /**
+ * Indicates whether this GL object uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ * @see GLContext#isGL3core()
+ */
+ public boolean isGL3core();
+
+ /**
+ * Indicates whether this GL object uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GL2ES2 ].</p>
+ * @see GLContext#isGLcore()
+ */
+ public boolean isGLcore();
+
+ /**
* Indicates whether this GL object is compatible with the core OpenGL ES2 functionality.
* @return true if this context is an ES2 context or implements
- * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * @see GLContext#isGLES2Compatible()
*/
public boolean isGLES2Compatible();
/**
- * Indicates whether this GL object conforms to a GL2GL3 compatible profile.
+ * Indicates whether this GL object is compatible with the core OpenGL ES3 functionality.
+ * <p>
+ * Return true if the underlying context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * </p>
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ * @see GLContext#isGLES3Compatible()
*/
- public boolean isGL2GL3();
+ public boolean isGLES3Compatible();
- /** Indicates whether this GL object supports GLSL. */
+ /**
+ * Indicates whether this GL object supports GLSL.
+ * @see GLContext#hasGLSL()
+ */
public boolean hasGLSL();
/**
+ * Returns the downstream GL instance in case this is a wrapping pipeline, otherwise <code>null</code>.
+ * <p>
+ * See {@link #getRootGL()} for retrieving the implementing root instance.
+ * </p>
+ * @throws GLException if the downstream instance is not null and not a GL implementation
+ * @see #getRootGL()
+ */
+ public GL getDownstreamGL() throws GLException;
+
+ /**
+ * Returns the implementing root instance, considering a wrapped pipelined hierarchy, see {@link #getDownstreamGL()}.
+ * <p>
+ * If this instance is not a wrapping pipeline, i.e. has no downstream instance,
+ * this instance is returned.
+ * </p>
+ * @throws GLException if the root instance is not a GL implementation
+ */
+ public GL getRootGL() throws GLException;
+
+ /**
* Casts this object to the GL interface.
- * @throws GLException if this GLObject is not a GL implementation
+ * @throws GLException if this object is not a GL implementation
*/
public GL getGL() throws GLException;
/**
* Casts this object to the GL4bc interface.
- * @throws GLException if this GLObject is not a GL4bc implementation
+ * @throws GLException if this object is not a GL4bc implementation
*/
public GL4bc getGL4bc() throws GLException;
/**
* Casts this object to the GL4 interface.
- * @throws GLException if this GLObject is not a GL4 implementation
+ * @throws GLException if this object is not a GL4 implementation
*/
public GL4 getGL4() throws GLException;
/**
* Casts this object to the GL3bc interface.
- * @throws GLException if this GLObject is not a GL3bc implementation
+ * @throws GLException if this object is not a GL3bc implementation
*/
public GL3bc getGL3bc() throws GLException;
/**
* Casts this object to the GL3 interface.
- * @throws GLException if this GLObject is not a GL3 implementation
+ * @throws GLException if this object is not a GL3 implementation
*/
public GL3 getGL3() throws GLException;
/**
* Casts this object to the GL2 interface.
- * @throws GLException if this GLObject is not a GL2 implementation
+ * @throws GLException if this object is not a GL2 implementation
*/
public GL2 getGL2() throws GLException;
/**
* Casts this object to the GLES1 interface.
- * @throws GLException if this GLObject is not a GLES1 implementation
+ * @throws GLException if this object is not a GLES1 implementation
*/
public GLES1 getGLES1() throws GLException;
/**
* Casts this object to the GLES2 interface.
- * @throws GLException if this GLObject is not a GLES2 implementation
+ * @throws GLException if this object is not a GLES2 implementation
*/
public GLES2 getGLES2() throws GLException;
/**
+ * Casts this object to the GLES3 interface.
+ * @throws GLException if this object is not a GLES3 implementation
+ */
+ public GLES3 getGLES3() throws GLException;
+
+ /**
* Casts this object to the GL2ES1 interface.
- * @throws GLException if this GLObject is not a GL2ES1 implementation
+ * @throws GLException if this object is not a GL2ES1 implementation
*/
public GL2ES1 getGL2ES1() throws GLException;
/**
* Casts this object to the GL2ES2 interface.
- * @throws GLException if this GLObject is not a GL2ES2 implementation
+ * @throws GLException if this object is not a GL2ES2 implementation
*/
public GL2ES2 getGL2ES2() throws GLException;
/**
+ * Casts this object to the GL3ES3 interface.
+ * @throws GLException if this object is not a GL3ES3 implementation
+ */
+ public GL3ES3 getGL3ES3() throws GLException;
+
+ /**
+ * Casts this object to the GL4ES3 interface.
+ * @throws GLException if this object is not a GL4ES3 implementation
+ */
+ public GL4ES3 getGL4ES3() throws GLException;
+
+ /**
* Casts this object to the GL2GL3 interface.
- * @throws GLException if this GLObject is not a GL2GL3 implementation
+ * @throws GLException if this object is not a GL2GL3 implementation
*/
public GL2GL3 getGL2GL3() throws GLException;
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index abafabb1c..aa5fca2c2 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -42,7 +42,7 @@ package javax.media.opengl;
import java.nio.IntBuffer;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Set;
@@ -73,6 +73,10 @@ import com.jogamp.opengl.GLRendererQuirks;
refer to a given context. */
public abstract class GLContext {
+ public static final boolean DEBUG = Debug.debug("GLContext");
+ public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
+ public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;
+
/**
* If <code>true</code> (default), bootstrapping the available GL profiles
* will use the highest compatible GL context for each profile,
@@ -102,10 +106,6 @@ public abstract class GLContext {
protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true);
protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true);
- public static final boolean DEBUG = Debug.debug("GLContext");
- public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
- public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;
-
/** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
public static final boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
/** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */
@@ -131,17 +131,30 @@ public abstract class GLContext {
/* Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
public static final VersionNumber Version150 = new VersionNumber(1, 50, 0);
- /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
- public static final VersionNumber Version32 = new VersionNumber(3, 2, 0);
+ /** Version 3.0. As an OpenGL version, it qualifies for desktop {@link #isGL2()} only, or ES 3.0. */
+ public static final VersionNumber Version300 = new VersionNumber(3, 0, 0);
/** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
- public static final VersionNumber Version31 = new VersionNumber(3, 1, 0);
+ public static final VersionNumber Version310 = new VersionNumber(3, 1, 0);
- /** Version 3.0. As an OpenGL version, it qualifies for {@link #isGL2()} only */
- public static final VersionNumber Version30 = new VersionNumber(3, 0, 0);
+ /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
+ public static final VersionNumber Version320 = new VersionNumber(3, 2, 0);
+
+ /** Version 4.3. As an OpenGL version, it qualifies for <code>GL_ARB_ES3_compatibility</code> */
+ public static final VersionNumber Version430 = new VersionNumber(4, 3, 0);
- protected static final VersionNumber Version80 = new VersionNumber(8, 0, 0);
+ protected static final VersionNumber Version800 = new VersionNumber(8, 0, 0);
+ //
+ // Cached keys, bits [0..15]
+ //
+
+ /** Context option bits, full bit mask covering bits [0..15], i.e. <code>0x0000FFFF</code>, {@value}. */
+ protected static final int CTX_IMPL_FULL_MASK = 0x0000FFFF;
+
+ /** Context option bits, cached bit mask covering 9 bits [0..8], i.e. <code>0x000001FF</code>, {@value}. Leaving 7 bits for non cached options, i.e. 9:7. */
+ protected static final int CTX_IMPL_CACHE_MASK = 0x000001FF;
+
/** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
/** <code>ARB_create_context</code> related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
@@ -154,20 +167,36 @@ public abstract class GLContext {
protected static final int CTX_OPTION_FORWARD = 1 << 4;
/** <code>ARB_create_context</code> related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
+ /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 6;
+ //
+ // Non cached keys, bits [9..15]
+ //
+
/** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
- protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
+ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 9;
- /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
+ /** <code>GL_ARB_ES3_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES3Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ES3_COMPAT = 1 << 10;
+
+ /**
+ * Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
* Not a cache key.
* @see #hasBasicFBOSupport()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
*/
- protected static final int CTX_IMPL_FBO = 1 << 9;
-
- /** 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 int CTX_IMPL_FBO = 1 << 11;
+ /**
+ * Context supports <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points,
+ * see {@link #hasFP32CompatAPI()}.
+ * Not a cache key.
+ * @see #hasFP32CompatAPI()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 12;
+
private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
@@ -481,6 +510,17 @@ public abstract class GLContext {
public abstract void destroy();
/**
+ * Returns the implementing root GL instance of this GLContext's GL object,
+ * considering a wrapped pipelined hierarchy, see {@link GLBase#getDownstreamGL()}.
+ * @throws GLException if the root instance is not a GL implementation
+ * @see GLBase#getRootGL()
+ * @see GLBase#getDownstreamGL()
+ * @see #getGL()
+ * @see #setGL(GL)
+ */
+ public abstract GL getRootGL();
+
+ /**
* Returns the GL pipeline object for this GLContext.
*
* @return the aggregated GL instance, or null if this context was not yet made current.
@@ -671,10 +711,6 @@ public abstract class GLContext {
return ctxVersionString;
}
- /** @deprecated Use {@link #getGLVersionNumber()} */
- public final int getGLVersionMajor() { return ctxVersion.getMajor(); }
- /** @deprecated Use {@link #getGLVersionNumber()} */
- public final int getGLVersionMinor() { return ctxVersion.getMinor(); }
/**
* Returns this context OpenGL version.
* @see #getGLSLVersionNumber()
@@ -729,9 +765,19 @@ public abstract class GLContext {
/**
* Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
- * i.e.:
+ * i.e. for desktop
* <pre>
* #version 110
+ * ..
+ * #version 150
+ * #version 330
+ * ...
+ * </pre>
+ * And for ES:
+ * <pre>
+ * #version 100
+ * #version 300 es
+ * ..
* </pre>
* <p>
* If context has not been made current yet, a string of zero length is returned.
@@ -743,14 +789,17 @@ public abstract class GLContext {
return "";
}
final int minor = ctxGLSLVersion.getMinor();
- return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + "\n" ;
+ final String esSuffix = isGLES() && ctxGLSLVersion.compareTo(Version300) >= 0 ? " es" : "";
+ return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + esSuffix + "\n" ;
}
protected static final VersionNumber getStaticGLSLVersionNumber(int glMajorVersion, int glMinorVersion, int ctxOptions) {
if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
- return Version100; // ES 2.0 -> GLSL 1.00
+ if( 3 > glMajorVersion ) {
+ return Version100; // ES 2.0 -> GLSL 1.00
+ }
} else if( 1 == glMajorVersion ) {
- return Version110; // GL 1.x -> GLSL 1.10
+ return Version110; // GL 1.x -> GLSL 1.10
} else if( 2 == glMajorVersion ) {
switch ( glMinorVersion ) {
case 0: return Version110; // GL 2.0 -> GLSL 1.10
@@ -758,21 +807,32 @@ public abstract class GLContext {
}
} else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
switch ( glMinorVersion ) {
- case 0: return Version130; // GL 3.0 -> GLSL 1.30
- case 1: return Version140; // GL 3.1 -> GLSL 1.40
- default: return Version150; // GL 3.2 -> GLSL 1.50
+ case 0: return Version130; // GL 3.0 -> GLSL 1.30
+ case 1: return Version140; // GL 3.1 -> GLSL 1.40
+ default: return Version150; // GL 3.2 -> GLSL 1.50
}
- } else { // >= 3.3
- return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N -> GLSL M.N
}
+ // The new default: GL >= 3.3, ES >= 3.0
+ return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N -> GLSL M.N
}
/**
* @return true if this context is an ES2 context or implements
- * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * the extension <code>GL_ARB_ES3_compatibility</code> or <code>GL_ARB_ES2_compatibility</code>, otherwise false
*/
public final boolean isGLES2Compatible() {
- return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
+ return 0 != ( ctxOptions & ( CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ) ) ;
+ }
+
+ /**
+ * Return true if this context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public final boolean isGLES3Compatible() {
+ return 0 != ( ctxOptions & CTX_IMPL_ES3_COMPAT ) ;
}
/**
@@ -811,6 +871,15 @@ public abstract class GLContext {
}
/**
+ * Returns <code>true</code> if <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points available,
+ * otherwise <code>false</code>.
+ * @see #CTX_IMPL_FP32_COMPAT_API
+ */
+ public final boolean hasFP32CompatAPI() {
+ return 0 != ( ctxOptions & CTX_IMPL_FP32_COMPAT_API ) ;
+ }
+
+ /**
* Returns <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
@@ -866,78 +935,198 @@ public abstract class GLContext {
isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
- /** @see GLProfile#isGL4bc() */
+ /**
+ * Indicates whether this GLContext is capable of GL4bc. <p>Includes [ GL4bc ].</p>
+ * @see GLProfile#isGL4bc()
+ */
public final boolean isGL4bc() {
- return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.getMajor() >= 4;
}
- /** @see GLProfile#isGL4() */
+ /**
+ * Indicates whether this GLContext is capable of GL4. <p>Includes [ GL4bc, GL4 ].</p>
+ * @see GLProfile#isGL4()
+ */
public final boolean isGL4() {
- return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.getMajor() >= 4;
}
- /** Indicates whether this profile is capable of GL4 (core only). <p>Includes [ GL4 ].</p> */
+ /**
+ * Indicates whether this GLContext uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ */
public final boolean isGL4core() {
- return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_CORE);
+ return 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.getMajor() >= 4;
}
- /** @see GLProfile#isGL3bc() */
+ /**
+ * Indicates whether this GLContext is capable of GL3bc. <p>Includes [ GL4bc, GL3bc ].</p>
+ * @see GLProfile#isGL3bc()
+ */
public final boolean isGL3bc() {
- return ctxVersion.compareTo(Version31) >= 0
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.compareTo(Version310) >= 0 ;
}
- /** @see GLProfile#isGL3() */
+ /**
+ * Indicates whether this GLContext is capable of GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3 ].</p>
+ * @see GLProfile#isGL3()
+ */
public final boolean isGL3() {
- return ctxVersion.compareTo(Version31) >= 0
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
- }
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.compareTo(Version310) >= 0 ;
+ }
- /** Indicates whether this profile is capable of GL3 (core only). GL3 starts w/ OpenGL 3.1 <p>Includes [ GL4, GL3 ].</p> */
+ /**
+ * Indicates whether this GLContext uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ */
public final boolean isGL3core() {
- return ctxVersion.compareTo(Version31) >= 0
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_CORE);
+ return 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GL2ES2 ].</p>
+ */
+ public final boolean isGLcore() {
+ return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ) ||
+ ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0
+ ) ;
+ }
+
+ /**
+ * Indicates whether this GLContext's native profile does not implement a default <i>vertex array object</i> (VAO),
+ * starting w/ OpenGL 3.1 core and GLES3.
+ * <p>Includes [ GL4, GL3, GLES3 ].</p>
+ * <pre>
+ Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
+ GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
+ there is no more default VAO buffer 0 bound, hence generating and binding one
+ to avoid INVALID_OPERATION at VertexAttribPointer.
+ More clear is GL 4.3 core spec: 10.4 (p 307).
+ * </pre>
+ * <pre>
+ GLES3 is included, since upcoming ES releases &gt; 3.0 may behave the same:
+ GL ES 3.0 spec F.1. Legacy Features (p 322).
+ * </pre>
+ * <p>
+ * If no default VAO is implemented in the native OpenGL profile,
+ * an own default VAO is being used, see {@link #getDefaultVAO()}.
+ * </p>
+ * @see #getDefaultVAO()
+ */
+ public final boolean hasNoDefaultVAO() {
+ return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ) ||
+ ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0
+ ) ;
}
- /** @see GLProfile#isGL2() */
+ /**
+ * If this GLContext does not implement a default VAO, see {@link #hasNoDefaultVAO()},
+ * an <i>own default VAO</i> will be created and bound at context creation.
+ * <p>
+ * If this GLContext does implement a default VAO, i.e. {@link #hasNoDefaultVAO()}
+ * returns <code>false</code>, this method returns <code>0</code>.
+ * </p>
+ * <p>
+ * Otherwise this method returns the VAO object name
+ * representing this GLContext's <i>own default VAO</i>.
+ * </p>
+ * @see #hasNoDefaultVAO()
+ */
+ public abstract int getDefaultVAO();
+
+ /**
+ * Indicates whether this GLContext is capable of GL2. <p>Includes [ GL4bc, GL3bc, GL2 ].</p>
+ * @see GLProfile#isGL2()
+ */
public final boolean isGL2() {
- return ctxVersion.getMajor()>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != ( ctxOptions & CTX_PROFILE_COMPAT ) && ctxVersion.getMajor()>=1 ;
}
- /** @see GLProfile#isGL2GL3() */
+ /**
+ * Indicates whether this GLContext is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2GL3()
+ */
public final boolean isGL2GL3() {
return isGL2() || isGL3();
}
- /** @see GLProfile#isGLES1() */
+ /**
+ * Indicates whether this GLContext is capable of GLES1. <p>Includes [ GLES1 ].</p>
+ * @see GLProfile#isGLES1()
+ */
public final boolean isGLES1() {
- return ctxVersion.getMajor() == 1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 1 ;
}
- /** @see GLProfile#isGLES2() */
+ /**
+ * Indicates whether this GLContext is capable of GLES2. <p>Includes [ GLES3, GLES2 ].</p>
+ * @see GLProfile#isGLES2()
+ */
public final boolean isGLES2() {
- return ctxVersion.getMajor() == 2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES3. <p>Includes [ GLES3 ].</p>
+ * @see GLProfile#isGLES3()
+ */
+ public final boolean isGLES3() {
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ;
}
- /** @see GLProfile#isGLES() */
+ /**
+ * Indicates whether this GLContext is capable of GLES. <p>Includes [ GLES3, GLES1, GLES2 ].</p>
+ * @see GLProfile#isGLES()
+ */
public final boolean isGLES() {
return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
}
- /** @see GLProfile#isGL2ES1() */
+ /**
+ * Indicates whether this GLContext is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p>
+ * @see GLProfile#isGL2ES1()
+ */
public final boolean isGL2ES1() {
- return isGL2() || isGLES1() ;
+ return isGLES1() || isGL2();
}
- /** @see GLProfile#isGL2ES2() */
+ /**
+ * Indicates whether this GLContext is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p>
+ * @see GLProfile#isGL2ES2()
+ */
public final boolean isGL2ES2() {
- return isGL2GL3() || isGLES2() ;
+ return isGLES2() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p>
+ * @see GLProfile#isGL3ES3()
+ */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
+ }
+
+ /**
+ * Returns true if this profile is capable of GL4ES3, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLProfile#isGL4ES3()
+ */
+ public final boolean isGL4ES3() {
+ return isGLES3Compatible() ;
}
/**
@@ -1148,38 +1337,73 @@ public abstract class GLContext {
/* 1.*/ { 0, 1, 2, 3, 4, 5 },
/* 2.*/ { 0, 1 },
/* 3.*/ { 0, 1, 2, 3 },
- /* 4.*/ { 0, 1, 2 } };
+ /* 4.*/ { 0, 1, 2, 3 } };
+
+ public static final int ES_VERSIONS[][] = {
+ /* 0.*/ { -1 },
+ /* 1.*/ { 0, 1 },
+ /* 2.*/ { 0 },
+ /* 3.*/ { 0 } };
- public static final int getMaxMajor() {
- return GL_VERSIONS.length-1;
+ public static final int getMaxMajor(int ctxProfile) {
+ return ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ? ES_VERSIONS.length-1 : GL_VERSIONS.length-1;
}
- public static final int getMaxMinor(int major) {
- if(1>major || major>=GL_VERSIONS.length) return -1;
- return GL_VERSIONS[major].length-1;
+ public static final int getMaxMinor(int ctxProfile, int major) {
+ if( 1>major ) {
+ return -1;
+ }
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
+ if( major>=ES_VERSIONS.length ) return -1;
+ return ES_VERSIONS[major].length-1;
+ } else {
+ if( major>=GL_VERSIONS.length ) return -1;
+ return GL_VERSIONS[major].length-1;
+ }
}
- public static final boolean isValidGLVersion(int major, int minor) {
- if(1>major || major>=GL_VERSIONS.length) return false;
- if(0>minor || minor>=GL_VERSIONS[major].length) return false;
+ public static final boolean isValidGLVersion(int ctxProfile, int major, int minor) {
+ if( 1>major || 0>minor ) {
+ return false;
+ }
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
+ if( major>=ES_VERSIONS.length) return false;
+ if( minor>=ES_VERSIONS[major].length) return false;
+ } else {
+ if( major>=GL_VERSIONS.length) return false;
+ if( minor>=GL_VERSIONS[major].length) return false;
+ }
return true;
}
- public static final boolean decrementGLVersion(int major[], int minor[]) {
+ public static final boolean decrementGLVersion(int ctxProfile, int major[], int minor[]) {
if(null==major || major.length<1 ||null==minor || minor.length<1) {
throw new GLException("invalid array arguments");
}
int m = major[0];
int n = minor[0];
- if(!isValidGLVersion(m, n)) return false;
+ if( !isValidGLVersion(ctxProfile, m, n) ) {
+ return false;
+ }
// decrement ..
n -= 1;
if(n < 0) {
- m -= 1;
- n = GL_VERSIONS[m].length-1;
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
+ if( m >= 3) {
+ m -= 1;
+ } else {
+ m = 0; // major decr [1,2] -> 0
+ }
+ n = ES_VERSIONS[m].length-1;
+ } else {
+ m -= 1;
+ n = GL_VERSIONS[m].length-1;
+ }
+ }
+ if( !isValidGLVersion(ctxProfile, m, n) ) {
+ return false;
}
- if(!isValidGLVersion(m, n)) return false;
major[0]=m;
minor[0]=n;
@@ -1209,12 +1433,12 @@ public abstract class GLContext {
/**
* @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int)
*/
- protected static /*final*/ HashMap<String, Integer> deviceVersionAvailable = new HashMap<String, Integer>();
+ protected static final IdentityHashMap<String, Integer> deviceVersionAvailable = new IdentityHashMap<String, Integer>();
/**
* @see #getUniqueDeviceString(javax.media.nativewindow.AbstractGraphicsDevice)
*/
- private static /*final*/ HashSet<String> deviceVersionsAvailableSet = new HashSet<String>();
+ private static final IdentityHashMap<String, String> deviceVersionsAvailableSet = new IdentityHashMap<String, String>();
/** clears the device/context mappings as well as the GL/GLX proc address tables. */
protected static void shutdown() {
@@ -1225,17 +1449,16 @@ public abstract class GLContext {
protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
synchronized ( deviceVersionsAvailableSet ) {
- return deviceVersionsAvailableSet.contains(device.getUniqueID());
+ return deviceVersionsAvailableSet.containsKey(device.getUniqueID());
}
}
protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
synchronized ( deviceVersionsAvailableSet ) {
- String devKey = device.getUniqueID();
- if ( deviceVersionsAvailableSet.contains(devKey) ) {
+ final String devKey = device.getUniqueID();
+ if( null != deviceVersionsAvailableSet.put(devKey, devKey) ) {
throw new InternalError("Already set: "+devKey);
}
- deviceVersionsAvailableSet.add(devKey);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
@@ -1243,8 +1466,13 @@ public abstract class GLContext {
}
}
+ /**
+ * Returns a unique String object using {@link String#intern()} for the given arguments,
+ * which object reference itself can be used as a key.
+ */
protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) {
- return device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ final String r = device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ return r.intern();
}
/**
@@ -1272,16 +1500,16 @@ public abstract class GLContext {
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 String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile);
final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
synchronized(deviceVersionAvailable) {
- return deviceVersionAvailable.put( key, val );
+ return deviceVersionAvailable.put( objectKey, val );
}
}
- protected static StringBuffer dumpAvailableGLVersions(StringBuffer sb) {
+ protected static StringBuilder dumpAvailableGLVersions(StringBuilder sb) {
if(null == sb) {
- sb = new StringBuffer();
+ sb = new StringBuilder();
}
synchronized(deviceVersionAvailable) {
final Set<String> keys = deviceVersionAvailable.keySet();
@@ -1315,10 +1543,10 @@ public abstract class GLContext {
* @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code>
*/
protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile) {
- String key = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
Integer val;
synchronized(deviceVersionAvailable) {
- val = deviceVersionAvailable.get( key );
+ val = deviceVersionAvailable.get( objectKey );
}
return val;
}
@@ -1377,9 +1605,9 @@ public abstract class GLContext {
*/
protected static final void getRequestMajorAndCompat(final GLProfile glp, int[/*2*/] reqMajorCTP) {
final GLProfile glpImpl = glp.getImpl();
- if(glpImpl.isGL4()) {
+ if( glpImpl.isGL4() ) {
reqMajorCTP[0]=4;
- } else if (glpImpl.isGL3()) {
+ } else if ( glpImpl.isGL3() || glpImpl.isGLES3() ) {
reqMajorCTP[0]=3;
} else if (glpImpl.isGLES1()) {
reqMajorCTP[0]=1;
@@ -1504,6 +1732,34 @@ public abstract class GLContext {
return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
}
+ public static boolean isGLES3Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ /**
+ * Returns true if a ES3 compatible profile is available,
+ * i.e. either a &ge; 4.3 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>,
+ * otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public static final boolean isGLES3CompatibleAvailable(AbstractGraphicsDevice device) {
+ int major[] = { 0 };
+ int minor[] = { 0 };
+ int ctp[] = { 0 };
+ boolean ok;
+
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_ES, major, minor, ctp);
+ if( !ok ) {
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, major, minor, ctp);
+ }
+ if( !ok ) {
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp);
+ }
+ return 0 != ( ctp[0] & CTX_IMPL_ES3_COMPAT );
+ }
+
public static boolean isGL4bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware);
}
@@ -1532,13 +1788,15 @@ public abstract class GLContext {
sb.append(minor);
sb.append(" (");
needColon = appendString(sb, "ES profile", needColon, 0 != ( CTX_PROFILE_ES & ctp ));
- needColon = appendString(sb, "Compatibility profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
+ needColon = appendString(sb, "Compat profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
needColon = appendString(sb, "Core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp ));
needColon = appendString(sb, "forward", needColon, 0 != ( CTX_OPTION_FORWARD & ctp ));
needColon = appendString(sb, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
- needColon = appendString(sb, "ES2 compatible", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "ES2 compat", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "ES3 compat", needColon, 0 != ( CTX_IMPL_ES3_COMPAT & ctp ));
needColon = appendString(sb, "FBO", needColon, 0 != ( CTX_IMPL_FBO & ctp ));
+ needColon = appendString(sb, "FP32 compat-api", needColon, 0 != ( CTX_IMPL_FP32_COMPAT_API & ctp ));
if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
needColon = appendString(sb, "software", needColon, true);
} else {
diff --git a/src/jogl/classes/javax/media/opengl/GLDebugMessage.java b/src/jogl/classes/javax/media/opengl/GLDebugMessage.java
index 3ab0683c6..f8959e653 100644
--- a/src/jogl/classes/javax/media/opengl/GLDebugMessage.java
+++ b/src/jogl/classes/javax/media/opengl/GLDebugMessage.java
@@ -73,8 +73,8 @@ public class GLDebugMessage {
// AMD category == ARB source/type
switch(amdDbgCategory) {
case GL2GL3.GL_DEBUG_CATEGORY_API_ERROR_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_API_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_ERROR_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_API;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_ERROR;
break;
//
@@ -82,18 +82,18 @@ public class GLDebugMessage {
//
case GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER;
break;
case GL2GL3.GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER;
break;
case GL2GL3.GL_DEBUG_CATEGORY_APPLICATION_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_APPLICATION;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER;
break;
@@ -102,24 +102,24 @@ public class GLDebugMessage {
//
case GL2GL3.GL_DEBUG_CATEGORY_DEPRECATION_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR;
break;
case GL2GL3.GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR;
break;
case GL2GL3.GL_DEBUG_CATEGORY_PERFORMANCE_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_PERFORMANCE_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_PERFORMANCE;
break;
case GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD:
default:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER;
}
return new GLDebugMessage(source, when, dbgSource, dbgType, dbgId, dbgSeverity, dbgMsg);
@@ -127,24 +127,24 @@ public class GLDebugMessage {
public static int translateARB2AMDCategory(int dbgSource, int dbgType) {
switch (dbgSource) {
- case GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
+ case GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM:
return GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD;
- case GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
+ case GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER:
return GL2GL3.GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD;
- case GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB:
+ case GL2GL3.GL_DEBUG_SOURCE_APPLICATION:
return GL2GL3.GL_DEBUG_CATEGORY_APPLICATION_AMD;
}
switch(dbgType) {
- case GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
+ case GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
return GL2GL3.GL_DEBUG_CATEGORY_DEPRECATION_AMD;
- case GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
+ case GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
return GL2GL3.GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD;
- case GL2GL3.GL_DEBUG_TYPE_PERFORMANCE_ARB:
+ case GL2GL3.GL_DEBUG_TYPE_PERFORMANCE:
return GL2GL3.GL_DEBUG_CATEGORY_PERFORMANCE_AMD;
}
@@ -204,33 +204,33 @@ public class GLDebugMessage {
public static String getDbgSourceString(int dbgSource) {
switch(dbgSource) {
- case GL2GL3.GL_DEBUG_SOURCE_API_ARB: return "GL API";
- case GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "GLSL or extension compiler";
- case GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "Native Windowing binding";
- case GL2GL3.GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "Third party";
- case GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB: return "Application";
- case GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB: return "generic";
+ case GL2GL3.GL_DEBUG_SOURCE_API: return "GL API";
+ case GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER: return "GLSL or extension compiler";
+ case GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "Native Windowing binding";
+ case GL2GL3.GL_DEBUG_SOURCE_THIRD_PARTY: return "Third party";
+ case GL2GL3.GL_DEBUG_SOURCE_APPLICATION: return "Application";
+ case GL2GL3.GL_DEBUG_SOURCE_OTHER: return "generic";
default: return "Unknown (" + toHexString(dbgSource) + ")";
}
}
public static String getDbgTypeString(int dbgType) {
switch(dbgType) {
- case GL2GL3.GL_DEBUG_TYPE_ERROR_ARB: return "Error";
- case GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "Warning: marked for deprecation";
- case GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "Warning: undefined behavior";
- case GL2GL3.GL_DEBUG_TYPE_PERFORMANCE_ARB: return "Warning: implementation dependent performance";
- case GL2GL3.GL_DEBUG_TYPE_PORTABILITY_ARB: return "Warning: vendor-specific extension use";
- case GL2GL3.GL_DEBUG_TYPE_OTHER_ARB: return "Warning: generic";
+ case GL2GL3.GL_DEBUG_TYPE_ERROR: return "Error";
+ case GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "Warning: marked for deprecation";
+ case GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "Warning: undefined behavior";
+ case GL2GL3.GL_DEBUG_TYPE_PERFORMANCE: return "Warning: implementation dependent performance";
+ case GL2GL3.GL_DEBUG_TYPE_PORTABILITY: return "Warning: vendor-specific extension use";
+ case GL2GL3.GL_DEBUG_TYPE_OTHER: return "Warning: generic";
default: return "Unknown (" + toHexString(dbgType) + ")";
}
}
public static String getDbgSeverityString(int dbgSeverity) {
switch(dbgSeverity) {
- case GL2GL3.GL_DEBUG_SEVERITY_HIGH_ARB: return "High: dangerous undefined behavior";
- case GL2GL3.GL_DEBUG_SEVERITY_MEDIUM_ARB: return "Medium: Severe performance/deprecation/other warnings";
- case GL2GL3.GL_DEBUG_SEVERITY_LOW_ARB: return "Low: Performance warnings (redundancy/undefined)";
+ case GL2GL3.GL_DEBUG_SEVERITY_HIGH: return "High: dangerous undefined behavior";
+ case GL2GL3.GL_DEBUG_SEVERITY_MEDIUM: return "Medium: Severe performance/deprecation/other warnings";
+ case GL2GL3.GL_DEBUG_SEVERITY_LOW: return "Low: Performance warnings (redundancy/undefined)";
default: return "Unknown (" + toHexString(dbgSeverity) + ")";
}
}
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index dbf6df0de..580d3a50b 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -40,8 +40,6 @@
package javax.media.opengl;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
@@ -118,13 +116,8 @@ public abstract class GLDrawableFactory {
private static GLDrawableFactory eglFactory;
private static GLDrawableFactory nativeOSFactory;
- protected static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
-
- // Shutdown hook mechanism for the factory
- private static boolean factoryShutdownHookRegistered = false;
- private static Thread factoryShutdownHook = null;
- private static volatile boolean isJVMShuttingDown = false;
-
+ private static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
+
/**
* Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones.
*/
@@ -139,7 +132,12 @@ public abstract class GLDrawableFactory {
}
}
private static final void initSingletonImpl() {
- registerFactoryShutdownHook();
+ NativeWindowFactory.initSingleton();
+ NativeWindowFactory.addCustomShutdownHook(false /* head */, new Runnable() {
+ public void run() {
+ shutdown0();
+ }
+ });
final String nwt = NativeWindowFactory.getNativeWindowType(true);
GLDrawableFactory tmp = null;
@@ -199,19 +197,35 @@ public abstract class GLDrawableFactory {
synchronized (GLDrawableFactory.class) {
if (isInit) {
isInit=false;
- shutdownImpl();
+ shutdown0();
}
}
}
}
- private static void shutdownImpl() {
+ private static void shutdown0() {
// Following code will _always_ remain in shutdown hook
// due to special semantics of native utils, i.e. X11Utils.
// The latter requires shutdown at JVM-Shutdown only.
synchronized(glDrawableFactories) {
- for(int i=0; i<glDrawableFactories.size(); i++) {
- glDrawableFactories.get(i).destroy();
+ final int gldfCount = glDrawableFactories.size();
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll "+gldfCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<gldfCount; i++) {
+ final GLDrawableFactory gldf = glDrawableFactories.get(i);
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll["+(i+1)+"/"+gldfCount+"]: "+gldf.getClass().getName());
+ }
+ try {
+ gldf.resetDisplayGamma();
+ gldf.destroy();
+ } catch (Throwable t) {
+ System.err.println("GLDrawableFactory.shutdownImpl: Catched "+t.getClass().getName()+" during factory shutdown #"+(i+1)+"/"+gldfCount+" "+gldf.getClass().getName());
+ if( DEBUG ) {
+ t.printStackTrace();
+ }
+ }
}
glDrawableFactories.clear();
@@ -220,28 +234,8 @@ public abstract class GLDrawableFactory {
eglFactory = null;
}
GLContext.shutdown();
- NativeWindowFactory.shutdown(isJVMShuttingDown);
}
- private static synchronized void registerFactoryShutdownHook() {
- if (factoryShutdownHookRegistered) {
- return;
- }
- factoryShutdownHook = new Thread(new Runnable() {
- public void run() {
- isJVMShuttingDown = true;
- GLDrawableFactory.shutdownImpl();
- }
- });
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Runtime.getRuntime().addShutdownHook(factoryShutdownHook);
- return null;
- }
- });
- factoryShutdownHookRegistered = true;
- }
-
protected GLDrawableFactory() {
synchronized(glDrawableFactories) {
glDrawableFactories.add(this);
@@ -258,6 +252,8 @@ public abstract class GLDrawableFactory {
protected abstract void destroy();
+ public abstract void resetDisplayGamma();
+
/**
* Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection},
* {@link AbstractGraphicsDevice#getUnitID() unit ID} and {@link AbstractGraphicsDevice#getUniqueID() unique ID name}. for this factory<br>
@@ -447,7 +443,7 @@ public abstract class GLDrawableFactory {
* </p>
* <p>
* A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
* </p>
* <p>
* If not onscreen and neither FBO nor Pbuffer is available,
@@ -458,7 +454,7 @@ public abstract class GLDrawableFactory {
* @throws GLException if any window system-specific errors caused
* the creation of the GLDrawable to fail.
*
- * @see #canCreateGLPbuffer(AbstractGraphicsDevice)
+ * @see #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile)
* @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile)
* @see javax.media.opengl.GLCapabilities#isOnscreen()
* @see javax.media.opengl.GLCapabilities#isFBO()
@@ -486,7 +482,7 @@ public abstract class GLDrawableFactory {
* </p>
* <p>
* A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
* </p>
* <p>
* If neither FBO nor Pbuffer is available,
@@ -524,7 +520,7 @@ public abstract class GLDrawableFactory {
* </p>
* <p>
* A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
* </p>
* <p>
* If neither FBO nor Pbuffer is available,
@@ -594,12 +590,16 @@ public abstract class GLDrawableFactory {
public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp);
/**
- * Returns true if it is possible to create a GLPbuffer. Some older
- * graphics cards do not have this capability.
+ * Returns true if it is possible to create an <i>pbuffer surface</i>.
+ * <p>
+ * Some older graphics cards do not have this capability,
+ * as well as some new GL implementation, i.e. OpenGL 3 core on OSX.
+ * </p>
*
* @param device which {@link 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
*/
- public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp);
/**
* Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions.
diff --git a/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java b/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java
index 2bfc77d4a..c6bf26235 100644
--- a/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java
@@ -51,8 +51,23 @@ public class GLPipelineFactory {
/**
* Creates a pipelined GL instance using the given downstream <code>downstream</code>
- * and optional arguments <code>additionalArgs</code> for the constructor.<br>
+ * and optional arguments <code>additionalArgs</code> for the constructor.
*
+ * <p>
+ * Sample code which installs a Debug and Trace pipeline
+ * automatic w/ user defined interface, here: GL2ES2:
+ * <pre>
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, gl, null) );
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, gl, new Object[] { System.err } ) );
+ * </pre>
+ * or automatic w/ automatic defined class:
+ * <pre>
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) );
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
+ * </pre>
+ * </p>
+ *
+ * <p>
* The upstream GL instance is determined as follows:
* <ul>
* <li> Use <code>pipelineClazzBaseName</code> as the class name's full basename, incl. package name</li>
@@ -65,7 +80,8 @@ public class GLPipelineFactory {
* <li> If upstream class is available use it, end loop.</li>
* </ul>
* </ul>
- * </ul><br>
+ * </ul>
+ * </p>
*
* @param pipelineClazzBaseName the basename of the pipline class name
* @param reqInterface optional requested interface to be used, may be null, in which case the first matching one is used
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 1b6af22d4..51b822449 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -132,7 +132,7 @@ public class GLProfile {
ReflectionUtil.createInstance(getGLImplBaseClassName(GL4bc)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
} catch (Throwable t) {}
try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GLES2)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
+ ReflectionUtil.createInstance(getGLImplBaseClassName(GLES3)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
} catch (Throwable t) {}
try {
ReflectionUtil.createInstance(getGLImplBaseClassName(GLES1)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
@@ -165,7 +165,7 @@ public class GLProfile {
initLock.unlock();
}
if(DEBUG) {
- if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES3Impl ) ) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
}
}
@@ -299,6 +299,17 @@ public class GLProfile {
}
if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES3").append(indent);
+ } else {
+ sb.append(", GLES3 ");
+ }
+ avail=isAvailableImpl(map, GLES3);
+ sb.append(avail);
+ if(avail) {
+ glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_ES);
+ }
+
+ if(useIndent) {
doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL3bc").append(indent);
} else {
sb.append(", GL3bc ");
@@ -332,11 +343,15 @@ public class GLProfile {
}
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES1").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES2").append(indent);
} else {
- sb.append(", GL2ES1 ");
+ sb.append(", GLES2 ");
+ }
+ avail=isAvailableImpl(map, GLES2);
+ sb.append(avail);
+ if(avail) {
+ glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES);
}
- sb.append(isAvailableImpl(map, GL2ES1));
if(useIndent) {
doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES1").append(indent);
@@ -350,6 +365,13 @@ public class GLProfile {
}
if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL4ES3").append(indent);
+ } else {
+ sb.append(", GL4ES3 ");
+ }
+ sb.append(isAvailableImpl(map, GL4ES3));
+
+ if(useIndent) {
doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES2").append(indent);
} else {
sb.append(", GL2ES2 ");
@@ -357,15 +379,11 @@ public class GLProfile {
sb.append(isAvailableImpl(map, GL2ES2));
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES2").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES1").append(indent);
} else {
- sb.append(", GLES2 ");
- }
- avail=isAvailableImpl(map, GLES2);
- sb.append(avail);
- if(avail) {
- glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES);
+ sb.append(", GL2ES1 ");
}
+ sb.append(isAvailableImpl(map, GL2ES1));
if(useIndent) {
indentCount--;
@@ -437,6 +455,9 @@ public class GLProfile {
/** The embedded OpenGL profile ES 2.x, with x >= 0 */
public static final String GLES2 = "GLES2";
+ /** The embedded OpenGL profile ES 3.x, with x >= 0 */
+ public static final String GLES3 = "GLES3";
+
/** The intersection of the desktop GL2 and embedded ES1 profile */
public static final String GL2ES1 = "GL2ES1";
@@ -446,6 +467,9 @@ public class GLProfile {
/** The intersection of the desktop GL3 and GL2 profile */
public static final String GL2GL3 = "GL2GL3";
+ /** The intersection of the desktop GL4 and ES3 profile */
+ public static final String GL4ES3 = "GL4ES3";
+
/** The default profile, used for the device default profile map */
private static final String GL_DEFAULT = "GL_DEFAULT";
@@ -456,62 +480,66 @@ public class GLProfile {
* <p> This includes the generic subset profiles GL2GL3, GL2ES2 and GL2ES1.</p>
*
* <ul>
- * <li> GL4bc
- * <li> GL3bc
- * <li> GL2
- * <li> GL4
- * <li> GL3
- * <li> GL2GL3
- * <li> GLES2
- * <li> GL2ES2
- * <li> GLES1
- * <li> GL2ES1
+ * <li> GL4bc </li>
+ * <li> GL3bc </li>
+ * <li> GL2 </li>
+ * <li> GL4 </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL4ES3 </li>
+ * <li> GL2GL3 </li>
+ * <li> GLES2 </li>
+ * <li> GL2ES2 </li>
+ * <li> GLES1 </li>
+ * <li> GL2ES1 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 };
-
+ public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GLES3, GL4ES3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 };
+
/**
* Order of maximum profiles.
*
* <ul>
- * <li> GL4bc
- * <li> GL4
- * <li> GL3bc
- * <li> GL3
- * <li> GL2
- * <li> GLES2
- * <li> GLES1
+ * <li> GL4bc </li>
+ * <li> GL4 </li>
+ * <li> GL3bc </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL2 </li>
+ * <li> GLES2 </li>
+ * <li> GLES1 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2, GLES1 };
+ public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2, GLES1 };
/**
* Order of minimum profiles.
*
* <ul>
- * <li> GLES1
- * <li> GLES2
- * <li> GL2
- * <li> GL3
- * <li> GL3bc
- * <li> GL4
- * <li> GL4bc
+ * <li> GLES1 </li>
+ * <li> GLES2 </li>
+ * <li> GL2 </li>
+ * <li> GLES3 </li>
+ * <li> GL3 </li>
+ * <li> GL3bc </li>
+ * <li> GL4 </li>
+ * <li> GL4bc </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GL3, GL3bc, GL4, GL4bc };
+ public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GLES3, GL3, GL3bc, GL4, GL4bc };
/**
* Order of minimum original desktop profiles.
*
* <ul>
- * <li> GL2
- * <li> GL3bc
- * <li> GL4bc
- * <li> GL3
- * <li> GL4
+ * <li> GL2 </li>
+ * <li> GL3bc </li>
+ * <li> GL4bc </li>
+ * <li> GL3 </li>
+ * <li> GL4 </li>
* </ul>
*
*/
@@ -521,10 +549,10 @@ public class GLProfile {
* Order of maximum fixed function profiles
*
* <ul>
- * <li> GL4bc
- * <li> GL3bc
- * <li> GL2
- * <li> GLES1
+ * <li> GL4bc </li>
+ * <li> GL3bc </li>
+ * <li> GL2 </li>
+ * <li> GLES1 </li>
* </ul>
*
*/
@@ -534,28 +562,30 @@ public class GLProfile {
* Order of maximum programmable shader profiles
*
* <ul>
- * <li> GL4bc
- * <li> GL4
- * <li> GL3bc
- * <li> GL3
- * <li> GL2
- * <li> GLES2
+ * <li> GL4bc </li>
+ * <li> GL4 </li>
+ * <li> GL3bc </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL2 </li>
+ * <li> GLES2 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2 };
+ public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2 };
/**
* Order of maximum programmable shader <i>core only</i> profiles
*
* <ul>
- * <li> GL4
- * <li> GL3
- * <li> GLES2
+ * <li> GL4 </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GLES2 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER_CORE = new String[] { GL4, GL3, GLES2 };
+ public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER_CORE = new String[] { GL4, GL3, GLES3, GLES2 };
/** Returns a default GLProfile object, reflecting the best for the running platform.
* It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL}
@@ -755,6 +785,36 @@ public class GLProfile {
}
/**
+ * Returns the GL4ES3 profile implementation, hence compatible w/ GL4ES3.<br/>
+ * It returns:
+ * <pre>
+ * GLProfile.get(device, GLProfile.GL4ES3).getImpl());
+ * </pre>
+ * <p>Selection favors hardware rasterizer.</p>
+ *
+ * @throws GLException if no GL4ES3 compatible profile is available for the default device.
+ * @see #isGL4ES3()
+ * @see #get(AbstractGraphicsDevice, String)
+ * @see #getImpl()
+ */
+ public static GLProfile getGL4ES3(AbstractGraphicsDevice device)
+ throws GLException
+ {
+ return get(device, GL4ES3).getImpl();
+ }
+
+ /**
+ * Calls {@link #getGL4ES3(AbstractGraphicsDevice)} using the default device.
+ * <p>Selection favors hardware rasterizer.</p>
+ * @see #getGL4ES3(AbstractGraphicsDevice)
+ */
+ public static GLProfile getGL4ES3()
+ throws GLException
+ {
+ return get(defaultDevice, GL4ES3).getImpl();
+ }
+
+ /**
* Returns the GL2GL3 profile implementation, hence compatible w/ GL2GL3.<br/>
* It returns:
* <pre>
@@ -872,13 +932,20 @@ public class GLProfile {
return GLES1.equals(profileImpl);
}
- /** Indicates whether the native OpenGL ES2 profile is in use.
- * This requires an EGL or ES2 compatible interface.
+ /** Indicates whether the native OpenGL ES3 or ES2 profile is in use.
+ * This requires an EGL, ES3 or ES2 compatible interface.
*/
public static boolean usesNativeGLES2(String profileImpl) {
- return GLES2.equals(profileImpl);
+ return GLES3.equals(profileImpl) || GLES2.equals(profileImpl);
}
+ /** Indicates whether the native OpenGL ES2 profile is in use.
+ * This requires an EGL, ES3 compatible interface.
+ */
+ public static boolean usesNativeGLES3(String profileImpl) {
+ return GLES3.equals(profileImpl);
+ }
+
/** Indicates whether either of the native OpenGL ES profiles are in use. */
public static boolean usesNativeGLES(String profileImpl) {
return usesNativeGLES2(profileImpl) || usesNativeGLES1(profileImpl);
@@ -937,8 +1004,8 @@ public class GLProfile {
}
private static final String getGLImplBaseClassName(String profileImpl) {
- if( GLES2 == profileImpl ) {
- return "jogamp.opengl.es2.GLES2";
+ if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+ return "jogamp.opengl.es3.GLES3";
} else if( GLES1 == profileImpl ) {
return "jogamp.opengl.es1.GLES1";
} else if ( GL4bc == profileImpl ||
@@ -1025,7 +1092,7 @@ public class GLProfile {
return isGL4() || isGL3bc() || GL3 == profile;
}
- /** Indicates whether this context is a GL2 context <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */
+ /** Indicates whether this profile is capable of GL2 . <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */
public final boolean isGL2() {
return isGL3bc() || GL2 == profile;
}
@@ -1035,14 +1102,19 @@ public class GLProfile {
return GLES1 == profile;
}
- /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES2 ].</p> */
+ /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES3, GLES2 ].</p> */
public final boolean isGLES2() {
- return GLES2 == profile;
+ return GLES3 == profile || GLES2 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GLES3. <p>Includes [ GLES3 ].</p> */
+ public final boolean isGLES3() {
+ return GLES3 == profile;
}
- /** Indicates whether this profile is capable of GLES. <p>Includes [ GLES1, GLES2 ].</p> */
+ /** Indicates whether this profile is capable of GLES. <p>Includes [ GLES3, GLES1, GLES2 ].</p> */
public final boolean isGLES() {
- return GLES2 == profile || GLES1 == profile;
+ return GLES3 == profile || GLES2 == profile || GLES1 == profile;
}
/** Indicates whether this profile is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p> */
@@ -1050,17 +1122,27 @@ public class GLProfile {
return GL2ES1 == profile || isGLES1() || isGL2();
}
- /** Indicates whether this profile is capable os GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */
+ /** Indicates whether this profile is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */
public final boolean isGL2GL3() {
return GL2GL3 == profile || isGL3() || isGL2();
}
-
- /** Indicates whether this profile is capable os GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */
+
+ /** Indicates whether this profile is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */
public final boolean isGL2ES2() {
return GL2ES2 == profile || isGLES2() || isGL2GL3();
}
- /** Indicates whether this profile supports GLSL, ie. {@link #isGL2ES2()}. */
+ /** Indicates whether this profile is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p> */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
+ }
+
+ /** Indicates whether this profile is capable of GL4ES3. <p>Includes [ GL4bc, GL4, GLES3 ].</p> */
+ public final boolean isGL4ES3() {
+ return GL4ES3 == profile || isGLES3() || isGL4();
+ }
+
+ /** Indicates whether this profile supports GLSL, i.e. {@link #isGL2ES2()}. */
public final boolean hasGLSL() {
return isGL2ES2() ;
}
@@ -1072,7 +1154,12 @@ public class GLProfile {
/** Indicates whether this profile uses the native OpenGL ES2 implementations. */
public final boolean usesNativeGLES2() {
- return GLES2 == getImplName();
+ return GLES3 == getImplName() || GLES2 == getImplName();
+ }
+
+ /** Indicates whether this profile uses the native OpenGL ES2 implementations. */
+ public final boolean usesNativeGLES3() {
+ return GLES3 == getImplName();
}
/** Indicates whether this profile uses either of the native OpenGL ES implementations. */
@@ -1117,8 +1204,8 @@ public class GLProfile {
public boolean isValidArrayDataType(int index, int comps, int type,
boolean isVertexAttribPointer, boolean throwException) {
- String arrayName = getGLArrayName(index);
- if(isGLES1()) {
+ final String arrayName = getGLArrayName(index);
+ if( isGLES1() ) {
if(isVertexAttribPointer) {
if(throwException) {
throw new GLException("Illegal array type for "+arrayName+" on profile GLES1: VertexAttribPointer");
@@ -1201,7 +1288,7 @@ public class GLProfile {
}
break;
}
- } else if(isGLES2()) {
+ } else if( isGLES2() ) {
// simply ignore !isVertexAttribPointer case, since it is simulated anyway ..
switch(type) {
case GL.GL_UNSIGNED_BYTE:
@@ -1386,7 +1473,7 @@ public class GLProfile {
private static /*final*/ boolean hasDesktopGLFactory;
private static /*final*/ boolean hasGL234Impl;
private static /*final*/ boolean hasEGLFactory;
- private static /*final*/ boolean hasGLES2Impl;
+ private static /*final*/ boolean hasGLES3Impl;
private static /*final*/ boolean hasGLES1Impl;
private static /*final*/ GLDrawableFactoryImpl eglFactory = null;
@@ -1419,7 +1506,7 @@ public class GLProfile {
// depends on hasEGLFactory
hasGLES1Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es1.GLES1Impl", classloader);
- hasGLES2Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es2.GLES2Impl", classloader);
+ hasGLES3Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es3.GLES3Impl", classloader);
//
// Iteration of desktop GL availability detection
@@ -1471,8 +1558,8 @@ public class GLProfile {
eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
if(null != eglFactory) {
hasEGLFactory = true;
- // update hasGLES1Impl, hasGLES2Impl based on EGL
- hasGLES2Impl = null!=eglFactory.getGLDynamicLookupHelper(2) && hasGLES2Impl;
+ // update hasGLES1Impl, hasGLES3Impl based on EGL
+ hasGLES3Impl = null!=eglFactory.getGLDynamicLookupHelper(2) && hasGLES3Impl;
hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(1) && hasGLES1Impl;
}
} catch (LinkageError le) {
@@ -1493,7 +1580,7 @@ public class GLProfile {
final AbstractGraphicsDevice defaultEGLDevice;
if(null == eglFactory) {
- hasGLES2Impl = false;
+ hasGLES3Impl = false;
hasGLES1Impl = false;
defaultEGLDevice = null;
if(DEBUG) {
@@ -1532,7 +1619,7 @@ public class GLProfile {
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 hasGLES3Impl "+hasGLES3Impl);
System.err.println("GLProfile.init defaultDevice "+defaultDevice);
System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice);
System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice);
@@ -1609,8 +1696,8 @@ public class GLProfile {
final boolean deviceIsEGLCompatible = hasEGLFactory && eglFactory.getIsDeviceCompatible(device);
- // also test GLES1 and GLES2 on desktop, since we have implementations / emulations available.
- if( deviceIsEGLCompatible && ( hasGLES2Impl || hasGLES1Impl ) ) {
+ // also test GLES1, GLES2 and GLES3 on desktop, since we have implementations / emulations available.
+ if( deviceIsEGLCompatible && ( hasGLES3Impl || hasGLES1Impl ) ) {
// 1st pretend we have all EGL profiles ..
computeProfileMap(device, false /* desktopCtxUndef*/, true /* esCtxUndef */);
@@ -1629,7 +1716,7 @@ public class GLProfile {
// but it seems even EGL.eglInitialize(eglDisplay, null, null)
// fails in some scenarios (eg VirtualBox 4.1.6) w/ EGL error 0x3001 (EGL_NOT_INITIALIZED).
hasEGLFactory = false;
- hasGLES2Impl = false;
+ hasGLES3Impl = false;
hasGLES1Impl = false;
}
if (DEBUG) {
@@ -1647,7 +1734,7 @@ public class GLProfile {
System.err.println("GLProfile: desktoplFactory "+desktopFactory);
System.err.println("GLProfile: eglFactory "+eglFactory);
System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl);
- System.err.println("GLProfile: hasGLES2Impl "+hasGLES2Impl);
+ System.err.println("GLProfile: hasGLES3Impl "+hasGLES3Impl);
}
}
@@ -1725,18 +1812,18 @@ public class GLProfile {
final boolean isHardwareRasterizer[] = new boolean[1];
GLProfile defaultGLProfileAny = null;
GLProfile defaultGLProfileHW = null;
- HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(GL_PROFILE_LIST_ALL.length + 1 /* default */);
+ final HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(GL_PROFILE_LIST_ALL.length + 1 /* default */);
for(int i=0; i<GL_PROFILE_LIST_ALL.length; i++) {
- String profile = GL_PROFILE_LIST_ALL[i];
- String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer);
- if(null!=profileImpl) {
+ final String profile = GL_PROFILE_LIST_ALL[i];
+ final String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer);
+ if( null != profileImpl ) {
final GLProfile glProfile;
- if(profile.equals(profileImpl)) {
+ if( profile.equals( profileImpl ) ) {
glProfile = new GLProfile(profile, null, isHardwareRasterizer[0]);
} else {
- final GLProfile _mglp = _mappedProfiles.get(profileImpl);
- if(null == _mglp) {
- throw new InternalError("XXX0");
+ final GLProfile _mglp = _mappedProfiles.get( profileImpl );
+ if( null == _mglp ) {
+ throw new InternalError("XXX0 profile["+i+"]: "+profile+" -> profileImpl "+profileImpl+" !!! not mapped ");
}
glProfile = new GLProfile(profile, _mglp, isHardwareRasterizer[0]);
}
@@ -1744,12 +1831,12 @@ public class GLProfile {
if (DEBUG) {
System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
}
- if(null==defaultGLProfileHW && isHardwareRasterizer[0]) {
+ if( null == defaultGLProfileHW && isHardwareRasterizer[0] ) {
defaultGLProfileHW=glProfile;
if (DEBUG) {
System.err.println("GLProfile.init map defaultHW "+glProfile+" on device "+device.getConnection());
}
- } else if(null==defaultGLProfileAny) {
+ } else if( null == defaultGLProfileAny ) {
defaultGLProfileAny=glProfile;
if (DEBUG) {
System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getConnection());
@@ -1761,9 +1848,9 @@ public class GLProfile {
}
}
}
- if(null!=defaultGLProfileHW) {
+ if( null != defaultGLProfileHW ) {
_mappedProfiles.put(GL_DEFAULT, defaultGLProfileHW);
- } else if(null!=defaultGLProfileAny) {
+ } else if( null != defaultGLProfileAny ) {
_mappedProfiles.put(GL_DEFAULT, defaultGLProfileAny);
}
setProfileMap(device, _mappedProfiles);
@@ -1774,10 +1861,6 @@ public class GLProfile {
* Returns the profile implementation
*/
private static String computeProfileImpl(AbstractGraphicsDevice device, String profile, boolean desktopCtxUndef, boolean esCtxUndef, boolean isHardwareRasterizer[]) {
- // OSX GL3.. doesn't support GLSL<150,
- // hence GL2ES2 and GL2GL3 need to be mapped on GL2 on OSX for GLSL compatibility.
- final boolean isOSX = Platform.OS_TYPE == Platform.OSType.MACOS;
-
if (GL2ES1.equals(profile)) {
final boolean es1HardwareRasterizer[] = new boolean[1];
final boolean gles1Available = hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, es1HardwareRasterizer) );
@@ -1805,29 +1888,27 @@ public class GLProfile {
}
} else if (GL2ES2.equals(profile)) {
final boolean es2HardwareRasterizer[] = new boolean[1];
- final boolean gles2Available = hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, es2HardwareRasterizer) );
+ final boolean gles2Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES2Available(device, es2HardwareRasterizer) );
final boolean gles2HWAvailable = gles2Available && es2HardwareRasterizer[0] ;
if(hasGL234Impl) {
- if(!isOSX) {
- if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL4bc;
- }
+ if(GLContext.isGL4Available(device, isHardwareRasterizer)) {
+ if(!gles2HWAvailable || isHardwareRasterizer[0]) {
+ return GL4;
}
- if(GLContext.isGL4Available(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL4;
- }
+ }
+ if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
+ if(!gles2HWAvailable || isHardwareRasterizer[0]) {
+ return GL4bc;
}
- if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL3bc;
- }
+ }
+ if(GLContext.isGL3Available(device, isHardwareRasterizer)) {
+ if(!gles2HWAvailable || isHardwareRasterizer[0]) {
+ return GL3;
}
- if(GLContext.isGL3Available(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL3;
- }
+ }
+ if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
+ if(!gles2HWAvailable || isHardwareRasterizer[0]) {
+ return GL3bc;
}
}
if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) {
@@ -1840,15 +1921,48 @@ public class GLProfile {
isHardwareRasterizer[0] = es2HardwareRasterizer[0];
return GLES2;
}
+ } else if (GL4ES3.equals(profile)) {
+ final boolean gles3CompatAvail = GLContext.isGLES3CompatibleAvailable(device);
+ if( desktopCtxUndef || esCtxUndef || gles3CompatAvail ) {
+ final boolean es3HardwareRasterizer[] = new boolean[1];
+ final boolean gles3Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, es3HardwareRasterizer) );
+ final boolean gles3HWAvailable = gles3Available && es3HardwareRasterizer[0] ;
+ if(hasGL234Impl) {
+ if(GLContext.isGL4Available(device, isHardwareRasterizer)) {
+ if(!gles3HWAvailable || isHardwareRasterizer[0]) {
+ return GL4;
+ }
+ }
+ if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
+ if(!gles3HWAvailable || isHardwareRasterizer[0]) {
+ return GL4bc;
+ }
+ }
+ if(GLContext.isGL3Available(device, isHardwareRasterizer)) {
+ if(!gles3HWAvailable || isHardwareRasterizer[0]) {
+ return GL3;
+ }
+ }
+ if( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
+ if(!gles3HWAvailable || isHardwareRasterizer[0]) {
+ return GL3bc;
+ }
+ }
+ }
+ if(gles3Available) {
+ isHardwareRasterizer[0] = es3HardwareRasterizer[0];
+ return GLES3;
+ }
+ }
} else if(GL2GL3.equals(profile)) {
if(hasGL234Impl) {
- if(!isOSX && GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
+ if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
return GL4bc;
- } else if(!isOSX && GLContext.isGL4Available(device, isHardwareRasterizer)) {
+ } else if( GLContext.isGL4Available(device, isHardwareRasterizer)) {
return GL4;
- } else if(!isOSX && GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
+ } else if( GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
return GL3bc;
- } else if(!isOSX && GLContext.isGL3Available(device, isHardwareRasterizer)) {
+ } else if( GLContext.isGL3Available(device, isHardwareRasterizer)) {
return GL3;
} else if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) {
return GL2;
@@ -1864,7 +1978,9 @@ public class GLProfile {
return GL3;
} else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) {
return GL2;
- } else if(GLES2.equals(profile) && hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) {
+ } else if(GLES3.equals(profile) && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, isHardwareRasterizer))) {
+ return GLES3;
+ } else if(GLES2.equals(profile) && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) {
return GLES2;
} else if(GLES1.equals(profile) && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, isHardwareRasterizer))) {
return GLES1;
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL2.java b/src/jogl/classes/javax/media/opengl/TraceGL2.java
new file mode 100644
index 000000000..58f5d9f99
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL2.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL2 extends TraceGL4bc {
+ public TraceGL2(GL2 downstream, PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL3.java b/src/jogl/classes/javax/media/opengl/TraceGL3.java
new file mode 100644
index 000000000..616b31f61
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL3.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL3 extends TraceGL4bc {
+ public TraceGL3(GL3 downstream, PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL3bc.java b/src/jogl/classes/javax/media/opengl/TraceGL3bc.java
new file mode 100644
index 000000000..f3761d4d6
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL3bc.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL3bc extends TraceGL4bc {
+ public TraceGL3bc(GL3bc downstream, PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL4.java b/src/jogl/classes/javax/media/opengl/TraceGL4.java
new file mode 100644
index 000000000..a12bf0f47
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL4.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL4 extends TraceGL4bc {
+ public TraceGL4(GL4 downstream, PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGLES2.java b/src/jogl/classes/javax/media/opengl/TraceGLES2.java
new file mode 100644
index 000000000..38d60e3ac
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGLES2.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGLES2 extends TraceGLES3 {
+ public TraceGLES2(GLES2 downstream, PrintStream stream) {
+ super((GLES3)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index b11f359be..2a23defbe 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -110,6 +110,7 @@ import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvide
<P>
In case FBO is used and GLSL is available, a fragment shader is utilized
to flip the FBO texture vertically. This hardware-accelerated step can be disabled via system property <code>jogl.gljpanel.noglsl</code>.
+ See <a href="#fboGLSLVerticalFlip">details here</a>.
</P>
<P>
The OpenGL path is concluded by copying the rendered pixels an {@link BufferedImage} via {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
@@ -125,15 +126,21 @@ import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvide
on the prepared {@link BufferedImage} as described above.
</p>
<P>
- * Please read <A HREF="GLCanvas.html#java2dgl">Java2D OpenGL Remarks</A>.
+ * Please read <a href="GLCanvas.html#java2dgl">Java2D OpenGL Remarks</a>.
* </P>
+ *
+ <a name="fboGLSLVerticalFlip"><h5>FBO / GLSL Vertical Flip</h5></a>
+ The FBO / GLSL code path uses one texture-unit and binds the FBO texture to it's active texture-target,
+ see {@link #setTextureUnit(int)} and {@link #getTextureUnit()}.
+ If the application uses the same texture-unit, ensure it setup their texture properly, i.e. texture-unit bind, enable and then it's parameters,
+ see {@link Texture#textureCallOrder Order of Texture Commands}.
*/
@SuppressWarnings("serial")
public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol {
- private static final boolean DEBUG = Debug.debug("GLJPanel");
- private static final boolean DEBUG_VIEWPORT = Debug.isPropertyDefined("jogl.debug.GLJPanel.Viewport", true);
- private static final boolean USE_GLSL_TEXTURE_RASTERIZER = !Debug.isPropertyDefined("jogl.gljpanel.noglsl", true);
+ private static final boolean DEBUG;
+ private static final boolean DEBUG_VIEWPORT;
+ private static final boolean USE_GLSL_TEXTURE_RASTERIZER;
/** Indicates whether the Java 2D OpenGL pipeline is requested by user. */
private static final boolean java2dOGLEnabledByProp;
@@ -145,11 +152,17 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private static boolean java2DGLPipelineOK;
static {
+ Debug.initSingleton();
+ DEBUG = Debug.debug("GLJPanel");
+ DEBUG_VIEWPORT = Debug.isPropertyDefined("jogl.debug.GLJPanel.Viewport", true);
+ USE_GLSL_TEXTURE_RASTERIZER = !Debug.isPropertyDefined("jogl.gljpanel.noglsl", true);
+
boolean enabled = false;
final String sVal = System.getProperty("sun.java2d.opengl");
if( null != sVal ) {
enabled = Boolean.valueOf(sVal);
}
+ Debug.initSingleton();
java2dOGLEnabledByProp = enabled && !Debug.isPropertyDefined("jogl.gljpanel.noogl", true);
enabled = false;
@@ -212,6 +225,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private int viewportX;
private int viewportY;
+ private int requestedTextureUnit = 0; // default
+
// The backend in use
private volatile Backend backend;
@@ -731,6 +746,40 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return factory;
}
+ /**
+ * Returns the used texture unit, i.e. a value of [0..n], or -1 if non used.
+ * <p>
+ * If implementation uses a texture-unit, it will be known only after the first initialization, i.e. display call.
+ * </p>
+ * <p>
+ * See <a href="#fboGLSLVerticalFlip">FBO / GLSL Vertical Flip</a>.
+ * </p>
+ */
+ public final int getTextureUnit() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return -1;
+ }
+ return b.getTextureUnit();
+ }
+
+ /**
+ * Allows user to request a texture unit to be used,
+ * must be called before the first initialization, i.e. {@link #display()} call.
+ * <p>
+ * Defaults to <code>0</code>.
+ * </p>
+ * <p>
+ * See <a href="#fboGLSLVerticalFlip">FBO / GLSL Vertical Flip</a>.
+ * </p>
+ *
+ * @param v requested texture unit
+ * @see #getTextureUnit()
+ */
+ public final void setTextureUnit(int v) {
+ requestedTextureUnit = v;
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -947,6 +996,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Called to get the current backend's GLDrawable
public GLDrawable getDrawable();
+ /** Returns the used texture unit, i.e. a value of [0..n], or -1 if non used. */
+ public int getTextureUnit();
+
// Called to fetch the "real" GLCapabilities for the backend
public GLCapabilitiesImmutable getChosenGLCapabilities();
@@ -987,7 +1039,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private GLDrawableImpl offscreenDrawable;
private FBObject fboFlipped;
private GLSLTextureRaster glslTextureRaster;
- private final int fboTextureUnit = 0;
private GLContextImpl offscreenContext;
private boolean flipVertical;
@@ -1035,12 +1086,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode();
helper.setAutoSwapBufferMode(false);
final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
+ fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
try {
fboFlipped = new FBObject();
fboFlipped.reset(gl, fboDrawable.getWidth(), fboDrawable.getHeight(), 0, false);
fboFlipped.attachTexture2D(gl, 0, chosenCaps.getAlphaBits()>0);
// fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
- glslTextureRaster = new GLSLTextureRaster(fboTextureUnit, true);
+ glslTextureRaster = new GLSLTextureRaster(fboDrawable.getTextureUnit(), true);
glslTextureRaster.init(gl.getGL2ES2());
glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, fboDrawable.getWidth(), fboDrawable.getHeight());
} catch (Exception ex) {
@@ -1210,7 +1262,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
fboDrawable.swapBuffers();
fboFlipped.bind(gl);
- // gl.glActiveTexture(fboDrawable.getTextureUnit()); // implicit!
+ // gl.glActiveTexture(GL.GL_TEXTURE0 + fboDrawable.getTextureUnit()); // implicit by GLFBODrawableImpl: swapBuffers/contextMadeCurent -> swapFBOImpl
gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
// gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
glslTextureRaster.display(gl.getGL2ES2());
@@ -1244,6 +1296,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// correctness on all platforms
}
}
+
+ @Override
+ public int getTextureUnit() {
+ if(null != glslTextureRaster && null != offscreenDrawable) { // implies flippedVertical
+ return ((GLFBODrawable)offscreenDrawable).getTextureUnit();
+ }
+ return -1;
+ }
@Override
public void doPaintComponent(Graphics g) {
@@ -1446,6 +1506,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public int getTextureUnit() { return -1; }
+
+ @Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
// FIXME: should do better than this; is it possible to using only platform-independent code?
return new GLCapabilities(null);
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp
index 06edbeaee..fb71abd14 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp
@@ -7,6 +7,7 @@
#if __VERSION__ >= 130
#define varying in
out vec4 mgl_FragColor;
+ #define texture2D texture
#else
#define mgl_FragColor gl_FragColor
#endif
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp
index 07a005709..8e5600dd9 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp
@@ -7,6 +7,7 @@
#if __VERSION__ >= 130
#define varying in
out vec4 mgl_FragColor;
+ #define texture2D texture
#else
#define mgl_FragColor gl_FragColor
#endif
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
index 0f762e79c..8479c08ca 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
@@ -71,7 +71,7 @@ public class TypecastFontConstructor implements FontConstructor {
int len=0;
Font f = null;
try {
- tf = IOUtil.createTempFile( "jogl.font", ".ttf", false, null);
+ tf = IOUtil.createTempFile( "jogl.font", ".ttf", false);
len = IOUtil.copyURLConn2File(fconn, tf);
if(len==0) {
tf.delete();
diff --git a/src/jogl/classes/jogamp/opengl/Debug.java b/src/jogl/classes/jogamp/opengl/Debug.java
index 4287c1960..b88a09b71 100644
--- a/src/jogl/classes/jogamp/opengl/Debug.java
+++ b/src/jogl/classes/jogamp/opengl/Debug.java
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * 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
@@ -39,6 +40,9 @@
package jogamp.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -49,7 +53,12 @@ public class Debug extends PropertyAccess {
private static final boolean debugAll;
static {
- PropertyAccess.addTrustedPrefix("jogl.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("jogl.");
+ return null;
+ } } );
+
verbose = isPropertyDefined("jogl.verbose", true);
debugAll = isPropertyDefined("jogl.debug", true);
if (verbose) {
@@ -59,28 +68,19 @@ public class Debug extends PropertyAccess {
System.err.println("JOGL implementation vendor " + p.getImplementationVendor());
}
}
-
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static String getProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getProperty(property, jnlpAlias, null);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(String subcomponent) {
return debugAll() || isPropertyDefined("jogl.debug." + subcomponent, true);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
index f77f1135b..ef9477a31 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
@@ -32,7 +32,7 @@ import java.util.List;
import java.util.ArrayList;
public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
- private static List<String> glueLibNames;
+ private static final List<String> glueLibNames;
static {
glueLibNames = new ArrayList<String>();
@@ -49,7 +49,7 @@ public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibrary
}
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(String funcName) {
return true;
}
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
index ff49303ca..8eb3468ed 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
+++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
@@ -37,9 +37,9 @@ public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper {
super(info);
}
- public DesktopGLDynamicLibraryBundleInfo getDesktopGLBundleInfo() { return (DesktopGLDynamicLibraryBundleInfo) getBundleInfo(); }
+ public final DesktopGLDynamicLibraryBundleInfo getDesktopGLBundleInfo() { return (DesktopGLDynamicLibraryBundleInfo) getBundleInfo(); }
- public synchronized boolean loadGLULibrary() {
+ public final synchronized boolean loadGLULibrary() {
/** hacky code .. where all platform GLU libs are tried ..*/
if(null==gluLib) {
List<String> gluLibNames = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
index 7c7ea1508..94acf93b0 100644
--- a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
+++ b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
@@ -219,17 +219,17 @@ final class ExtensionAvailabilityCache {
System.err.println(getThreadName() + ":ExtensionAvailabilityCache: ALL EXTENSIONS: "+availableExtensionCache.size());
}
- if(!context.isGLES()) {
- final VersionNumber version = context.getGLVersionNumber();
- int major[] = new int[] { version.getMajor() };
- int minor[] = new int[] { version.getMinor() };
- while (GLContext.isValidGLVersion(major[0], minor[0])) {
- availableExtensionCache.add("GL_VERSION_" + major[0] + "_" + minor[0]);
- if (DEBUG) {
- System.err.println(getThreadName() + ":ExtensionAvailabilityCache: Added GL_VERSION_" + major[0] + "_" + minor[0] + " to known extensions");
- }
- if(!GLContext.decrementGLVersion(major, minor)) break;
+ final int ctxOptions = context.getCtxOptions();
+ final VersionNumber version = context.getGLVersionNumber();
+ int major[] = new int[] { version.getMajor() };
+ int minor[] = new int[] { version.getMinor() };
+ while (GLContext.isValidGLVersion(ctxOptions, major[0], minor[0])) {
+ final String GL_XX_VERSION = ( context.isGLES() ? "GL_ES_VERSION_" : "GL_VERSION_" ) + major[0] + "_" + minor[0];
+ availableExtensionCache.add(GL_XX_VERSION);
+ if (DEBUG) {
+ System.err.println(getThreadName() + ":ExtensionAvailabilityCache: Added "+GL_XX_VERSION+" to known extensions");
}
+ if(!GLContext.decrementGLVersion(ctxOptions, major, minor)) break;
}
// put a dummy var in here so that the cache is no longer empty even if
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java
index 78ab7cc93..17646cc7b 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java
@@ -87,6 +87,13 @@ import com.jogamp.common.util.IntLongHashMap;
*/
public class GLBufferSizeTracker {
+ protected static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferSizeTracker", true);
+ }
+
// Map from buffer names to sizes.
// Note: should probably have some way of shrinking this map, but
// can't just make it a WeakHashMap because nobody holds on to the
@@ -95,8 +102,7 @@ public class GLBufferSizeTracker {
// pattern of buffer objects indicates that the fact that this map
// never shrinks is probably not that bad.
private IntLongHashMap bufferSizeMap;
- protected static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferSizeTracker", true);
-
+
public GLBufferSizeTracker() {
bufferSizeMap = new IntLongHashMap();
bufferSizeMap.setKeyNotFoundValue(0xFFFFFFFFFFFFFFFFL);
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
index 7f5316fbd..890c82c90 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
@@ -76,7 +76,13 @@ import com.jogamp.common.util.IntIntHashMap;
*/
public class GLBufferStateTracker {
- protected static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferStateTracker", true);
+ protected static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferStateTracker", true);
+ }
+
// Maps binding targets to buffer objects. A null value indicates
// that the binding is unknown. A zero value indicates that it is
// known that no buffer is bound to the target, according to the
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index cab629c3a..996a47590 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -40,8 +40,11 @@
package jogamp.opengl;
+import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
@@ -65,6 +68,7 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL3ES3;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDebugListener;
@@ -259,6 +263,17 @@ public abstract class GLContextImpl extends GLContext {
}
@Override
+ public final GL getRootGL() {
+ GL _gl = gl;
+ GL _parent = _gl.getDownstreamGL();
+ while ( null != _parent ) {
+ _gl = _parent;
+ _parent = _gl.getDownstreamGL();
+ }
+ return _gl;
+ }
+
+ @Override
public final GL getGL() {
return gl;
}
@@ -275,6 +290,11 @@ public abstract class GLContextImpl extends GLContext {
return gl;
}
+ @Override
+ public final int getDefaultVAO() {
+ return defaultVAO;
+ }
+
/**
* Call this method to notify the OpenGL context
* that the drawable has changed (size or position).
@@ -394,9 +414,10 @@ public abstract class GLContextImpl extends GLContext {
associateDrawableException = t;
}
if ( 0 != defaultVAO ) {
- int[] tmp = new int[] { defaultVAO };
- gl.getGL2GL3().glBindVertexArray(0);
- gl.getGL2GL3().glDeleteVertexArrays(1, tmp, 0);
+ final int[] tmp = new int[] { defaultVAO };
+ final GL3ES3 gl3es3 = gl.getRootGL().getGL3ES3();
+ gl3es3.glBindVertexArray(0);
+ gl3es3.glDeleteVertexArrays(1, tmp, 0);
defaultVAO = 0;
}
glDebugHandler.enable(false);
@@ -631,16 +652,12 @@ public abstract class GLContextImpl extends GLContext {
final boolean created;
try {
created = createImpl(shareWith); // may throws exception if fails!
- if( created && isGL3core() ) {
- // Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
- // GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
- // there is no more default VAO buffer 0 bound, hence generating and binding one
- // to avoid INVALID_OPERATION at VertexAttribPointer.
- // More clear is GL 4.3 core spec: 10.4 (p 307).
+ if( created && hasNoDefaultVAO() ) {
final int[] tmp = new int[1];
- gl.getGL2GL3().glGenVertexArrays(1, tmp, 0);
+ final GL3ES3 gl3es3 = gl.getRootGL().getGL3ES3();
+ gl3es3.glGenVertexArrays(1, tmp, 0);
defaultVAO = tmp[0];
- gl.getGL2GL3().glBindVertexArray(defaultVAO);
+ gl3es3.glBindVertexArray(defaultVAO);
}
} finally {
if (null != shareWith) {
@@ -669,7 +686,7 @@ public abstract class GLContextImpl extends GLContext {
if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile
final int reqMajor;
final int reqProfile;
- if( ctxVersion.compareTo(Version30) <= 0 ) {
+ if( ctxVersion.compareTo(Version300) <= 0 ) {
reqMajor = 2;
} else {
reqMajor = ctxVersion.getMajor();
@@ -834,6 +851,7 @@ public abstract class GLContextImpl extends GLContext {
boolean hasGL2 = false;
boolean hasGL4 = false;
boolean hasGL3 = false;
+ boolean hasES3 = false;
// Even w/ PROFILE_ALIASING, try to use true core GL profiles
// ensuring proper user behavior across platforms due to different feature sets!
@@ -902,6 +920,13 @@ public abstract class GLContextImpl extends GLContext {
resetStates(); // clean this context states, since creation was temporary
}
}
+ if(!hasES3) {
+ hasES3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_ES); // ES3
+ success |= hasES3;
+ if(hasES3) {
+ resetStates(); // clean this context states, since creation was temporary
+ }
+ }
if(success) {
// only claim GL versions set [and hence detected] if ARB context creation was successful
GLContext.setAvailableGLVersionsSet(device);
@@ -923,12 +948,7 @@ public abstract class GLContextImpl extends GLContext {
**/
private final boolean createContextARBMapVersionsAvailable(int reqMajor, int reqProfile) {
long _context;
- int ctp = CTX_IS_ARB_CREATED;
- if(CTX_PROFILE_COMPAT == reqProfile) {
- ctp |= CTX_PROFILE_COMPAT ;
- } else {
- ctp |= CTX_PROFILE_CORE ;
- }
+ int ctp = CTX_IS_ARB_CREATED | reqProfile;
// To ensure GL profile compatibility within the JOGL application
// we always try to map against the highest GL version,
@@ -938,10 +958,10 @@ public abstract class GLContextImpl extends GLContext {
int major[] = new int[1];
int minor[] = new int[1];
if( 4 == reqMajor ) {
- majorMax=4; minorMax=GLContext.getMaxMinor(majorMax);
+ majorMax=4; minorMax=GLContext.getMaxMinor(ctp, majorMax);
majorMin=4; minorMin=0;
} else if( 3 == reqMajor ) {
- majorMax=3; minorMax=GLContext.getMaxMinor(majorMax);
+ majorMax=3; minorMax=GLContext.getMaxMinor(ctp, majorMax);
majorMin=3; minorMin=1;
} else /* if( glp.isGL2() ) */ {
// our minimum desktop OpenGL runtime requirements are 1.1,
@@ -1001,7 +1021,7 @@ public abstract class GLContextImpl extends GLContext {
minor[0]=minorMax;
long _context=0;
- while ( GLContext.isValidGLVersion(major[0], minor[0]) &&
+ while ( GLContext.isValidGLVersion(ctxOptionFlags, major[0], minor[0]) &&
( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) {
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARBVersions: share "+share+", direct "+direct+", version "+major[0]+"."+minor[0]);
@@ -1017,7 +1037,7 @@ public abstract class GLContextImpl extends GLContext {
}
}
- if(!GLContext.decrementGLVersion(major, minor)) {
+ if(!GLContext.decrementGLVersion(ctxOptionFlags, major, minor)) {
break;
}
}
@@ -1038,11 +1058,11 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
}
- if (!GLContext.isValidGLVersion(major, minor)) {
+ if (!GLContext.isValidGLVersion(ctp, major, minor)) {
throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
}
ctxVersion = new VersionNumber(major, minor, 0);
- ctxVersionString = getGLVersion(major, minor, ctxOptions, glVersion);
+ ctxVersionString = getGLVersion(major, minor, ctp, glVersion);
ctxVendorVersion = glVendorVersion;
ctxOptions = ctp;
if(useGL) {
@@ -1085,6 +1105,27 @@ public abstract class GLContextImpl extends GLContext {
*/
return gl;
}
+
+ /**
+ * Finalizes GL instance initialization after this context has been initialized.
+ * <p>
+ * Method calls 'void finalizeInit()' of instance 'gl' as retrieved by reflection, if exist.
+ * </p>
+ */
+ private void finalizeInit(GL gl) {
+ Method finalizeInit = null;
+ try {
+ finalizeInit = ReflectionUtil.getMethod(gl.getClass(), "finalizeInit", new Class<?>[]{ });
+ } catch ( Throwable t ) {
+ if(DEBUG) {
+ System.err.println("Catched "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ if( null != finalizeInit ) {
+ ReflectionUtil.callMethod(gl, finalizeInit, new Object[]{ });
+ }
+ }
public final ProcAddressTable getGLProcAddressTable() {
return glProcAddressTable;
@@ -1095,24 +1136,24 @@ public abstract class GLContextImpl extends GLContext {
* ie for GLXExt, EGLExt, ..
*/
public abstract ProcAddressTable getPlatformExtProcAddressTable();
-
+
/**
- * Pbuffer support; given that this is a GLContext associated with a
- * pbuffer, binds this pbuffer to its texture target.
- * @throws GLException if not implemented (default)
- * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer
+ * Part of <code>GL_NV_vertex_array_range</code>.
+ * <p>
+ * Provides platform-independent access to the <code>wglAllocateMemoryNV</code> /
+ * <code>glXAllocateMemoryNV</code>.
+ * </p>
*/
- public void bindPbufferToTexture() { throw new GLException("not implemented"); }
+ public abstract ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority);
/**
- * Pbuffer support; given that this is a GLContext associated with a
- * pbuffer, releases this pbuffer from its texture target.
- * @throws GLException if not implemented (default)
- * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer
- */
- public void releasePbufferFromTexture() { throw new GLException("not implemented"); }
-
- public abstract ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3);
+ * Part of <code>GL_NV_vertex_array_range</code>.
+ * <p>
+ * Provides platform-independent access to the <code>wglFreeMemoryNV</code> /
+ * <code>glXFreeMemoryNV</code>.
+ * </p>
+ */
+ public abstract void glFreeMemoryNV(ByteBuffer pointer);
/** Maps the given "platform-independent" function name to a real function
name. Currently this is only used to map "glAllocateMemoryNV" and
@@ -1144,10 +1185,15 @@ public abstract class GLContextImpl extends GLContext {
/** Helper routine which resets a ProcAddressTable generated by the
GLEmitter by looking up anew all of its function pointers. */
- protected final void resetProcAddressTable(ProcAddressTable table) {
- table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
+ protected final void resetProcAddressTable(final ProcAddressTable table) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
+ return null;
+ }
+ } );
}
-
+
private final boolean initGLRendererAndGLVersionStrings() {
final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString");
@@ -1217,7 +1263,7 @@ public abstract class GLContextImpl extends GLContext {
int[] major = new int[] { version.getMajor() };
int[] minor = new int[] { version.getMinor() };
limitNonARBContextVersion(major, minor, ctp);
- if ( GLContext.isValidGLVersion(major[0], minor[0]) ) {
+ if ( GLContext.isValidGLVersion(ctp, major[0], minor[0]) ) {
return new VersionNumber(major[0], minor[0], 0);
}
}
@@ -1253,6 +1299,11 @@ public abstract class GLContextImpl extends GLContext {
}
}
+ protected final int getCtxOptions() {
+ return ctxOptions;
+ }
+
+
/**
* Sets the OpenGL implementation class and
* the cache of which GL functions are available for calling through this
@@ -1284,7 +1335,7 @@ public abstract class GLContextImpl extends GLContext {
return true; // already done and not forced
}
- if ( 0 < major && !GLContext.isValidGLVersion(major, minor) ) {
+ if ( 0 < major && !GLContext.isValidGLVersion(ctxProfileBits, major, minor) ) {
throw new GLException("Invalid GL Version Request "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
}
@@ -1345,7 +1396,7 @@ public abstract class GLContextImpl extends GLContext {
}
// Only validate if a valid int version was fetched, otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX!
- if ( GLContext.isValidGLVersion(glIntMajor[0], glIntMinor[0]) ) {
+ if ( GLContext.isValidGLVersion(ctxProfileBits, glIntMajor[0], glIntMinor[0]) ) {
if( glIntMajor[0]<major || ( glIntMajor[0]==major && glIntMinor[0]<minor ) || 0 == major ) {
if( strictMatch && 2 < major ) { // relaxed match for versions major < 3 requests, last resort!
if(DEBUG) {
@@ -1400,8 +1451,8 @@ public abstract class GLContextImpl extends GLContext {
System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: post version verification "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", strictMatch "+strictMatch+", versionValidated "+versionValidated+", versionGL3IntFailed "+versionGL3IntFailed);
}
- if( 2 > major ) { // there is no ES2-compat for a profile w/ major < 2
- ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT;
+ if( 2 > major ) { // there is no ES2/3-compat for a profile w/ major < 2
+ ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT ) ;
}
final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
@@ -1477,13 +1528,31 @@ public abstract class GLContextImpl extends GLContext {
}
}
- if( ( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && major >= 2 ) || isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) ) {
+ if( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) ) {
+ if( major >= 3 ) {
+ ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ;
+ ctxProfileBits |= CTX_IMPL_FBO;
+ } else if( major >= 2 ) {
+ ctxProfileBits |= CTX_IMPL_ES2_COMPAT;
+ ctxProfileBits |= CTX_IMPL_FBO;
+ }
+ } else if( ( major > 4 || major == 4 && minor >= 3 ) ||
+ ( ( major > 3 || major == 3 && minor >= 1 ) && isExtensionAvailable( GLExtensions.ARB_ES3_compatibility ) ) ) {
+ // See GLContext.isGLES3CompatibleAvailable(..)/isGLES3Compatible()
+ // Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ;
+ ctxProfileBits |= CTX_IMPL_FBO;
+ } else if( isExtensionAvailable( GLExtensions.ARB_ES2_compatibility ) ) {
ctxProfileBits |= CTX_IMPL_ES2_COMPAT;
ctxProfileBits |= CTX_IMPL_FBO;
} else if( hasFBOImpl(major, ctxProfileBits, extensionAvailability) ) {
ctxProfileBits |= CTX_IMPL_FBO;
}
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && major == 1 ) || isExtensionAvailable(GLExtensions.OES_single_precision) ) {
+ ctxProfileBits |= CTX_IMPL_FP32_COMPAT_API;
+ }
+
if(FORCE_NO_FBO_SUPPORT) {
ctxProfileBits &= ~CTX_IMPL_FBO ;
}
@@ -1493,6 +1562,8 @@ public abstract class GLContextImpl extends GLContext {
//
setContextVersion(major, minor, ctxProfileBits, vendorVersion, true);
+ finalizeInit(gl);
+
setDefaultSwapInterval();
final int glErrX = gl.glGetError(); // clear GL error, maybe caused by above operations
@@ -1508,6 +1579,8 @@ public abstract class GLContextImpl extends GLContext {
int i = 0;
final String MesaSP = "Mesa ";
+ // final String MesaRendererAMDsp = " AMD ";
+ // final String MesaRendererIntelsp = "Intel(R)";
final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT );
final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT );
final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium ");
@@ -1596,7 +1669,7 @@ public abstract class GLContextImpl extends GLContext {
//
final int quirk = GLRendererQuirks.DontCloseX11Display;
if( glRenderer.contains(MesaSP) ) {
- if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version80) < 0 ) {
+ if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version800) < 0 ) {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
}
@@ -1632,7 +1705,7 @@ public abstract class GLContextImpl extends GLContext {
}
quirks[i++] = quirk;
}
- if( hwAccel /* glRenderer.contains("Intel(R)") || glRenderer.contains("AMD ") */ )
+ if( hwAccel /* glRenderer.contains( MesaRendererIntelsp ) || glRenderer.contains( MesaRendererAMDsp ) */ )
{
final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer;
if(DEBUG) {
@@ -1640,14 +1713,13 @@ public abstract class GLContextImpl extends GLContext {
}
quirks[i++] = quirk;
}
- if( glRenderer.contains("Intel(R)") && compatCtx && ( major > 3 || major == 3 && minor >= 1 ) )
- {
- // FIXME: Apply vendor version constraints!
- final int quirk = GLRendererQuirks.GLNonCompliant;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
- }
- quirks[i++] = quirk;
+ if (compatCtx && (major > 3 || (major == 3 && minor >= 1))) {
+ // FIXME: Apply vendor version constraints!
+ final int quirk = GLRendererQuirks.GLNonCompliant;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks[i++] = quirk;
}
if( Platform.getOSType() == Platform.OSType.WINDOWS && glRenderer.contains("SVGA3D") )
{
@@ -1748,7 +1820,7 @@ public abstract class GLContextImpl extends GLContext {
// Check GL 1st (cached)
if(null!=glProcAddressTable) { // null if this context wasn't not created
try {
- if(0!=glProcAddressTable.getAddressFor(glFunctionName)) {
+ if( glProcAddressTable.isFunctionAvailable( glFunctionName ) ) {
return true;
}
} catch (Exception e) {}
@@ -1758,31 +1830,28 @@ public abstract class GLContextImpl extends GLContext {
final ProcAddressTable pTable = getPlatformExtProcAddressTable();
if(null!=pTable) {
try {
- if(0!=pTable.getAddressFor(glFunctionName)) {
+ if( pTable.isFunctionAvailable( glFunctionName ) ) {
return true;
}
} catch (Exception e) {}
}
// dynamic function lookup at last incl name aliasing (not cached)
- DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
- String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
- long addr = 0;
+ final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
+ final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
+ boolean res = false;
int variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
- for(int i = 0; 0==addr && i < variants; i++) {
- String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
+ for(int i = 0; !res && i < variants; i++) {
+ final String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
try {
- addr = dynLookup.dynamicLookupFunction(tmp);
+ res = dynLookup.isFunctionAvailable(tmp);
} catch (Exception e) { }
}
- if(0!=addr) {
- return true;
- }
- return false;
+ return res;
}
@Override
- public boolean isExtensionAvailable(String glExtensionName) {
+ public final boolean isExtensionAvailable(String glExtensionName) {
if(null!=extensionAvailability) {
return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName));
}
@@ -1824,7 +1893,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_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ;
+ ctxProfileBits &= CTX_IMPL_CACHE_MASK;
return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits));
}
@@ -1900,10 +1969,6 @@ public abstract class GLContextImpl extends GLContext {
return glStateTracker;
}
- public final boolean isDefaultVAO(int vao) {
- return defaultVAO == vao;
- }
-
//---------------------------------------------------------------------------
// Helpers for context optimization where the last context is left
// current on the OpenGL worker thread
@@ -2009,7 +2074,7 @@ public abstract class GLContextImpl extends GLContext {
public final int getContextCreationFlags() {
return additionalCtxCreationFlags;
}
-
+
@Override
public final void setContextCreationFlags(int flags) {
if(!isCreated()) {
@@ -2052,7 +2117,7 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled) {
if(glDebugHandler.isExtensionARB()) {
- gl.getGL2GL3().glDebugMessageControlARB(source, type, severity, count, ids, enabled);
+ gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, enabled);
} else if(glDebugHandler.isExtensionAMD()) {
gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, enabled);
}
@@ -2061,7 +2126,7 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final void glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled) {
if(glDebugHandler.isExtensionARB()) {
- gl.getGL2GL3().glDebugMessageControlARB(source, type, severity, count, ids, ids_offset, enabled);
+ gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, ids_offset, enabled);
} else if(glDebugHandler.isExtensionAMD()) {
gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, ids_offset, enabled);
}
@@ -2071,15 +2136,15 @@ public abstract class GLContextImpl extends GLContext {
public final void glDebugMessageInsert(int source, int type, int id, int severity, String buf) {
final int len = (null != buf) ? buf.length() : 0;
if(glDebugHandler.isExtensionARB()) {
- gl.getGL2GL3().glDebugMessageInsertARB(source, type, id, severity, len, buf);
+ gl.getGL2GL3().glDebugMessageInsert(source, type, id, severity, len, buf);
} else if(glDebugHandler.isExtensionAMD()) {
gl.getGL2GL3().glDebugMessageInsertAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, id, len, buf);
}
}
/** Internal bootstraping glGetString(GL_RENDERER) */
- protected static native String glGetStringInt(int name, long procAddress);
+ private static native String glGetStringInt(int name, long procAddress);
/** Internal bootstraping glGetIntegerv(..) for version */
- protected static native void glGetIntegervInt(int pname, int[] params, int params_offset, long procAddress);
+ private static native void glGetIntegervInt(int pname, int[] params, int params_offset, long procAddress);
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
index 0000e6199..9ecaca75d 100644
--- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
+++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
@@ -27,6 +27,8 @@
*/
package jogamp.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import javax.media.nativewindow.NativeWindowException;
@@ -39,8 +41,6 @@ import com.jogamp.common.os.Platform;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.opengl.GLExtensions;
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
-
/**
* The GLDebugMessageHandler, handling <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>
* debug messages.<br>
@@ -107,6 +107,18 @@ public class GLDebugMessageHandler {
}
}
+ private final long getAddressFor(final ProcAddressTable table, final String functionName) {
+ return AccessController.doPrivileged(new PrivilegedAction<Long>() {
+ public Long run() {
+ try {
+ return Long.valueOf( table.getAddressFor(functionName) );
+ } catch (IllegalArgumentException iae) {
+ return Long.valueOf(0);
+ }
+ }
+ } ).longValue();
+ }
+
public void init() {
ctx.validateCurrent();
if( isAvailable()) {
@@ -148,17 +160,17 @@ public class GLDebugMessageHandler {
}
final ProcAddressTable procAddressTable = ctx.getGLProcAddressTable();
- if( procAddressTable instanceof GL4bcProcAddressTable) {
- final GL4bcProcAddressTable desktopProcAddressTable = (GL4bcProcAddressTable)procAddressTable;
+ if( !ctx.isGLES1() && !ctx.isGLES2() ) {
switch(extType) {
case EXT_ARB:
- glDebugMessageCallbackProcAddress = desktopProcAddressTable._addressof_glDebugMessageCallbackARB;
+ glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackARB");
break;
case EXT_AMD:
- glDebugMessageCallbackProcAddress = desktopProcAddressTable._addressof_glDebugMessageCallbackAMD;
+ glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackAMD");
break;
}
} else {
+ glDebugMessageCallbackProcAddress = 0;
if(DEBUG) {
System.err.println("Non desktop context not supported");
}
@@ -212,9 +224,9 @@ public class GLDebugMessageHandler {
private final void setSynchronousImpl() {
if(isExtensionARB()) {
if(synchronous) {
- ctx.getGL().glEnable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ ctx.getGL().glEnable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS);
} else {
- ctx.getGL().glDisable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ ctx.getGL().glDisable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
if(DEBUG) {
System.err.println("GLDebugMessageHandler: synchronous "+synchronous);
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 06e856d41..41ea06deb 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -247,7 +247,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
@Override
- public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp);
@Override
public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
@@ -263,7 +263,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- if ( !canCreateGLPbuffer(device) ) {
+ if ( !canCreateGLPbuffer(device, capsRequested.getGLProfile()) ) {
throw new GLException("Pbuffer not available with device: "+device);
}
@@ -575,16 +575,16 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
rampEntry = 0.0f;
gammaRamp[i] = rampEntry;
}
- registerGammaShutdownHook();
+ needsGammaRampReset = true;
return setGammaRamp(gammaRamp);
}
+ @Override
public synchronized void resetDisplayGamma() {
- if (gammaShutdownHook == null) {
- throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first");
+ if( needsGammaRampReset ) {
+ resetGammaRamp(originalGammaRamp);
+ needsGammaRampReset = false;
}
- resetGammaRamp(originalGammaRamp);
- unregisterGammaShutdownHook();
}
//------------------------------------------------------
@@ -616,35 +616,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
}
// Shutdown hook mechanism for resetting gamma
- private boolean gammaShutdownHookRegistered;
- private Thread gammaShutdownHook;
- private Buffer originalGammaRamp;
- private synchronized void registerGammaShutdownHook() {
- if (gammaShutdownHookRegistered)
- return;
- if (gammaShutdownHook == null) {
- gammaShutdownHook = new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (GLDrawableFactoryImpl.this) {
- resetGammaRamp(originalGammaRamp);
- }
- }
- });
- originalGammaRamp = getGammaRamp();
- }
- Runtime.getRuntime().addShutdownHook(gammaShutdownHook);
- gammaShutdownHookRegistered = true;
- }
-
- private synchronized void unregisterGammaShutdownHook() {
- if (!gammaShutdownHookRegistered)
- return;
- if (gammaShutdownHook == null) {
- throw new InternalError("Error in gamma shutdown hook logic");
- }
- Runtime.getRuntime().removeShutdownHook(gammaShutdownHook);
- gammaShutdownHookRegistered = false;
- // Leave the original gamma ramp data alone
- }
+ private volatile Buffer originalGammaRamp;
+ private volatile boolean needsGammaRampReset = false;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 177c465da..5418fbaf3 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -62,8 +62,13 @@ import javax.media.opengl.GLRunnable;
methods to be able to share it between GLAutoDrawable implementations like GLAutoDrawableBase, GLCanvas and GLJPanel. */
public class GLDrawableHelper {
/** true if property <code>jogl.debug.GLDrawable.PerfStats</code> is defined. */
- private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
+ private static final boolean PERF_STATS;
+ static {
+ Debug.initSingleton();
+ PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
+ }
+
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
private final Object listenersLock = new Object();
private final ArrayList<GLEventListener> listeners = new ArrayList<GLEventListener>();
@@ -531,10 +536,10 @@ public class GLDrawableHelper {
}
}
- private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
+ private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape, boolean setViewport) {
l.init(drawable);
if(sendReshape) {
- reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */);
+ reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), setViewport, false /* checkInit */);
}
}
@@ -545,33 +550,40 @@ public class GLDrawableHelper {
public final void init(GLAutoDrawable drawable, boolean sendReshape) {
synchronized(listenersLock) {
final ArrayList<GLEventListener> _listeners = listeners;
- for (int i=0; i < _listeners.size(); i++) {
- final GLEventListener listener = _listeners.get(i) ;
-
- // If make ctx current, 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),
- // hence it must be called unconditional, always.
- listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init
- init( listener, drawable, sendReshape);
+ final int listenerCount = _listeners.size();
+ if( listenerCount > 0 ) {
+ for (int i=0; i < listenerCount; i++) {
+ final GLEventListener listener = _listeners.get(i) ;
+
+ // If make ctx current, 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),
+ // hence it must be called unconditional, always.
+ listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init
+ init( listener, drawable, sendReshape, 0==i /* setViewport */);
+ }
+ } else {
+ // Expose same GL initialization if not using GLEventListener
+ drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
}
}
}
public final void display(GLAutoDrawable drawable) {
displayImpl(drawable);
- if(!execGLRunnables(drawable)) {
+ if( glRunnables.size()>0 && !execGLRunnables(drawable) ) { // glRunnables volatile OK; execGL.. only executed if size > 0
displayImpl(drawable);
}
}
private final void displayImpl(GLAutoDrawable drawable) {
synchronized(listenersLock) {
final ArrayList<GLEventListener> _listeners = listeners;
- for (int i=0; i < _listeners.size(); i++) {
+ final int listenerCount = _listeners.size();
+ for (int i=0; i < listenerCount; 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
if( listenersToBeInit.remove(listener) ) {
- init( listener, drawable, true /* sendReshape */) ;
+ init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ );
}
listener.display(drawable);
}
@@ -585,7 +597,7 @@ public class GLDrawableHelper {
// in case this one is added after the realization of the GLAutoDrawable
synchronized(listenersLock) {
if( listenersToBeInit.remove(listener) ) {
- init( listener, drawable, false /* sendReshape */) ;
+ listener.init(drawable);
}
}
}
@@ -598,29 +610,27 @@ public class GLDrawableHelper {
public final void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
synchronized(listenersLock) {
for (int i=0; i < listeners.size(); i++) {
- reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i, true);
+ reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i /* setViewport */, true /* checkInit */);
}
}
}
- private final boolean execGLRunnables(GLAutoDrawable drawable) {
+ private final boolean execGLRunnables(GLAutoDrawable drawable) { // glRunnables.size()>0
boolean res = true;
- if(glRunnables.size()>0) { // volatile OK
- // swap one-shot list asap
- final ArrayList<GLRunnableTask> _glRunnables;
- synchronized(glRunnablesLock) {
- if(glRunnables.size()>0) {
- _glRunnables = glRunnables;
- glRunnables = new ArrayList<GLRunnableTask>();
- } else {
- _glRunnables = null;
- }
+ // swap one-shot list asap
+ final ArrayList<GLRunnableTask> _glRunnables;
+ synchronized(glRunnablesLock) {
+ if(glRunnables.size()>0) {
+ _glRunnables = glRunnables;
+ glRunnables = new ArrayList<GLRunnableTask>();
+ } else {
+ _glRunnables = null;
}
-
- if(null!=_glRunnables) {
- for (int i=0; i < _glRunnables.size(); i++) {
- res = _glRunnables.get(i).run(drawable) && res;
- }
+ }
+
+ if(null!=_glRunnables) {
+ for (int i=0; i < _glRunnables.size(); i++) {
+ res = _glRunnables.get(i).run(drawable) && res;
}
}
return res;
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 877e7b60b..e1088da29 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -116,6 +116,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
* {@link GL#glFlush()} has been called already and
* the implementation may execute implementation specific code.
* </p>
+ * @param doubleBuffered indicates whether double buffering is enabled, see above.
*/
protected abstract void swapBuffersImpl(boolean doubleBuffered);
diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
index 4c82fc2b3..8ba9f617b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
@@ -36,16 +36,29 @@ public abstract class GLDynamicLibraryBundleInfo implements DynamicLibraryBundle
protected GLDynamicLibraryBundleInfo() {
}
- /** default **/
- @Override
- public boolean shallLinkGlobal() { return false; }
-
- /** default **/
+ /**
+ * Returns <code>true</code>,
+ * since we might load a desktop GL library and allow symbol access to subsequent libs.
+ * <p>
+ * This respects old DRI requirements:
+ * <pre>
+ * http://dri.sourceforge.net/doc/DRIuserguide.html
+ * </pre>
+ * </p>
+ */
+ public final boolean shallLinkGlobal() { return true; }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>false</code>.
+ * </p>
+ */
@Override
public boolean shallLookupGlobal() { return false; }
@Override
- public RunnableExecutor getLibLoaderExecutor() {
+ public final RunnableExecutor getLibLoaderExecutor() {
return DynamicLibraryBundle.getDefaultRunnableExecutor();
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
index d2dac8148..1ed73f15e 100644
--- a/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
@@ -36,7 +36,7 @@ public class GLDynamicLookupHelper extends DynamicLibraryBundle {
super(info);
}
- public GLDynamicLibraryBundleInfo getGLBundleInfo() { return (GLDynamicLibraryBundleInfo) getBundleInfo(); }
+ public final GLDynamicLibraryBundleInfo getGLBundleInfo() { return (GLDynamicLibraryBundleInfo) getBundleInfo(); }
/** NOP per default */
public boolean loadGLULibrary() { return false; }
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 85f63b52c..3833e6852 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -37,8 +37,14 @@ import com.jogamp.opengl.JoglVersion;
* @see GLDrawableImpl#getDefaultReadFramebuffer()
*/
public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
- protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
- protected static final boolean DEBUG_SWAP = Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true);
+ protected static final boolean DEBUG;
+ protected static final boolean DEBUG_SWAP;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
+ DEBUG_SWAP = Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true);
+ }
private final GLDrawableImpl parent;
private GLCapabilitiesImmutable origParentChosenCaps;
@@ -52,7 +58,10 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
private int fboIBack; // points to GL_BACK buffer
private int fboIFront; // points to GL_FRONT buffer
private int pendingFBOReset = -1;
+ /** Indicated whether the FBO is bound. */
private boolean fboBound;
+ /** Indicated whether the FBO is swapped, resets to false after makeCurrent -> contextMadeCurrent. */
+ private boolean fboSwapped;
/** dump fboResetQuirk info only once pre ClassLoader and only in DEBUG mode */
private static volatile boolean resetQuirkInfoDumped = false;
@@ -139,21 +148,20 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
}
fbos[fboIFront].resetSamplingSink(gl);
- fboBound = false;
+
fbos[0].formatToGLCapabilities(chosenFBOCaps);
chosenFBOCaps.setDoubleBuffered( chosenFBOCaps.getDoubleBuffered() || samples > 0 );
-
- initialized = true;
} else {
- initialized = false;
-
for(int i=0; i<fbos.length; i++) {
fbos[i].destroy(gl);
}
fbos=null;
- fboBound = false;
- pendingFBOReset = -1;
}
+ fboBound = false;
+ fboSwapped = false;
+ pendingFBOReset = -1;
+ initialized = realize;
+
if(DEBUG) {
System.err.println("GLFBODrawableImpl.initialize("+realize+"): "+this);
Thread.dumpStack();
@@ -230,6 +238,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
ourContext.makeCurrent();
gl.glFinish(); // sync GL command stream
fboBound = false; // clear bound-flag immediatly, caused by contextMadeCurrent(..) - otherwise we would swap @ release
+ fboSwapped = false;
try {
final int maxSamples = gl.getMaxRenderbufferSamples();
newSamples = newSamples <= maxSamples ? newSamples : maxSamples;
@@ -340,10 +349,12 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
fbos[fboIBack].bind(gl);
fboBound = true;
- } else if( fboBound ) {
+ fboSwapped = false;
+ } else if( fboBound && !fboSwapped ) {
swapFBOImpl(glc);
swapFBOImplPost(glc);
fboBound=false;
+ fboSwapped=true;
if(DEBUG_SWAP) {
System.err.println("Post FBO swap(@release): done");
}
@@ -353,14 +364,16 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
@Override
protected void swapBuffersImpl(boolean doubleBuffered) {
final GLContext ctx = GLContext.getCurrent();
- boolean doPostSwap = false;
+ boolean doPostSwap;
if( null != ctx && ctx.getGLDrawable() == this && fboBound ) {
swapFBOImpl(ctx);
doPostSwap = true;
- fboBound=false;
+ fboSwapped = true;
if(DEBUG_SWAP) {
System.err.println("Post FBO swap(@swap): done");
}
+ } else {
+ doPostSwap = false;
}
if( null != swapBufferContext ) {
swapBufferContext.swapBuffers(doubleBuffered);
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index 48b509263..d54da4d28 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -200,8 +200,9 @@ public class GLGraphicsConfigurationUtil {
if(null == device) {
device = factory.getDefaultDevice();
}
- final boolean fboAvailable = GLContext.isFBOAvailable(device, capsRequested.getGLProfile());
- final boolean pbufferAvailable = factory.canCreateGLPbuffer(device);
+ final GLProfile glp = capsRequested.getGLProfile();
+ final boolean fboAvailable = GLContext.isFBOAvailable(device, glp);
+ final boolean pbufferAvailable = factory.canCreateGLPbuffer(device, glp);
final GLRendererQuirks glrq = factory.getRendererQuirks(device);
final boolean bitmapAvailable;
diff --git a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
index cea3ac4ab..e4187b35b 100644
--- a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
+++ b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
@@ -110,7 +110,7 @@ public class GLVersionNumber extends VersionNumberString {
String str;
{
final GLVersionNumber glv = create(versionString);
- str = versionString.substring(glv.endOfStringMatch());
+ str = versionString.substring(glv.endOfStringMatch()).trim();
}
while ( str.length() > 0 ) {
@@ -120,7 +120,7 @@ public class GLVersionNumber extends VersionNumberString {
if( version.hasMajor() && version.hasMinor() ) { // Requires at least a defined major and minor version component!
return version;
}
- str = str.substring( eosm );
+ str = str.substring( eosm ).trim();
} else {
break; // no match
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
index cddd142e9..3d59d1d53 100644
--- a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
@@ -36,8 +36,8 @@ import jogamp.opengl.*;
* Implementation of the DynamicLookupHelper for Desktop ES2 (AMD, ..)
* where EGL and ES2 functions reside within the desktop OpenGL library.
*/
-public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
- static List<String> glueLibNames;
+public final class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
+ static final List<String> glueLibNames;
static {
glueLibNames = new ArrayList<String>();
glueLibNames.add("jogl_mobile");
@@ -47,16 +47,6 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn
super();
}
- /**
- * Might be a desktop GL library, and might need to allow symbol access to subsequent libs.
- *
- * This respects old DRI requirements:<br>
- * <pre>
- * http://dri.sourceforge.net/doc/DRIuserguide.html
- * </pre>
- */
- public boolean shallLinkGlobal() { return true; }
-
public final List<String> getToolGetProcAddressFuncNameList() {
List<String> res = new ArrayList<String>();
res.add("eglGetProcAddress");
@@ -71,7 +61,7 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn
return true;
}
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 2b8ca31c9..e7977e3fb 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -171,7 +171,7 @@ public class EGLContext extends GLContextImpl {
try {
// might be unavailable on EGL < 1.2
- if(!EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API)) {
+ if( !EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API) ) {
throw new GLException("Catched: eglBindAPI to ES failed , error "+toHexString(EGL.eglGetError()));
}
} catch (GLException glex) {
@@ -188,18 +188,21 @@ public class EGLContext extends GLContextImpl {
}
final IntBuffer contextAttrsNIO;
+ final int contextVersionReq, contextVersionAttr;
{
- final int[] contextAttrs = new int[] {
- EGL.EGL_CONTEXT_CLIENT_VERSION, -1,
- EGL.EGL_NONE
- };
- if (glProfile.usesNativeGLES2()) {
- contextAttrs[1] = 2;
- } else if (glProfile.usesNativeGLES1()) {
- contextAttrs[1] = 1;
+ if ( glProfile.usesNativeGLES3() ) {
+ contextVersionReq = 3;
+ contextVersionAttr = 2;
+ } else if ( glProfile.usesNativeGLES2() ) {
+ contextVersionReq = 2;
+ contextVersionAttr = 2;
+ } else if ( glProfile.usesNativeGLES1() ) {
+ contextVersionReq = 1;
+ contextVersionAttr = 1;
} else {
throw new GLException("Error creating OpenGL context - invalid GLProfile: "+glProfile);
}
+ final int[] contextAttrs = new int[] { EGL.EGL_CONTEXT_CLIENT_VERSION, contextVersionAttr, EGL.EGL_NONE };
contextAttrsNIO = Buffers.newDirectIntBuffer(contextAttrs);
}
contextHandle = EGL.eglCreateContext(eglDisplay, eglConfig, shareWithHandle, contextAttrsNIO);
@@ -219,8 +222,7 @@ public class EGLContext extends GLContextImpl {
throw new GLException("Error making context " +
toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError()));
}
- setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES, false);
- return true;
+ return setGLFunctionAvailability(true, contextVersionReq, 0, CTX_PROFILE_ES, contextVersionReq>=3); // strict match for es >= 3
}
@Override
@@ -259,8 +261,7 @@ public class EGLContext extends GLContextImpl {
protected final StringBuilder getPlatformExtensionsStringImpl() {
StringBuilder sb = new StringBuilder();
if (!eglQueryStringInitialized) {
- eglQueryStringAvailable =
- getDrawableImpl().getGLDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0;
+ eglQueryStringAvailable = getDrawableImpl().getGLDynamicLookupHelper().isFunctionAvailable("eglQueryString");
eglQueryStringInitialized = true;
}
if (eglQueryStringAvailable) {
@@ -293,16 +294,25 @@ public class EGLContext extends GLContextImpl {
final GLProfile glp = caps.getGLProfile();
final int[] reqMajorCTP = new int[2];
GLContext.getRequestMajorAndCompat(glp, reqMajorCTP);
- if(glp.isGLES() && reqMajorCTP[0] >= 2) {
- reqMajorCTP[1] |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ if( glp.isGLES() ) {
+ if( reqMajorCTP[0] >= 3 ) {
+ reqMajorCTP[1] |= GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ } else if( reqMajorCTP[0] >= 2 ) {
+ reqMajorCTP[1] |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ }
}
- if(!caps.getHardwareAccelerated()) {
+ if( !caps.getHardwareAccelerated() ) {
reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT;
}
mapStaticGLVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]);
}
- /* pp */ 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 );
+ /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, final int major) {
+ int ctp = GLContext.CTX_PROFILE_ES;
+ if( major >= 3 ) {
+ ctp |= GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ } else if( major >= 2 ) {
+ ctp |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ }
mapStaticGLVersion(device, major, 0, ctp);
}
/* pp */ static void mapStaticGLVersion(AbstractGraphicsDevice device, int major, int minor, int ctp) {
@@ -344,9 +354,13 @@ public class EGLContext extends GLContextImpl {
throw new GLException("Not yet implemented");
}
-
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
+ throw new GLException("Should not call this");
+ }
+
+ @Override
+ public final void glFreeMemoryNV(ByteBuffer pointer) {
throw new GLException("Should not call this");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index adb78b3b9..5d99e3eba 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -84,26 +84,30 @@ import com.jogamp.opengl.GLRendererQuirks;
public class EGLDrawableFactory extends GLDrawableFactoryImpl {
protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; // allow package access
- /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
+ /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK;
+
+ static {
+ Debug.initSingleton();
+ QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
+ }
private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null;
private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null;
private static final boolean isANGLE(GLDynamicLookupHelper dl) {
if(Platform.OSType.WINDOWS == Platform.OS_TYPE) {
- final boolean r = 0 != dl.dynamicLookupFunction("eglQuerySurfacePointerANGLE") ||
- 0 != dl.dynamicLookupFunction("glBlitFramebufferANGLE") ||
- 0 != dl.dynamicLookupFunction("glRenderbufferStorageMultisampleANGLE");
- return r;
+ return dl.isFunctionAvailable("eglQuerySurfacePointerANGLE") ||
+ dl.isFunctionAvailable("glBlitFramebufferANGLE") ||
+ dl.isFunctionAvailable("glRenderbufferStorageMultisampleANGLE");
} else {
return false;
}
}
private static final boolean includesES1(GLDynamicLookupHelper dl) {
- return 0 != dl.dynamicLookupFunction("glLoadIdentity") &&
- 0 != dl.dynamicLookupFunction("glEnableClientState") &&
- 0 != dl.dynamicLookupFunction("glColorPointer");
+ return dl.isFunctionAvailable("glLoadIdentity") &&
+ dl.isFunctionAvailable("glEnableClientState") &&
+ dl.isFunctionAvailable("glColorPointer");
}
public EGLDrawableFactory() {
@@ -253,8 +257,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
String key = keyI.next();
SharedResource sr = sharedMap.get(key);
System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", "+
- "es1 [avail "+sr.wasES1ContextCreated+", pbuffer "+sr.hasPBufferES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+
- "es2 [avail "+sr.wasES2ContextCreated+", pbuffer "+sr.hasPBufferES2+", quirks "+sr.rendererQuirksES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES2, null)+"]");
+ "es1 [avail "+sr.wasES1ContextCreated+", pbuffer "+sr.hasPBufferES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+
+ "es2/3 [es2 "+sr.wasES2ContextCreated+", es3 "+sr.wasES3ContextCreated+", [pbuffer "+sr.hasPBufferES3ES2+", quirks "+sr.rendererQuirksES3ES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES3ES2, null)+"]]");
}
;
}
@@ -271,38 +275,45 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
private final EGLGraphicsDevice device;
// private final EGLContext contextES1;
// private final EGLContext contextES2;
- private final GLRendererQuirks rendererQuirksES1;
- private final GLRendererQuirks rendererQuirksES2;
- private final int ctpES1;
- private final int ctpES2;
+ // private final EGLContext contextES3;
private final boolean wasES1ContextCreated;
private final boolean wasES2ContextCreated;
+ private final boolean wasES3ContextCreated;
+ private final GLRendererQuirks rendererQuirksES1;
+ private final GLRendererQuirks rendererQuirksES3ES2;
+ private final int ctpES1;
+ private final int ctpES3ES2;
private final boolean hasPBufferES1;
- private final boolean hasPBufferES2;
+ private final boolean hasPBufferES3ES2;
SharedResource(EGLGraphicsDevice dev,
boolean wasContextES1Created, boolean hasPBufferES1, GLRendererQuirks rendererQuirksES1, int ctpES1,
- boolean wasContextES2Created, boolean hasPBufferES2, GLRendererQuirks rendererQuirksES2, int ctpES2) {
+ boolean wasContextES2Created, boolean wasContextES3Created,
+ boolean hasPBufferES3ES2, GLRendererQuirks rendererQuirksES3ES2, int ctpES3ES2) {
this.device = dev;
// this.contextES1 = ctxES1;
- // this.contextES2 = ctxES2;
+ this.wasES1ContextCreated = wasContextES1Created;
+ this.hasPBufferES1= hasPBufferES1;
this.rendererQuirksES1 = rendererQuirksES1;
- this.rendererQuirksES2 = rendererQuirksES2;
this.ctpES1 = ctpES1;
- this.ctpES2 = ctpES2;
- this.wasES1ContextCreated = wasContextES1Created;
+
+ // this.contextES2 = ctxES2;
+ // this.contextES3 = ctxES3;
this.wasES2ContextCreated = wasContextES2Created;
- this.hasPBufferES1= hasPBufferES1;
- this.hasPBufferES2= hasPBufferES2;
+ this.wasES3ContextCreated = wasContextES3Created;
+ this.hasPBufferES3ES2= hasPBufferES3ES2;
+ this.rendererQuirksES3ES2 = rendererQuirksES3ES2;
+ this.ctpES3ES2 = ctpES3ES2;
}
@Override
public final boolean isValid() {
- return wasES1ContextCreated || wasES2ContextCreated;
+ return wasES1ContextCreated || wasES2ContextCreated || wasES3ContextCreated;
}
@Override
public final EGLGraphicsDevice getDevice() { return device; }
// final EGLContext getContextES1() { return contextES1; }
// final EGLContext getContextES2() { return contextES2; }
+ // final EGLContext getContextES3() { return contextES3; }
@Override
public AbstractGraphicsScreen getScreen() {
@@ -318,7 +329,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
public GLRendererQuirks getRendererQuirks() {
- return null != rendererQuirksES2 ? rendererQuirksES2 : rendererQuirksES1 ;
+ return null != rendererQuirksES3ES2 ? rendererQuirksES3ES2 : rendererQuirksES1 ;
}
}
@@ -353,18 +364,30 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
boolean[] hasPBuffer, GLRendererQuirks[] rendererQuirks, int[] ctp) {
final String profileString;
switch( esProfile ) {
+ case 3:
+ profileString = GLProfile.GLES3; break;
+ case 2:
+ profileString = GLProfile.GLES2; break;
case 1:
profileString = GLProfile.GLES1; break;
- case 2:
default:
- profileString = GLProfile.GLES2; break;
+ throw new GLException("Invalid ES profile number "+esProfile);
}
if ( !GLProfile.isAvailable(adevice, profileString) ) {
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice);
+ }
return false;
}
final GLProfile glp = GLProfile.get(adevice, profileString) ;
final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
final boolean mapsADeviceToDefaultDevice = !QUERY_EGL_ES_NATIVE_TK || null == desktopFactory || adevice instanceof EGLGraphicsDevice ;
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" ( "+esProfile+" ), "+
+ "defaultSharedResourceSet "+(null!=defaultSharedResource)+", mapsADeviceToDefaultDevice "+mapsADeviceToDefaultDevice+
+ " (QUERY_EGL_ES_NATIVE_TK "+QUERY_EGL_ES_NATIVE_TK+", hasDesktopFactory "+(null != desktopFactory)+
+ ", isEGLGraphicsDevice "+(adevice instanceof EGLGraphicsDevice)+")");
+ }
EGLGraphicsDevice eglDevice = null;
NativeSurface surface = null;
@@ -387,16 +410,29 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if( adevice != defaultDevice ) {
if(null == defaultSharedResource) {
return false;
- }
+ }
switch(esProfile) {
+ case 3:
+ if( !defaultSharedResource.wasES3ContextCreated ) {
+ return false;
+ }
+ rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2;
+ ctp[0] = defaultSharedResource.ctpES3ES2;
+ break;
+ case 2:
+ if( !defaultSharedResource.wasES2ContextCreated ) {
+ return false;
+ }
+ rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2;
+ ctp[0] = defaultSharedResource.ctpES3ES2;
+ break;
case 1:
+ if( !defaultSharedResource.wasES1ContextCreated ) {
+ return false;
+ }
rendererQuirks[0] = defaultSharedResource.rendererQuirksES1;
ctp[0] = defaultSharedResource.ctpES1;
break;
- case 2:
- rendererQuirks[0] = defaultSharedResource.rendererQuirksES2;
- ctp[0] = defaultSharedResource.ctpES2;
- break;
}
EGLContext.mapStaticGLVersion(adevice, esProfile, 0, ctp[0]);
return true;
@@ -421,7 +457,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
success = true;
}
if(DEBUG) {
- System.err.println("EGLDrawableFactory.isEGLContextAvailable() no pbuffer config available, detected !pbuffer config: "+success);
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "+success);
EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err);
}
}
@@ -457,13 +493,13 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
} else {
// Oops .. something is wrong
if(DEBUG) {
- System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
}
}
}
} catch (GLException gle) {
if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed");
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed");
gle.printStackTrace();
}
} finally {
@@ -557,14 +593,15 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
private SharedResource createEGLSharedResourceImpl(AbstractGraphicsDevice adevice) {
final boolean madeCurrentES1;
final boolean madeCurrentES2;
+ final boolean madeCurrentES3;
boolean[] hasPBufferES1 = new boolean[] { false };
- boolean[] hasPBufferES2 = new boolean[] { false };
+ boolean[] hasPBufferES3ES2 = new boolean[] { false };
// EGLContext[] eglCtxES1 = new EGLContext[] { null };
// EGLContext[] eglCtxES2 = new EGLContext[] { null };
GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null };
- GLRendererQuirks[] rendererQuirksES2 = new GLRendererQuirks[] { null };
+ GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null };
int[] ctpES1 = new int[] { -1 };
- int[] ctpES2 = new int[] { -1 };
+ int[] ctpES3ES2 = new int[] { -1 };
if (DEBUG) {
@@ -577,9 +614,16 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
madeCurrentES1 = false;
}
if( null != eglES2DynamicLookupHelper ) {
- madeCurrentES2 = mapAvailableEGLESConfig(adevice, 2, hasPBufferES2, rendererQuirksES2, ctpES2);
+ madeCurrentES3 = mapAvailableEGLESConfig(adevice, 3, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2);
+ if( madeCurrentES3 ) {
+ madeCurrentES2 = true;
+ EGLContext.mapStaticGLVersion(adevice, 2, 0, ctpES3ES2[0]);
+ } else {
+ madeCurrentES2 = mapAvailableEGLESConfig(adevice, 2, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2);
+ }
} else {
madeCurrentES2 = false;
+ madeCurrentES3 = false;
}
if( !EGLContext.getAvailableGLVersionsSet(adevice) ) {
@@ -589,10 +633,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
if( hasX11 ) {
handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]);
- handleDontCloseX11DisplayQuirk(rendererQuirksES2[0]);
+ handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]);
}
final SharedResource sr = new SharedResource(defaultDevice, madeCurrentES1, hasPBufferES1[0], rendererQuirksES1[0], ctpES1[0],
- madeCurrentES2, hasPBufferES2[0], rendererQuirksES2[0], ctpES2[0]);
+ madeCurrentES2, madeCurrentES3, hasPBufferES3ES2[0], rendererQuirksES3ES2[0], ctpES3ES2[0]);
synchronized(sharedMap) {
sharedMap.put(adevice.getUniqueID(), sr);
@@ -600,7 +644,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if (DEBUG) {
System.err.println("EGLDrawableFactory.createShared: devices: queried nativeTK "+QUERY_EGL_ES_NATIVE_TK+", adevice " + adevice + ", defaultDevice " + defaultDevice);
System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", hasPBuffer "+hasPBufferES1[0]);
- System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES2[0]);
+ System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES3ES2[0]);
+ System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", hasPBuffer "+hasPBufferES3ES2[0]);
dumpMap();
}
return sr;
@@ -663,7 +708,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ public boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
// SharedResource sr = getOrCreateEGLSharedResource(device);
// return sr.hasES1PBuffer() || sr.hasES2PBuffer();
return true;
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
index fe9d7573d..778f0cb38 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
@@ -29,6 +29,7 @@
package jogamp.opengl.egl;
import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.common.os.Platform;
import java.util.*;
@@ -38,10 +39,10 @@ import jogamp.opengl.*;
* Abstract implementation of the DynamicLookupHelper for EGL,
* which decouples it's dependencies to EGLDrawable.
*
- * Currently two implementations exist, one for ES1 and one for ES2.
+ * Currently two implementations exist, one for ES1 and one for ES3 and ES2.
*/
public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
- static List<String> glueLibNames;
+ static final List<String> glueLibNames;
static {
glueLibNames = new ArrayList<String>();
glueLibNames.add("jogl_mobile");
@@ -52,19 +53,12 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
}
/**
- * Might be a desktop GL library, and might need to allow symbol access to subsequent libs.
- *
- * This respects old DRI requirements:<br>
- * <pre>
- * http://dri.sourceforge.net/doc/DRIuserguide.html
- * </pre>
+ * Returns <code>true</code> on <code>Android</code>,
+ * and <code>false</code> otherwise.
*/
@Override
- public boolean shallLinkGlobal() { return true; }
-
- @Override
- public boolean shallLookupGlobal() {
- if ( AndroidVersion.isAvailable ) {
+ public final boolean shallLookupGlobal() {
+ if ( Platform.OSType.ANDROID == Platform.OS_TYPE ) {
// Android requires global symbol lookup
return true;
}
@@ -94,7 +88,7 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
}
}
- protected List<String> getEGLLibNamesList() {
+ protected final List<String> getEGLLibNamesList() {
List<String> eglLibNames = new ArrayList<String>();
// this is the default EGL lib name, according to the spec
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
index 0a373eb7f..dd3d6faea 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
@@ -30,12 +30,12 @@ package jogamp.opengl.egl;
import java.util.*;
-public class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
+public final class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
protected EGLES1DynamicLibraryBundleInfo() {
super();
}
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
{
final List<String> libsGL = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
index d4ee852b1..0d20fd4e8 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
@@ -30,28 +30,48 @@ package jogamp.opengl.egl;
import java.util.*;
-public class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
+/**
+ * <p>
+ * Covering ES3 and ES2.
+ * </p>
+ */
+public final class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
protected EGLES2DynamicLibraryBundleInfo() {
super();
}
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
{
final List<String> libsGL = new ArrayList<String>();
- // this is the default lib name, according to the spec
+ // ES3: This is the default lib name, according to the spec
+ libsGL.add("libGLESv3.so.3");
+
+ // ES3: Try these as well, if spec fails
+ libsGL.add("libGLESv3.so");
+ libsGL.add("GLESv3");
+
+ // ES3: Alternative names
+ libsGL.add("GLES30");
+
+ // ES3: For windows distributions using the 'unlike' lib prefix
+ // where our tool does not add it.
+ libsGL.add("libGLESv3");
+ libsGL.add("libGLES30");
+
+ // ES2: This is the default lib name, according to the spec
libsGL.add("libGLESv2.so.2");
- // try these as well, if spec fails
+ // ES2: Try these as well, if spec fails
libsGL.add("libGLESv2.so");
libsGL.add("GLESv2");
- // alternative names
+ // ES2: Alternative names
libsGL.add("GLES20");
libsGL.add("GLESv2_CM");
- // for windows distributions using the 'unlike' lib prefix
+ // ES2: For windows distributions using the 'unlike' lib prefix
// where our tool does not add it.
libsGL.add("libGLESv2");
libsGL.add("libGLESv2_CM");
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
index f857c6b5c..b61624d79 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
@@ -101,12 +101,16 @@ public class EGLGLCapabilities extends GLCapabilities {
if(null == glp) {
return true;
}
- if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && glp.usesNativeGLES1()) {
+ /** FIXME: EGLExt.EGL_OPENGL_ES3_BIT_KHR OK ? */
+ if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR) && glp.usesNativeGLES3()) {
return true;
}
if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && glp.usesNativeGLES2()) {
return true;
}
+ if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && glp.usesNativeGLES1()) {
+ return true;
+ }
if(0 != (renderableType & EGL.EGL_OPENGL_BIT) && !glp.usesNativeGLES()) {
return true;
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index b90609ff1..6787ef500 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -52,7 +52,7 @@ import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GL3;
+import javax.media.opengl.GL3ES3;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -74,14 +74,13 @@ import com.jogamp.common.util.VersionNumber;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
-import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.GLRendererQuirks;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
public class MacOSXCGLContext extends GLContextImpl
-{
+{
// Abstract interface for implementation of this context (either
// NSOpenGL-based or CGL-based)
protected interface GLBackendImpl {
@@ -142,7 +141,7 @@ public class MacOSXCGLContext extends GLContextImpl
private static final String shaderBasename = "texture01_xxx";
- private static ShaderProgram createCALayerShader(GL3 gl) {
+ private static ShaderProgram createCALayerShader(GL3ES3 gl) {
// Create & Link the shader program
final ShaderProgram sp = new ShaderProgram();
final ShaderCode vp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MacOSXCGLContext.class,
@@ -420,12 +419,18 @@ public class MacOSXCGLContext extends GLContextImpl
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
// FIXME: apparently the Apple extension doesn't require a custom memory allocator
throw new GLException("Not yet implemented");
}
@Override
+ public final void glFreeMemoryNV(ByteBuffer pointer) {
+ // FIXME: apparently the Apple extension doesn't require a custom memory allocator
+ throw new GLException("Not yet implemented");
+ }
+
+ @Override
protected final void updateGLXProcAddressTable() {
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
@@ -459,15 +464,6 @@ public class MacOSXCGLContext extends GLContextImpl
return new StringBuilder();
}
- @Override
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
- glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
- return true;
- }
- return super.isExtensionAvailable(glExtensionName);
- }
-
// Support for "mode switching" as described in MacOSXCGLDrawable
public void setOpenGLMode(GLBackendType mode) {
if (mode == openGLMode) {
@@ -846,7 +842,7 @@ public class MacOSXCGLContext extends GLContextImpl
}
if( MacOSXCGLContext.this.isGL3core() ) {
if( null == gl3ShaderProgram) {
- gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3());
+ gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3ES3());
}
gl3ShaderProgramName = gl3ShaderProgram.program();
} else {
@@ -939,7 +935,7 @@ public class MacOSXCGLContext extends GLContextImpl
if(0 == cglCtx) {
throw new InternalError("Null CGLContext for: "+this);
}
- int err = CGL.CGLLockContext(cglCtx);
+ final int err = CGL.CGLLockContext(cglCtx);
if(CGL.kCGLNoError == err) {
validatePBufferConfig(ctx); // required to handle pbuffer change ASAP
return CGL.makeCurrentContext(ctx);
@@ -1000,6 +996,8 @@ public class MacOSXCGLContext extends GLContextImpl
CGL.setNSOpenGLLayerSwapInterval(l, interval);
if( 0 < interval ) {
vsyncTimeout = interval * screenVSyncTimeout + 1000; // +1ms
+ } else {
+ vsyncTimeout = 1 * screenVSyncTimeout + 1000; // +1ms
}
if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); }
}
@@ -1008,6 +1006,14 @@ public class MacOSXCGLContext extends GLContextImpl
}
private int skipSync=0;
+ /** TODO: Remove after discussion
+ private boolean perfIterReset = false;
+ private int perfIter = 0;
+ private long waitGLS = 0;
+ private long finishGLS = 0;
+ private long frameXS = 0;
+ private long lastFrameStart = 0;
+ */
@Override
public boolean swapBuffers() {
@@ -1036,6 +1042,45 @@ public class MacOSXCGLContext extends GLContextImpl
res = CGL.flushBuffer(contextHandle);
if(res) {
if(0 == skipSync) {
+ /** TODO: Remove after discussion
+ perfIter++;
+ if( !perfIterReset && 100 == perfIter ) {
+ perfIterReset = true;
+ perfIter = 1;
+ waitGLS = 0;
+ finishGLS = 0;
+ frameXS = 0;
+ }
+ final long lastFramePeriod0 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+ gl.glFinish(); // Require to finish previous GL rendering to give CALayer proper result
+ final long lastFramePeriod1 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+
+ // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
+ // while still synchronizing w/ CALayer.
+ // If v-sync is enabled wait until next swap interval (v-sync).
+ CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout);
+ final long lastFramePeriodX = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+
+ final long finishGL = lastFramePeriod1 - lastFramePeriod0;
+ final long waitGL = lastFramePeriodX - lastFramePeriod1;
+ finishGLS += finishGL;
+ waitGLS += waitGL;
+ frameXS += lastFramePeriodX;
+
+ System.err.println("XXX["+perfIter+"] TO "+vsyncTimeout/1000+" ms, "+
+ "lFrame0 "+lastFramePeriod0/1000+" ms, "+
+ "lFrameX "+lastFramePeriodX/1000+" / "+frameXS/1000+" ~"+(frameXS/perfIter)/1000.0+" ms, "+
+ "finishGL "+finishGL/1000+" / "+finishGLS/1000+" ~"+(finishGLS/perfIter)/1000.0+" ms, "+
+ "waitGL "+waitGL/1000+" / "+waitGLS/1000+" ~"+(waitGLS/perfIter)/1000.0+" ms");
+ */
+ //
+ // Required(?) to finish previous GL rendering to give CALayer proper result,
+ // i.e. synchronize both threads each w/ their GLContext sharing same resources.
+ //
+ // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above,
+ // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks!
+ gl.glFinish();
+
// If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
// while still synchronizing w/ CALayer.
// If v-sync is enabled wait until next swap interval (v-sync).
@@ -1050,6 +1095,7 @@ public class MacOSXCGLContext extends GLContextImpl
// trigger CALayer to update incl. possible surface change (new pbuffer handle)
CGL.setNSOpenGLLayerNeedsDisplayPBuffer(cmd.nsOpenGLLayer, drawable.getHandle());
}
+ // lastFrameStart = TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
}
} else {
res = true;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index 910158d1f..4bd7bc994 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -117,8 +117,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
createdContexts.add(new WeakReference<MacOSXCGLContext>(osxCtx));
} else {
for(int i=0; i<createdContexts.size(); ) {
- final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
- final MacOSXCGLContext _ctx = ref.get();
+ final MacOSXCGLContext _ctx = createdContexts.get(i).get();
if( _ctx == null || _ctx == ctx) {
createdContexts.remove(i);
} else {
@@ -134,8 +133,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
if(doubleBuffered) {
synchronized (createdContexts) {
for(int i=0; i<createdContexts.size(); ) {
- final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
- final MacOSXCGLContext ctx = ref.get();
+ final MacOSXCGLContext ctx = createdContexts.get(i).get();
if (ctx != null) {
ctx.swapBuffers();
i++;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index c9402b33d..83d656475 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -332,8 +332,13 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
- return true;
+ public boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
+ if( glp.isGL2() ) {
+ // OSX only supports pbuffer w/ compatible, non-core, context.
+ return true;
+ } else {
+ return false;
+ }
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
index 03ec94db6..f8c874a53 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
@@ -31,13 +31,13 @@ package jogamp.opengl.macosx.cgl;
import jogamp.opengl.*;
import java.util.*;
-public class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
+public final class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
protected MacOSXCGLDynamicLibraryBundleInfo() {
super();
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib");
diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java b/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java
new file mode 100644
index 000000000..69223d0b9
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java
@@ -0,0 +1,19 @@
+package jogamp.opengl.openal.av;
+
+import jogamp.opengl.util.av.impl.FFMPEGMediaPlayer;
+
+import com.jogamp.openal.AL;
+import com.jogamp.openal.JoalVersion;
+
+/**
+ * Demo JOAL usage w/ av dependency, i.e. FFMPEGMediaPlayer ..
+ */
+public class ALDummyUsage {
+ static AL al;
+ static FFMPEGMediaPlayer.PixelFormat pfmt;
+
+ public static void main(String args[]) {
+ System.err.println("JOGL> Hello JOAL");
+ System.err.println("JOAL: "+JoalVersion.getInstance().toString());
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
index 32c863553..2d40fe4ec 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -28,6 +28,8 @@
package jogamp.opengl.util.av.impl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -53,10 +55,10 @@ import com.jogamp.common.util.RunnableExecutor;
* Tue Feb 28 12:07:53 2012 322537478b63c6bc01e640643550ff539864d790 minor 1 -> 2
*/
class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
- private static List<String> glueLibNames = new ArrayList<String>(); // none
+ private static final List<String> glueLibNames = new ArrayList<String>(); // none
private static final int symbolCount = 31;
- private static String[] symbolNames = {
+ private static final String[] symbolNames = {
"avcodec_version",
"avformat_version",
/* 3 */ "avutil_version",
@@ -97,7 +99,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
};
// alternate symbol names
- private static String[][] altSymbolNames = {
+ private static final String[][] altSymbolNames = {
{ "avcodec_open", "avcodec_open2" }, // old, 53.6.0
{ "avcodec_decode_audio3", "avcodec_decode_audio4" }, // old, 53.25.0
{ "av_close_input_file", "avformat_close_input" }, // old, 53.17.0
@@ -105,7 +107,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
};
// optional symbol names
- private static String[] optionalSymbolNames = {
+ private static final String[] optionalSymbolNames = {
"avformat_free_context", // 52.96.0 (opt)
"avformat_network_init", // 53.13.0 (opt)
"avformat_network_deinit", // 53.13.0 (opt)
@@ -131,8 +133,11 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
static boolean initSingleton() { return ready; }
- private static boolean initSymbols() {
- final DynamicLibraryBundle dl = new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
+ private static final boolean initSymbols() {
+ final DynamicLibraryBundle dl = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
+ public DynamicLibraryBundle run() {
+ return new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
+ } } );
final boolean avutilLoaded = dl.isToolLibLoaded(0);
final boolean avformatLoaded = dl.isToolLibLoaded(1);
final boolean avcodecLoaded = dl.isToolLibLoaded(2);
@@ -166,9 +171,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
// lookup
- for(int i = 0; i<symbolCount; i++) {
- symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
- }
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ for(int i = 0; i<symbolCount; i++) {
+ symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
+ }
+ return null;
+ } } );
// validate results
for(int i = 0; i<symbolCount; i++) {
@@ -206,10 +215,18 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public boolean shallLinkGlobal() { return true; }
+ public final boolean shallLinkGlobal() { return true; }
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>true</code>.
+ * </p>
+ */
@Override
- public boolean shallLookupGlobal() { return true; }
+ public final boolean shallLookupGlobal() {
+ return true;
+ }
@Override
public final List<String> getGlueLibNames() {
@@ -217,7 +234,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> avutil = new ArrayList<String>();
@@ -274,12 +291,12 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(String funcName) {
return false;
}
@Override
- public RunnableExecutor getLibLoaderExecutor() {
+ public final RunnableExecutor getLibLoaderExecutor() {
return DynamicLibraryBundle.getDefaultRunnableExecutor();
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index 4be2bcb58..f416bb1f8 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -31,6 +31,8 @@ package jogamp.opengl.util.av.impl;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
@@ -43,9 +45,6 @@ import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureSequence;
import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.es1.GLES1ProcAddressTable;
-import jogamp.opengl.es2.GLES2ProcAddressTable;
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
import jogamp.opengl.util.av.EGLMediaPlayerImpl;
/***
@@ -194,25 +193,43 @@ public class FFMPEGMediaPlayer extends EGLMediaPlayerImpl {
System.out.println("setURL: p2 "+this);
int tf, tif=GL.GL_RGBA; // texture format and internal format
switch(vBytesPerPixelPerPlane) {
- case 1: tf = GL2ES2.GL_ALPHA; tif=GL.GL_ALPHA; break;
- case 3: tf = GL2ES2.GL_RGB; tif=GL.GL_RGB; break;
- case 4: tf = GL2ES2.GL_RGBA; tif=GL.GL_RGBA; break;
+ case 1:
+ if( gl.isGL3ES3() ) {
+ tf = GL2ES2.GL_RED; tif=GL2ES2.GL_RED; // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core!
+ } else {
+ tf = GL2ES2.GL_ALPHA; tif=GL2ES2.GL_ALPHA; // ALPHA is supported on ES2 and GL2
+ }
+ break;
+ case 3: tf = GL2ES2.GL_RGB; tif=GL.GL_RGB; break;
+ case 4: tf = GL2ES2.GL_RGBA; tif=GL.GL_RGBA; break;
default: throw new RuntimeException("Unsupported bytes-per-pixel / plane "+vBytesPerPixelPerPlane);
}
setTextureFormat(tif, tf);
setTextureType(GL.GL_UNSIGNED_BYTE);
- GLContextImpl ctx = (GLContextImpl)gl.getContext();
- ProcAddressTable pt = ctx.getGLProcAddressTable();
- if(pt instanceof GLES2ProcAddressTable) {
- procAddrGLTexSubImage2D = ((GLES2ProcAddressTable)pt)._addressof_glTexSubImage2D;
- } else if(pt instanceof GLES1ProcAddressTable) {
- procAddrGLTexSubImage2D = ((GLES1ProcAddressTable)pt)._addressof_glTexSubImage2D;
- } else if(pt instanceof GL4bcProcAddressTable) {
- procAddrGLTexSubImage2D = ((GL4bcProcAddressTable)pt)._addressof_glTexSubImage2D;
- } else {
- throw new InternalError("Unknown ProcAddressTable: "+pt.getClass().getName()+" of "+ctx.getClass().getName());
+ final GLContextImpl ctx = (GLContextImpl)gl.getContext();
+ final ProcAddressTable pt = ctx.getGLProcAddressTable();
+ procAddrGLTexSubImage2D = getAddressFor(pt, "glTexSubImage2D");
+ if( 0 == procAddrGLTexSubImage2D ) {
+ throw new InternalError("glTexSubImage2D n/a in ProcAddressTable: "+pt.getClass().getName()+" of "+ctx.getGLVersion());
}
}
+
+ /**
+ * Catches IllegalArgumentException and returns 0 if functionName is n/a,
+ * otherwise the ProcAddressTable's field value.
+ */
+ private final long getAddressFor(final ProcAddressTable table, final String functionName) {
+ return AccessController.doPrivileged(new PrivilegedAction<Long>() {
+ public Long run() {
+ try {
+ return Long.valueOf( table.getAddressFor(functionName) );
+ } catch (IllegalArgumentException iae) {
+ return Long.valueOf(0);
+ }
+ }
+ } ).longValue();
+ }
+
private void updateAttributes2(int pixFmt, int planes, int bitsPerPixel, int bytesPerPixelPerPlane,
int lSz0, int lSz1, int lSz2,
int tWd0, int tWd1, int tWd2) {
@@ -296,9 +313,9 @@ public class FFMPEGMediaPlayer extends EGLMediaPlayerImpl {
" vec2 v_off = vec2("+tc_w_1+", 0.5);\n"+
" vec2 tc_half = texCoord*0.5;\n"+
" float y,u,v,r,g,b;\n"+
- " y = texture2D(image, texCoord).a;\n"+
- " u = texture2D(image, u_off+tc_half).a;\n"+
- " v = texture2D(image, v_off+tc_half).a;\n"+
+ " y = texture2D(image, texCoord).r;\n"+
+ " u = texture2D(image, u_off+tc_half).r;\n"+
+ " v = texture2D(image, v_off+tc_half).r;\n"+
" y = 1.1643*(y-0.0625);\n"+
" u = u-0.5;\n"+
" v = v-0.5;\n"+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
index f4f20ac7c..2e924cbfb 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
@@ -66,7 +66,13 @@ import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
* </p>
*/
public class FixedFuncPipeline {
- protected static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.FixedFuncPipeline", true);
+ protected static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.isPropertyDefined("jogl.debug.FixedFuncPipeline", true);
+ }
+
/** The maximum texture units which could be used, depending on {@link ShaderSelectionMode}. */
public static final int MAX_TEXTURE_UNITS = 8;
public static final int MAX_LIGHTS = 8;
diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
index 251291a14..833771dd1 100644
--- a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
+++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
@@ -301,13 +301,15 @@ public class JPEGDecoder {
private final ArrayHashSet<Integer> compIDs;
private final ComponentIn[] comps;
private final int compCount;
+ /** quantization tables */
+ final int[][] qtt;
int maxCompID;
int maxH;
int maxV;
int mcusPerLine;
int mcusPerColumn;
- Frame(boolean progressive, int precision, int scanLines, int samplesPerLine, int componentsCount) {
+ Frame(boolean progressive, int precision, int scanLines, int samplesPerLine, int componentsCount, int[][] qtt) {
this.progressive = progressive;
this.precision = precision;
this.scanLines = scanLines;
@@ -315,6 +317,7 @@ public class JPEGDecoder {
compIDs = new ArrayHashSet<Integer>(componentsCount);
comps = new ComponentIn[componentsCount];
this.compCount = componentsCount;
+ this.qtt = qtt;
}
private final void checkBounds(int idx) {
@@ -322,6 +325,17 @@ public class JPEGDecoder {
throw new CodecException("Idx out of bounds "+idx+", "+this);
}
}
+ public final void validateComponents() {
+ for(int i=0; i<compCount; i++) {
+ final ComponentIn c = comps[i];
+ if( null == c ) {
+ throw new CodecException("Component["+i+"] null");
+ }
+ if( null == this.qtt[c.qttIdx] ) {
+ throw new CodecException("Component["+i+"].qttIdx -> null QTT");
+ }
+ }
+ }
public final int getCompCount() { return compCount; }
public final int getMaxCompID() { return maxCompID; }
@@ -357,7 +371,8 @@ public class JPEGDecoder {
/** The JPEG encoded components */
class ComponentIn {
final int h, v;
- final int[] quantizationTable;
+ /** index to frame.qtt[] */
+ final int qttIdx;
int blocksPerColumn;
int blocksPerColumnForMcu;
int blocksPerLine;
@@ -368,10 +383,10 @@ public class JPEGDecoder {
BinObj huffmanTableAC;
BinObj huffmanTableDC;
- ComponentIn(int h, int v, int[] quantizationTable) {
+ ComponentIn(int h, int v, int qttIdx) {
this.h = h;
this.v = v;
- this.quantizationTable = quantizationTable;
+ this.qttIdx = qttIdx;
}
public final void allocateBlocks(int blocksPerColumn, int blocksPerColumnForMcu, int blocksPerLine, int blocksPerLineForMcu) {
@@ -389,7 +404,7 @@ public class JPEGDecoder {
}
public final String toString() {
- return "CompIn[h "+h+", v "+v+", blocks["+blocksPerColumn+", mcu "+blocksPerColumnForMcu+"]["+blocksPerLine+", mcu "+blocksPerLineForMcu+"][64]]";
+ return "CompIn[h "+h+", v "+v+", qttIdx "+qttIdx+", blocks["+blocksPerColumn+", mcu "+blocksPerColumnForMcu+"]["+blocksPerLine+", mcu "+blocksPerLineForMcu+"][64]]";
}
}
@@ -526,12 +541,14 @@ public class JPEGDecoder {
}
public synchronized JPEGDecoder parse(final InputStream inputStream) throws IOException {
clear(inputStream);
- Frame frame = null;
- int resetInterval = 0;
- int[][] quantizationTables = new int[0x0F][]; // 4 bits
- ArrayList<Frame> frames = new ArrayList<Frame>();
+
+ final int[][] quantizationTables = new int[0x0F][]; // 4 bits
final BinObj[] huffmanTablesAC = new BinObj[0x0F]; // Huffman table spec - 4 bits
final BinObj[] huffmanTablesDC = new BinObj[0x0F]; // Huffman table spec - 4 bits
+ // final ArrayList<Frame> frames = new ArrayList<Frame>(); // JAU: max 1-frame
+
+ Frame frame = null;
+ int resetInterval = 0;
int fileMarker = readUint16();
if ( fileMarker != M_SOI ) {
throw new CodecException("SOI not found, but has marker "+toHexString(fileMarker));
@@ -579,6 +596,7 @@ public class JPEGDecoder {
while( count < quantizationTablesLength ) {
final int quantizationTableSpec = readUint8(); count++;
final int precisionID = quantizationTableSpec >> 4;
+ final int tableIdx = quantizationTableSpec & 0x0F;
final int[] tableData = new int[64];
if ( precisionID == 0 ) { // 8 bit values
for (int j = 0; j < 64; j++) {
@@ -591,12 +609,15 @@ public class JPEGDecoder {
tableData[z] = readUint16(); count+=2;
}
} else {
- throw new CodecException("DQT: invalid table precision "+precisionID+", quantizationTableSpec "+quantizationTableSpec);
+ throw new CodecException("DQT: invalid table precision "+precisionID+", quantizationTableSpec "+quantizationTableSpec+", idx "+tableIdx);
}
- quantizationTables[quantizationTableSpec & 0x0F] = tableData;
+ quantizationTables[tableIdx] = tableData;
+ if( DEBUG ) {
+ System.err.println("JPEG.parse.QTT["+tableIdx+"]: spec "+quantizationTableSpec+", precision "+precisionID+", data "+count+"/"+quantizationTablesLength);
+ }
}
if(count!=quantizationTablesLength){
- throw new CodecException("ERROR: QTT format error [count!=Length]");
+ throw new CodecException("ERROR: QTT format error [count!=Length]: "+count+"/"+quantizationTablesLength);
}
fileMarker = 0; // consumed and get-next
}
@@ -604,6 +625,9 @@ public class JPEGDecoder {
case M_SOF0:
case M_SOF2: {
+ if( null != frame ) { // JAU: max 1-frame
+ throw new CodecException("only single frame JPEGs supported");
+ }
int count = 0;
final int sofLen = readUint16(); count+=2; // header length;
final int componentsCount;
@@ -613,7 +637,7 @@ public class JPEGDecoder {
final int scanLines = readUint16(); count+=2;
final int samplesPerLine = readUint16(); count+=2;
componentsCount = readUint8(); count++;
- frame = new Frame(progressive, precision, scanLines, samplesPerLine, componentsCount);
+ frame = new Frame(progressive, precision, scanLines, samplesPerLine, componentsCount, quantizationTables);
width = frame.samplesPerLine;
height = frame.scanLines;
}
@@ -622,14 +646,15 @@ public class JPEGDecoder {
final int temp = readUint8(); count++;
final int h = temp >> 4;
final int v = temp & 0x0F;
- final int qId = readUint8(); count++;
- frame.putOrdered(componentId, new ComponentIn(h, v, quantizationTables[qId]));
+ final int qttIdx = readUint8(); count++;
+ final ComponentIn compIn = new ComponentIn(h, v, qttIdx);
+ frame.putOrdered(componentId, compIn);
}
if(count!=sofLen){
throw new CodecException("ERROR: SOF format error [count!=Length]");
}
prepareComponents(frame);
- frames.add(frame);
+ // frames.add(frame); // JAU: max 1-frame
if(DEBUG) { System.err.println("JPG.parse.SOF[02]: Got frame "+frame); }
fileMarker = 0; // consumed and get-next
}
@@ -711,14 +736,21 @@ public class JPEGDecoder {
}
}
if(DEBUG) { System.err.println("JPG.parse.2: End of parsing input "+this); }
+ /** // JAU: max 1-frame
if ( frames.size() != 1 ) {
- throw new CodecException("only single frame JPEGs supported");
+ throw new CodecException("only single frame JPEGs supported "+this);
+ } */
+ if( null == frame ) {
+ throw new CodecException("no single frame found in stream "+this);
}
+ frame.validateComponents();
final int compCount = frame.getCompCount();
this.components = new ComponentOut[compCount];
for (int i = 0; i < compCount; i++) {
final ComponentIn component = frame.getCompByIndex(i);
+ // System.err.println("JPG.parse.buildComponentData["+i+"]: "+component); // JAU
+ // System.err.println("JPG.parse.buildComponentData["+i+"]: "+frame); // JAU
this.components[i] = new ComponentOut( output.buildComponentData(frame, component),
(float)component.h / (float)frame.maxH,
(float)component.v / (float)frame.maxV );
@@ -834,12 +866,14 @@ public class JPEGDecoder {
final byte[] r = new byte[64];
for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
- int scanLine = blockRow << 3;
+ final int scanLine = blockRow << 3;
+ // System.err.println("JPG.buildComponentData: row "+blockRow+"/"+blocksPerColumn+" -> scanLine "+scanLine); // JAU
for (int i = 0; i < 8; i++) {
lines.add(new byte[samplesPerLine]);
}
for (int blockCol = 0; blockCol < blocksPerLine; blockCol++) {
- quantizeAndInverse(component.getBlock(blockRow, blockCol), r, R, component.quantizationTable);
+ // System.err.println("JPG.buildComponentData: col "+blockCol+"/"+blocksPerLine+", comp.qttIdx "+component.qttIdx+", qtt "+frame.qtt[component.qttIdx]); // JAU
+ quantizeAndInverse(component.getBlock(blockRow, blockCol), r, R, frame.qtt[component.qttIdx]);
final int sample = blockCol << 3;
int offset = 0;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java b/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
index e88a95a33..0fffc85b1 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
@@ -1,5 +1,7 @@
package jogamp.opengl.util.pngj;
+import java.util.HashMap;
+
/**
* Internal PNG predictor filter, or strategy to select it.
*
@@ -26,15 +28,18 @@ public enum FilterType {
*/
FILTER_PAETH(4),
/**
- * Default strategy: select one of the above filters depending on global image parameters
+ * Default strategy: select one of the above filters depending on global
+ * image parameters
*/
FILTER_DEFAULT(-1),
/**
- * Aggressive strategy: select one of the above filters trying each of the filters (every 8 rows)
+ * Aggressive strategy: select one of the above filters trying each of the
+ * filters (every 8 rows)
*/
FILTER_AGGRESSIVE(-2),
/**
- * Very aggressive strategy: select one of the above filters trying each of the filters (for every row!)
+ * Very aggressive strategy: select one of the above filters trying each of
+ * the filters (for every row!)
*/
FILTER_VERYAGGRESSIVE(-3),
/**
@@ -52,12 +57,17 @@ public enum FilterType {
this.val = val;
}
- public static FilterType getByVal(int i) {
+ private static HashMap<Integer, FilterType> byVal;
+
+ static {
+ byVal = new HashMap<Integer, FilterType>();
for (FilterType ft : values()) {
- if (ft.val == i)
- return ft;
+ byVal.put(ft.val, ft);
}
- return null;
+ }
+
+ public static FilterType getByVal(int i) {
+ return byVal.get(i);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
index 26562ef3e..e62134cd5 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
@@ -3,7 +3,8 @@ package jogamp.opengl.util.pngj;
/**
* Simple immutable wrapper for basic image info.
* <p>
- * Some parameters are redundant, but the constructor receives an 'orthogonal' subset.
+ * Some parameters are redundant, but the constructor receives an 'orthogonal'
+ * subset.
* <p>
* ref: http://www.w3.org/TR/PNG/#11IHDR
*/
@@ -23,14 +24,15 @@ public class ImageInfo {
public final int rows;
/**
- * Bits per sample (per channel) in the buffer (1-2-4-8-16). This is 8-16 for RGB/ARGB images, 1-2-4-8 for
- * grayscale. For indexed images, number of bits per palette index (1-2-4-8)
+ * Bits per sample (per channel) in the buffer (1-2-4-8-16). This is 8-16
+ * for RGB/ARGB images, 1-2-4-8 for grayscale. For indexed images, number of
+ * bits per palette index (1-2-4-8)
*/
public final int bitDepth;
/**
- * Number of channels, as used internally: 3 for RGB, 4 for RGBA, 2 for GA (gray with alpha), 1 for grayscale or
- * indexed.
+ * Number of channels, as used internally: 3 for RGB, 4 for RGBA, 2 for GA
+ * (gray with alpha), 1 for grayscale or indexed.
*/
public final int channels;
@@ -50,7 +52,8 @@ public class ImageInfo {
public final boolean indexed;
/**
- * Flag: true if image internally uses less than one byte per sample (bit depth 1-2-4)
+ * Flag: true if image internally uses less than one byte per sample (bit
+ * depth 1-2-4)
*/
public final boolean packed;
@@ -75,10 +78,12 @@ public class ImageInfo {
public final int samplesPerRow;
/**
- * Amount of "packed samples" : when several samples are stored in a single byte (bitdepth 1,2 4) they are counted
- * as one "packed sample". This is less that samplesPerRow only when bitdepth is 1-2-4 (flag packed = true)
+ * Amount of "packed samples" : when several samples are stored in a single
+ * byte (bitdepth 1,2 4) they are counted as one "packed sample". This is
+ * less that samplesPerRow only when bitdepth is 1-2-4 (flag packed = true)
* <p>
- * This equals the number of elements in the scanline array if working with packedMode=true
+ * This equals the number of elements in the scanline array if working with
+ * packedMode=true
* <p>
* For internal use, client code should rarely access this.
*/
@@ -99,7 +104,8 @@ public class ImageInfo {
* @param rows
* Height in pixels
* @param bitdepth
- * Bits per sample, in the buffer : 8-16 for RGB true color and greyscale
+ * Bits per sample, in the buffer : 8-16 for RGB true color and
+ * greyscale
* @param alpha
* Flag: has an alpha channel (RGBA or GA)
* @param grayscale
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
index 9f8a13230..e34e6a226 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
@@ -5,7 +5,8 @@ import jogamp.opengl.util.pngj.ImageLineHelper.ImageLineStats;
/**
* Lightweight wrapper for an image scanline, used for read and write.
* <p>
- * This object can be (usually it is) reused while iterating over the image lines.
+ * This object can be (usually it is) reused while iterating over the image
+ * lines.
* <p>
* See <code>scanline</code> field, to understand the format.
*/
@@ -18,21 +19,25 @@ public class ImageLine {
private int rown = 0;
/**
- * The 'scanline' is an array of integers, corresponds to an image line (row).
+ * The 'scanline' is an array of integers, corresponds to an image line
+ * (row).
* <p>
- * Except for 'packed' formats (gray/indexed with 1-2-4 bitdepth) each <code>int</code> is a "sample" (one for
- * channel), (0-255 or 0-65535) in the corresponding PNG sequence: <code>R G B R G B...</code> or
+ * Except for 'packed' formats (gray/indexed with 1-2-4 bitdepth) each
+ * <code>int</code> is a "sample" (one for channel), (0-255 or 0-65535) in
+ * the corresponding PNG sequence: <code>R G B R G B...</code> or
* <code>R G B A R G B A...</tt>
* or <code>g g g ...</code> or <code>i i i</code> (palette index)
* <p>
- * For bitdepth=1/2/4 , and if samplesUnpacked=false, each value is a PACKED byte!
+ * For bitdepth=1/2/4 , and if samplesUnpacked=false, each value is a PACKED
+ * byte!
* <p>
- * To convert a indexed line to RGB balues, see <code>ImageLineHelper.palIdx2RGB()</code> (you can't do the reverse)
+ * To convert a indexed line to RGB balues, see
+ * <code>ImageLineHelper.palIdx2RGB()</code> (you can't do the reverse)
*/
public final int[] scanline;
/**
- * Same as {@link #scanline}, but with one byte per sample. Only one of scanline and scanlineb is valid - this
- * depends on {@link #sampleType}
+ * Same as {@link #scanline}, but with one byte per sample. Only one of
+ * scanline and scanlineb is valid - this depends on {@link #sampleType}
*/
public final byte[] scanlineb;
@@ -53,10 +58,11 @@ public class ImageLine {
public final SampleType sampleType;
/**
- * true: each element of the scanline array represents a sample always, even for internally packed PNG formats
+ * true: each element of the scanline array represents a sample always, even
+ * for internally packed PNG formats
*
- * false: if the original image was of packed type (bit depth less than 8) we keep samples packed in a single array
- * element
+ * false: if the original image was of packed type (bit depth less than 8)
+ * we keep samples packed in a single array element
*/
public final boolean samplesUnpacked;
@@ -70,11 +76,14 @@ public class ImageLine {
/**
*
* @param imgInfo
- * Inmutable ImageInfo, basic parameter of the image we are reading or writing
+ * Inmutable ImageInfo, basic parameter of the image we are
+ * reading or writing
* @param stype
- * INT or BYTE : this determines which scanline is the really used one
+ * INT or BYTE : this determines which scanline is the really
+ * used one
* @param unpackedMode
- * If true, we use unpacked format, even for packed original images
+ * If true, we use unpacked format, even for packed original
+ * images
*
*/
public ImageLine(ImageInfo imgInfo, SampleType stype, boolean unpackedMode) {
@@ -226,7 +235,10 @@ public class ImageLine {
}
}
- /** size original: samplesPerRow sizeFinal: samplesPerRowPacked (trailing elements are trash!) **/
+ /**
+ * size original: samplesPerRow sizeFinal: samplesPerRowPacked (trailing
+ * elements are trash!)
+ **/
static void packInplaceByte(final ImageInfo iminfo, final byte[] src, final byte[] dst, final boolean scaled) {
final int bitDepth = iminfo.bitDepth;
if (bitDepth >= 8)
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
index 98f235662..91516a704 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
@@ -5,11 +5,14 @@ import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
/**
- * Bunch of utility static methods to process/analyze an image line at the pixel level.
+ * Bunch of utility static methods to process/analyze an image line at the pixel
+ * level.
* <p>
- * Not essential at all, some methods are probably to be removed if future releases.
+ * Not essential at all, some methods are probably to be removed if future
+ * releases.
* <p>
- * WARNING: most methods for getting/setting values work currently only for integer base imageLines
+ * WARNING: most methods for getting/setting values work currently only for
+ * integer base imageLines
*/
public class ImageLineHelper {
@@ -18,7 +21,8 @@ public class ImageLineHelper {
private final static double BIG_VALUE_NEG = Double.MAX_VALUE * (-0.5);
/**
- * Given an indexed line with a palette, unpacks as a RGB array, or RGBA if a non nul PngChunkTRNS chunk is passed
+ * Given an indexed line with a palette, unpacks as a RGB array, or RGBA if
+ * a non nul PngChunkTRNS chunk is passed
*
* @param line
* ImageLine as returned from PngReader
@@ -26,7 +30,8 @@ public class ImageLineHelper {
* Palette chunk
* @param buf
* Preallocated array, optional
- * @return R G B (A), one sample 0-255 per array element. Ready for pngw.writeRowInt()
+ * @return R G B (A), one sample 0-255 per array element. Ready for
+ * pngw.writeRowInt()
*/
public static int[] palette2rgb(ImageLine line, PngChunkPLTE pal, PngChunkTRNS trns, int[] buf) {
boolean isalpha = trns != null;
@@ -53,9 +58,12 @@ public class ImageLineHelper {
return palette2rgb(line, pal, null, buf);
}
- /** what follows is pretty uninteresting/untested/obsolete, subject to change */
/**
- * Just for basic info or debugging. Shows values for first and last pixel. Does not include alpha
+ * what follows is pretty uninteresting/untested/obsolete, subject to change
+ */
+ /**
+ * Just for basic info or debugging. Shows values for first and last pixel.
+ * Does not include alpha
*/
public static String infoFirstLastPixels(ImageLine line) {
return line.imgInfo.channels == 1 ? String.format("first=(%d) last=(%d)", line.scanline[0],
@@ -71,8 +79,8 @@ public class ImageLineHelper {
}
/**
- * Computes some statistics for the line. Not very efficient or elegant, mainly for tests. Only for RGB/RGBA Outputs
- * values as doubles (0.0 - 1.0)
+ * Computes some statistics for the line. Not very efficient or elegant,
+ * mainly for tests. Only for RGB/RGBA Outputs values as doubles (0.0 - 1.0)
*/
static class ImageLineStats {
public double[] prom = { 0.0, 0.0, 0.0, 0.0 }; // channel averages
@@ -237,9 +245,11 @@ public class ImageLineHelper {
/**
* Unpacks scanline (for bitdepth 1-2-4) into a array <code>int[]</code>
* <p>
- * You can (OPTIONALLY) pass an preallocated array, that will be filled and returned. If null, it will be allocated
+ * You can (OPTIONALLY) pass an preallocated array, that will be filled and
+ * returned. If null, it will be allocated
* <p>
- * If <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+ * If
+ * <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
* <p>
* You probably should use {@link ImageLine#unpackToNewImageLine()}
*
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
index 1e0ab746a..feb50e7b6 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
@@ -3,10 +3,12 @@ package jogamp.opengl.util.pngj;
import jogamp.opengl.util.pngj.ImageLine.SampleType;
/**
- * Wraps in a matrix a set of image rows, not necessarily contiguous - but equispaced.
+ * Wraps in a matrix a set of image rows, not necessarily contiguous - but
+ * equispaced.
*
- * The fields mirrors those of {@link ImageLine}, and you can access each row as a ImageLine backed by the matrix row,
- * see {@link #getImageLineAtMatrixRow(int)}
+ * The fields mirrors those of {@link ImageLine}, and you can access each row as
+ * a ImageLine backed by the matrix row, see
+ * {@link #getImageLineAtMatrixRow(int)}
*/
public class ImageLines {
@@ -23,7 +25,8 @@ public class ImageLines {
public final byte[][] scanlinesb;
/**
- * Allocates a matrix to store {@code nRows} image rows. See {@link ImageLine} and {@link PngReader#readRowsInt()}
+ * Allocates a matrix to store {@code nRows} image rows. See
+ * {@link ImageLine} and {@link PngReader#readRowsInt()}
* {@link PngReader#readRowsByte()}
*
* @param imgInfo
@@ -54,8 +57,9 @@ public class ImageLines {
}
/**
- * Warning: this always returns a valid matrix row (clamping on 0 : nrows-1, and rounding down) Eg:
- * rowOffset=4,rowStep=2 imageRowToMatrixRow(17) returns 6 , imageRowToMatrixRow(1) returns 0
+ * Warning: this always returns a valid matrix row (clamping on 0 : nrows-1,
+ * and rounding down) Eg: rowOffset=4,rowStep=2 imageRowToMatrixRow(17)
+ * returns 6 , imageRowToMatrixRow(1) returns 0
*/
public int imageRowToMatrixRow(int imrow) {
int r = (imrow - rowOffset) / rowStep;
@@ -86,9 +90,11 @@ public class ImageLines {
* Returns a ImageLine is backed by the matrix, no allocation done
*
* @param mrow
- * Matrix row, from 0 to nRows This is not necessarily the image row, see
- * {@link #imageRowToMatrixRow(int)} and {@link #matrixRowToImageRow(int)}
- * @return A new ImageLine, backed by the matrix, with the correct ('real') rownumber
+ * Matrix row, from 0 to nRows This is not necessarily the image
+ * row, see {@link #imageRowToMatrixRow(int)} and
+ * {@link #matrixRowToImageRow(int)}
+ * @return A new ImageLine, backed by the matrix, with the correct ('real')
+ * rownumber
*/
public ImageLine getImageLineAtMatrixRow(int mrow) {
if (mrow < 0 || mrow > nRows)
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
index 63edf8d17..a950c6b33 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
@@ -144,18 +144,23 @@ public class PngHelperInternal {
}
}
- public static void skipBytes(InputStream is, int len) {
- byte[] buf = new byte[8192 * 4];
- int read, remain = len;
+ public static void skipBytes(InputStream is, long len) {
try {
- while (remain > 0) {
- read = is.read(buf, 0, remain > buf.length ? buf.length : remain);
- if (read < 0)
- throw new PngjInputException("error reading (skipping) : EOF");
- remain -= read;
+ while (len > 0) {
+ long n1 = is.skip(len);
+ if (n1 > 0) {
+ len -= n1;
+ } else if (n1 == 0) { // should we retry? lets read one byte
+ if (is.read() == -1) // EOF
+ break;
+ else
+ len--;
+ } else
+ // negative? this should never happen but...
+ throw new IOException("skip() returned a negative value ???");
}
} catch (IOException e) {
- throw new PngjInputException("error reading (skipping)", e);
+ throw new PngjInputException(e);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
index 6cc39b0e6..cdad09809 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
@@ -37,7 +37,8 @@ class PngIDatChunkInputStream extends InputStream {
List<IdatChunkInfo> foundChunksInfo = new ArrayList<IdatChunkInfo>();
/**
- * Constructor must be called just after reading length and id of first IDAT chunk
+ * Constructor must be called just after reading length and id of first IDAT
+ * chunk
**/
PngIDatChunkInputStream(InputStream iStream, int lenFirstChunk, long offset) {
this.offset = offset;
@@ -95,7 +96,8 @@ class PngIDatChunkInputStream extends InputStream {
}
/**
- * sometimes last row read does not fully consumes the chunk here we read the reamaing dummy bytes
+ * sometimes last row read does not fully consumes the chunk here we read
+ * the reamaing dummy bytes
*/
void forceChunkEnd() {
if (!ended) {
@@ -108,7 +110,8 @@ class PngIDatChunkInputStream extends InputStream {
}
/**
- * This can return less than len, but never 0 Returns -1 if "pseudo file" ended prematurely. That is our error.
+ * This can return less than len, but never 0 Returns -1 if "pseudo file"
+ * ended prematurely. That is our error.
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
index 8cb4295a5..e42dd8733 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
@@ -1,940 +1,1000 @@
-package jogamp.opengl.util.pngj;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.zip.CRC32;
-import java.util.zip.InflaterInputStream;
-
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.ImageLine.SampleType;
-import jogamp.opengl.util.pngj.chunks.ChunkHelper;
-import jogamp.opengl.util.pngj.chunks.ChunkLoadBehaviour;
-import jogamp.opengl.util.pngj.chunks.ChunkRaw;
-import jogamp.opengl.util.pngj.chunks.ChunksList;
-import jogamp.opengl.util.pngj.chunks.PngChunk;
-import jogamp.opengl.util.pngj.chunks.PngChunkIDAT;
-import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
-import jogamp.opengl.util.pngj.chunks.PngChunkSkipped;
-import jogamp.opengl.util.pngj.chunks.PngMetadata;
-
-/**
- * Reads a PNG image, line by line.
- * <p>
- * The reading sequence is as follows: <br>
- * 1. At construction time, the header and IHDR chunk are read (basic image info) <br>
- * 2. Afterwards you can set some additional global options. Eg. {@link #setUnpackedMode(boolean)},
- * {@link #setCrcCheckDisabled()}.<br>
- * 3. Optional: If you call getMetadata() or getChunksLisk() before start reading the rows, all the chunks before IDAT
- * are automatically loaded and available <br>
- * 4a. The rows are read onen by one of the <tt>readRowXXX</tt> methods: {@link #readRowInt(int)},
- * {@link PngReader#readRowByte(int)}, etc, in order, from 0 to nrows-1 (you can skip or repeat rows, but not go
- * backwards)<br>
- * 4b. Alternatively, you can read all rows, or a subset, in a single call: {@link #readRowsInt()},
- * {@link #readRowsByte()} ,etc. In general this consumes more memory, but for interlaced images this is equally
- * efficient, and more so if reading a small subset of rows.<br>
- * 5. Read of the last row auyomatically loads the trailing chunks, and ends the reader.<br>
- * 6. end() forcibly finishes/aborts the reading and closes the stream
- */
-public class PngReader {
- /**
- * Basic image info - final and inmutable.
- */
- public final ImageInfo imgInfo;
-
- /**
- * not necesarily a filename, can be a description - merely informative
- */
- protected final String filename;
-
- private ChunkLoadBehaviour chunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS; // see setter/getter
-
- private boolean shouldCloseStream = true; // true: closes stream after ending - see setter/getter
-
- // some performance/defensive limits
- private long maxTotalBytesRead = 200 * 1024 * 1024; // 200MB
- private int maxBytesMetadata = 5 * 1024 * 1024; // for ancillary chunks - see setter/getter
- private int skipChunkMaxSize = 2 * 1024 * 1024; // chunks exceeding this size will be skipped (nor even CRC checked)
- private String[] skipChunkIds = { "fdAT" }; // chunks with these ids will be skipped (nor even CRC checked)
- private HashSet<String> skipChunkIdsSet; // lazily created from skipChunksById
-
- protected final PngMetadata metadata; // this a wrapper over chunks
- protected final ChunksList chunksList;
-
- protected ImageLine imgLine;
-
- // line as bytes, counting from 1 (index 0 is reserved for filter type)
- protected byte[] rowb = null;
- protected byte[] rowbprev = null; // rowb previous
- protected byte[] rowbfilter = null; // current line 'filtered': exactly as in uncompressed stream
-
- // only set for interlaced PNG
- private final boolean interlaced;
- private final PngDeinterlacer deinterlacer;
-
- private boolean crcEnabled = true;
-
- // this only influences the 1-2-4 bitdepth format
- private boolean unpackedMode = false;
- /**
- * Current chunk group, (0-6) already read or reading
- * <p>
- * see {@link ChunksList}
- */
- protected int currentChunkGroup = -1;
-
- protected int rowNum = -1; // last read row number, starting from 0
- private long offset = 0; // offset in InputStream = bytes read
- private int bytesChunksLoaded; // bytes loaded from anciallary chunks
-
- protected final InputStream inputStream;
- protected InflaterInputStream idatIstream;
- protected PngIDatChunkInputStream iIdatCstream;
-
- protected CRC32 crctest; // If set to non null, it gets a CRC of the unfiltered bytes, to check for images equality
-
- /**
- * Constructs a PngReader from an InputStream.
- * <p>
- * See also <code>FileHelper.createPngReader(File f)</code> if available.
- *
- * Reads only the signature and first chunk (IDHR)
- *
- * @param filenameOrDescription
- * : Optional, can be a filename or a description. Just for error/debug messages
- *
- */
- public PngReader(InputStream inputStream, String filenameOrDescription) {
- this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
- this.inputStream = inputStream;
- this.chunksList = new ChunksList(null);
- this.metadata = new PngMetadata(chunksList);
- // starts reading: signature
- byte[] pngid = new byte[8];
- PngHelperInternal.readBytes(inputStream, pngid, 0, pngid.length);
- offset += pngid.length;
- if (!Arrays.equals(pngid, PngHelperInternal.getPngIdSignature()))
- throw new PngjInputException("Bad PNG signature");
- // reads first chunk
- currentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
- int clen = PngHelperInternal.readInt4(inputStream);
- offset += 4;
- if (clen != 13)
- throw new PngjInputException("IDHR chunk len != 13 ?? " + clen);
- byte[] chunkid = new byte[4];
- PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
- if (!Arrays.equals(chunkid, ChunkHelper.b_IHDR))
- throw new PngjInputException("IHDR not found as first chunk??? [" + ChunkHelper.toString(chunkid) + "]");
- offset += 4;
- PngChunkIHDR ihdr = (PngChunkIHDR) readChunk(chunkid, clen, false);
- boolean alpha = (ihdr.getColormodel() & 0x04) != 0;
- boolean palette = (ihdr.getColormodel() & 0x01) != 0;
- boolean grayscale = (ihdr.getColormodel() == 0 || ihdr.getColormodel() == 4);
- // creates ImgInfo and imgLine, and allocates buffers
- imgInfo = new ImageInfo(ihdr.getCols(), ihdr.getRows(), ihdr.getBitspc(), alpha, grayscale, palette);
- // allocation: one extra byte for filter type one pixel
- rowbfilter = new byte[imgInfo.bytesPerRow + 1];
- rowb = new byte[imgInfo.bytesPerRow + 1];
- rowbprev = new byte[rowb.length];
- interlaced = ihdr.getInterlaced() == 1;
- deinterlacer = interlaced ? new PngDeinterlacer(imgInfo) : null;
- // some checks
- if (ihdr.getFilmeth() != 0 || ihdr.getCompmeth() != 0 || (ihdr.getInterlaced() & 0xFFFE) != 0)
- throw new PngjInputException("compression method o filter method or interlaced unrecognized ");
- if (ihdr.getColormodel() < 0 || ihdr.getColormodel() > 6 || ihdr.getColormodel() == 1
- || ihdr.getColormodel() == 5)
- throw new PngjInputException("Invalid colormodel " + ihdr.getColormodel());
- if (ihdr.getBitspc() != 1 && ihdr.getBitspc() != 2 && ihdr.getBitspc() != 4 && ihdr.getBitspc() != 8
- && ihdr.getBitspc() != 16)
- throw new PngjInputException("Invalid bit depth " + ihdr.getBitspc());
- }
-
- private boolean firstChunksNotYetRead() {
- return currentChunkGroup < ChunksList.CHUNK_GROUP_1_AFTERIDHR;
- }
-
- /**
- * Reads last Internally called after having read the last line. It reads extra chunks after IDAT, if present.
- */
- private void readLastAndClose() {
- // offset = iIdatCstream.getOffset();
- if (currentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT) {
- try {
- idatIstream.close();
- } catch (Exception e) {
- }
- readLastChunks();
- }
- close();
- }
-
- private void close() {
- if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END) { // this could only happen if forced close
- try {
- idatIstream.close();
- } catch (Exception e) {
- }
- currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
- }
- if (shouldCloseStream) {
- try {
- inputStream.close();
- } catch (Exception e) {
- throw new PngjInputException("error closing input stream!", e);
- }
- }
- }
-
- // nbytes: NOT including the filter byte. leaves result in rowb
- private void unfilterRow(int nbytes) {
- int ftn = rowbfilter[0];
- FilterType ft = FilterType.getByVal(ftn);
- if (ft == null)
- throw new PngjInputException("Filter type " + ftn + " invalid");
- switch (ft) {
- case FILTER_NONE:
- unfilterRowNone(nbytes);
- break;
- case FILTER_SUB:
- unfilterRowSub(nbytes);
- break;
- case FILTER_UP:
- unfilterRowUp(nbytes);
- break;
- case FILTER_AVERAGE:
- unfilterRowAverage(nbytes);
- break;
- case FILTER_PAETH:
- unfilterRowPaeth(nbytes);
- break;
- default:
- throw new PngjInputException("Filter type " + ftn + " not implemented");
- }
- if (crctest != null)
- crctest.update(rowb, 1, rowb.length - 1);
- }
-
- private void unfilterRowAverage(final int nbytes) {
- int i, j, x;
- for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
- x = j > 0 ? (rowb[j] & 0xff) : 0;
- rowb[i] = (byte) (rowbfilter[i] + (x + (rowbprev[i] & 0xFF)) / 2);
- }
- }
-
- private void unfilterRowNone(final int nbytes) {
- for (int i = 1; i <= nbytes; i++) {
- rowb[i] = (byte) (rowbfilter[i]);
- }
- }
-
- private void unfilterRowPaeth(final int nbytes) {
- int i, j, x, y;
- for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
- x = j > 0 ? (rowb[j] & 0xFF) : 0;
- y = j > 0 ? (rowbprev[j] & 0xFF) : 0;
- rowb[i] = (byte) (rowbfilter[i] + PngHelperInternal.filterPaethPredictor(x, rowbprev[i] & 0xFF, y));
- }
- }
-
- private void unfilterRowSub(final int nbytes) {
- int i, j;
- for (i = 1; i <= imgInfo.bytesPixel; i++) {
- rowb[i] = (byte) (rowbfilter[i]);
- }
- for (j = 1, i = imgInfo.bytesPixel + 1; i <= nbytes; i++, j++) {
- rowb[i] = (byte) (rowbfilter[i] + rowb[j]);
- }
- }
-
- private void unfilterRowUp(final int nbytes) {
- for (int i = 1; i <= nbytes; i++) {
- rowb[i] = (byte) (rowbfilter[i] + rowbprev[i]);
- }
- }
-
- /**
- * Reads chunks before first IDAT. Normally this is called automatically
- * <p>
- * Position before: after IDHR (crc included) Position after: just after the first IDAT chunk id
- * <P>
- * This can be called several times (tentatively), it does nothing if already run
- * <p>
- * (Note: when should this be called? in the constructor? hardly, because we loose the opportunity to call
- * setChunkLoadBehaviour() and perhaps other settings before reading the first row? but sometimes we want to access
- * some metadata (plte, phys) before. Because of this, this method can be called explicitly but is also called
- * implicititly in some methods (getMetatada(), getChunksList())
- */
- private final void readFirstChunks() {
- if (!firstChunksNotYetRead())
- return;
- int clen = 0;
- boolean found = false;
- byte[] chunkid = new byte[4]; // it's important to reallocate in each iteration
- currentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
- while (!found) {
- clen = PngHelperInternal.readInt4(inputStream);
- offset += 4;
- if (clen < 0)
- break;
- PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
- offset += 4;
- if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
- found = true;
- currentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
- // add dummy idat chunk to list
- chunksList.appendReadChunk(new PngChunkIDAT(imgInfo, clen, offset - 8), currentChunkGroup);
- break;
- } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
- throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset);
- }
- if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
- currentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
- readChunk(chunkid, clen, false);
- if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
- currentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
- }
- int idatLen = found ? clen : -1;
- if (idatLen < 0)
- throw new PngjInputException("first idat chunk not found!");
- iIdatCstream = new PngIDatChunkInputStream(inputStream, idatLen, offset);
- idatIstream = new InflaterInputStream(iIdatCstream);
- if (!crcEnabled)
- iIdatCstream.disableCrcCheck();
- }
-
- /**
- * Reads (and processes) chunks after last IDAT.
- **/
- void readLastChunks() {
- // PngHelper.logdebug("idat ended? " + iIdatCstream.isEnded());
- currentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
- if (!iIdatCstream.isEnded())
- iIdatCstream.forceChunkEnd();
- int clen = iIdatCstream.getLenLastChunk();
- byte[] chunkid = iIdatCstream.getIdLastChunk();
- boolean endfound = false;
- boolean first = true;
- boolean skip = false;
- while (!endfound) {
- skip = false;
- if (!first) {
- clen = PngHelperInternal.readInt4(inputStream);
- offset += 4;
- if (clen < 0)
- throw new PngjInputException("bad chuck len " + clen);
- PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
- offset += 4;
- }
- first = false;
- if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
- skip = true; // extra dummy (empty?) idat chunk, it can happen, ignore it
- } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
- currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
- endfound = true;
- }
- readChunk(chunkid, clen, skip);
- }
- if (!endfound)
- throw new PngjInputException("end chunk not found - offset=" + offset);
- // PngHelper.logdebug("end chunk found ok offset=" + offset);
- }
-
- /**
- * Reads chunkd from input stream, adds to ChunksList, and returns it. If it's skipped, a PngChunkSkipped object is
- * created
- */
- private PngChunk readChunk(byte[] chunkid, int clen, boolean skipforced) {
- if (clen < 0)
- throw new PngjInputException("invalid chunk lenght: " + clen);
- // skipChunksByIdSet is created lazyly, if fist IHDR has already been read
- if (skipChunkIdsSet == null && currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR)
- skipChunkIdsSet = new HashSet<String>(Arrays.asList(skipChunkIds));
- String chunkidstr = ChunkHelper.toString(chunkid);
- boolean critical = ChunkHelper.isCritical(chunkidstr);
- PngChunk pngChunk = null;
- boolean skip = skipforced;
- if (maxTotalBytesRead > 0 && clen + offset > maxTotalBytesRead)
- throw new PngjInputException("Maximum total bytes to read exceeeded: " + maxTotalBytesRead + " offset:"
- + offset + " clen=" + clen);
- // an ancillary chunks can be skipped because of several reasons:
- if (currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR && !critical)
- skip = skip || (skipChunkMaxSize > 0 && clen >= skipChunkMaxSize) || skipChunkIdsSet.contains(chunkidstr)
- || (maxBytesMetadata > 0 && clen > maxBytesMetadata - bytesChunksLoaded)
- || !ChunkHelper.shouldLoad(chunkidstr, chunkLoadBehaviour);
- if (skip) {
- PngHelperInternal.skipBytes(inputStream, clen);
- PngHelperInternal.readInt4(inputStream); // skip - we dont call PngHelperInternal.skipBytes(inputStream,
- // clen + 4) for risk of overflow
- pngChunk = new PngChunkSkipped(chunkidstr, imgInfo, clen);
- } else {
- ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
- chunk.readChunkData(inputStream, crcEnabled || critical);
- pngChunk = PngChunk.factory(chunk, imgInfo);
- if (!pngChunk.crit)
- bytesChunksLoaded += chunk.len;
- }
- pngChunk.setOffset(offset - 8L);
- chunksList.appendReadChunk(pngChunk, currentChunkGroup);
- offset += clen + 4L;
- return pngChunk;
- }
-
- /**
- * Logs/prints a warning.
- * <p>
- * The default behaviour is print to stderr, but it can be overriden.
- * <p>
- * This happens rarely - most errors are fatal.
- */
- protected void logWarn(String warn) {
- System.err.println(warn);
- }
-
- /**
- * @see #setChunkLoadBehaviour(ChunkLoadBehaviour)
- */
- public ChunkLoadBehaviour getChunkLoadBehaviour() {
- return chunkLoadBehaviour;
- }
-
- /**
- * Determines which ancillary chunks (metada) are to be loaded
- *
- * @param chunkLoadBehaviour
- * {@link ChunkLoadBehaviour}
- */
- public void setChunkLoadBehaviour(ChunkLoadBehaviour chunkLoadBehaviour) {
- this.chunkLoadBehaviour = chunkLoadBehaviour;
- }
-
- /**
- * All loaded chunks (metada). If we have not yet end reading the image, this will include only the chunks before
- * the pixels data (IDAT)
- * <p>
- * Critical chunks are included, except that all IDAT chunks appearance are replaced by a single dummy-marker IDAT
- * chunk. These might be copied to the PngWriter
- * <p>
- *
- * @see #getMetadata()
- */
- public ChunksList getChunksList() {
- if (firstChunksNotYetRead())
- readFirstChunks();
- return chunksList;
- }
-
- int getCurrentChunkGroup() {
- return currentChunkGroup;
- }
-
- /**
- * High level wrapper over chunksList
- *
- * @see #getChunksList()
- */
- public PngMetadata getMetadata() {
- if (firstChunksNotYetRead())
- readFirstChunks();
- return metadata;
- }
-
- /**
- * If called for first time, calls readRowInt. Elsewhere, it calls the appropiate readRowInt/readRowByte
- * <p>
- * In general, specifying the concrete readRowInt/readRowByte is preferrable
- *
- * @see #readRowInt(int) {@link #readRowByte(int)}
- */
- public ImageLine readRow(int nrow) {
- if (imgLine == null)
- imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
- return imgLine.sampleType != SampleType.BYTE ? readRowInt(nrow) : readRowByte(nrow);
- }
-
- /**
- * Reads the row as INT, storing it in the {@link #imgLine} property and returning it.
- *
- * The row must be greater or equal than the last read row.
- *
- * @param nrow
- * Row number, from 0 to rows-1. Increasing order.
- * @return ImageLine object, also available as field. Data is in {@link ImageLine#scanline} (int) field.
- */
- public ImageLine readRowInt(int nrow) {
- if (imgLine == null)
- imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
- if (imgLine.getRown() == nrow) // already read
- return imgLine;
- readRowInt(imgLine.scanline, nrow);
- imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
- imgLine.setRown(nrow);
- return imgLine;
- }
-
- /**
- * Reads the row as BYTES, storing it in the {@link #imgLine} property and returning it.
- *
- * The row must be greater or equal than the last read row. This method allows to pass the same row that was last
- * read.
- *
- * @param nrow
- * Row number, from 0 to rows-1. Increasing order.
- * @return ImageLine object, also available as field. Data is in {@link ImageLine#scanlineb} (byte) field.
- */
- public ImageLine readRowByte(int nrow) {
- if (imgLine == null)
- imgLine = new ImageLine(imgInfo, SampleType.BYTE, unpackedMode);
- if (imgLine.getRown() == nrow) // already read
- return imgLine;
- readRowByte(imgLine.scanlineb, nrow);
- imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
- imgLine.setRown(nrow);
- return imgLine;
- }
-
- /**
- * @see #readRowInt(int[], int)
- */
- public final int[] readRow(int[] buffer, final int nrow) {
- return readRowInt(buffer, nrow);
- }
-
- /**
- * Reads a line and returns it as a int[] array.
- * <p>
- * You can pass (optionally) a prealocatted buffer.
- * <p>
- * If the bitdepth is less than 8, the bytes are packed - unless {@link #unpackedMode} is true.
- *
- * @param buffer
- * Prealocated buffer, or null.
- * @param nrow
- * Row number (0 is top). Most be strictly greater than the last read row.
- *
- * @return The scanline in the same passwd buffer if it was allocated, a newly allocated one otherwise
- */
- public final int[] readRowInt(int[] buffer, final int nrow) {
- if (buffer == null)
- buffer = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
- if (!interlaced) {
- if (nrow <= rowNum)
- throw new PngjInputException("rows must be read in increasing order: " + nrow);
- int bytesread = 0;
- while (rowNum < nrow)
- bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
- decodeLastReadRowToInt(buffer, bytesread);
- } else { // interlaced
- if (deinterlacer.getImageInt() == null)
- deinterlacer.setImageInt(readRowsInt().scanlines); // read all image and store it in deinterlacer
- System.arraycopy(deinterlacer.getImageInt()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
- : imgInfo.samplesPerRowPacked);
- }
- return buffer;
- }
-
- /**
- * Reads a line and returns it as a byte[] array.
- * <p>
- * You can pass (optionally) a prealocatted buffer.
- * <p>
- * If the bitdepth is less than 8, the bytes are packed - unless {@link #unpackedMode} is true. <br>
- * If the bitdepth is 16, the least significant byte is lost.
- * <p>
- *
- * @param buffer
- * Prealocated buffer, or null.
- * @param nrow
- * Row number (0 is top). Most be strictly greater than the last read row.
- *
- * @return The scanline in the same passwd buffer if it was allocated, a newly allocated one otherwise
- */
- public final byte[] readRowByte(byte[] buffer, final int nrow) {
- if (buffer == null)
- buffer = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
- if (!interlaced) {
- if (nrow <= rowNum)
- throw new PngjInputException("rows must be read in increasing order: " + nrow);
- int bytesread = 0;
- while (rowNum < nrow)
- bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
- decodeLastReadRowToByte(buffer, bytesread);
- } else { // interlaced
- if (deinterlacer.getImageByte() == null)
- deinterlacer.setImageByte(readRowsByte().scanlinesb); // read all image and store it in deinterlacer
- System.arraycopy(deinterlacer.getImageByte()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
- : imgInfo.samplesPerRowPacked);
- }
- return buffer;
- }
-
- /**
- * @param nrow
- * @deprecated Now {@link #readRow(int)} implements the same funcion. This method will be removed in future releases
- */
- public ImageLine getRow(int nrow) {
- return readRow(nrow);
- }
-
- private void decodeLastReadRowToInt(int[] buffer, int bytesRead) {
- if (imgInfo.bitDepth <= 8)
- for (int i = 0, j = 1; i < bytesRead; i++)
- buffer[i] = (rowb[j++] & 0xFF); // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
- else
- for (int i = 0, j = 1; j <= bytesRead; i++)
- buffer[i] = ((rowb[j++] & 0xFF) << 8) + (rowb[j++] & 0xFF); // 16 bitspc
- if (imgInfo.packed && unpackedMode)
- ImageLine.unpackInplaceInt(imgInfo, buffer, buffer, false);
- }
-
- private void decodeLastReadRowToByte(byte[] buffer, int bytesRead) {
- if (imgInfo.bitDepth <= 8)
- System.arraycopy(rowb, 1, buffer, 0, bytesRead);
- else
- for (int i = 0, j = 1; j < bytesRead; i++, j += 2)
- buffer[i] = rowb[j];// 16 bits in 1 byte: this discards the LSB!!!
- if (imgInfo.packed && unpackedMode)
- ImageLine.unpackInplaceByte(imgInfo, buffer, buffer, false);
- }
-
- /**
- * Reads a set of lines and returns it as a ImageLines object, which wraps matrix. Internally it reads all lines,
- * but decodes and stores only the wanted ones. This starts and ends the reading, and cannot be combined with other
- * reading methods.
- * <p>
- * This it's more efficient (speed an memory) that doing calling readRowInt() for each desired line only if the
- * image is interlaced.
- * <p>
- * Notice that the columns in the matrix is not the pixel width of the image, but rather pixels x channels
- *
- * @see #readRowInt(int) to read about the format of each row
- *
- * @param rowOffset
- * Number of rows to be skipped
- * @param nRows
- * Total number of rows to be read. -1: read all available
- * @param rowStep
- * Row increment. If 1, we read consecutive lines; if 2, we read even/odd lines, etc
- * @return Set of lines as a ImageLines, which wraps a matrix
- */
- public ImageLines readRowsInt(int rowOffset, int nRows, int rowStep) {
- if (nRows < 0)
- nRows = (imgInfo.rows - rowOffset) / rowStep;
- if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
- throw new PngjInputException("bad args");
- ImageLines imlines = new ImageLines(imgInfo, SampleType.INT, unpackedMode, rowOffset, nRows, rowStep);
- if (!interlaced) {
- for (int j = 0; j < imgInfo.rows; j++) {
- int bytesread = readRowRaw(j); // read and perhaps discards
- int mrow = imlines.imageRowToMatrixRowStrict(j);
- if (mrow >= 0)
- decodeLastReadRowToInt(imlines.scanlines[mrow], bytesread);
- }
- } else { // and now, for something completely different (interlaced)
- int[] buf = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
- for (int p = 1; p <= 7; p++) {
- deinterlacer.setPass(p);
- for (int i = 0; i < deinterlacer.getRows(); i++) {
- int bytesread = readRowRaw(i);
- int j = deinterlacer.getCurrRowReal();
- int mrow = imlines.imageRowToMatrixRowStrict(j);
- if (mrow >= 0) {
- decodeLastReadRowToInt(buf, bytesread);
- deinterlacer.deinterlaceInt(buf, imlines.scanlines[mrow], !unpackedMode);
- }
- }
- }
- }
- end();
- return imlines;
- }
-
- /**
- * Same as readRowsInt(0, imgInfo.rows, 1)
- *
- * @see #readRowsInt(int, int, int)
- */
- public ImageLines readRowsInt() {
- return readRowsInt(0, imgInfo.rows, 1);
- }
-
- /**
- * Reads a set of lines and returns it as a ImageLines object, which wrapas a byte[][] matrix. Internally it reads
- * all lines, but decodes and stores only the wanted ones. This starts and ends the reading, and cannot be combined
- * with other reading methods.
- * <p>
- * This it's more efficient (speed an memory) that doing calling readRowByte() for each desired line only if the
- * image is interlaced.
- * <p>
- * Notice that the columns in the matrix is not the pixel width of the image, but rather pixels x channels
- *
- * @see #readRowByte(int) to read about the format of each row. Notice that if the bitdepth is 16 this will lose
- * information
- *
- * @param rowOffset
- * Number of rows to be skipped
- * @param nRows
- * Total number of rows to be read. -1: read all available
- * @param rowStep
- * Row increment. If 1, we read consecutive lines; if 2, we read even/odd lines, etc
- * @return Set of lines as a matrix
- */
- public ImageLines readRowsByte(int rowOffset, int nRows, int rowStep) {
- if (nRows < 0)
- nRows = (imgInfo.rows - rowOffset) / rowStep;
- if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
- throw new PngjInputException("bad args");
- ImageLines imlines = new ImageLines(imgInfo, SampleType.BYTE, unpackedMode, rowOffset, nRows, rowStep);
- if (!interlaced) {
- for (int j = 0; j < imgInfo.rows; j++) {
- int bytesread = readRowRaw(j); // read and perhaps discards
- int mrow = imlines.imageRowToMatrixRowStrict(j);
- if (mrow >= 0)
- decodeLastReadRowToByte(imlines.scanlinesb[mrow], bytesread);
- }
- } else { // and now, for something completely different (interlaced)
- byte[] buf = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
- for (int p = 1; p <= 7; p++) {
- deinterlacer.setPass(p);
- for (int i = 0; i < deinterlacer.getRows(); i++) {
- int bytesread = readRowRaw(i);
- int j = deinterlacer.getCurrRowReal();
- int mrow = imlines.imageRowToMatrixRowStrict(j);
- if (mrow >= 0) {
- decodeLastReadRowToByte(buf, bytesread);
- deinterlacer.deinterlaceByte(buf, imlines.scanlinesb[mrow], !unpackedMode);
- }
- }
- }
- }
- end();
- return imlines;
- }
-
- /**
- * Same as readRowsByte(0, imgInfo.rows, 1)
- *
- * @see #readRowsByte(int, int, int)
- */
- public ImageLines readRowsByte() {
- return readRowsByte(0, imgInfo.rows, 1);
- }
-
- /*
- * For the interlaced case, nrow indicates the subsampled image - the pass must be set already.
- *
- * This must be called in strict order, both for interlaced or no interlaced.
- *
- * Updates rowNum.
- *
- * Leaves raw result in rowb
- *
- * Returns bytes actually read (not including the filter byte)
- */
- private int readRowRaw(final int nrow) {
- //
- if (nrow == 0 && firstChunksNotYetRead())
- readFirstChunks();
- if (nrow == 0 && interlaced)
- Arrays.fill(rowb, (byte) 0); // new subimage: reset filters: this is enough, see the swap that happens lines
- // below
- int bytesRead = imgInfo.bytesPerRow; // NOT including the filter byte
- if (interlaced) {
- if (nrow < 0 || nrow > deinterlacer.getRows() || (nrow != 0 && nrow != deinterlacer.getCurrRowSubimg() + 1))
- throw new PngjInputException("invalid row in interlaced mode: " + nrow);
- deinterlacer.setRow(nrow);
- bytesRead = (imgInfo.bitspPixel * deinterlacer.getPixelsToRead() + 7) / 8;
- if (bytesRead < 1)
- throw new PngjExceptionInternal("wtf??");
- } else { // check for non interlaced
- if (nrow < 0 || nrow >= imgInfo.rows || nrow != rowNum + 1)
- throw new PngjInputException("invalid row: " + nrow);
- }
- rowNum = nrow;
- // swap buffers
- byte[] tmp = rowb;
- rowb = rowbprev;
- rowbprev = tmp;
- // loads in rowbfilter "raw" bytes, with filter
- PngHelperInternal.readBytes(idatIstream, rowbfilter, 0, bytesRead + 1);
- offset = iIdatCstream.getOffset();
- if (offset < 0)
- throw new PngjExceptionInternal("bad offset ??" + offset);
- if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
- throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
- + " offset:" + offset);
- rowb[0] = 0;
- unfilterRow(bytesRead);
- rowb[0] = rowbfilter[0];
- if ((rowNum == imgInfo.rows - 1 && !interlaced) || (interlaced && deinterlacer.isAtLastRow()))
- readLastAndClose();
- return bytesRead;
- }
-
- /**
- * Reads all the (remaining) file, skipping the pixels data. This is much more efficient that calling readRow(),
- * specially for big files (about 10 times faster!), because it doesn't even decompress the IDAT stream and disables
- * CRC check Use this if you are not interested in reading pixels,only metadata.
- */
- public void readSkippingAllRows() {
- if (firstChunksNotYetRead())
- readFirstChunks();
- // we read directly from the compressed stream, we dont decompress nor chec CRC
- iIdatCstream.disableCrcCheck();
- try {
- int r;
- do {
- r = iIdatCstream.read(rowbfilter, 0, rowbfilter.length);
- } while (r >= 0);
- } catch (IOException e) {
- throw new PngjInputException("error in raw read of IDAT", e);
- }
- offset = iIdatCstream.getOffset();
- if (offset < 0)
- throw new PngjExceptionInternal("bad offset ??" + offset);
- if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
- throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
- + " offset:" + offset);
- readLastAndClose();
- }
-
- /**
- * Set total maximum bytes to read (0: unlimited; default: 200MB). <br>
- * These are the bytes read (not loaded) in the input stream. If exceeded, an exception will be thrown.
- */
- public void setMaxTotalBytesRead(long maxTotalBytesToRead) {
- this.maxTotalBytesRead = maxTotalBytesToRead;
- }
-
- /**
- * @return Total maximum bytes to read.
- */
- public long getMaxTotalBytesRead() {
- return maxTotalBytesRead;
- }
-
- /**
- * Set total maximum bytes to load from ancillary chunks (0: unlimited; default: 5Mb).<br>
- * If exceeded, some chunks will be skipped
- */
- public void setMaxBytesMetadata(int maxBytesChunksToLoad) {
- this.maxBytesMetadata = maxBytesChunksToLoad;
- }
-
- /**
- * @return Total maximum bytes to load from ancillary ckunks.
- */
- public int getMaxBytesMetadata() {
- return maxBytesMetadata;
- }
-
- /**
- * Set maximum size in bytes for individual ancillary chunks (0: unlimited; default: 2MB). <br>
- * Chunks exceeding this length will be skipped (the CRC will not be checked) and the chunk will be saved as a
- * PngChunkSkipped object. See also setSkipChunkIds
- */
- public void setSkipChunkMaxSize(int skipChunksBySize) {
- this.skipChunkMaxSize = skipChunksBySize;
- }
-
- /**
- * @return maximum size in bytes for individual ancillary chunks.
- */
- public int getSkipChunkMaxSize() {
- return skipChunkMaxSize;
- }
-
- /**
- * Chunks ids to be skipped. <br>
- * These chunks will be skipped (the CRC will not be checked) and the chunk will be saved as a PngChunkSkipped
- * object. See also setSkipChunkMaxSize
- */
- public void setSkipChunkIds(String[] skipChunksById) {
- this.skipChunkIds = skipChunksById == null ? new String[] {} : skipChunksById;
- }
-
- /**
- * @return Chunk-IDs to be skipped.
- */
- public String[] getSkipChunkIds() {
- return skipChunkIds;
- }
-
- /**
- * if true, input stream will be closed after ending read
- * <p>
- * default=true
- */
- public void setShouldCloseStream(boolean shouldCloseStream) {
- this.shouldCloseStream = shouldCloseStream;
- }
-
- /**
- * Normally this does nothing, but it can be used to force a premature closing. Its recommended practice to call it
- * after reading the image pixels.
- */
- public void end() {
- if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END)
- close();
- }
-
- /**
- * Interlaced PNG is accepted -though not welcomed- now...
- */
- public boolean isInterlaced() {
- return interlaced;
- }
-
- /**
- * set/unset "unpackedMode"<br>
- * If false (default) packed types (bitdepth=1,2 or 4) will keep several samples packed in one element (byte or int) <br>
- * If true, samples will be unpacked on reading, and each element in the scanline will be sample. This implies more
- * processing and memory, but it's the most efficient option if you intend to read individual pixels. <br>
- * This option should only be set before start reading.
- *
- * @param unPackedMode
- */
- public void setUnpackedMode(boolean unPackedMode) {
- this.unpackedMode = unPackedMode;
- }
-
- /**
- * @see PngReader#setUnpackedMode(boolean)
- */
- public boolean isUnpackedMode() {
- return unpackedMode;
- }
-
- /**
- * Disables the CRC integrity check in IDAT chunks and ancillary chunks, this gives a slight increase in reading
- * speed for big files
- */
- public void setCrcCheckDisabled() {
- crcEnabled = false;
- }
-
- /**
- * Just for testing. TO be called after ending reading, only if initCrctest() was called before start
- *
- * @return CRC of the raw pixels values
- */
- long getCrctestVal() {
- return crctest.getValue();
- }
-
- /**
- * Inits CRC object and enables CRC calculation
- */
- void initCrctest() {
- this.crctest = new CRC32();
- }
-
- /**
- * Basic info, for debugging.
- */
- public String toString() { // basic info
- return "filename=" + filename + " " + imgInfo.toString();
- }
-
-}
+package jogamp.opengl.util.pngj;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.zip.CRC32;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
+import jogamp.opengl.util.pngj.chunks.ChunkHelper;
+import jogamp.opengl.util.pngj.chunks.ChunkLoadBehaviour;
+import jogamp.opengl.util.pngj.chunks.ChunkRaw;
+import jogamp.opengl.util.pngj.chunks.ChunksList;
+import jogamp.opengl.util.pngj.chunks.PngChunk;
+import jogamp.opengl.util.pngj.chunks.PngChunkIDAT;
+import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
+import jogamp.opengl.util.pngj.chunks.PngChunkSkipped;
+import jogamp.opengl.util.pngj.chunks.PngMetadata;
+
+/**
+ * Reads a PNG image, line by line.
+ * <p>
+ * The reading sequence is as follows: <br>
+ * 1. At construction time, the header and IHDR chunk are read (basic image
+ * info) <br>
+ * 2. Afterwards you can set some additional global options. Eg.
+ * {@link #setUnpackedMode(boolean)}, {@link #setCrcCheckDisabled()}.<br>
+ * 3. Optional: If you call getMetadata() or getChunksLisk() before start
+ * reading the rows, all the chunks before IDAT are automatically loaded and
+ * available <br>
+ * 4a. The rows are read onen by one of the <tt>readRowXXX</tt> methods:
+ * {@link #readRowInt(int)}, {@link PngReader#readRowByte(int)}, etc, in order,
+ * from 0 to nrows-1 (you can skip or repeat rows, but not go backwards)<br>
+ * 4b. Alternatively, you can read all rows, or a subset, in a single call:
+ * {@link #readRowsInt()}, {@link #readRowsByte()} ,etc. In general this
+ * consumes more memory, but for interlaced images this is equally efficient,
+ * and more so if reading a small subset of rows.<br>
+ * 5. Read of the last row auyomatically loads the trailing chunks, and ends the
+ * reader.<br>
+ * 6. end() forcibly finishes/aborts the reading and closes the stream
+ */
+public class PngReader {
+
+ /**
+ * Basic image info - final and inmutable.
+ */
+ public final ImageInfo imgInfo;
+ /**
+ * not necesarily a filename, can be a description - merely informative
+ */
+ protected final String filename;
+ private ChunkLoadBehaviour chunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS; // see setter/getter
+ private boolean shouldCloseStream = true; // true: closes stream after ending - see setter/getter
+ // some performance/defensive limits
+ private long maxTotalBytesRead = 200 * 1024 * 1024; // 200MB
+ private int maxBytesMetadata = 5 * 1024 * 1024; // for ancillary chunks - see setter/getter
+ private int skipChunkMaxSize = 2 * 1024 * 1024; // chunks exceeding this size will be skipped (nor even CRC checked)
+ private String[] skipChunkIds = { "fdAT" }; // chunks with these ids will be skipped (nor even CRC checked)
+ private HashSet<String> skipChunkIdsSet; // lazily created from skipChunksById
+ protected final PngMetadata metadata; // this a wrapper over chunks
+ protected final ChunksList chunksList;
+ protected ImageLine imgLine;
+ // line as bytes, counting from 1 (index 0 is reserved for filter type)
+ protected final int buffersLen; // nominal length is imgInfo.bytesPerRow + 1 but it can be larger
+ protected byte[] rowb = null;
+ protected byte[] rowbprev = null; // rowb previous
+ protected byte[] rowbfilter = null; // current line 'filtered': exactly as in uncompressed stream
+ // only set for interlaced PNG
+ private final boolean interlaced;
+ private final PngDeinterlacer deinterlacer;
+ private boolean crcEnabled = true;
+ // this only influences the 1-2-4 bitdepth format
+ private boolean unpackedMode = false;
+ private Inflater inflater = null; // can be reused among several objects. see reuseBuffersFrom()
+ /**
+ * Current chunk group, (0-6) already read or reading
+ * <p>
+ * see {@link ChunksList}
+ */
+ protected int currentChunkGroup = -1;
+ protected int rowNum = -1; // last read row number, starting from 0
+ private long offset = 0; // offset in InputStream = bytes read
+ private int bytesChunksLoaded; // bytes loaded from anciallary chunks
+ protected final InputStream inputStream;
+ protected InflaterInputStream idatIstream;
+ protected PngIDatChunkInputStream iIdatCstream;
+ protected CRC32 crctest; // If set to non null, it gets a CRC of the unfiltered bytes, to check for images equality
+
+ /**
+ * Constructs a PngReader from an InputStream.
+ * <p>
+ * See also <code>FileHelper.createPngReader(File f)</code> if available.
+ *
+ * Reads only the signature and first chunk (IDHR)
+ *
+ * @param filenameOrDescription
+ * : Optional, can be a filename or a description. Just for
+ * error/debug messages
+ *
+ */
+ public PngReader(InputStream inputStream, String filenameOrDescription) {
+ this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
+ this.inputStream = inputStream;
+ this.chunksList = new ChunksList(null);
+ this.metadata = new PngMetadata(chunksList);
+ // starts reading: signature
+ byte[] pngid = new byte[8];
+ PngHelperInternal.readBytes(inputStream, pngid, 0, pngid.length);
+ offset += pngid.length;
+ if (!Arrays.equals(pngid, PngHelperInternal.getPngIdSignature()))
+ throw new PngjInputException("Bad PNG signature");
+ // reads first chunk
+ currentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
+ int clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen != 13)
+ throw new PngjInputException("IDHR chunk len != 13 ?? " + clen);
+ byte[] chunkid = new byte[4];
+ PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
+ if (!Arrays.equals(chunkid, ChunkHelper.b_IHDR))
+ throw new PngjInputException("IHDR not found as first chunk??? [" + ChunkHelper.toString(chunkid) + "]");
+ offset += 4;
+ PngChunkIHDR ihdr = (PngChunkIHDR) readChunk(chunkid, clen, false);
+ boolean alpha = (ihdr.getColormodel() & 0x04) != 0;
+ boolean palette = (ihdr.getColormodel() & 0x01) != 0;
+ boolean grayscale = (ihdr.getColormodel() == 0 || ihdr.getColormodel() == 4);
+ // creates ImgInfo and imgLine, and allocates buffers
+ imgInfo = new ImageInfo(ihdr.getCols(), ihdr.getRows(), ihdr.getBitspc(), alpha, grayscale, palette);
+ interlaced = ihdr.getInterlaced() == 1;
+ deinterlacer = interlaced ? new PngDeinterlacer(imgInfo) : null;
+ buffersLen = imgInfo.bytesPerRow + 1;
+ // some checks
+ if (ihdr.getFilmeth() != 0 || ihdr.getCompmeth() != 0 || (ihdr.getInterlaced() & 0xFFFE) != 0)
+ throw new PngjInputException("compression method o filter method or interlaced unrecognized ");
+ if (ihdr.getColormodel() < 0 || ihdr.getColormodel() > 6 || ihdr.getColormodel() == 1
+ || ihdr.getColormodel() == 5)
+ throw new PngjInputException("Invalid colormodel " + ihdr.getColormodel());
+ if (ihdr.getBitspc() != 1 && ihdr.getBitspc() != 2 && ihdr.getBitspc() != 4 && ihdr.getBitspc() != 8
+ && ihdr.getBitspc() != 16)
+ throw new PngjInputException("Invalid bit depth " + ihdr.getBitspc());
+ }
+
+ private boolean firstChunksNotYetRead() {
+ return currentChunkGroup < ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ }
+
+ private void allocateBuffers() { // only if needed
+ if (rowbfilter == null || rowbfilter.length < buffersLen) {
+ rowbfilter = new byte[buffersLen];
+ rowb = new byte[buffersLen];
+ rowbprev = new byte[buffersLen];
+ }
+ }
+
+ /**
+ * Reads last Internally called after having read the last line. It reads
+ * extra chunks after IDAT, if present.
+ */
+ private void readLastAndClose() {
+ // offset = iIdatCstream.getOffset();
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT) {
+ try {
+ idatIstream.close();
+ } catch (Exception e) {
+ }
+ readLastChunks();
+ }
+ close();
+ }
+
+ private void close() {
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END) { // this could only happen if forced close
+ try {
+ idatIstream.close();
+ } catch (Exception e) {
+ }
+ currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
+ }
+ if (shouldCloseStream) {
+ try {
+ inputStream.close();
+ } catch (Exception e) {
+ throw new PngjInputException("error closing input stream!", e);
+ }
+ }
+ }
+
+ // nbytes: NOT including the filter byte. leaves result in rowb
+ private void unfilterRow(int nbytes) {
+ int ftn = rowbfilter[0];
+ FilterType ft = FilterType.getByVal(ftn);
+ if (ft == null)
+ throw new PngjInputException("Filter type " + ftn + " invalid");
+ switch (ft) {
+ case FILTER_NONE:
+ unfilterRowNone(nbytes);
+ break;
+ case FILTER_SUB:
+ unfilterRowSub(nbytes);
+ break;
+ case FILTER_UP:
+ unfilterRowUp(nbytes);
+ break;
+ case FILTER_AVERAGE:
+ unfilterRowAverage(nbytes);
+ break;
+ case FILTER_PAETH:
+ unfilterRowPaeth(nbytes);
+ break;
+ default:
+ throw new PngjInputException("Filter type " + ftn + " not implemented");
+ }
+ if (crctest != null)
+ crctest.update(rowb, 1, buffersLen - 1);
+ }
+
+ private void unfilterRowAverage(final int nbytes) {
+ int i, j, x;
+ for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
+ x = j > 0 ? (rowb[j] & 0xff) : 0;
+ rowb[i] = (byte) (rowbfilter[i] + (x + (rowbprev[i] & 0xFF)) / 2);
+ }
+ }
+
+ private void unfilterRowNone(final int nbytes) {
+ for (int i = 1; i <= nbytes; i++) {
+ rowb[i] = (byte) (rowbfilter[i]);
+ }
+ }
+
+ private void unfilterRowPaeth(final int nbytes) {
+ int i, j, x, y;
+ for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
+ x = j > 0 ? (rowb[j] & 0xFF) : 0;
+ y = j > 0 ? (rowbprev[j] & 0xFF) : 0;
+ rowb[i] = (byte) (rowbfilter[i] + PngHelperInternal.filterPaethPredictor(x, rowbprev[i] & 0xFF, y));
+ }
+ }
+
+ private void unfilterRowSub(final int nbytes) {
+ int i, j;
+ for (i = 1; i <= imgInfo.bytesPixel; i++) {
+ rowb[i] = (byte) (rowbfilter[i]);
+ }
+ for (j = 1, i = imgInfo.bytesPixel + 1; i <= nbytes; i++, j++) {
+ rowb[i] = (byte) (rowbfilter[i] + rowb[j]);
+ }
+ }
+
+ private void unfilterRowUp(final int nbytes) {
+ for (int i = 1; i <= nbytes; i++) {
+ rowb[i] = (byte) (rowbfilter[i] + rowbprev[i]);
+ }
+ }
+
+ /**
+ * Reads chunks before first IDAT. Normally this is called automatically
+ * <p>
+ * Position before: after IDHR (crc included) Position after: just after the
+ * first IDAT chunk id
+ * <P>
+ * This can be called several times (tentatively), it does nothing if
+ * already run
+ * <p>
+ * (Note: when should this be called? in the constructor? hardly, because we
+ * loose the opportunity to call setChunkLoadBehaviour() and perhaps other
+ * settings before reading the first row? but sometimes we want to access
+ * some metadata (plte, phys) before. Because of this, this method can be
+ * called explicitly but is also called implicititly in some methods
+ * (getMetatada(), getChunksList())
+ */
+ private final void readFirstChunks() {
+ if (!firstChunksNotYetRead())
+ return;
+ int clen = 0;
+ boolean found = false;
+ byte[] chunkid = new byte[4]; // it's important to reallocate in each iteration
+ currentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ while (!found) {
+ clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen < 0)
+ break;
+ PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
+ offset += 4;
+ if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
+ found = true;
+ currentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
+ // add dummy idat chunk to list
+ chunksList.appendReadChunk(new PngChunkIDAT(imgInfo, clen, offset - 8), currentChunkGroup);
+ break;
+ } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
+ throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset);
+ }
+ if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
+ currentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
+ readChunk(chunkid, clen, false);
+ if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
+ currentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
+ }
+ int idatLen = found ? clen : -1;
+ if (idatLen < 0)
+ throw new PngjInputException("first idat chunk not found!");
+ iIdatCstream = new PngIDatChunkInputStream(inputStream, idatLen, offset);
+ if(inflater == null) {
+ inflater = new Inflater();
+ } else {
+ inflater.reset();
+ }
+ idatIstream = new InflaterInputStream(iIdatCstream, inflater);
+ if (!crcEnabled)
+ iIdatCstream.disableCrcCheck();
+ }
+
+ /**
+ * Reads (and processes) chunks after last IDAT.
+ **/
+ void readLastChunks() {
+ // PngHelper.logdebug("idat ended? " + iIdatCstream.isEnded());
+ currentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
+ if (!iIdatCstream.isEnded())
+ iIdatCstream.forceChunkEnd();
+ int clen = iIdatCstream.getLenLastChunk();
+ byte[] chunkid = iIdatCstream.getIdLastChunk();
+ boolean endfound = false;
+ boolean first = true;
+ boolean skip = false;
+ while (!endfound) {
+ skip = false;
+ if (!first) {
+ clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen < 0)
+ throw new PngjInputException("bad chuck len " + clen);
+ PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
+ offset += 4;
+ }
+ first = false;
+ if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
+ skip = true; // extra dummy (empty?) idat chunk, it can happen, ignore it
+ } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
+ currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
+ endfound = true;
+ }
+ readChunk(chunkid, clen, skip);
+ }
+ if (!endfound)
+ throw new PngjInputException("end chunk not found - offset=" + offset);
+ // PngHelper.logdebug("end chunk found ok offset=" + offset);
+ }
+
+ /**
+ * Reads chunkd from input stream, adds to ChunksList, and returns it. If
+ * it's skipped, a PngChunkSkipped object is created
+ */
+ private PngChunk readChunk(byte[] chunkid, int clen, boolean skipforced) {
+ if (clen < 0)
+ throw new PngjInputException("invalid chunk lenght: " + clen);
+ // skipChunksByIdSet is created lazyly, if fist IHDR has already been read
+ if (skipChunkIdsSet == null && currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR)
+ skipChunkIdsSet = new HashSet<String>(Arrays.asList(skipChunkIds));
+ String chunkidstr = ChunkHelper.toString(chunkid);
+ boolean critical = ChunkHelper.isCritical(chunkidstr);
+ PngChunk pngChunk = null;
+ boolean skip = skipforced;
+ if (maxTotalBytesRead > 0 && clen + offset > maxTotalBytesRead)
+ throw new PngjInputException("Maximum total bytes to read exceeeded: " + maxTotalBytesRead + " offset:"
+ + offset + " clen=" + clen);
+ // an ancillary chunks can be skipped because of several reasons:
+ if (currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR && !critical)
+ skip = skip || (skipChunkMaxSize > 0 && clen >= skipChunkMaxSize) || skipChunkIdsSet.contains(chunkidstr)
+ || (maxBytesMetadata > 0 && clen > maxBytesMetadata - bytesChunksLoaded)
+ || !ChunkHelper.shouldLoad(chunkidstr, chunkLoadBehaviour);
+ if (skip) {
+ PngHelperInternal.skipBytes(inputStream, clen);
+ PngHelperInternal.readInt4(inputStream); // skip - we dont call PngHelperInternal.skipBytes(inputStream,
+ // clen + 4) for risk of overflow
+ pngChunk = new PngChunkSkipped(chunkidstr, imgInfo, clen);
+ } else {
+ ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
+ chunk.readChunkData(inputStream, crcEnabled || critical);
+ pngChunk = PngChunk.factory(chunk, imgInfo);
+ if (!pngChunk.crit)
+ bytesChunksLoaded += chunk.len;
+ }
+ pngChunk.setOffset(offset - 8L);
+ chunksList.appendReadChunk(pngChunk, currentChunkGroup);
+ offset += clen + 4L;
+ return pngChunk;
+ }
+
+ /**
+ * Logs/prints a warning.
+ * <p>
+ * The default behaviour is print to stderr, but it can be overriden.
+ * <p>
+ * This happens rarely - most errors are fatal.
+ */
+ protected void logWarn(String warn) {
+ System.err.println(warn);
+ }
+
+ /**
+ * @see #setChunkLoadBehaviour(ChunkLoadBehaviour)
+ */
+ public ChunkLoadBehaviour getChunkLoadBehaviour() {
+ return chunkLoadBehaviour;
+ }
+
+ /**
+ * Determines which ancillary chunks (metada) are to be loaded
+ *
+ * @param chunkLoadBehaviour
+ * {@link ChunkLoadBehaviour}
+ */
+ public void setChunkLoadBehaviour(ChunkLoadBehaviour chunkLoadBehaviour) {
+ this.chunkLoadBehaviour = chunkLoadBehaviour;
+ }
+
+ /**
+ * All loaded chunks (metada). If we have not yet end reading the image,
+ * this will include only the chunks before the pixels data (IDAT)
+ * <p>
+ * Critical chunks are included, except that all IDAT chunks appearance are
+ * replaced by a single dummy-marker IDAT chunk. These might be copied to
+ * the PngWriter
+ * <p>
+ *
+ * @see #getMetadata()
+ */
+ public ChunksList getChunksList() {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ return chunksList;
+ }
+
+ int getCurrentChunkGroup() {
+ return currentChunkGroup;
+ }
+
+ /**
+ * High level wrapper over chunksList
+ *
+ * @see #getChunksList()
+ */
+ public PngMetadata getMetadata() {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ return metadata;
+ }
+
+ /**
+ * If called for first time, calls readRowInt. Elsewhere, it calls the
+ * appropiate readRowInt/readRowByte
+ * <p>
+ * In general, specifying the concrete readRowInt/readRowByte is preferrable
+ *
+ * @see #readRowInt(int) {@link #readRowByte(int)}
+ */
+ public ImageLine readRow(int nrow) {
+ if (imgLine == null)
+ imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
+ return imgLine.sampleType != SampleType.BYTE ? readRowInt(nrow) : readRowByte(nrow);
+ }
+
+ /**
+ * Reads the row as INT, storing it in the {@link #imgLine} property and
+ * returning it.
+ *
+ * The row must be greater or equal than the last read row.
+ *
+ * @param nrow
+ * Row number, from 0 to rows-1. Increasing order.
+ * @return ImageLine object, also available as field. Data is in
+ * {@link ImageLine#scanline} (int) field.
+ */
+ public ImageLine readRowInt(int nrow) {
+ if (imgLine == null)
+ imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
+ if (imgLine.getRown() == nrow) // already read
+ return imgLine;
+ readRowInt(imgLine.scanline, nrow);
+ imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
+ imgLine.setRown(nrow);
+ return imgLine;
+ }
+
+ /**
+ * Reads the row as BYTES, storing it in the {@link #imgLine} property and
+ * returning it.
+ *
+ * The row must be greater or equal than the last read row. This method
+ * allows to pass the same row that was last read.
+ *
+ * @param nrow
+ * Row number, from 0 to rows-1. Increasing order.
+ * @return ImageLine object, also available as field. Data is in
+ * {@link ImageLine#scanlineb} (byte) field.
+ */
+ public ImageLine readRowByte(int nrow) {
+ if (imgLine == null)
+ imgLine = new ImageLine(imgInfo, SampleType.BYTE, unpackedMode);
+ if (imgLine.getRown() == nrow) // already read
+ return imgLine;
+ readRowByte(imgLine.scanlineb, nrow);
+ imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
+ imgLine.setRown(nrow);
+ return imgLine;
+ }
+
+ /**
+ * @see #readRowInt(int[], int)
+ */
+ public final int[] readRow(int[] buffer, final int nrow) {
+ return readRowInt(buffer, nrow);
+ }
+
+ /**
+ * Reads a line and returns it as a int[] array.
+ * <p>
+ * You can pass (optionally) a prealocatted buffer.
+ * <p>
+ * If the bitdepth is less than 8, the bytes are packed - unless
+ * {@link #unpackedMode} is true.
+ *
+ * @param buffer
+ * Prealocated buffer, or null.
+ * @param nrow
+ * Row number (0 is top). Most be strictly greater than the last
+ * read row.
+ *
+ * @return The scanline in the same passwd buffer if it was allocated, a
+ * newly allocated one otherwise
+ */
+ public final int[] readRowInt(int[] buffer, final int nrow) {
+ if (buffer == null)
+ buffer = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ if (!interlaced) {
+ if (nrow <= rowNum)
+ throw new PngjInputException("rows must be read in increasing order: " + nrow);
+ int bytesread = 0;
+ while (rowNum < nrow)
+ bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
+ decodeLastReadRowToInt(buffer, bytesread);
+ } else { // interlaced
+ if (deinterlacer.getImageInt() == null)
+ deinterlacer.setImageInt(readRowsInt().scanlines); // read all image and store it in deinterlacer
+ System.arraycopy(deinterlacer.getImageInt()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
+ : imgInfo.samplesPerRowPacked);
+ }
+ return buffer;
+ }
+
+ /**
+ * Reads a line and returns it as a byte[] array.
+ * <p>
+ * You can pass (optionally) a prealocatted buffer.
+ * <p>
+ * If the bitdepth is less than 8, the bytes are packed - unless
+ * {@link #unpackedMode} is true. <br>
+ * If the bitdepth is 16, the least significant byte is lost.
+ * <p>
+ *
+ * @param buffer
+ * Prealocated buffer, or null.
+ * @param nrow
+ * Row number (0 is top). Most be strictly greater than the last
+ * read row.
+ *
+ * @return The scanline in the same passwd buffer if it was allocated, a
+ * newly allocated one otherwise
+ */
+ public final byte[] readRowByte(byte[] buffer, final int nrow) {
+ if (buffer == null)
+ buffer = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ if (!interlaced) {
+ if (nrow <= rowNum)
+ throw new PngjInputException("rows must be read in increasing order: " + nrow);
+ int bytesread = 0;
+ while (rowNum < nrow)
+ bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
+ decodeLastReadRowToByte(buffer, bytesread);
+ } else { // interlaced
+ if (deinterlacer.getImageByte() == null)
+ deinterlacer.setImageByte(readRowsByte().scanlinesb); // read all image and store it in deinterlacer
+ System.arraycopy(deinterlacer.getImageByte()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
+ : imgInfo.samplesPerRowPacked);
+ }
+ return buffer;
+ }
+
+ /**
+ * @param nrow
+ * @deprecated Now {@link #readRow(int)} implements the same funcion. This
+ * method will be removed in future releases
+ */
+ public ImageLine getRow(int nrow) {
+ return readRow(nrow);
+ }
+
+ private void decodeLastReadRowToInt(int[] buffer, int bytesRead) {
+ if (imgInfo.bitDepth <= 8)
+ for (int i = 0, j = 1; i < bytesRead; i++)
+ buffer[i] = (rowb[j++] & 0xFF); // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+ else
+ for (int i = 0, j = 1; j <= bytesRead; i++)
+ buffer[i] = ((rowb[j++] & 0xFF) << 8) + (rowb[j++] & 0xFF); // 16 bitspc
+ if (imgInfo.packed && unpackedMode)
+ ImageLine.unpackInplaceInt(imgInfo, buffer, buffer, false);
+ }
+
+ private void decodeLastReadRowToByte(byte[] buffer, int bytesRead) {
+ if (imgInfo.bitDepth <= 8)
+ System.arraycopy(rowb, 1, buffer, 0, bytesRead);
+ else
+ for (int i = 0, j = 1; j < bytesRead; i++, j += 2)
+ buffer[i] = rowb[j];// 16 bits in 1 byte: this discards the LSB!!!
+ if (imgInfo.packed && unpackedMode)
+ ImageLine.unpackInplaceByte(imgInfo, buffer, buffer, false);
+ }
+
+ /**
+ * Reads a set of lines and returns it as a ImageLines object, which wraps
+ * matrix. Internally it reads all lines, but decodes and stores only the
+ * wanted ones. This starts and ends the reading, and cannot be combined
+ * with other reading methods.
+ * <p>
+ * This it's more efficient (speed an memory) that doing calling
+ * readRowInt() for each desired line only if the image is interlaced.
+ * <p>
+ * Notice that the columns in the matrix is not the pixel width of the
+ * image, but rather pixels x channels
+ *
+ * @see #readRowInt(int) to read about the format of each row
+ *
+ * @param rowOffset
+ * Number of rows to be skipped
+ * @param nRows
+ * Total number of rows to be read. -1: read all available
+ * @param rowStep
+ * Row increment. If 1, we read consecutive lines; if 2, we read
+ * even/odd lines, etc
+ * @return Set of lines as a ImageLines, which wraps a matrix
+ */
+ public ImageLines readRowsInt(int rowOffset, int nRows, int rowStep) {
+ if (nRows < 0)
+ nRows = (imgInfo.rows - rowOffset) / rowStep;
+ if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
+ throw new PngjInputException("bad args");
+ ImageLines imlines = new ImageLines(imgInfo, SampleType.INT, unpackedMode, rowOffset, nRows, rowStep);
+ if (!interlaced) {
+ for (int j = 0; j < imgInfo.rows; j++) {
+ int bytesread = readRowRaw(j); // read and perhaps discards
+ int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0)
+ decodeLastReadRowToInt(imlines.scanlines[mrow], bytesread);
+ }
+ } else { // and now, for something completely different (interlaced)
+ int[] buf = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ for (int p = 1; p <= 7; p++) {
+ deinterlacer.setPass(p);
+ for (int i = 0; i < deinterlacer.getRows(); i++) {
+ int bytesread = readRowRaw(i);
+ int j = deinterlacer.getCurrRowReal();
+ int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0) {
+ decodeLastReadRowToInt(buf, bytesread);
+ deinterlacer.deinterlaceInt(buf, imlines.scanlines[mrow], !unpackedMode);
+ }
+ }
+ }
+ }
+ end();
+ return imlines;
+ }
+
+ /**
+ * Same as readRowsInt(0, imgInfo.rows, 1)
+ *
+ * @see #readRowsInt(int, int, int)
+ */
+ public ImageLines readRowsInt() {
+ return readRowsInt(0, imgInfo.rows, 1);
+ }
+
+ /**
+ * Reads a set of lines and returns it as a ImageLines object, which wrapas
+ * a byte[][] matrix. Internally it reads all lines, but decodes and stores
+ * only the wanted ones. This starts and ends the reading, and cannot be
+ * combined with other reading methods.
+ * <p>
+ * This it's more efficient (speed an memory) that doing calling
+ * readRowByte() for each desired line only if the image is interlaced.
+ * <p>
+ * Notice that the columns in the matrix is not the pixel width of the
+ * image, but rather pixels x channels
+ *
+ * @see #readRowByte(int) to read about the format of each row. Notice that
+ * if the bitdepth is 16 this will lose information
+ *
+ * @param rowOffset
+ * Number of rows to be skipped
+ * @param nRows
+ * Total number of rows to be read. -1: read all available
+ * @param rowStep
+ * Row increment. If 1, we read consecutive lines; if 2, we read
+ * even/odd lines, etc
+ * @return Set of lines as a matrix
+ */
+ public ImageLines readRowsByte(int rowOffset, int nRows, int rowStep) {
+ if (nRows < 0)
+ nRows = (imgInfo.rows - rowOffset) / rowStep;
+ if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
+ throw new PngjInputException("bad args");
+ ImageLines imlines = new ImageLines(imgInfo, SampleType.BYTE, unpackedMode, rowOffset, nRows, rowStep);
+ if (!interlaced) {
+ for (int j = 0; j < imgInfo.rows; j++) {
+ int bytesread = readRowRaw(j); // read and perhaps discards
+ int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0)
+ decodeLastReadRowToByte(imlines.scanlinesb[mrow], bytesread);
+ }
+ } else { // and now, for something completely different (interlaced)
+ byte[] buf = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ for (int p = 1; p <= 7; p++) {
+ deinterlacer.setPass(p);
+ for (int i = 0; i < deinterlacer.getRows(); i++) {
+ int bytesread = readRowRaw(i);
+ int j = deinterlacer.getCurrRowReal();
+ int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0) {
+ decodeLastReadRowToByte(buf, bytesread);
+ deinterlacer.deinterlaceByte(buf, imlines.scanlinesb[mrow], !unpackedMode);
+ }
+ }
+ }
+ }
+ end();
+ return imlines;
+ }
+
+ /**
+ * Same as readRowsByte(0, imgInfo.rows, 1)
+ *
+ * @see #readRowsByte(int, int, int)
+ */
+ public ImageLines readRowsByte() {
+ return readRowsByte(0, imgInfo.rows, 1);
+ }
+
+ /*
+ * For the interlaced case, nrow indicates the subsampled image - the pass must be set already.
+ *
+ * This must be called in strict order, both for interlaced or no interlaced.
+ *
+ * Updates rowNum.
+ *
+ * Leaves raw result in rowb
+ *
+ * Returns bytes actually read (not including the filter byte)
+ */
+ private int readRowRaw(final int nrow) {
+ if (nrow == 0) {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ allocateBuffers();
+ if (interlaced)
+ Arrays.fill(rowb, (byte) 0); // new subimage: reset filters: this is enough, see the swap that happens lines
+ }
+ // below
+ int bytesRead = imgInfo.bytesPerRow; // NOT including the filter byte
+ if (interlaced) {
+ if (nrow < 0 || nrow > deinterlacer.getRows() || (nrow != 0 && nrow != deinterlacer.getCurrRowSubimg() + 1))
+ throw new PngjInputException("invalid row in interlaced mode: " + nrow);
+ deinterlacer.setRow(nrow);
+ bytesRead = (imgInfo.bitspPixel * deinterlacer.getPixelsToRead() + 7) / 8;
+ if (bytesRead < 1)
+ throw new PngjExceptionInternal("wtf??");
+ } else { // check for non interlaced
+ if (nrow < 0 || nrow >= imgInfo.rows || nrow != rowNum + 1)
+ throw new PngjInputException("invalid row: " + nrow);
+ }
+ rowNum = nrow;
+ // swap buffers
+ byte[] tmp = rowb;
+ rowb = rowbprev;
+ rowbprev = tmp;
+ // loads in rowbfilter "raw" bytes, with filter
+ PngHelperInternal.readBytes(idatIstream, rowbfilter, 0, bytesRead + 1);
+ offset = iIdatCstream.getOffset();
+ if (offset < 0)
+ throw new PngjExceptionInternal("bad offset ??" + offset);
+ if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
+ throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
+ + " offset:" + offset);
+ rowb[0] = 0;
+ unfilterRow(bytesRead);
+ rowb[0] = rowbfilter[0];
+ if ((rowNum == imgInfo.rows - 1 && !interlaced) || (interlaced && deinterlacer.isAtLastRow()))
+ readLastAndClose();
+ return bytesRead;
+ }
+
+ /**
+ * Reads all the (remaining) file, skipping the pixels data. This is much
+ * more efficient that calling readRow(), specially for big files (about 10
+ * times faster!), because it doesn't even decompress the IDAT stream and
+ * disables CRC check Use this if you are not interested in reading
+ * pixels,only metadata.
+ */
+ public void readSkippingAllRows() {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ // we read directly from the compressed stream, we dont decompress nor chec CRC
+ iIdatCstream.disableCrcCheck();
+ allocateBuffers();
+ try {
+ int r;
+ do {
+ r = iIdatCstream.read(rowbfilter, 0, buffersLen);
+ } while (r >= 0);
+ } catch (IOException e) {
+ throw new PngjInputException("error in raw read of IDAT", e);
+ }
+ offset = iIdatCstream.getOffset();
+ if (offset < 0)
+ throw new PngjExceptionInternal("bad offset ??" + offset);
+ if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
+ throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
+ + " offset:" + offset);
+ readLastAndClose();
+ }
+
+ /**
+ * Set total maximum bytes to read (0: unlimited; default: 200MB). <br>
+ * These are the bytes read (not loaded) in the input stream. If exceeded,
+ * an exception will be thrown.
+ */
+ public void setMaxTotalBytesRead(long maxTotalBytesToRead) {
+ this.maxTotalBytesRead = maxTotalBytesToRead;
+ }
+
+ /**
+ * @return Total maximum bytes to read.
+ */
+ public long getMaxTotalBytesRead() {
+ return maxTotalBytesRead;
+ }
+
+ /**
+ * Set total maximum bytes to load from ancillary chunks (0: unlimited;
+ * default: 5Mb).<br>
+ * If exceeded, some chunks will be skipped
+ */
+ public void setMaxBytesMetadata(int maxBytesChunksToLoad) {
+ this.maxBytesMetadata = maxBytesChunksToLoad;
+ }
+
+ /**
+ * @return Total maximum bytes to load from ancillary ckunks.
+ */
+ public int getMaxBytesMetadata() {
+ return maxBytesMetadata;
+ }
+
+ /**
+ * Set maximum size in bytes for individual ancillary chunks (0: unlimited;
+ * default: 2MB). <br>
+ * Chunks exceeding this length will be skipped (the CRC will not be
+ * checked) and the chunk will be saved as a PngChunkSkipped object. See
+ * also setSkipChunkIds
+ */
+ public void setSkipChunkMaxSize(int skipChunksBySize) {
+ this.skipChunkMaxSize = skipChunksBySize;
+ }
+
+ /**
+ * @return maximum size in bytes for individual ancillary chunks.
+ */
+ public int getSkipChunkMaxSize() {
+ return skipChunkMaxSize;
+ }
+
+ /**
+ * Chunks ids to be skipped. <br>
+ * These chunks will be skipped (the CRC will not be checked) and the chunk
+ * will be saved as a PngChunkSkipped object. See also setSkipChunkMaxSize
+ */
+ public void setSkipChunkIds(String[] skipChunksById) {
+ this.skipChunkIds = skipChunksById == null ? new String[] {} : skipChunksById;
+ }
+
+ /**
+ * @return Chunk-IDs to be skipped.
+ */
+ public String[] getSkipChunkIds() {
+ return skipChunkIds;
+ }
+
+ /**
+ * if true, input stream will be closed after ending read
+ * <p>
+ * default=true
+ */
+ public void setShouldCloseStream(boolean shouldCloseStream) {
+ this.shouldCloseStream = shouldCloseStream;
+ }
+
+ /**
+ * Normally this does nothing, but it can be used to force a premature
+ * closing. Its recommended practice to call it after reading the image
+ * pixels.
+ */
+ public void end() {
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END)
+ close();
+ }
+
+ /**
+ * Interlaced PNG is accepted -though not welcomed- now...
+ */
+ public boolean isInterlaced() {
+ return interlaced;
+ }
+
+ /**
+ * set/unset "unpackedMode"<br>
+ * If false (default) packed types (bitdepth=1,2 or 4) will keep several
+ * samples packed in one element (byte or int) <br>
+ * If true, samples will be unpacked on reading, and each element in the
+ * scanline will be sample. This implies more processing and memory, but
+ * it's the most efficient option if you intend to read individual pixels. <br>
+ * This option should only be set before start reading.
+ *
+ * @param unPackedMode
+ */
+ public void setUnpackedMode(boolean unPackedMode) {
+ this.unpackedMode = unPackedMode;
+ }
+
+ /**
+ * @see PngReader#setUnpackedMode(boolean)
+ */
+ public boolean isUnpackedMode() {
+ return unpackedMode;
+ }
+
+ /**
+ * Tries to reuse the allocated buffers from other already used PngReader
+ * object. This will have no effect if the buffers are smaller than necessary.
+ * It also reuses the inflater.
+ *
+ * @param other A PngReader that has already finished reading pixels. Can be null.
+ */
+ public void reuseBuffersFrom(PngReader other) {
+ if(other==null) return;
+ if (other.currentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT)
+ throw new PngjInputException("PngReader to be reused have not yet ended reading pixels");
+ if (other.rowbfilter != null && other.rowbfilter.length >= buffersLen) {
+ rowbfilter = other.rowbfilter;
+ rowb = other.rowb;
+ rowbprev = other.rowbprev;
+ }
+ inflater = other.inflater;
+ }
+
+ /**
+ * Disables the CRC integrity check in IDAT chunks and ancillary chunks,
+ * this gives a slight increase in reading speed for big files
+ */
+ public void setCrcCheckDisabled() {
+ crcEnabled = false;
+ }
+
+ /**
+ * Just for testing. TO be called after ending reading, only if
+ * initCrctest() was called before start
+ *
+ * @return CRC of the raw pixels values
+ */
+ long getCrctestVal() {
+ return crctest.getValue();
+ }
+
+ /**
+ * Inits CRC object and enables CRC calculation
+ */
+ void initCrctest() {
+ this.crctest = new CRC32();
+ }
+
+ /**
+ * Basic info, for debugging.
+ */
+ public String toString() { // basic info
+ return "filename=" + filename + " " + imgInfo.toString();
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
index 601cd96c0..3e684a881 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
@@ -83,8 +83,9 @@ public class PngWriter {
}
/**
- * Constructs a new PngWriter from a output stream. After construction nothing is writen yet. You still can set some
- * parameters (compression, filters) and queue chunks before start writing the pixels.
+ * Constructs a new PngWriter from a output stream. After construction
+ * nothing is writen yet. You still can set some parameters (compression,
+ * filters) and queue chunks before start writing the pixels.
* <p>
* See also <code>FileHelper.createPngWriter()</code> if available.
*
@@ -418,13 +419,15 @@ public class PngWriter {
/**
* Copies first (pre IDAT) ancillary chunks from a PngReader.
* <p>
- * Should be called when creating an image from another, before starting writing lines, to copy relevant chunks.
+ * Should be called when creating an image from another, before starting
+ * writing lines, to copy relevant chunks.
* <p>
*
* @param reader
* : PngReader object, already opened.
* @param copy_mask
- * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code> constants
+ * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code>
+ * constants
*/
public void copyChunksFirst(PngReader reader, int copy_mask) {
copyChunks(reader, copy_mask, false);
@@ -433,14 +436,15 @@ public class PngWriter {
/**
* Copies last (post IDAT) ancillary chunks from a PngReader.
* <p>
- * Should be called when creating an image from another, after writing all lines, before closing the writer, to copy
- * additional chunks.
+ * Should be called when creating an image from another, after writing all
+ * lines, before closing the writer, to copy additional chunks.
* <p>
*
* @param reader
* : PngReader object, already opened and fully read.
* @param copy_mask
- * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code> constants
+ * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code>
+ * constants
*/
public void copyChunksLast(PngReader reader, int copy_mask) {
copyChunks(reader, copy_mask, true);
@@ -449,8 +453,8 @@ public class PngWriter {
/**
* Computes compressed size/raw size, approximate.
* <p>
- * Actually: compressed size = total size of IDAT data , raw size = uncompressed pixel bytes = rows * (bytesPerRow +
- * 1).
+ * Actually: compressed size = total size of IDAT data , raw size =
+ * uncompressed pixel bytes = rows * (bytesPerRow + 1).
*
* This must be called after pngw.end()
*/
@@ -463,7 +467,8 @@ public class PngWriter {
}
/**
- * Finalizes the image creation and closes the stream. This MUST be called after writing the lines.
+ * Finalizes the image creation and closes the stream. This MUST be called
+ * after writing the lines.
*/
public void end() {
if (rowNum != imgInfo.rows - 1)
@@ -525,15 +530,17 @@ public class PngWriter {
* See also setCompLevel()
*
* @param filterType
- * One of the five prediction types or strategy to choose it (see <code>PngFilterType</code>) Recommended
- * values: DEFAULT (default) or AGGRESIVE
+ * One of the five prediction types or strategy to choose it (see
+ * <code>PngFilterType</code>) Recommended values: DEFAULT
+ * (default) or AGGRESIVE
*/
public void setFilterType(FilterType filterType) {
filterStrat = new FilterWriteStrategy(imgInfo, filterType);
}
/**
- * Sets maximum size of IDAT fragments. This has little effect on performance you should rarely call this
+ * Sets maximum size of IDAT fragments. This has little effect on
+ * performance you should rarely call this
* <p>
*
* @param idatMaxSize
@@ -553,7 +560,8 @@ public class PngWriter {
}
/**
- * Deflater strategy: one of Deflater.FILTERED Deflater.HUFFMAN_ONLY Deflater.DEFAULT_STRATEGY
+ * Deflater strategy: one of Deflater.FILTERED Deflater.HUFFMAN_ONLY
+ * Deflater.DEFAULT_STRATEGY
* <p>
* Default: Deflater.FILTERED . This should be changed very rarely.
*/
@@ -562,8 +570,8 @@ public class PngWriter {
}
/**
- * Writes line, checks that the row number is consistent with that of the ImageLine See writeRow(int[] newrow, int
- * rown)
+ * Writes line, checks that the row number is consistent with that of the
+ * ImageLine See writeRow(int[] newrow, int rown)
*
* @deprecated Better use writeRow(ImageLine imgline, int rownumber)
*/
@@ -607,18 +615,22 @@ public class PngWriter {
/**
* Writes a full image row.
* <p>
- * This must be called sequentially from n=0 to n=rows-1 One integer per sample , in the natural order: R G B R G B
- * ... (or R G B A R G B A... if has alpha) The values should be between 0 and 255 for 8 bitspc images, and between
- * 0- 65535 form 16 bitspc images (this applies also to the alpha channel if present) The array can be reused.
+ * This must be called sequentially from n=0 to n=rows-1 One integer per
+ * sample , in the natural order: R G B R G B ... (or R G B A R G B A... if
+ * has alpha) The values should be between 0 and 255 for 8 bitspc images,
+ * and between 0- 65535 form 16 bitspc images (this applies also to the
+ * alpha channel if present) The array can be reused.
* <p>
- * Warning: the array might be modified in some cases (unpacked row with low bitdepth)
+ * Warning: the array might be modified in some cases (unpacked row with low
+ * bitdepth)
* <p>
*
* @param newrow
- * Array of pixel values. Warning: the array size should be exact (samplesPerRowP)
+ * Array of pixel values. Warning: the array size should be exact
+ * (samplesPerRowP)
* @param rown
- * Row number, from 0 (top) to rows-1 (bottom). This is just used as a check. Pass -1 if you want to
- * autocompute it
+ * Row number, from 0 (top) to rows-1 (bottom). This is just used
+ * as a check. Pass -1 if you want to autocompute it
*/
public void writeRowInt(int[] newrow, int rown) {
prepareEncodeRow(rown);
@@ -627,8 +639,9 @@ public class PngWriter {
}
/**
- * Same semantics as writeRowInt but using bytes. Each byte is still a sample. If 16bitdepth, we are passing only
- * the most significant byte (and hence losing some info)
+ * Same semantics as writeRowInt but using bytes. Each byte is still a
+ * sample. If 16bitdepth, we are passing only the most significant byte (and
+ * hence losing some info)
*
* @see PngWriter#writeRowInt(int[], int)
*/
@@ -659,12 +672,15 @@ public class PngWriter {
}
/**
- * If false (default), and image has bitdepth 1-2-4, the scanlines passed are assumed to be already packed.
+ * If false (default), and image has bitdepth 1-2-4, the scanlines passed
+ * are assumed to be already packed.
* <p>
- * If true, each element is a sample, the writer will perform the packing if necessary.
+ * If true, each element is a sample, the writer will perform the packing if
+ * necessary.
* <p>
- * Warning: when using {@link #writeRow(ImageLine, int)} (recommended) the <tt>packed</tt> flag of the ImageLine
- * object overrides (and overwrites!) this field.
+ * Warning: when using {@link #writeRow(ImageLine, int)} (recommended) the
+ * <tt>packed</tt> flag of the ImageLine object overrides (and overwrites!)
+ * this field.
*/
public void setUseUnPackedMode(boolean useUnpackedMode) {
this.unpackedMode = useUnpackedMode;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
index 963abc50e..c429b893b 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
@@ -1,7 +1,8 @@
package jogamp.opengl.util.pngj;
/**
- * Exception for anomalous internal problems (sort of asserts) that point to some issue with the library
+ * Exception for anomalous internal problems (sort of asserts) that point to
+ * some issue with the library
*
* @author Hernan J Gonzalez
*
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java
index 0801e33bb..f68458d19 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java
@@ -1,7 +1,8 @@
package jogamp.opengl.util.pngj;
/**
- * Exception thrown because of some valid feature of PNG standard that this library does not support
+ * Exception thrown because of some valid feature of PNG standard that this
+ * library does not support
*/
public class PngjUnsupportedException extends RuntimeException {
private static final long serialVersionUID = 1L;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
index a5bad666c..4516a0886 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
@@ -4,7 +4,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
- * stream that outputs to memory and allows to flush fragments every 'size' bytes to some other destination
+ * stream that outputs to memory and allows to flush fragments every 'size'
+ * bytes to some other destination
*/
abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
private final int size;
@@ -50,8 +51,8 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
}
/**
- * if it's time to flush data (or if forced==true) calls abstract method flushBuffer() and cleans those bytes from
- * own buffer
+ * if it's time to flush data (or if forced==true) calls abstract method
+ * flushBuffer() and cleans those bytes from own buffer
*/
private final void checkFlushBuffer(boolean forced) {
while (forced || count >= size) {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
index ed091d35a..a995e4481 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
@@ -1,253 +1,297 @@
-package jogamp.opengl.util.pngj.chunks;
-
-// see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
-// http://www.w3.org/TR/PNG/#5Chunk-naming-conventions
-// http://www.w3.org/TR/PNG/#table53
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.InflaterInputStream;
-
-import jogamp.opengl.util.pngj.PngHelperInternal;
-import jogamp.opengl.util.pngj.PngjException;
-
-
-public class ChunkHelper {
- public static final String IHDR = "IHDR";
- public static final String PLTE = "PLTE";
- public static final String IDAT = "IDAT";
- public static final String IEND = "IEND";
- public static final byte[] b_IHDR = toBytes(IHDR);
- public static final byte[] b_PLTE = toBytes(PLTE);
- public static final byte[] b_IDAT = toBytes(IDAT);
- public static final byte[] b_IEND = toBytes(IEND);
-
- public static final String cHRM = "cHRM";
- public static final String gAMA = "gAMA";
- public static final String iCCP = "iCCP";
- public static final String sBIT = "sBIT";
- public static final String sRGB = "sRGB";
- public static final String bKGD = "bKGD";
- public static final String hIST = "hIST";
- public static final String tRNS = "tRNS";
- public static final String pHYs = "pHYs";
- public static final String sPLT = "sPLT";
- public static final String tIME = "tIME";
- public static final String iTXt = "iTXt";
- public static final String tEXt = "tEXt";
- public static final String zTXt = "zTXt";
-
- /**
- * Converts to bytes using Latin1 (ISO-8859-1)
- */
- public static byte[] toBytes(String x) {
- return x.getBytes(PngHelperInternal.charsetLatin1);
- }
-
- /**
- * Converts to String using Latin1 (ISO-8859-1)
- */
- public static String toString(byte[] x) {
- return new String(x, PngHelperInternal.charsetLatin1);
- }
-
- /**
- * Converts to String using Latin1 (ISO-8859-1)
- */
- public static String toString(byte[] x, int offset, int len) {
- return new String(x, offset, len, PngHelperInternal.charsetLatin1);
- }
-
- /**
- * Converts to bytes using UTF-8
- */
- public static byte[] toBytesUTF8(String x) {
- return x.getBytes(PngHelperInternal.charsetUTF8);
- }
-
- /**
- * Converts to string using UTF-8
- */
- public static String toStringUTF8(byte[] x) {
- return new String(x, PngHelperInternal.charsetUTF8);
- }
-
- /**
- * Converts to string using UTF-8
- */
- public static String toStringUTF8(byte[] x, int offset, int len) {
- return new String(x, offset, len, PngHelperInternal.charsetUTF8);
- }
-
- /**
- * critical chunk : first letter is uppercase
- */
- public static boolean isCritical(String id) {
- return (Character.isUpperCase(id.charAt(0)));
- }
-
- /**
- * public chunk: second letter is uppercase
- */
- public static boolean isPublic(String id) { //
- return (Character.isUpperCase(id.charAt(1)));
- }
-
- /**
- * Safe to copy chunk: fourth letter is lower case
- */
- public static boolean isSafeToCopy(String id) {
- return (!Character.isUpperCase(id.charAt(3)));
- }
-
- /**
- * "Unknown" just means that our chunk factory (even when it has been augmented by client code) did not recognize
- * its id
- */
- public static boolean isUnknown(PngChunk c) {
- return c instanceof PngChunkUNKNOWN;
- }
-
- /**
- * Finds position of null byte in array
- *
- * @param b
- * @return -1 if not found
- */
- public static int posNullByte(byte[] b) {
- for (int i = 0; i < b.length; i++)
- if (b[i] == 0)
- return i;
- return -1;
- }
-
- /**
- * Decides if a chunk should be loaded, according to a ChunkLoadBehaviour
- *
- * @param id
- * @param behav
- * @return true/false
- */
- public static boolean shouldLoad(String id, ChunkLoadBehaviour behav) {
- if (isCritical(id))
- return true;
- boolean kwown = PngChunk.isKnown(id);
- switch (behav) {
- case LOAD_CHUNK_ALWAYS:
- return true;
- case LOAD_CHUNK_IF_SAFE:
- return kwown || isSafeToCopy(id);
- case LOAD_CHUNK_KNOWN:
- return kwown;
- case LOAD_CHUNK_NEVER:
- return false;
- }
- return false; // should not reach here
- }
-
- public final static byte[] compressBytes(byte[] ori, boolean compress) {
- return compressBytes(ori, 0, ori.length, compress);
- }
-
- public static byte[] compressBytes(byte[] ori, int offset, int len, boolean compress) {
- try {
- ByteArrayInputStream inb = new ByteArrayInputStream(ori, offset, len);
- InputStream in = compress ? inb : new InflaterInputStream(inb);
- ByteArrayOutputStream outb = new ByteArrayOutputStream();
- OutputStream out = compress ? new DeflaterOutputStream(outb) : outb;
- shovelInToOut(in, out);
- in.close();
- out.close();
- return outb.toByteArray();
- } catch (Exception e) {
- throw new PngjException(e);
- }
- }
-
- /**
- * Shovels all data from an input stream to an output stream.
- */
- private static void shovelInToOut(InputStream in, OutputStream out) throws IOException {
- byte[] buffer = new byte[1024];
- int len;
- while ((len = in.read(buffer)) > 0) {
- out.write(buffer, 0, len);
- }
- }
-
- public static boolean maskMatch(int v, int mask) {
- return (v & mask) != 0;
- }
-
- /**
- * Returns only the chunks that "match" the predicate
- *
- * See also trimList()
- */
- public static List<PngChunk> filterList(List<PngChunk> target, ChunkPredicate predicateKeep) {
- List<PngChunk> result = new ArrayList<PngChunk>();
- for (PngChunk element : target) {
- if (predicateKeep.match(element)) {
- result.add(element);
- }
- }
- return result;
- }
-
- /**
- * Remove (in place) the chunks that "match" the predicate
- *
- * See also filterList
- */
- public static int trimList(List<PngChunk> target, ChunkPredicate predicateRemove) {
- Iterator<PngChunk> it = target.iterator();
- int cont = 0;
- while (it.hasNext()) {
- PngChunk c = it.next();
- if (predicateRemove.match(c)) {
- it.remove();
- cont++;
- }
- }
- return cont;
- }
-
- /**
- * MY adhoc criteria: two chunks are "equivalent" ("practically equal") if they have same id and (perhaps, if
- * multiple are allowed) if the match also in some "internal key" (eg: key for string values, palette for sPLT, etc)
- *
- * Notice that the use of this is optional, and that the PNG standard allows Text chunks that have same key
- *
- * @return true if "equivalent"
- */
- public static final boolean equivalent(PngChunk c1, PngChunk c2) {
- if (c1 == c2)
- return true;
- if (c1 == null || c2 == null || !c1.id.equals(c2.id))
- return false;
- // same id
- if (c1.getClass() != c2.getClass())
- return false; // should not happen
- if (!c2.allowsMultiple())
- return true;
- if (c1 instanceof PngChunkTextVar) {
- return ((PngChunkTextVar) c1).getKey().equals(((PngChunkTextVar) c2).getKey());
- }
- if (c1 instanceof PngChunkSPLT) {
- return ((PngChunkSPLT) c1).getPalName().equals(((PngChunkSPLT) c2).getPalName());
- }
- // unknown chunks that allow multiple? consider they don't match
- return false;
- }
-
- public static boolean isText(PngChunk c) {
- return c instanceof PngChunkTextVar;
- }
-
-}
+package jogamp.opengl.util.pngj.chunks;
+
+
+// see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+// http://www.w3.org/TR/PNG/#5Chunk-naming-conventions
+// http://www.w3.org/TR/PNG/#table53
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+
+
+public class ChunkHelper {
+ public static final String IHDR = "IHDR";
+ public static final String PLTE = "PLTE";
+ public static final String IDAT = "IDAT";
+ public static final String IEND = "IEND";
+ public static final byte[] b_IHDR = toBytes(IHDR);
+ public static final byte[] b_PLTE = toBytes(PLTE);
+ public static final byte[] b_IDAT = toBytes(IDAT);
+ public static final byte[] b_IEND = toBytes(IEND);
+
+ public static final String cHRM = "cHRM";
+ public static final String gAMA = "gAMA";
+ public static final String iCCP = "iCCP";
+ public static final String sBIT = "sBIT";
+ public static final String sRGB = "sRGB";
+ public static final String bKGD = "bKGD";
+ public static final String hIST = "hIST";
+ public static final String tRNS = "tRNS";
+ public static final String pHYs = "pHYs";
+ public static final String sPLT = "sPLT";
+ public static final String tIME = "tIME";
+ public static final String iTXt = "iTXt";
+ public static final String tEXt = "tEXt";
+ public static final String zTXt = "zTXt";
+
+ private static final ThreadLocal<Inflater> inflaterProvider = new ThreadLocal<Inflater>() {
+ protected Inflater initialValue() {
+ return new Inflater();
+ }
+ };
+
+ private static final ThreadLocal<Deflater> deflaterProvider = new ThreadLocal<Deflater>() {
+ protected Deflater initialValue() {
+ return new Deflater();
+ }
+ };
+
+ /*
+ * static auxiliary buffer. any method that uses this should synchronize against this
+ */
+ private static byte[] tmpbuffer = new byte[4096];
+
+ /**
+ * Converts to bytes using Latin1 (ISO-8859-1)
+ */
+ public static byte[] toBytes(String x) {
+ return x.getBytes(PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to String using Latin1 (ISO-8859-1)
+ */
+ public static String toString(byte[] x) {
+ return new String(x, PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to String using Latin1 (ISO-8859-1)
+ */
+ public static String toString(byte[] x, int offset, int len) {
+ return new String(x, offset, len, PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to bytes using UTF-8
+ */
+ public static byte[] toBytesUTF8(String x) {
+ return x.getBytes(PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * Converts to string using UTF-8
+ */
+ public static String toStringUTF8(byte[] x) {
+ return new String(x, PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * Converts to string using UTF-8
+ */
+ public static String toStringUTF8(byte[] x, int offset, int len) {
+ return new String(x, offset, len, PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * critical chunk : first letter is uppercase
+ */
+ public static boolean isCritical(String id) {
+ return (Character.isUpperCase(id.charAt(0)));
+ }
+
+ /**
+ * public chunk: second letter is uppercase
+ */
+ public static boolean isPublic(String id) { //
+ return (Character.isUpperCase(id.charAt(1)));
+ }
+
+ /**
+ * Safe to copy chunk: fourth letter is lower case
+ */
+ public static boolean isSafeToCopy(String id) {
+ return (!Character.isUpperCase(id.charAt(3)));
+ }
+
+ /**
+ * "Unknown" just means that our chunk factory (even when it has been
+ * augmented by client code) did not recognize its id
+ */
+ public static boolean isUnknown(PngChunk c) {
+ return c instanceof PngChunkUNKNOWN;
+ }
+
+ /**
+ * Finds position of null byte in array
+ *
+ * @param b
+ * @return -1 if not found
+ */
+ public static int posNullByte(byte[] b) {
+ for (int i = 0; i < b.length; i++)
+ if (b[i] == 0)
+ return i;
+ return -1;
+ }
+
+ /**
+ * Decides if a chunk should be loaded, according to a ChunkLoadBehaviour
+ *
+ * @param id
+ * @param behav
+ * @return true/false
+ */
+ public static boolean shouldLoad(String id, ChunkLoadBehaviour behav) {
+ if (isCritical(id))
+ return true;
+ boolean kwown = PngChunk.isKnown(id);
+ switch (behav) {
+ case LOAD_CHUNK_ALWAYS:
+ return true;
+ case LOAD_CHUNK_IF_SAFE:
+ return kwown || isSafeToCopy(id);
+ case LOAD_CHUNK_KNOWN:
+ return kwown;
+ case LOAD_CHUNK_NEVER:
+ return false;
+ }
+ return false; // should not reach here
+ }
+
+ public final static byte[] compressBytes(byte[] ori, boolean compress) {
+ return compressBytes(ori, 0, ori.length, compress);
+ }
+
+ public static byte[] compressBytes(byte[] ori, int offset, int len, boolean compress) {
+ try {
+ ByteArrayInputStream inb = new ByteArrayInputStream(ori, offset, len);
+ InputStream in = compress ? inb : new InflaterInputStream(inb, getInflater());
+ ByteArrayOutputStream outb = new ByteArrayOutputStream();
+ OutputStream out = compress ? new DeflaterOutputStream(outb) : outb;
+ shovelInToOut(in, out);
+ in.close();
+ out.close();
+ return outb.toByteArray();
+ } catch (Exception e) {
+ throw new PngjException(e);
+ }
+ }
+
+ /**
+ * Shovels all data from an input stream to an output stream.
+ */
+ private static void shovelInToOut(InputStream in, OutputStream out) throws IOException {
+ synchronized (tmpbuffer) {
+ int len;
+ while ((len = in.read(tmpbuffer)) > 0) {
+ out.write(tmpbuffer, 0, len);
+ }
+ }
+ }
+
+ public static boolean maskMatch(int v, int mask) {
+ return (v & mask) != 0;
+ }
+
+ /**
+ * Returns only the chunks that "match" the predicate
+ *
+ * See also trimList()
+ */
+ public static List<PngChunk> filterList(List<PngChunk> target, ChunkPredicate predicateKeep) {
+ List<PngChunk> result = new ArrayList<PngChunk>();
+ for (PngChunk element : target) {
+ if (predicateKeep.match(element)) {
+ result.add(element);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Remove (in place) the chunks that "match" the predicate
+ *
+ * See also filterList
+ */
+ public static int trimList(List<PngChunk> target, ChunkPredicate predicateRemove) {
+ Iterator<PngChunk> it = target.iterator();
+ int cont = 0;
+ while (it.hasNext()) {
+ PngChunk c = it.next();
+ if (predicateRemove.match(c)) {
+ it.remove();
+ cont++;
+ }
+ }
+ return cont;
+ }
+
+ /**
+ * MY adhoc criteria: two chunks are "equivalent" ("practically equal") if
+ * they have same id and (perhaps, if multiple are allowed) if the match
+ * also in some "internal key" (eg: key for string values, palette for sPLT,
+ * etc)
+ *
+ * Notice that the use of this is optional, and that the PNG standard allows
+ * Text chunks that have same key
+ *
+ * @return true if "equivalent"
+ */
+ public static final boolean equivalent(PngChunk c1, PngChunk c2) {
+ if (c1 == c2)
+ return true;
+ if (c1 == null || c2 == null || !c1.id.equals(c2.id))
+ return false;
+ // same id
+ if (c1.getClass() != c2.getClass())
+ return false; // should not happen
+ if (!c2.allowsMultiple())
+ return true;
+ if (c1 instanceof PngChunkTextVar) {
+ return ((PngChunkTextVar) c1).getKey().equals(((PngChunkTextVar) c2).getKey());
+ }
+ if (c1 instanceof PngChunkSPLT) {
+ return ((PngChunkSPLT) c1).getPalName().equals(((PngChunkSPLT) c2).getPalName());
+ }
+ // unknown chunks that allow multiple? consider they don't match
+ return false;
+ }
+
+ public static boolean isText(PngChunk c) {
+ return c instanceof PngChunkTextVar;
+ }
+
+ /**
+ * thread-local inflater, just reset : this should be only used for short
+ * individual chunks compression
+ */
+ public static Inflater getInflater() {
+ Inflater inflater = inflaterProvider.get();
+ inflater.reset();
+ return inflater;
+ }
+
+ /**
+ * thread-local deflater, just reset : this should be only used for short
+ * individual chunks decompression
+ */
+ public static Deflater getDeflater() {
+ Deflater deflater = deflaterProvider.get();
+ deflater.reset();
+ return deflater;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
index 03d50c2c4..82ab3bcf9 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
@@ -1,7 +1,8 @@
package jogamp.opengl.util.pngj.chunks;
/**
- * Defines gral strategy about what to do with ancillary (non-critical) chunks when reading
+ * Defines gral strategy about what to do with ancillary (non-critical) chunks
+ * when reading
*/
public enum ChunkLoadBehaviour {
/**
@@ -9,7 +10,8 @@ public enum ChunkLoadBehaviour {
*/
LOAD_CHUNK_NEVER,
/**
- * Ancillary chunks are loaded only if 'known' (registered with the factory).
+ * Ancillary chunks are loaded only if 'known' (registered with the
+ * factory).
*/
LOAD_CHUNK_KNOWN,
/**
@@ -19,7 +21,8 @@ public enum ChunkLoadBehaviour {
LOAD_CHUNK_IF_SAFE,
/**
* Load all chunks. <br>
- * Notice that other restrictions might apply, see PngReader.skipChunkMaxSize PngReader.skipChunkIds
+ * Notice that other restrictions might apply, see
+ * PngReader.skipChunkMaxSize PngReader.skipChunkIds
*/
LOAD_CHUNK_ALWAYS;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
index 8dd0ef476..3aba26cca 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
@@ -13,13 +13,15 @@ import jogamp.opengl.util.pngj.PngjOutputException;
/**
* Raw (physical) chunk.
* <p>
- * Short lived object, to be created while serialing/deserializing Do not reuse it for different chunks. <br>
+ * Short lived object, to be created while serialing/deserializing Do not reuse
+ * it for different chunks. <br>
* See http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
*/
public class ChunkRaw {
/**
- * The length counts only the data field, not itself, the chunk type code, or the CRC. Zero is a valid length.
- * Although encoders and decoders should treat the length as unsigned, its value must not exceed 231-1 bytes.
+ * The length counts only the data field, not itself, the chunk type code,
+ * or the CRC. Zero is a valid length. Although encoders and decoders should
+ * treat the length as unsigned, its value must not exceed 231-1 bytes.
*/
public final int len;
@@ -29,12 +31,14 @@ public class ChunkRaw {
public final byte[] idbytes = new byte[4];
/**
- * The data bytes appropriate to the chunk type, if any. This field can be of zero length. Does not include crc
+ * The data bytes appropriate to the chunk type, if any. This field can be
+ * of zero length. Does not include crc
*/
public byte[] data = null;
/**
- * A 4-byte CRC (Cyclic Redundancy Check) calculated on the preceding bytes in the chunk, including the chunk type
- * code and chunk data fields, but not including the length field.
+ * A 4-byte CRC (Cyclic Redundancy Check) calculated on the preceding bytes
+ * in the chunk, including the chunk type code and chunk data fields, but
+ * not including the length field.
*/
private int crcval = 0;
@@ -71,7 +75,8 @@ public class ChunkRaw {
}
/**
- * Computes the CRC and writes to the stream. If error, a PngjOutputException is thrown
+ * Computes the CRC and writes to the stream. If error, a
+ * PngjOutputException is thrown
*/
public void writeChunk(OutputStream os) {
if (idbytes.length != 4)
@@ -85,8 +90,8 @@ public class ChunkRaw {
}
/**
- * position before: just after chunk id. positon after: after crc Data should be already allocated. Checks CRC
- * Return number of byte read.
+ * position before: just after chunk id. positon after: after crc Data
+ * should be already allocated. Checks CRC Return number of byte read.
*/
public int readChunkData(InputStream is, boolean checkCrc) {
PngHelperInternal.readBytes(is, data, 0, len);
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
index ad788f154..5ce94ff9f 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
@@ -49,8 +49,8 @@ public class ChunksList {
}
/**
- * Returns a copy of the list (but the chunks are not copied) <b> This should not be used for general metadata
- * handling
+ * Returns a copy of the list (but the chunks are not copied) <b> This
+ * should not be used for general metadata handling
*/
public ArrayList<PngChunk> getChunks() {
return new ArrayList<PngChunk>(chunks);
@@ -96,7 +96,8 @@ public class ChunksList {
}
/**
- * If innerid!=null and the chunk is PngChunkTextVar or PngChunkSPLT, it's filtered by that id
+ * If innerid!=null and the chunk is PngChunkTextVar or PngChunkSPLT, it's
+ * filtered by that id
*
* @param id
* @return innerid Only used for text and SPLT chunks
@@ -119,8 +120,9 @@ public class ChunksList {
/**
* Returns only one chunk or null if nothing found - does not include queued
* <p>
- * If more than one chunk is found, then an exception is thrown (failifMultiple=true or chunk is single) or the last
- * one is returned (failifMultiple=false)
+ * If more than one chunk is found, then an exception is thrown
+ * (failifMultiple=true or chunk is single) or the last one is returned
+ * (failifMultiple=false)
**/
public PngChunk getById1(final String id, final boolean failIfMultiple) {
return getById1(id, null, failIfMultiple);
@@ -129,8 +131,9 @@ public class ChunksList {
/**
* Returns only one chunk or null if nothing found - does not include queued
* <p>
- * If more than one chunk (after filtering by inner id) is found, then an exception is thrown (failifMultiple=true
- * or chunk is single) or the last one is returned (failifMultiple=false)
+ * If more than one chunk (after filtering by inner id) is found, then an
+ * exception is thrown (failifMultiple=true or chunk is single) or the last
+ * one is returned (failifMultiple=false)
**/
public PngChunk getById1(final String id, final String innerid, final boolean failIfMultiple) {
List<? extends PngChunk> list = getById(id, innerid);
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
index 204c4c2a5..e76456ad4 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
@@ -13,7 +13,8 @@ import jogamp.opengl.util.pngj.PngjOutputException;
public class ChunksListForWrite extends ChunksList {
/**
- * chunks not yet writen - does not include IHDR, IDAT, END, perhaps yes PLTE
+ * chunks not yet writen - does not include IHDR, IDAT, END, perhaps yes
+ * PLTE
*/
private final List<PngChunk> queuedChunks = new ArrayList<PngChunk>();
@@ -67,8 +68,9 @@ public class ChunksListForWrite extends ChunksList {
/**
* Remove Chunk: only from queued
*
- * WARNING: this depends on c.equals() implementation, which is straightforward for SingleChunks. For
- * MultipleChunks, it will normally check for reference equality!
+ * WARNING: this depends on c.equals() implementation, which is
+ * straightforward for SingleChunks. For MultipleChunks, it will normally
+ * check for reference equality!
*/
public boolean removeChunk(PngChunk c) {
return queuedChunks.remove(c);
@@ -87,7 +89,8 @@ public class ChunksListForWrite extends ChunksList {
}
/**
- * this should be called only for ancillary chunks and PLTE (groups 1 - 3 - 5)
+ * this should be called only for ancillary chunks and PLTE (groups 1 - 3 -
+ * 5)
**/
private static boolean shouldWrite(PngChunk c, int currentGroup) {
if (currentGroup == CHUNK_GROUP_2_PLTE)
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
index 1d630591e..a45979ec2 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
@@ -12,13 +12,16 @@ import jogamp.opengl.util.pngj.PngjExceptionInternal;
* Represents a instance of a PNG chunk.
* <p>
* See <a
- * href="http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html">http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks
- * .html</a> </a>
+ * href="http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html">http://www
+ * .libpng.org/pub/png/spec/1.2/PNG-Chunks .html</a> </a>
* <p>
- * Concrete classes should extend {@link PngChunkSingle} or {@link PngChunkMultiple}
+ * Concrete classes should extend {@link PngChunkSingle} or
+ * {@link PngChunkMultiple}
* <p>
- * Note that some methods/fields are type-specific (getOrderingConstraint(), allowsMultiple()),<br>
- * some are 'almost' type-specific (id,crit,pub,safe; the exception is PngUKNOWN), <br>
+ * Note that some methods/fields are type-specific (getOrderingConstraint(),
+ * allowsMultiple()),<br>
+ * some are 'almost' type-specific (id,crit,pub,safe; the exception is
+ * PngUKNOWN), <br>
* and the rest are instance-specific
*/
public abstract class PngChunk {
@@ -35,8 +38,9 @@ public abstract class PngChunk {
protected final ImageInfo imgInfo;
/**
- * Possible ordering constraint for a PngChunk type -only relevant for ancillary chunks. Theoretically, there could
- * be more general constraints, but these cover the constraints for standard chunks.
+ * Possible ordering constraint for a PngChunk type -only relevant for
+ * ancillary chunks. Theoretically, there could be more general constraints,
+ * but these cover the constraints for standard chunks.
*/
public enum ChunkOrderingConstraint {
/**
@@ -83,8 +87,8 @@ public abstract class PngChunk {
/**
* This static map defines which PngChunk class correspond to which ChunkID
* <p>
- * The client can add other chunks to this map statically, before reading an image, calling
- * PngChunk.factoryRegister(id,class)
+ * The client can add other chunks to this map statically, before reading an
+ * image, calling PngChunk.factoryRegister(id,class)
*/
private final static Map<String, Class<? extends PngChunk>> factoryMap = new HashMap<String, Class<? extends PngChunk>>();
static {
@@ -114,8 +118,9 @@ public abstract class PngChunk {
/**
* Registers a chunk-id (4 letters) to be associated with a PngChunk class
* <p>
- * This method should be called by user code that wants to add some chunks (not implmemented in this library) to the
- * factory, so that the PngReader knows about it.
+ * This method should be called by user code that wants to add some chunks
+ * (not implmemented in this library) to the factory, so that the PngReader
+ * knows about it.
*/
public static void factoryRegister(String chunkId, Class<? extends PngChunk> chunkClass) {
factoryMap.put(chunkId, chunkClass);
@@ -124,9 +129,11 @@ public abstract class PngChunk {
/**
* True if the chunk-id type is known.
* <p>
- * A chunk is known if we recognize its class, according with <code>factoryMap</code>
+ * A chunk is known if we recognize its class, according with
+ * <code>factoryMap</code>
* <p>
- * This is not necessarily the same as being "STANDARD", or being implemented in this library
+ * This is not necessarily the same as being "STANDARD", or being
+ * implemented in this library
* <p>
* Unknown chunks will be parsed as instances of {@link PngChunkUNKNOWN}
*/
@@ -143,7 +150,8 @@ public abstract class PngChunk {
}
/**
- * This factory creates the corresponding chunk and parses the raw chunk. This is used when reading.
+ * This factory creates the corresponding chunk and parses the raw chunk.
+ * This is used when reading.
*/
public static PngChunk factory(ChunkRaw chunk, ImageInfo info) {
PngChunk c = factoryFromId(ChunkHelper.toString(chunk.idbytes), info);
@@ -153,7 +161,8 @@ public abstract class PngChunk {
}
/**
- * Creates one new blank chunk of the corresponding type, according to factoryMap (PngChunkUNKNOWN if not known)
+ * Creates one new blank chunk of the corresponding type, according to
+ * factoryMap (PngChunkUNKNOWN if not known)
*/
public static PngChunk factoryFromId(String cid, ImageInfo info) {
PngChunk chunk = null;
@@ -189,7 +198,8 @@ public abstract class PngChunk {
}
/**
- * In which "chunkGroup" (see {@link ChunksList}for definition) this chunks instance was read or written.
+ * In which "chunkGroup" (see {@link ChunksList}for definition) this chunks
+ * instance was read or written.
* <p>
* -1 if not read or written (eg, queued)
*/
@@ -236,16 +246,16 @@ public abstract class PngChunk {
}
/**
- * Creates the physical chunk. This is used when writing (serialization). Each particular chunk class implements its
- * own logic.
+ * Creates the physical chunk. This is used when writing (serialization).
+ * Each particular chunk class implements its own logic.
*
* @return A newly allocated and filled raw chunk
*/
public abstract ChunkRaw createRawChunk();
/**
- * Parses raw chunk and fill inside data. This is used when reading (deserialization). Each particular chunk class
- * implements its own logic.
+ * Parses raw chunk and fill inside data. This is used when reading
+ * (deserialization). Each particular chunk class implements its own logic.
*/
public abstract void parseFromRaw(ChunkRaw c);
@@ -254,7 +264,8 @@ public abstract class PngChunk {
* <p>
* This is used when copying chunks from a reader to a writer
* <p>
- * It should normally be a deep copy, and after the cloning this.equals(other) should return true
+ * It should normally be a deep copy, and after the cloning
+ * this.equals(other) should return true
*/
public abstract void cloneDataFromRead(PngChunk other);
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
index b816db205..911513c0d 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
@@ -7,7 +7,8 @@ import jogamp.opengl.util.pngj.ImageInfo;
* <p>
* see http://www.w3.org/TR/PNG/#11IDAT
* <p>
- * This is dummy placeholder - we write/read this chunk (actually several) by special code.
+ * This is dummy placeholder - we write/read this chunk (actually several) by
+ * special code.
*/
public class PngChunkIDAT extends PngChunkMultiple {
public final static String ID = ChunkHelper.IDAT;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
index 696edd431..d44250a2f 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
@@ -17,7 +17,8 @@ public abstract class PngChunkMultiple extends PngChunk {
}
/**
- * NOTE: this chunk uses the default Object's equals() hashCode() implementation.
+ * NOTE: this chunk uses the default Object's equals() hashCode()
+ * implementation.
*
* This is the right thing to do, normally.
*
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
index 286f39db0..5247169e0 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
@@ -3,7 +3,8 @@ package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
/**
- * PNG chunk type (abstract) that does not allow multiple instances in same image.
+ * PNG chunk type (abstract) that does not allow multiple instances in same
+ * image.
*/
public abstract class PngChunkSingle extends PngChunk {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
index 1de5c0833..b68776477 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
@@ -1,143 +1,141 @@
-package jogamp.opengl.util.pngj.chunks;
-
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelperInternal;
-import jogamp.opengl.util.pngj.PngjException;
-
-/**
- * tRNS chunk.
- * <p>
- * see http://www.w3.org/TR/PNG/#11tRNS
- * <p>
- * this chunk structure depends on the image type
- */
-public class PngChunkTRNS extends PngChunkSingle {
- public final static String ID = ChunkHelper.tRNS;
-
- // http://www.w3.org/TR/PNG/#11tRNS
-
- // only one of these is meaningful, depending on the image type
- private int gray;
- private int red, green, blue;
- private int[] paletteAlpha = new int[] {};
-
- public PngChunkTRNS(ImageInfo info) {
- super(ID, info);
- }
-
- @Override
- public ChunkOrderingConstraint getOrderingConstraint() {
- return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
- }
-
- @Override
- public ChunkRaw createRawChunk() {
- ChunkRaw c = null;
- if (imgInfo.greyscale) {
- c = createEmptyChunk(2, true);
- PngHelperInternal.writeInt2tobytes(gray, c.data, 0);
- } else if (imgInfo.indexed) {
- c = createEmptyChunk(paletteAlpha.length, true);
- for (int n = 0; n < c.len; n++) {
- c.data[n] = (byte) paletteAlpha[n];
- }
- } else {
- c = createEmptyChunk(6, true);
- PngHelperInternal.writeInt2tobytes(red, c.data, 0);
- PngHelperInternal.writeInt2tobytes(green, c.data, 0);
- PngHelperInternal.writeInt2tobytes(blue, c.data, 0);
- }
- return c;
- }
-
- @Override
- public void parseFromRaw(ChunkRaw c) {
- if (imgInfo.greyscale) {
- gray = PngHelperInternal.readInt2fromBytes(c.data, 0);
- } else if (imgInfo.indexed) {
- int nentries = c.data.length;
- paletteAlpha = new int[nentries];
- for (int n = 0; n < nentries; n++) {
- paletteAlpha[n] = (int) (c.data[n] & 0xff);
- }
- } else {
- red = PngHelperInternal.readInt2fromBytes(c.data, 0);
- green = PngHelperInternal.readInt2fromBytes(c.data, 2);
- blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
- }
- }
-
- @Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkTRNS otherx = (PngChunkTRNS) other;
- gray = otherx.gray;
- red = otherx.red;
- green = otherx.red;
- blue = otherx.red;
- if (otherx.paletteAlpha != null) {
- paletteAlpha = new int[otherx.paletteAlpha.length];
- System.arraycopy(otherx.paletteAlpha, 0, paletteAlpha, 0, paletteAlpha.length);
- }
- }
-
- /**
- * Set rgb values
- *
- */
- public void setRGB(int r, int g, int b) {
- if (imgInfo.greyscale || imgInfo.indexed)
- throw new PngjException("only rgb or rgba images support this");
- red = r;
- green = g;
- blue = b;
- }
-
- public int[] getRGB() {
- if (imgInfo.greyscale || imgInfo.indexed)
- throw new PngjException("only rgb or rgba images support this");
- return new int[] { red, green, blue };
- }
-
- public void setGray(int g) {
- if (!imgInfo.greyscale)
- throw new PngjException("only grayscale images support this");
- gray = g;
- }
-
- public int getGray() {
- if (!imgInfo.greyscale)
- throw new PngjException("only grayscale images support this");
- return gray;
- }
-
- /**
- * WARNING: non deep copy
- */
- public void setPalletteAlpha(int[] palAlpha) {
- if (!imgInfo.indexed)
- throw new PngjException("only indexed images support this");
- paletteAlpha = palAlpha;
- }
-
- /**
- * to use when only one pallete index is set as totally transparent
- */
- public void setIndexEntryAsTransparent(int palAlphaIndex) {
- if (!imgInfo.indexed)
- throw new PngjException("only indexed images support this");
- paletteAlpha = new int[] { palAlphaIndex + 1 };
- for (int i = 0; i < palAlphaIndex; i++)
- paletteAlpha[i] = 255;
- paletteAlpha[palAlphaIndex] = 0;
- }
-
- /**
- * WARNING: non deep copy
- */
- public int[] getPalletteAlpha() {
- if (!imgInfo.indexed)
- throw new PngjException("only indexed images support this");
- return paletteAlpha;
- }
-
-}
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * tRNS chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tRNS
+ * <p>
+ * this chunk structure depends on the image type
+ */
+public class PngChunkTRNS extends PngChunkSingle {
+ public final static String ID = ChunkHelper.tRNS;
+
+ // http://www.w3.org/TR/PNG/#11tRNS
+
+ // only one of these is meaningful, depending on the image type
+ private int gray;
+ private int red, green, blue;
+ private int[] paletteAlpha = new int[] {};
+
+ public PngChunkTRNS(ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ ChunkRaw c = null;
+ if (imgInfo.greyscale) {
+ c = createEmptyChunk(2, true);
+ PngHelperInternal.writeInt2tobytes(gray, c.data, 0);
+ } else if (imgInfo.indexed) {
+ c = createEmptyChunk(paletteAlpha.length, true);
+ for (int n = 0; n < c.len; n++) {
+ c.data[n] = (byte) paletteAlpha[n];
+ }
+ } else {
+ c = createEmptyChunk(6, true);
+ PngHelperInternal.writeInt2tobytes(red, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(green, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(blue, c.data, 0);
+ }
+ return c;
+ }
+
+ @Override
+ public void parseFromRaw(ChunkRaw c) {
+ if (imgInfo.greyscale) {
+ gray = PngHelperInternal.readInt2fromBytes(c.data, 0);
+ } else if (imgInfo.indexed) {
+ int nentries = c.data.length;
+ paletteAlpha = new int[nentries];
+ for (int n = 0; n < nentries; n++) {
+ paletteAlpha[n] = (int) (c.data[n] & 0xff);
+ }
+ } else {
+ red = PngHelperInternal.readInt2fromBytes(c.data, 0);
+ green = PngHelperInternal.readInt2fromBytes(c.data, 2);
+ blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
+ }
+ }
+
+ @Override
+ public void cloneDataFromRead(PngChunk other) {
+ PngChunkTRNS otherx = (PngChunkTRNS) other;
+ gray = otherx.gray;
+ red = otherx.red;
+ green = otherx.green;
+ blue = otherx.blue;
+ if (otherx.paletteAlpha != null) {
+ paletteAlpha = new int[otherx.paletteAlpha.length];
+ System.arraycopy(otherx.paletteAlpha, 0, paletteAlpha, 0, paletteAlpha.length);
+ }
+ }
+
+ /**
+ * Set rgb values
+ *
+ */
+ public void setRGB(int r, int g, int b) {
+ if (imgInfo.greyscale || imgInfo.indexed)
+ throw new PngjException("only rgb or rgba images support this");
+ red = r;
+ green = g;
+ blue = b;
+ }
+
+ public int[] getRGB() {
+ if (imgInfo.greyscale || imgInfo.indexed)
+ throw new PngjException("only rgb or rgba images support this");
+ return new int[] { red, green, blue };
+ }
+
+ public void setGray(int g) {
+ if (!imgInfo.greyscale)
+ throw new PngjException("only grayscale images support this");
+ gray = g;
+ }
+
+ public int getGray() {
+ if (!imgInfo.greyscale)
+ throw new PngjException("only grayscale images support this");
+ return gray;
+ }
+
+ /**
+ * WARNING: non deep copy
+ */
+ public void setPalletteAlpha(int[] palAlpha) {
+ if (!imgInfo.indexed)
+ throw new PngjException("only indexed images support this");
+ paletteAlpha = palAlpha;
+ }
+
+ /**
+ * to use when only one pallete index is set as totally transparent
+ */
+ public void setIndexEntryAsTransparent(int palAlphaIndex) {
+ if (!imgInfo.indexed)
+ throw new PngjException("only indexed images support this");
+ paletteAlpha = new int[] { palAlphaIndex + 1 };
+ for (int i = 0; i < palAlphaIndex; i++)
+ paletteAlpha[i] = 255;
+ paletteAlpha[palAlphaIndex] = 0;
+ }
+
+ /**
+ * WARNING: non deep copy
+ */
+ public int[] getPalletteAlpha() {
+ return paletteAlpha;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
index 52d1b22c1..ecf8b98c3 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
@@ -7,13 +7,13 @@ import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
/**
- * We consider "image metadata" every info inside the image except for the most basic image info (IHDR chunk - ImageInfo
- * class) and the pixels values.
+ * We consider "image metadata" every info inside the image except for the most
+ * basic image info (IHDR chunk - ImageInfo class) and the pixels values.
* <p>
* This includes the palette (if present) and all the ancillary chunks
* <p>
- * This class provides a wrapper over the collection of chunks of a image (read or to write) and provides some high
- * level methods to access them
+ * This class provides a wrapper over the collection of chunks of a image (read
+ * or to write) and provides some high level methods to access them
*/
public class PngMetadata {
private final ChunksList chunkList;
@@ -31,8 +31,9 @@ public class PngMetadata {
/**
* Queues the chunk at the writer
* <p>
- * lazyOverwrite: if true, checks if there is a queued "equivalent" chunk and if so, overwrites it. However if that
- * not check for already written chunks.
+ * lazyOverwrite: if true, checks if there is a queued "equivalent" chunk
+ * and if so, overwrites it. However if that not check for already written
+ * chunks.
*/
public void queueChunk(final PngChunk c, boolean lazyOverwrite) {
ChunksListForWrite cl = getChunkListW();
@@ -87,7 +88,8 @@ public class PngMetadata {
* Creates a time chunk with current time, less secsAgo seconds
* <p>
*
- * @return Returns the created-queued chunk, just in case you want to examine or modify it
+ * @return Returns the created-queued chunk, just in case you want to
+ * examine or modify it
*/
public PngChunkTIME setTimeNow(int secsAgo) {
PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
@@ -104,7 +106,8 @@ public class PngMetadata {
* Creates a time chunk with diven date-time
* <p>
*
- * @return Returns the created-queued chunk, just in case you want to examine or modify it
+ * @return Returns the created-queued chunk, just in case you want to
+ * examine or modify it
*/
public PngChunkTIME setTimeYMDHMS(int yearx, int monx, int dayx, int hourx, int minx, int secx) {
PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
@@ -137,7 +140,8 @@ public class PngMetadata {
* (arbitrary, should be latin1 if useLatin1)
* @param useLatin1
* @param compress
- * @return Returns the created-queued chunks, just in case you want to examine, touch it
+ * @return Returns the created-queued chunks, just in case you want to
+ * examine, touch it
*/
public PngChunkTextVar setText(String k, String val, boolean useLatin1, boolean compress) {
if (compress && !useLatin1)
@@ -180,7 +184,8 @@ public class PngMetadata {
}
/**
- * Returns empty if not found, concatenated (with newlines) if multiple! - and trimmed
+ * Returns empty if not found, concatenated (with newlines) if multiple! -
+ * and trimmed
* <p>
* Use getTxtsForKey() if you don't want this behaviour
*/
@@ -204,7 +209,8 @@ public class PngMetadata {
}
/**
- * Creates a new empty palette chunk, queues it for write and return it to the caller, who should fill its entries
+ * Creates a new empty palette chunk, queues it for write and return it to
+ * the caller, who should fill its entries
*/
public PngChunkPLTE createPLTEChunk() {
PngChunkPLTE plte = new PngChunkPLTE(chunkList.imageInfo);
@@ -222,7 +228,8 @@ public class PngMetadata {
}
/**
- * Creates a new empty TRNS chunk, queues it for write and return it to the caller, who should fill its entries
+ * Creates a new empty TRNS chunk, queues it for write and return it to the
+ * caller, who should fill its entries
*/
public PngChunkTRNS createTRNSChunk() {
PngChunkTRNS trns = new PngChunkTRNS(chunkList.imageInfo);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index 4444e9d63..bf2d3fa47 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
@@ -80,7 +80,7 @@ public class WGLGLCapabilities extends GLCapabilities {
public static final String PFD2String(PIXELFORMATDESCRIPTOR pfd, int pfdID) {
final int dwFlags = pfd.getDwFlags();
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
boolean sep = false;
if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) {
@@ -270,4 +270,4 @@ public class WGLGLCapabilities extends GLCapabilities {
sink.append(": ");
return super.toString(sink);
}
-} \ No newline at end of file
+}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
index f1598d580..3e788d286 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
@@ -51,6 +51,7 @@ public class WGLUtil {
public static final boolean USE_WGLVersion_Of_5WGLGDIFuncSet;
static {
+ Debug.initSingleton();
USE_WGLVersion_Of_5WGLGDIFuncSet = Debug.isPropertyDefined("jogl.windows.useWGLVersionOf5WGLGDIFuncSet", true);
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
System.err.println("Use WGL version of 5 WGL/GDI functions.");
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 94153d96d..b8979c91e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -563,7 +563,13 @@ public class WindowsWGLContext extends GLContextImpl {
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
+ return getWGLExt().wglAllocateMemoryNV(size, readFrequency, writeFrequency, priority);
}
+
+ @Override
+ public final void glFreeMemoryNV(ByteBuffer pointer) {
+ getWGLExt().wglFreeMemoryNV(pointer);
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
index 8b8cb2052..741e671eb 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
@@ -51,7 +51,13 @@ import jogamp.opengl.GLDynamicLookupHelper;
public abstract class WindowsWGLDrawable extends GLDrawableImpl {
- private static final boolean PROFILING = Debug.isPropertyDefined("jogl.debug.GLDrawable.profiling", true);
+ private static final boolean PROFILING;
+
+ static {
+ Debug.initSingleton();
+ PROFILING = Debug.isPropertyDefined("jogl.debug.GLDrawable.profiling", true);
+ }
+
private static final int PROFILING_TICKS = 200;
private int profilingSwapBuffersTicks;
private long profilingSwapBuffersTime;
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 5fb01d1a3..338a351cb 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -43,6 +43,8 @@ package jogamp.opengl.windows.wgl;
import java.nio.Buffer;
import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -88,19 +90,24 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
super();
synchronized(WindowsWGLDrawableFactory.class) {
- if(null==windowsWGLDynamicLookupHelper) {
- DesktopGLDynamicLookupHelper tmp = null;
- try {
- tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo());
- } catch (GLException gle) {
- if(DEBUG) {
- gle.printStackTrace();
+ if( null == windowsWGLDynamicLookupHelper ) {
+ windowsWGLDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
+ public DesktopGLDynamicLookupHelper run() {
+ DesktopGLDynamicLookupHelper tmp;
+ try {
+ tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo());
+ if(null!=tmp && tmp.isLibComplete()) {
+ WGL.getWGLProcAddressTable().reset(tmp);
+ }
+ } catch (Exception ex) {
+ tmp = null;
+ if(DEBUG) {
+ ex.printStackTrace();
+ }
+ }
+ return tmp;
}
- }
- if(null!=tmp && tmp.isLibComplete()) {
- windowsWGLDynamicLookupHelper = tmp;
- WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper);
- }
+ } );
}
}
@@ -463,7 +470,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasARBPBuffer();
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
index a553bd4c2..7ec6c50f8 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
@@ -31,13 +31,13 @@ package jogamp.opengl.windows.wgl;
import jogamp.opengl.*;
import java.util.*;
-public class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
+public final class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
protected WindowsWGLDynamicLibraryBundleInfo() {
super();
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
libsGL.add("OpenGL32");
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index c37bcee50..4bfe0cb86 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -524,16 +524,6 @@ public class X11GLXContext extends GLContextImpl {
}
@Override
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
- glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
- return getGLDrawable().getFactory().canCreateGLPbuffer(
- drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice() );
- }
- return super.isExtensionAvailable(glExtensionName);
- }
-
- @Override
protected boolean setSwapIntervalImpl(int interval) {
if( !drawable.getChosenGLCapabilities().isOnscreen() ) { return false; }
@@ -633,11 +623,16 @@ public class X11GLXContext extends GLContextImpl {
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3);
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
+ return getGLXExt().glXAllocateMemoryNV(size, readFrequency, writeFrequency, priority);
}
@Override
+ public final void glFreeMemoryNV(ByteBuffer pointer) {
+ getGLXExt().glXFreeMemoryNV(pointer);
+ }
+
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 394293bc0..52069b88f 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -39,6 +39,8 @@ package jogamp.opengl.x11.glx;
import java.nio.Buffer;
import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -91,19 +93,24 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
super();
synchronized(X11GLXDrawableFactory.class) {
- if(null==x11GLXDynamicLookupHelper) {
- DesktopGLDynamicLookupHelper tmp = null;
- try {
- tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo());
- } catch (GLException gle) {
- if(DEBUG) {
- gle.printStackTrace();
+ if( null == x11GLXDynamicLookupHelper ) {
+ x11GLXDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
+ public DesktopGLDynamicLookupHelper run() {
+ DesktopGLDynamicLookupHelper tmp;
+ try {
+ tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo());
+ if(null!=tmp && tmp.isLibComplete()) {
+ GLX.getGLXProcAddressTable().reset(tmp);
+ }
+ } catch (Exception ex) {
+ tmp = null;
+ if(DEBUG) {
+ ex.printStackTrace();
+ }
+ }
+ return tmp;
}
- }
- if(null!=tmp && tmp.isLibComplete()) {
- x11GLXDynamicLookupHelper = tmp;
- GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper);
- }
+ } );
}
}
@@ -483,7 +490,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
if(null == device) {
SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(defaultDevice);
if(null!=sr) {
@@ -544,7 +551,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
@Override
public final boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
- return canCreateGLPbuffer(device);
+ return canCreateGLPbuffer(device, null /* GLProfile not used for query on X11 */);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
index 108c157a8..f25f7ae2c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
@@ -31,13 +31,13 @@ package jogamp.opengl.x11.glx;
import jogamp.opengl.*;
import java.util.*;
-public class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
+public final class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
protected X11GLXDynamicLibraryBundleInfo() {
super();
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
@@ -60,15 +60,6 @@ public class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundl
return libsList;
}
- /**
- * This respects old DRI requirements:<br>
- * <pre>
- * http://dri.sourceforge.net/doc/DRIuserguide.html
- * </pre>
- */
- @Override
- public boolean shallLinkGlobal() { return true; }
-
@Override
public final List<String> getToolGetProcAddressFuncNameList() {
List<String> res = new ArrayList<String>();
diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c
index fea9d90ce..2e9d6033a 100644
--- a/src/jogl/native/GLDebugMessageHandler.c
+++ b/src/jogl/native/GLDebugMessageHandler.c
@@ -21,11 +21,11 @@
static jmethodID glDebugMessageARB = NULL; // int source, int type, int id, int severity, String msg
static jmethodID glDebugMessageAMD = NULL; // int id, int category, int severity, String msg
-typedef void (GLAPIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
-typedef void (GLAPIENTRY* _local_GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+typedef void (APIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
+typedef void (APIENTRY* _local_GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
-typedef void (GLAPIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, const GLvoid *userParam);
-typedef void (GLAPIENTRY* _local_GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+typedef void (APIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, const GLvoid *userParam);
+typedef void (APIENTRY* _local_GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
/*
* Class: jogamp_opengl_GLDebugMessageHandler
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index 6738364a7..046171efc 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -818,40 +818,39 @@ static const GLfloat gl_verts[] = {
- (void)waitUntilRenderSignal: (long) to_micros
{
- BOOL ready = NO;
- int wr = 0;
+ struct timespec t0, to_until;
+ BOOL tooLate;
+ int wr;
+ if( 0 >= to_micros ) {
+ to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
+ NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
+ }
pthread_mutex_lock(&renderLock);
- SYNC_PRINT("{W %ld us", to_micros);
- do {
- if(0 >= swapInterval) {
- ready = YES;
- }
- if(NO == ready) {
- #ifdef DBG_SYNC
- struct timespec t0, t1, td, td2;
- timespec_now(&t0);
- #endif
- if( 0 >= to_micros ) {
- to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
- NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
- }
- struct timespec to_abs = lastWaitTime;
- timespec_addmicros(&to_abs, to_micros);
- #ifdef DBG_SYNC
- timespec_subtract(&td, &to_abs, &t0);
- fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
- #endif
- wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- ready = YES;
+ timespec_now(&t0);
+ to_until = lastWaitTime;
+ timespec_addmicros(&to_until, to_micros);
+ tooLate = timespec_compare(&to_until, &t0) < 0;
+ #ifdef DBG_SYNC
+ struct timespec td_until;
+ timespec_subtract(&td_until, &to_until, &t0);
+ SYNC_PRINT("{W %ld ms, to %ld ms, late %d", to_micros/1000, timespec_milliseconds(&td_until), tooLate);
+ #endif
+ if( 0 < swapInterval ) {
+ if( tooLate ) {
+ // adjust!
+ to_until = t0;
+ timespec_addmicros(&to_until, to_micros);
}
- } while (NO == ready && 0 == wr) ;
- SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready);
+ wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_until);
+ #ifdef DBG_SYNC
+ struct timespec t1, td, td2;
+ timespec_now(&t1);
+ timespec_subtract(&td, &t1, &t0);
+ timespec_subtract(&td2, &t1, &lastWaitTime);
+ fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
+ #endif
+ }
+ SYNC_PRINT("-%d-%d}\n", shallDraw, wr);
timespec_now(&lastWaitTime);
pthread_mutex_unlock(&renderLock);
}
diff --git a/src/jogl/native/timespec.c b/src/jogl/native/timespec.c
index 50f0ca8c5..a69f4635e 100644
--- a/src/jogl/native/timespec.c
+++ b/src/jogl/native/timespec.c
@@ -75,3 +75,8 @@ long timespec_milliseconds(struct timespec *a)
{
return a->tv_sec*1000 + a->tv_nsec/1000000;
}
+
+long timespec_microseconds(struct timespec *a)
+{
+ return a->tv_sec*1000000 + a->tv_nsec/1000;
+}
diff --git a/src/jogl/native/timespec.h b/src/jogl/native/timespec.h
index f900bfa16..a621562b9 100644
--- a/src/jogl/native/timespec.h
+++ b/src/jogl/native/timespec.h
@@ -17,4 +17,7 @@ void timespec_subtract(struct timespec *r, struct timespec *a, struct timespec *
/** convert the timespec into milliseconds (may overflow) */
long timespec_milliseconds(struct timespec *a);
+/** convert the timespec into microseconds (may overflow) */
+long timespec_microseconds(struct timespec *a);
+
#endif /* _timespec_h */