diff options
Diffstat (limited to 'src/jogl/classes/com')
43 files changed, 2407 insertions, 1257 deletions
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java index bbfe72b08..30b3fd278 100644 --- a/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java @@ -36,6 +36,9 @@ import java.io.*; import java.nio.*; import java.util.*; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; + // Needed only for NIO workarounds on CVM import java.lang.reflect.*; @@ -43,9 +46,10 @@ public class Mixer { // This class is a singleton private static Mixer mixer; - private volatile boolean shutdown; - private volatile Object shutdownLock = new Object(); - private volatile boolean shutdownDone; + volatile boolean fillerAlive; + volatile boolean mixerAlive; + volatile boolean shutdown; + volatile Object shutdownLock = new Object(); // Windows Event object private final long event; @@ -63,6 +67,9 @@ public class Mixer { private Mixer() { event = CreateEvent(); + fillerAlive = false; + mixerAlive = false; + shutdown = false; new FillerThread().start(); final MixerThread m = new MixerThread(); m.setPriority(Thread.MAX_PRIORITY - 1); @@ -118,50 +125,57 @@ public class Mixer { shutdown = true; SetEvent(event); try { - shutdownLock.wait(); + while(fillerAlive || mixerAlive) { + shutdownLock.wait(); + } } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } } } - class FillerThread extends Thread { + class FillerThread extends InterruptSource.Thread { FillerThread() { - super("Mixer Thread"); + super(null, null, "Mixer Thread"); } @Override public void run() { - while (!shutdown) { - final List<Track> curTracks = tracks; + fillerAlive = true; + try { + while (!shutdown) { + final List<Track> curTracks = tracks; - for (final Iterator<Track> iter = curTracks.iterator(); iter.hasNext(); ) { - final Track track = iter.next(); + for (final Iterator<Track> iter = curTracks.iterator(); iter.hasNext(); ) { + final Track track = iter.next(); + try { + track.fill(); + } catch (final IOException e) { + e.printStackTrace(); + remove(track); + } + } try { - track.fill(); - } catch (final IOException e) { - e.printStackTrace(); - remove(track); + // Run ten times per second + java.lang.Thread.sleep(100); + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } } - - try { - // Run ten times per second - Thread.sleep(100); - } catch (final InterruptedException e) { - e.printStackTrace(); - } + } finally { + fillerAlive = false; } } } - class MixerThread extends Thread { + class MixerThread extends InterruptSource.Thread { // Temporary mixing buffer // Interleaved left and right channels float[] mixingBuffer; private final Vec3f temp = new Vec3f(); MixerThread() { - super("Mixer Thread"); + super(null, null, "Mixer Thread"); if (!initializeWaveOut(event)) { throw new InternalError("Error initializing waveout device"); } @@ -169,108 +183,113 @@ public class Mixer { @Override public void run() { - while (!shutdown) { - // Get the next buffer - final long mixerBuffer = getNextMixerBuffer(); - if (mixerBuffer != 0) { - ByteBuffer buf = getMixerBufferData(mixerBuffer); - - if (buf == null) { - // This is happening on CVM because - // JNI_NewDirectByteBuffer isn't implemented - // by default and isn't compatible with the - // JSR-239 NIO implementation (apparently) - buf = newDirectByteBuffer(getMixerBufferDataAddress(mixerBuffer), - getMixerBufferDataCapacity(mixerBuffer)); - } + mixerAlive = true; + try { + while (!shutdown) { + // Get the next buffer + final long mixerBuffer = getNextMixerBuffer(); + if (mixerBuffer != 0) { + ByteBuffer buf = getMixerBufferData(mixerBuffer); + + if (buf == null) { + // This is happening on CVM because + // JNI_NewDirectByteBuffer isn't implemented + // by default and isn't compatible with the + // JSR-239 NIO implementation (apparently) + buf = newDirectByteBuffer(getMixerBufferDataAddress(mixerBuffer), + getMixerBufferDataCapacity(mixerBuffer)); + } - if (buf == null) { - throw new InternalError("Couldn't wrap the native address with a direct byte buffer"); - } + if (buf == null) { + throw new InternalError("Couldn't wrap the native address with a direct byte buffer"); + } - // System.out.println("Mixing buffer"); + // System.out.println("Mixing buffer"); - // If we don't have enough samples in our mixing buffer, expand it - // FIXME: knowledge of native output rendering format - if ((mixingBuffer == null) || (mixingBuffer.length < (buf.capacity() / 2 /* bytes / sample */))) { - mixingBuffer = new float[buf.capacity() / 2]; - } else { - // Zap it - for (int i = 0; i < mixingBuffer.length; i++) { - mixingBuffer[i] = 0.0f; + // If we don't have enough samples in our mixing buffer, expand it + // FIXME: knowledge of native output rendering format + if ((mixingBuffer == null) || (mixingBuffer.length < (buf.capacity() / 2 /* bytes / sample */))) { + mixingBuffer = new float[buf.capacity() / 2]; + } else { + // Zap it + for (int i = 0; i < mixingBuffer.length; i++) { + mixingBuffer[i] = 0.0f; + } } - } - - // This assertion should be in place if we have stereo - if ((mixingBuffer.length % 2) != 0) { - final String msg = "FATAL ERROR: odd number of samples in the mixing buffer"; - System.out.println(msg); - throw new InternalError(msg); - } - // Run down all of the registered tracks mixing them in - final List<Track> curTracks = tracks; + // This assertion should be in place if we have stereo + if ((mixingBuffer.length % 2) != 0) { + final String msg = "FATAL ERROR: odd number of samples in the mixing buffer"; + System.out.println(msg); + throw new InternalError(msg); + } - for (final Iterator<Track> iter = curTracks.iterator(); iter.hasNext(); ) { - final Track track = iter.next(); - // Consider only playing tracks - if (track.isPlaying()) { - // First recompute its gain - final Vec3f pos = track.getPosition(); - final float leftGain = gain(pos, leftSpeakerPosition); - final float rightGain = gain(pos, rightSpeakerPosition); - // Now mix it in - int i = 0; - while (i < mixingBuffer.length) { - if (track.hasNextSample()) { - final float sample = track.nextSample(); - mixingBuffer[i++] = sample * leftGain; - mixingBuffer[i++] = sample * rightGain; - } else { - // This allows tracks to stall without being abruptly cancelled - if (track.done()) { - remove(track); + // Run down all of the registered tracks mixing them in + final List<Track> curTracks = tracks; + + for (final Iterator<Track> iter = curTracks.iterator(); iter.hasNext(); ) { + final Track track = iter.next(); + // Consider only playing tracks + if (track.isPlaying()) { + // First recompute its gain + final Vec3f pos = track.getPosition(); + final float leftGain = gain(pos, leftSpeakerPosition); + final float rightGain = gain(pos, rightSpeakerPosition); + // Now mix it in + int i = 0; + while (i < mixingBuffer.length) { + if (track.hasNextSample()) { + final float sample = track.nextSample(); + mixingBuffer[i++] = sample * leftGain; + mixingBuffer[i++] = sample * rightGain; + } else { + // This allows tracks to stall without being abruptly cancelled + if (track.done()) { + remove(track); + } + break; } - break; } } } - } - // Now that we have our data, send it down to the card - int outPos = 0; - for (int i = 0; i < mixingBuffer.length; i++) { - final short val = (short) mixingBuffer[i]; - buf.put(outPos++, (byte) val); - buf.put(outPos++, (byte) (val >> 8)); - } - if (!prepareMixerBuffer(mixerBuffer)) { - throw new RuntimeException("Error preparing mixer buffer"); - } - if (!writeMixerBuffer(mixerBuffer)) { - throw new RuntimeException("Error writing mixer buffer to device"); - } - } else { - // System.out.println("No mixer buffer available"); + // Now that we have our data, send it down to the card + int outPos = 0; + for (int i = 0; i < mixingBuffer.length; i++) { + final short val = (short) mixingBuffer[i]; + buf.put(outPos++, (byte) val); + buf.put(outPos++, (byte) (val >> 8)); + } + if (!prepareMixerBuffer(mixerBuffer)) { + throw new RuntimeException("Error preparing mixer buffer"); + } + if (!writeMixerBuffer(mixerBuffer)) { + throw new RuntimeException("Error writing mixer buffer to device"); + } + } else { + // System.out.println("No mixer buffer available"); - // Wait for a buffer to become available - if (!WaitForSingleObject(event)) { - throw new RuntimeException("Error while waiting for event object"); - } + // Wait for a buffer to become available + if (!WaitForSingleObject(event)) { + throw new RuntimeException("Error while waiting for event object"); + } - /* - try { - Thread.sleep(10); - } catch (InterruptedException e) { + /* + try { + Thread.sleep(10); + } catch (InterruptedException e) { + throw new InterruptedRuntimeException(e); + } + */ } - */ } - } - - // Need to shut down - shutdownWaveOut(); - synchronized(shutdownLock) { - shutdownLock.notifyAll(); + } finally { + mixerAlive = false; + // Need to shut down + shutdownWaveOut(); + synchronized(shutdownLock) { + shutdownLock.notifyAll(); + } } } diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java index 9381d318b..9f885e55d 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java @@ -391,35 +391,16 @@ public class BuildComposablePipeline { final PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(file))); - final List<Class<?>> baseInterfaces = Arrays.asList(baseInterfaceClass.getInterfaces()); - final HashSet<Class<?>> clazzList = new HashSet<Class<?>>(); - clazzList.add(baseInterfaceClass); - clazzList.addAll(baseInterfaces); - final int ifNamesNumber = clazzList.size(); - - // keep original order .. - clazzList.clear(); - final String[] ifNames = new String[ifNamesNumber]; - { - int i = 0; - - for (final Iterator<Class<?>> iter = baseInterfaces.iterator(); iter.hasNext();) { - final Class<?> ifClass = iter.next(); - if (!clazzList.contains(ifClass)) { - ifNames[i++] = ifClass.getName(); - clazzList.add(ifClass); - } - } + final HashSet<Class<?>> importClazzList = new HashSet<Class<?>>(); + importClazzList.add(baseInterfaceClass); + final String[] ifNames = new String[] { baseInterfaceClass.getName() }; - if ( !clazzList.contains(baseInterfaceClass) ) { - ifNames[i++] = baseInterfaceClass.getName(); - clazzList.add(baseInterfaceClass); - } - } + final List<Class<?>> baseInterfaces = Arrays.asList(baseInterfaceClass.getInterfaces()); + importClazzList.addAll(baseInterfaces); - clazzList.add(downstreamClass); + importClazzList.add(downstreamClass); if (null != prologClassOpt) { - clazzList.add(prologClassOpt); + importClazzList.add(prologClassOpt); } final ArrayList<String> imports = new ArrayList<String>(); @@ -427,7 +408,7 @@ public class BuildComposablePipeline { imports.add("com.jogamp.opengl.*"); imports.add("com.jogamp.gluegen.runtime.*"); imports.add(Buffer.class.getPackage().getName()+".*"); - for (final Class<?> clasS : clazzList) { + for (final Class<?> clasS : importClazzList) { imports.add(clasS.getName()); } diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java index d6f72ee29..1c034ebfb 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java @@ -254,6 +254,14 @@ public class GLConfiguration extends ProcAddressConfiguration { super.logRenames(); } + protected boolean isIgnoredExtension(final String extensionName) { + if( ignoredExtensions.contains(extensionName) ) { + return !forcedExtensions.contains(extensionName); + } else { + return false; + } + } + protected boolean shouldIgnoreExtension(final AliasedSymbol symbol) { final Set<String> symExtensionNames; // collect current-name symbol extensions diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java index 8df4a9488..a68fc6b2a 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java @@ -112,31 +112,35 @@ public class GLEmitter extends ProcAddressEmitter { final Set<String> extensionSet = isSemHeader ? config.getExtensionsRenamedIntoCore() : glInfo.getExtensions(); for (final String extension : extensionSet) { - LOG.log(INFO, "<RenameExtensionIntoCore: {0} BEGIN {1}", extension, headerType); - final Set<String> declarations = glInfo.getDeclarations(extension); - if (declarations != null) { - for (final Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) { - final String decl = iterator.next(); - final boolean isGLFunction = GLNameResolver.isGLFunction(decl); - boolean isGLEnumeration = false; - if (!isGLFunction) { - isGLEnumeration = GLNameResolver.isGLEnumeration(decl); - } - if (isGLFunction || isGLEnumeration) { - final String renamed = GLNameResolver.normalize(decl, isGLFunction); - if (!renamed.equals(decl)) { - if( isSemHeader ) { - // Sem + Doc - config.addJavaSymbolRename(decl, renamed); - } else { - // Doc only - config.addJavaDocSymbolRename(decl, renamed); + if( isSemHeader && config.isIgnoredExtension(extension) ) { + LOG.log(INFO, "<RenameExtensionIntoCore: {0} IGNORED {1}>", extension, headerType); + } else { + LOG.log(INFO, "<RenameExtensionIntoCore: {0} BEGIN {1}", extension, headerType); + final Set<String> declarations = glInfo.getDeclarations(extension); + if (declarations != null) { + for (final Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) { + final String decl = iterator.next(); + final boolean isGLFunction = GLNameResolver.isGLFunction(decl); + boolean isGLEnumeration = false; + if (!isGLFunction) { + isGLEnumeration = GLNameResolver.isGLEnumeration(decl); + } + if (isGLFunction || isGLEnumeration) { + final String renamed = GLNameResolver.normalize(decl, isGLFunction); + if (!renamed.equals(decl)) { + if( isSemHeader ) { + // Sem + Doc + config.addJavaSymbolRename(decl, renamed); + } else { + // Doc only + config.addJavaDocSymbolRename(decl, renamed); + } } } } } + LOG.log(INFO, "RenameExtensionIntoCore: {0} END>", extension, headerType); } - LOG.log(INFO, "RenameExtensionIntoCore: {0} END>", extension, headerType); } } diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java index d400381c8..d7e340630 100644 --- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java +++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java @@ -50,27 +50,30 @@ public class GLNameResolver { private static final String[] extensionsARB = { "ARB", "GL2", "OES", "KHR", "OML" }; private static final String[] extensionsVEN = { "3DFX", "AMD", + "ANDROID", "ANGLE", "ARM", "APPLE", "ATI", "EXT", + "FJ", "HI", "HP", "IBM", "IMG", + "INGR", + "INTEL", "MESA", "MESAX", "NV", + "PGI", "QCOM", "SGI", "SGIS", "SGIX", "SUN", "VIV", - "WIN" - }; - + "WIN" }; public static final boolean isGLFunction(final String str) { return str.startsWith("gl") || /* str.startsWith("glu") || str.startsWith("glX") || */ diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java index be16e030f..76badcda8 100644 --- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java +++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java @@ -199,7 +199,7 @@ public class FontFactory { throw new IOException(e); } } else { - stream = IOUtil.getResource(context, fname).getInputStream(); + stream = IOUtil.getResource(fname, context.getClassLoader(), context).getInputStream(); } if( null != stream ) { return FontFactory.get ( stream, true ) ; diff --git a/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java b/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java index 549efd569..38b8f770b 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java +++ b/src/jogl/classes/com/jogamp/opengl/GLAnimatorControl.java @@ -58,7 +58,8 @@ public interface GLAnimatorControl extends FPSCounter { * Any exception thrown by this method will be ignored. * </p> * @param animator the {@link GLAnimatorControl} - * @param drawable the causing {@link GLAutoDrawable} + * @param drawable the causing {@link GLAutoDrawable}, + * may be {@code null} in case {@link Throwable} caused unrelated to any {@link GLAutoDrawable}. * @param cause the uncaught exception * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler) * @since 2.2 diff --git a/src/jogl/classes/com/jogamp/opengl/GLBase.java b/src/jogl/classes/com/jogamp/opengl/GLBase.java index dee5f1488..0cbcbe40f 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLBase.java +++ b/src/jogl/classes/com/jogamp/opengl/GLBase.java @@ -237,6 +237,19 @@ public interface GLBase { public boolean isGLES31Compatible(); /** + * Indicates whether this GL object is compatible with the core OpenGL ES3.2 functionality. + * <p> + * Return true if the underlying context is an ES3 context ≥ 3.2 or implements + * the extension <code>GL_ARB_ES3_2_compatibility</code>, otherwise false. + * </p> + * <p> + * Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_2_compatibility and GLES3 ≥ 3.2 ] + * </p> + * @see GLContext#isGLES32Compatible() + */ + public boolean isGLES32Compatible(); + + /** * Indicates whether this GL object supports GLSL. * @see GLContext#hasGLSL() */ @@ -446,29 +459,43 @@ public interface GLBase { public boolean isTextureFormatBGRA8888Available(); - /** Provides a platform-independent way to specify the minimum swap - interval for buffer swaps. An argument of 0 disables - sync-to-vertical-refresh completely, while an argument of 1 - causes the application to wait until the next vertical refresh - until swapping buffers. The default, which is platform-specific, - is usually either 0 or 1. This function is not guaranteed to - have an effect, and in particular only affects heavyweight - onscreen components. - - @see #getSwapInterval - @throws GLException if this context is not the current + /** + * Set the swap interval of the current context and attached <i>onscreen {@link GLDrawable}</i>. + * <p> + * <i>offscreen {@link GLDrawable}</i> are ignored and {@code false} is returned. + * </p> + * <p> + * The {@code interval} semantics: + * <ul> + * <li><i>0</i> disables the vertical synchronization</li> + * <li><i>≥1</i> is the number of vertical refreshes before a swap buffer occurs</li> + * <li><i><0</i> enables <i>late swaps to occur without synchronization to the video frame</i>, a.k.a <i>EXT_swap_control_tear</i>. + * If supported, the absolute value is the minimum number of + * video frames between buffer swaps. If not supported, the absolute value is being used, see above. + * </li> + * </ul> + * </p> + * @param interval see above + * @return true if the operation was successful, otherwise false + * @throws GLException if the context is not current. + * @see GLContext#setSwapInterval(int) + * @see #getSwapInterval() */ - public void setSwapInterval(int interval); + public void setSwapInterval(int interval) throws GLException; - /** Provides a platform-independent way to get the swap - interval set by {@link #setSwapInterval}. <br> - - If the interval is not set by {@link #setSwapInterval} yet, - -1 is returned, indicating that the platforms default - is being used. - - @see #setSwapInterval - */ + /** + * Return the current swap interval. + * <p> + * If the context has not been made current at all, + * the default value {@code 0} is returned. + * </p> + * <p> + * For a valid context w/ an <o>onscreen {@link GLDrawable}</i> the default value is {@code 1}, + * otherwise the default value is {@code 0}. + * </p> + * @see GLContext#getSwapInterval() + * @see #setSwapInterval(int) + */ public int getSwapInterval(); /** @@ -494,12 +521,12 @@ public interface GLBase { * for accessing it, including which class or interface contains the * functions. * - * <P> - * + * <p> * Note: it is the intent to add new extensions as quickly as possible * to the core GL API. Therefore it is unlikely that most vendors will * use this extension mechanism, but it is being provided for * completeness. + * </p> */ public Object getExtension(String extensionName); diff --git a/src/jogl/classes/com/jogamp/opengl/GLContext.java b/src/jogl/classes/com/jogamp/opengl/GLContext.java index f68c029df..606e4b4ed 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/GLContext.java @@ -198,16 +198,19 @@ public abstract class GLContext { /** <code>GL_ARB_ES3_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES3Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES3_COMPAT = 1 << 11; - /** <code>GL_ARB_ES3_1_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES31Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ + /** <code>GL_ARB_ES3_1_compatibility</code> implementation related: Context is compatible w/ ES 3.1. Not a cache key. See {@link #isGLES31Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES31_COMPAT = 1 << 12; + /** <code>GL_ARB_ES3_2_compatibility</code> implementation related: Context is compatible w/ ES 3.2. Not a cache key. See {@link #isGLES32Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ + protected static final int CTX_IMPL_ES32_COMPAT = 1 << 13; + /** * 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 << 13; + protected static final int CTX_IMPL_FBO = 1 << 14; /** * Context supports <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points, @@ -216,7 +219,7 @@ public abstract class GLContext { * @see #hasFP32CompatAPI() * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile) */ - protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 14; + protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 15; private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>(); @@ -237,7 +240,6 @@ public abstract class GLContext { protected String ctxVersionString; protected VersionNumberString ctxVendorVersion; protected VersionNumber ctxGLSLVersion; - private int currentSwapInterval; protected GLRendererQuirks glRendererQuirks; /** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */ @@ -258,7 +260,6 @@ public abstract class GLContext { ctxGLSLVersion = VersionNumber.zeroVersion; attachedObjects.clear(); contextHandle=0; - currentSwapInterval = -1; glRendererQuirks = null; drawableRetargeted = false; } @@ -925,6 +926,17 @@ public abstract class GLContext { } /** + * Return true if this context is an ES3 context ≥ 3.2 or implements + * the extension <code>GL_ARB_ES3_2_compatibility</code>, otherwise false. + * <p> + * Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_2_compatibility and GLES3 ≥ 3.2 ] + * </p> + */ + public final boolean isGLES32Compatible() { + return 0 != ( ctxOptions & CTX_IMPL_ES32_COMPAT ) ; + } + + /** * @return true if impl. is a hardware rasterizer, otherwise false. * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile) * @see GLProfile#isHardwareRasterizer() @@ -1182,8 +1194,9 @@ public abstract class GLContext { if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) { final int major = ctxVersion.getMajor(); return 2 == major || 3 == major; + } else { + return false; } - return false; } /** @@ -1246,49 +1259,55 @@ public abstract class GLContext { } /** - * Set the swap interval of the current context and attached drawable. - * @param interval Should be ≥ 0. 0 disables the vertical synchronization, - * where ≥ 1 is the number of vertical refreshes before a swap buffer occurs. - * A value < 0 is ignored. + * Set the swap interval of the current context and attached <i>onscreen {@link GLDrawable}</i>. + * <p> + * <i>offscreen {@link GLDrawable}</i> are ignored and {@code false} is returned. + * </p> + * <p> + * The {@code interval} semantics: + * <ul> + * <li><i>0</i> disables the vertical synchronization</li> + * <li><i>≥1</i> is the number of vertical refreshes before a swap buffer occurs</li> + * <li><i><0</i> enables <i>late swaps to occur without synchronization to the video frame</i>, a.k.a <i>EXT_swap_control_tear</i>. + * If supported, the absolute value is the minimum number of + * video frames between buffer swaps. If not supported, the absolute value is being used, see above. + * </li> + * </ul> + * </p> + * @param interval see above * @return true if the operation was successful, otherwise false - * * @throws GLException if the context is not current. + * @see #getSwapInterval() */ - public final boolean setSwapInterval(final int interval) throws GLException { - validateCurrent(); - if(0<=interval) { - if( !drawableRetargeted || !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) ) { - if( setSwapIntervalImpl(interval) ) { - currentSwapInterval = interval; - return true; - } - } - } - return false; + public /* abstract */ boolean setSwapInterval(final int interval) throws GLException { + // FIXME: Make abstract for next version - just here to *not* break SEMVER! + throw new InternalError("Implemented in GLContextImpl"); } protected boolean setSwapIntervalImpl(final int interval) { - return false; + // FIXME: Remove for next version - just here to *not* break SEMVER! + throw new InternalError("Implemented in GLContextImpl"); } - /** Return the current swap interval. + + /** + * Return the current swap interval. * <p> * If the context has not been made current at all, - * the default value <code>-1</code> is returned. + * the default value {@code 0} is returned. * </p> * <p> - * For a valid context the default value is <code>1</code> - * in case of an EGL based profile (ES1 or ES2) and <code>-1</code> - * (undefined) for desktop. + * For a valid context w/ an <o>onscreen {@link GLDrawable}</i> the default value is {@code 1}, + * otherwise the default value is {@code 0}. * </p> + * @see #setSwapInterval(int) */ - public final int getSwapInterval() { - return currentSwapInterval; + public /* abstract */ int getSwapInterval() { + // FIXME: Make abstract for next version - just here to *not* break SEMVER! + throw new InternalError("Implemented in GLContextImpl"); } - protected final void setDefaultSwapInterval() { - if(this.isGLES()) { - currentSwapInterval = 1; - } else { - currentSwapInterval = -1; - } + + protected void setDefaultSwapInterval() { + // FIXME: Remove for next version - just here to *not* break SEMVER! + throw new InternalError("Implemented in GLContextImpl"); } public final boolean queryMaxSwapGroups(final int[] maxGroups, final int maxGroups_offset, @@ -1492,7 +1511,7 @@ public abstract class GLContext { /* 0.*/ { -1 }, /* 1.*/ { 0, 1 }, /* 2.*/ { 0 }, - /* 3.*/ { 0, 1 } }; + /* 3.*/ { 0, 1, 2 } }; public static final int getMaxMajor(final int ctxProfile) { return ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ? ES_VERSIONS.length-1 : GL_VERSIONS.length-1; @@ -1613,8 +1632,14 @@ public abstract class GLContext { ( ( b8 & 0x000000FF ) << 16 ) | ( ( c16 & 0x0000FFFF ) ) ; } + protected static VersionNumber decomposeBits(final int bits32, final int[] ctp) { + final int major = ( bits32 & 0xFF000000 ) >>> 24 ; + final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ; + ctp[0] = ( bits32 & 0x0000FFFF ) ; + return new VersionNumber(major, minor, 0); + } - private static void validateProfileBits(final int bits, final String argName) { + protected static void validateProfileBits(final int bits, final String argName) { int num = 0; if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; } if( 0 != ( CTX_PROFILE_CORE & bits ) ) { num++; } @@ -1660,7 +1685,7 @@ public abstract class GLContext { deviceVersionsAvailableSet.remove(devKey); } if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions SET "+devKey); System.err.println(GLContext.dumpAvailableGLVersions(null).toString()); } } @@ -1675,38 +1700,6 @@ public abstract class GLContext { return r.intern(); } - /** - * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable(int,int)} not intended to be used by - * implementations. However, if {@link jogamp.opengl.GLContextImpl#createContextARB(long, boolean)} is not being used within - * {@link com.jogamp.opengl.GLDrawableFactory#getOrCreateSharedContext(com.jogamp.nativewindow.AbstractGraphicsDevice)}, - * GLProfile has to map the available versions. - * - * @param reqMajor Key Value either 1, 2, 3 or 4 - * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} - * @return the old mapped value - * - * @see #createContextARBMapVersionsAvailable - */ - protected static Integer mapAvailableGLVersion(final AbstractGraphicsDevice device, - final int reqMajor, final int profile, final int resMajor, final int resMinor, int resCtp) - { - validateProfileBits(profile, "profile"); - validateProfileBits(resCtp, "resCtp"); - - if(FORCE_NO_FBO_SUPPORT) { - resCtp &= ~CTX_IMPL_FBO ; - } - if(DEBUG) { - System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null)); - // Thread.dumpStack(); - } - final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile); - final Integer val = Integer.valueOf(composeBits(resMajor, resMinor, resCtp)); - synchronized(deviceVersionAvailable) { - return deviceVersionAvailable.put( objectKey, val ); - } - } - protected static StringBuilder dumpAvailableGLVersions(StringBuilder sb) { if(null == sb) { sb = new StringBuilder(); @@ -1714,19 +1707,17 @@ public abstract class GLContext { synchronized(deviceVersionAvailable) { final Set<String> keys = deviceVersionAvailable.keySet(); boolean needsSeparator = false; - for(final Iterator<String> i = keys.iterator(); i.hasNext(); ) { + for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); ) { if(needsSeparator) { sb.append(Platform.getNewline()); } - final String key = i.next(); - sb.append(key).append(": "); + final String key = keyI.next(); + sb.append("MapGLVersions ").append(key).append(": "); final Integer valI = deviceVersionAvailable.get(key); if(null != valI) { - final int bits32 = valI.intValue(); - final int major = ( bits32 & 0xFF000000 ) >>> 24 ; - final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ; - final int ctp = ( bits32 & 0x0000FFFF ) ; - sb.append(GLContext.getGLVersion(major, minor, ctp, null)); + final int[] ctp = { 0 }; + final VersionNumber version = decomposeBits(valI.intValue(), ctp); + GLContext.getGLVersion(sb, version, ctp[0], null); } else { sb.append("n/a"); } @@ -1949,15 +1940,7 @@ public abstract class GLContext { return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware); } - /** - * Returns true if a ES3 compatible profile is available, - * i.e. either a ≥ 4.3 context or a ≥ 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>, - * otherwise false. - * <p> - * Includes [ GL ≥ 4.3, GL ≥ 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ] - * </p> - */ - public static final boolean isGLES3CompatibleAvailable(final AbstractGraphicsDevice device) { + private static final int getGL3ctp(final AbstractGraphicsDevice device) { final int major[] = { 0 }; final int minor[] = { 0 }; final int ctp[] = { 0 }; @@ -1970,7 +1953,19 @@ public abstract class GLContext { if( !ok ) { GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp); } - return 0 != ( ctp[0] & CTX_IMPL_ES3_COMPAT ); + return ctp[0]; + } + + /** + * Returns true if a ES3 compatible profile is available, + * i.e. either a ≥ 4.3 context or a ≥ 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>, + * otherwise false. + * <p> + * Includes [ GL ≥ 4.3, GL ≥ 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ] + * </p> + */ + public static final boolean isGLES3CompatibleAvailable(final AbstractGraphicsDevice device) { + return 0 != ( getGL3ctp(device) & CTX_IMPL_ES3_COMPAT ); } /** * Returns true if a ES3 ≥ 3.1 compatible profile is available, @@ -1981,19 +1976,18 @@ public abstract class GLContext { * </p> */ public static final boolean isGLES31CompatibleAvailable(final AbstractGraphicsDevice device) { - final int major[] = { 0 }; - final int minor[] = { 0 }; - final int ctp[] = { 0 }; - boolean ok; - - ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_ES, major, minor, ctp); - if( !ok ) { - ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, major, minor, ctp); - } - if( !ok ) { - GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp); - } - return 0 != ( ctp[0] & CTX_IMPL_ES31_COMPAT ); + return 0 != ( getGL3ctp(device) & CTX_IMPL_ES31_COMPAT ); + } + /** + * Returns true if a ES3 ≥ 3.2 compatible profile is available, + * i.e. either a ≥ 4.5 context or a ≥ 3.1 context supporting <code>GL_ARB_ES3_2_compatibility</code>, + * otherwise false. + * <p> + * Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_2_compatibility and GLES3 ≥ 3.2 ] + * </p> + */ + public static final boolean isGLES32CompatibleAvailable(final AbstractGraphicsDevice device) { + return 0 != ( getGL3ctp(device) & CTX_IMPL_ES32_COMPAT ); } public static boolean isGL4bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) { @@ -2016,13 +2010,8 @@ public abstract class GLContext { return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware); } - protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) { + protected static StringBuilder getGLProfile(final StringBuilder sb, final int ctp) { boolean needColon = false; - final StringBuilder sb = new StringBuilder(); - sb.append(major); - sb.append("."); - sb.append(minor); - sb.append(" ("); needColon = appendString(sb, "ES profile", needColon, 0 != ( CTX_PROFILE_ES & ctp )); needColon = appendString(sb, "Compat profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp )); needColon = appendString(sb, "Core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp )); @@ -2035,6 +2024,7 @@ public abstract class GLContext { needColon = appendString(sb, "ES2", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp )); needColon = appendString(sb, "ES3", needColon, 0 != ( CTX_IMPL_ES3_COMPAT & ctp )); needColon = appendString(sb, "ES31", needColon, 0 != ( CTX_IMPL_ES31_COMPAT & ctp )); + needColon = appendString(sb, "ES32", needColon, 0 != ( CTX_IMPL_ES32_COMPAT & ctp )); needColon = appendString(sb, "FP32", needColon, 0 != ( CTX_IMPL_FP32_COMPAT_API & ctp )); needColon = false; } @@ -2045,12 +2035,26 @@ public abstract class GLContext { } else { needColon = appendString(sb, "hardware", needColon, true); } + return sb; + } + protected static StringBuilder getGLVersion(final StringBuilder sb, final VersionNumber version, final int ctp, final String gl_version) { + return getGLVersion(sb, version.getMajor(), version.getMinor(), ctp, gl_version); + } + protected static StringBuilder getGLVersion(final StringBuilder sb, final int major, final int minor, final int ctp, final String gl_version) { + sb.append(major); + sb.append("."); + sb.append(minor); + sb.append(" ("); + getGLProfile(sb, ctp); sb.append(")"); if(null!=gl_version) { sb.append(" - "); sb.append(gl_version); } - return sb.toString(); + return sb; + } + protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) { + return getGLVersion(new StringBuilder(), major, minor, ctp, gl_version).toString(); } // diff --git a/src/jogl/classes/com/jogamp/opengl/GLDrawable.java b/src/jogl/classes/com/jogamp/opengl/GLDrawable.java index c801ba463..a4a9d2e06 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/GLDrawable.java @@ -134,7 +134,7 @@ public interface GLDrawable extends NativeSurfaceHolder { public void setRealized(boolean realized); /** - * Returns <code>true</code> if this drawable is realized, otherwise <code>true</code>. + * Returns <code>true</code> if this drawable is realized, otherwise <code>false</code>. * <p> * A drawable can be realized and unrealized via {@link #setRealized(boolean)}. * </p> diff --git a/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java index 7d78e3409..51da34ce0 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java @@ -421,6 +421,18 @@ public abstract class GLDrawableFactory { public abstract GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device, final GLProfile glp); /** + * Method returns {@code true} if underlying implementation may support native desktop OpenGL, + * otherwise {@code false}. + */ + public abstract boolean hasOpenGLDesktopSupport(); + + /** + * Method returns {@code true} if underlying implementation may support native embedded OpenGL ES, + * otherwise {@code false}. + */ + public abstract boolean hasOpenGLESSupport(); + + /** * Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null */ public static GLDrawableFactory getDesktopFactory() { diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java index 1bf8071ea..23e7dec31 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -36,6 +36,7 @@ public class GLExtensions { public static final String VERSION_1_5 = "GL_VERSION_1_5"; public static final String VERSION_2_0 = "GL_VERSION_2_0"; + public static final String GL_KHR_debug = "GL_KHR_debug"; public static final String ARB_debug_output = "GL_ARB_debug_output"; public static final String AMD_debug_output = "GL_AMD_debug_output"; @@ -53,6 +54,7 @@ public class GLExtensions { 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 ARB_ES3_1_compatibility = "GL_ARB_ES3_1_compatibility"; + public static final String ARB_ES3_2_compatibility = "GL_ARB_ES3_2_compatibility"; public static final String EXT_abgr = "GL_EXT_abgr"; public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8"; diff --git a/src/jogl/classes/com/jogamp/opengl/GLProfile.java b/src/jogl/classes/com/jogamp/opengl/GLProfile.java index a36a21ad5..e19535e5d 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLProfile.java +++ b/src/jogl/classes/com/jogamp/opengl/GLProfile.java @@ -39,6 +39,7 @@ package com.jogamp.opengl; import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; +import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.DesktopGLDynamicLookupHelper; import com.jogamp.common.ExceptionUtils; @@ -217,7 +218,7 @@ public class GLProfile { public Object run() { Platform.initSingleton(); - if(TempJarCache.isInitialized()) { + if( TempJarCache.isInitialized(true) ) { final ClassLoader cl = GLProfile.class.getClassLoader(); final String newtDebugClassName = "jogamp.newt.Debug"; final Class<?>[] classesFromJavaJars = new Class<?>[] { jogamp.nativewindow.Debug.class, jogamp.opengl.Debug.class, null }; @@ -242,7 +243,7 @@ public class GLProfile { initLock.unlock(); } if(DEBUG) { - if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES3Impl ) ) { + if( justInitialized && ( hasGL234Impl || hasGL234OnEGLImpl || hasGLES1Impl || hasGLES3Impl ) ) { System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true)); } } @@ -1629,6 +1630,7 @@ public class GLProfile { private static /*final*/ boolean hasEGLFactory; private static /*final*/ boolean hasGLES3Impl; private static /*final*/ boolean hasGLES1Impl; + private static /*final*/ boolean hasGL234OnEGLImpl; private static /*final*/ Constructor<?> ctorGL234Impl; private static /*final*/ Constructor<?> ctorGLES3Impl; private static /*final*/ Constructor<?> ctorGLES1Impl; @@ -1681,6 +1683,7 @@ public class GLProfile { ctorGL234ProcAddr = null; } } + hasGL234OnEGLImpl = hasGL234Impl; // depends on hasEGLFactory { @@ -1745,10 +1748,9 @@ public class GLProfile { try { desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GL2); if(null != desktopFactory) { - final DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(GL2); - if(null!=glLookupHelper) { - hasDesktopGLFactory = glLookupHelper.isLibComplete() && hasGL234Impl; - } + final DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(2, GLContext.CTX_PROFILE_COMPAT); + hasGL234Impl = null!=glLookupHelper && glLookupHelper.isLibComplete() && hasGL234Impl; + hasDesktopGLFactory = hasGL234Impl; } } catch (final LinkageError le) { t=le; @@ -1780,10 +1782,14 @@ public class GLProfile { try { eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2); if(null != eglFactory) { - hasEGLFactory = true; - // update hasGLES1Impl, hasGLES3Impl based on EGL - hasGLES3Impl = null!=eglFactory.getGLDynamicLookupHelper(GLES2) && hasGLES3Impl; - hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(GLES1) && hasGLES1Impl; + // update hasGLES1Impl, hasGLES3Impl, hasGL234OnEGLImpl based on library completion + final GLDynamicLookupHelper es2DynLookup = eglFactory.getGLDynamicLookupHelper(2, GLContext.CTX_PROFILE_ES); + final GLDynamicLookupHelper es1DynLookup = eglFactory.getGLDynamicLookupHelper(1, GLContext.CTX_PROFILE_ES); + final GLDynamicLookupHelper glXDynLookup = eglFactory.getGLDynamicLookupHelper(3, GLContext.CTX_PROFILE_CORE); + hasGLES3Impl = null!=es2DynLookup && es2DynLookup.isLibComplete() && hasGLES3Impl; + hasGLES1Impl = null!=es1DynLookup && es1DynLookup.isLibComplete() && hasGLES1Impl; + hasGL234OnEGLImpl = null!=glXDynLookup && glXDynLookup.isLibComplete() && hasGL234OnEGLImpl; + hasEGLFactory = hasGLES3Impl || hasGLES1Impl || hasGL234OnEGLImpl; } } catch (final LinkageError le) { t=le; @@ -1803,6 +1809,8 @@ public class GLProfile { final AbstractGraphicsDevice defaultEGLDevice; if(null == eglFactory) { + hasEGLFactory = false; + hasGL234OnEGLImpl= false; hasGLES3Impl = false; hasGLES1Impl = false; defaultEGLDevice = null; @@ -1843,6 +1851,7 @@ public class GLProfile { System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); System.err.println("GLProfile.init hasGLES3Impl "+hasGLES3Impl); + System.err.println("GLProfile.init hasGL234OnEGLImpl "+hasGL234OnEGLImpl); System.err.println("GLProfile.init defaultDevice "+defaultDevice); System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice); System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice); @@ -1887,7 +1896,9 @@ public class GLProfile { return null != map.get(GL_DEFAULT); } + HashMap<String, GLProfile> mappedDesktopProfiles = null; boolean addedDesktopProfile = false; + HashMap<String, GLProfile> mappedEGLProfiles = null; boolean addedEGLProfile = false; final boolean deviceIsDesktopCompatible = hasDesktopGLFactory && desktopFactory.getIsDeviceCompatible(device); @@ -1906,21 +1917,23 @@ public class GLProfile { if(null != sharedResourceThread) { initLock.removeOwner(sharedResourceThread); } - if (DEBUG) { - System.err.println("GLProfile.initProfilesForDevice: "+device+": desktop Shared Ctx "+desktopSharedCtxAvail); - } - if(!desktopSharedCtxAvail) { - hasDesktopGLFactory = false; - } else if( !GLContext.getAvailableGLVersionsSet(device) ) { - throw new InternalError("Available GLVersions not set"); + if( desktopSharedCtxAvail ) { + if( !GLContext.getAvailableGLVersionsSet(device) ) { + throw new InternalError("Available GLVersions not set for "+device); + } + mappedDesktopProfiles = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); + addedDesktopProfile = mappedDesktopProfiles.size() > 0; + if (DEBUG) { + System.err.println("GLProfile.initProfilesForDevice: "+device+": desktop Shared Ctx "+desktopSharedCtxAvail+ + ", profiles: "+(addedDesktopProfile ? mappedDesktopProfiles.size() : 0)); + } } - addedDesktopProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); } final boolean deviceIsEGLCompatible = hasEGLFactory && eglFactory.getIsDeviceCompatible(device); // also test GLES1, GLES2 and GLES3 on desktop, since we have implementations / emulations available. - if( deviceIsEGLCompatible && ( hasGLES3Impl || hasGLES1Impl ) ) { + if( deviceIsEGLCompatible ) { // 1st pretend we have all EGL profiles .. computeProfileMap(device, true /* desktopCtxUndef*/, true /* esCtxUndef */); @@ -1934,18 +1947,17 @@ public class GLProfile { if(null != sharedResourceThread) { initLock.removeOwner(sharedResourceThread); } - if(!eglSharedCtxAvail) { - // Remark: On Windows there is a libEGL.dll delivered w/ Chrome 15.0.874.121m and Firefox 8.0.1 - // but it seems even EGL.eglInitialize(eglDisplay, null, null) - // fails in some scenarios (eg VirtualBox 4.1.6) w/ EGL error 0x3001 (EGL_NOT_INITIALIZED). - hasEGLFactory = false; - hasGLES3Impl = false; - hasGLES1Impl = false; + if( eglSharedCtxAvail ) { + if( !GLContext.getAvailableGLVersionsSet(device) ) { + throw new InternalError("Available GLVersions not set for "+device); + } + mappedEGLProfiles = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); + addedEGLProfile = mappedEGLProfiles.size() > 0; } if (DEBUG) { - System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail); + System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail+ + ", profiles: "+(addedEGLProfile ? mappedEGLProfiles.size() : 0)); } - addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); } if( !addedDesktopProfile && !addedEGLProfile ) { @@ -1959,13 +1971,22 @@ public class GLProfile { System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl); System.err.println("GLProfile: hasGLES3Impl "+hasGLES3Impl); } + } else { + final HashMap<String, GLProfile> mappedAllProfiles = new HashMap<String, GLProfile>(); + if( addedEGLProfile ) { + mappedAllProfiles.putAll(mappedEGLProfiles); + } + if( addedDesktopProfile ) { + mappedAllProfiles.putAll(mappedDesktopProfiles); + } + setProfileMap(device, mappedAllProfiles); // union } GLContext.setAvailableGLVersionsSet(device, true); if (DEBUG) { - System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": added profile(s): desktop "+addedDesktopProfile+", egl "+addedEGLProfile); - System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": "+glAvailabilityToString(device)); + System.err.println("GLProfile.initProfilesForDevice: "+device.getUniqueID()+": added profile(s): desktop "+addedDesktopProfile+", egl "+addedEGLProfile); + System.err.println("GLProfile.initProfilesForDevice: "+device.getUniqueID()+": "+glAvailabilityToString(device)); if(addedDesktopProfile) { dumpGLInfo(desktopFactory, device); final List<GLCapabilitiesImmutable> availCaps = desktopFactory.getAvailableCapabilities(device); @@ -1996,6 +2017,9 @@ public class GLProfile { } } else { System.err.println("GLProfile.dumpGLInfo: shared context n/a"); + System.err.println(device.getClass().getSimpleName()+"[type "+ + device.getType()+", connection "+device.getConnection()+"]:"); + System.err.println(GLProfile.glAvailabilityToString(device, null, "\t", 1).toString()); } } @@ -2026,9 +2050,9 @@ public class GLProfile { sb.append("]"); } - private static boolean computeProfileMap(final AbstractGraphicsDevice device, final boolean desktopCtxUndef, final boolean esCtxUndef) { + private static HashMap<String, GLProfile> computeProfileMap(final AbstractGraphicsDevice device, final boolean desktopCtxUndef, final boolean esCtxUndef) { if (DEBUG) { - System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", esCtxUndef "+esCtxUndef); + System.err.println("GLProfile.init map "+device.getUniqueID()+", desktopCtxUndef "+desktopCtxUndef+", esCtxUndef "+esCtxUndef); } final boolean isHardwareRasterizer[] = new boolean[1]; GLProfile defaultGLProfileAny = null; @@ -2050,22 +2074,22 @@ public class GLProfile { } _mappedProfiles.put(profile, glProfile); if (DEBUG) { - System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection()); + System.err.println("GLProfile.init map "+glProfile+" on device "+device.getUniqueID()); } if( null == defaultGLProfileHW && isHardwareRasterizer[0] ) { defaultGLProfileHW=glProfile; if (DEBUG) { - System.err.println("GLProfile.init map defaultHW "+glProfile+" on device "+device.getConnection()); + System.err.println("GLProfile.init map defaultHW "+glProfile+" on device "+device.getUniqueID()); } } else if( null == defaultGLProfileAny ) { defaultGLProfileAny=glProfile; if (DEBUG) { - System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getConnection()); + System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getUniqueID()); } } } else { if (DEBUG) { - System.err.println("GLProfile.init map *** no mapping for "+profile+" on device "+device.getConnection()); + System.err.println("GLProfile.init map *** no mapping for "+profile+" on device "+device.getUniqueID()); } } } @@ -2075,13 +2099,14 @@ public class GLProfile { _mappedProfiles.put(GL_DEFAULT, defaultGLProfileAny); } setProfileMap(device, _mappedProfiles); - return _mappedProfiles.size() > 0; + return _mappedProfiles; } /** * Returns the profile implementation */ private static String computeProfileImpl(final AbstractGraphicsDevice device, final String profile, final boolean desktopCtxUndef, final boolean esCtxUndef, final boolean isHardwareRasterizer[]) { + final boolean hasAnyGL234Impl = hasGL234Impl || hasGL234OnEGLImpl; final boolean hardwareRasterizer[] = new boolean[1]; if ( GL2ES1 == profile ) { final boolean gles1Available; @@ -2093,7 +2118,7 @@ public class GLProfile { gles1Available = false; gles1HWAvailable = false; } - if(hasGL234Impl) { + if( hasAnyGL234Impl ) { final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer); final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ; final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer); @@ -2132,7 +2157,7 @@ public class GLProfile { gles3Available = false; gles3HWAvailable = false; } - if( hasGL234Impl ) { + if( hasAnyGL234Impl ) { final boolean gl4bcAvailable = GLContext.isGL4bcAvailable(device, hardwareRasterizer); final boolean gl4bcHWAvailable = gl4bcAvailable && hardwareRasterizer[0] ; final boolean gl3Available = GLContext.isGL3Available(device, hardwareRasterizer); @@ -2179,7 +2204,7 @@ public class GLProfile { final boolean es3HardwareRasterizer[] = new boolean[1]; final boolean gles3Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, es3HardwareRasterizer) ); final boolean gles3HWAvailable = gles3Available && es3HardwareRasterizer[0] ; - if( hasGL234Impl ) { + if( hasAnyGL234Impl ) { final boolean gl4bcAvailable = GLContext.isGL4bcAvailable(device, hardwareRasterizer); final boolean gl4bcHWAvailable = gl4bcAvailable && hardwareRasterizer[0] ; final boolean glAnyHWAvailable = gl4bcHWAvailable || @@ -2200,7 +2225,7 @@ public class GLProfile { } } } else if(GL2GL3 == profile) { - if(hasGL234Impl) { + if( hasAnyGL234Impl ) { final boolean gl4Available = GLContext.isGL4Available(device, hardwareRasterizer); final boolean gl4HWAvailable = gl4Available && hardwareRasterizer[0] ; final boolean gl3Available = GLContext.isGL3Available(device, hardwareRasterizer); @@ -2232,15 +2257,15 @@ public class GLProfile { return GL2; } } - } else if(GL4bc == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) { + } else if(GL4bc == profile && hasAnyGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) { return desktopCtxUndef ? GL4bc : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_COMPAT); - } else if(GL4 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) { + } else if(GL4 == profile && hasAnyGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) { return desktopCtxUndef ? GL4 : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_CORE); - } else if(GL3bc == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) { + } else if(GL3bc == profile && hasAnyGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) { return desktopCtxUndef ? GL3bc : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_COMPAT); - } else if(GL3 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) { + } else if(GL3 == profile && hasAnyGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) { return desktopCtxUndef ? GL3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_CORE); - } else if(GL2 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) { + } else if(GL2 == profile && hasAnyGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) { return desktopCtxUndef ? GL2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_COMPAT); } else if(GLES3 == profile && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, isHardwareRasterizer))) { return esCtxUndef ? GLES3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_ES); diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java index 55c02d92a..7898566f3 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java +++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java @@ -287,6 +287,7 @@ public class GLRendererQuirks { * <li>EGL_VERSION 1.4</li> * <li>GL_VENDOR NVIDIA Corporation</li> * <li>GL_VERSION OpenGL ES 3.0 331.38 (probably w/ 1st NV EGL lib on x86)</li> + * <li>GL_VERSION OpenGL ES 3.1 NVIDIA 355.06 (unstable)</li> * <li>Platform X11</li> * <li>CPU Family {@link Platform.CPUFamily#X86}</li> * </ul> @@ -393,7 +394,7 @@ public class GLRendererQuirks { * </p> */ public static final int NeedSharedObjectSync = 20; - + /** * No reliable ARB_create_context implementation, * even if driver claims otherwise. @@ -401,8 +402,8 @@ public class GLRendererQuirks { * Some drivers wrongly claim to support ARB_create_context. * However, the creation of such context fails: * <pre> - * com.jogamp.opengl.GLException: AWT-EventQueue-0: WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2 - * requested (OpenGL >= 3.0.1). Requested: GLProfile[GL3bc/GL3bc.hw], current: 2.1 (Compat profile, FBO, hardware) + * com.jogamp.opengl.GLException: AWT-EventQueue-0: WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2 + * requested (OpenGL >= 3.0.1). Requested: GLProfile[GL3bc/GL3bc.hw], current: 2.1 (Compat profile, FBO, hardware) * - 2.1.8787 * </pre> * </p> diff --git a/src/jogl/classes/com/jogamp/opengl/GLUniformData.java b/src/jogl/classes/com/jogamp/opengl/GLUniformData.java index 44f7f29c7..55a2e0cf1 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLUniformData.java +++ b/src/jogl/classes/com/jogamp/opengl/GLUniformData.java @@ -84,6 +84,7 @@ public class GLUniformData { public IntBuffer intBufferValue() { return (IntBuffer)data; }; public FloatBuffer floatBufferValue() { return (FloatBuffer)data; }; + @SuppressWarnings("deprecation") public StringBuilder toString(StringBuilder sb) { if(null == sb) { sb = new StringBuilder(); diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java index 7589b3776..560d99025 100644 --- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java +++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java @@ -144,8 +144,7 @@ public class JoglVersion extends JogampVersion { } sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline()); - sb.append(device.getClass().getSimpleName()).append("[type ") - .append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline()); + sb.append(device.toString()).append(':').append(Platform.getNewline()); if( withAvailabilityInfo ) { GLProfile.glAvailabilityToString(device, sb, "\t", 1); } diff --git a/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java index 5f59f7e6d..6af7bcda4 100644 --- a/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java @@ -157,12 +157,12 @@ import jogamp.opengl.awt.AWTTilePainter; * <li><pre>sun.awt.noerasebackground=true</pre></li> * </ul> * - * <p> - * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a> + * <h5><a name="contextSharing">OpenGL Context Sharing</a></h5> + * * To share a {@link GLContext} see the following note in the documentation overview: * <a href="../../../../overview-summary.html#SHARING">context sharing</a> * as well as {@link GLSharedContextSetter}. - * </p> + * */ @SuppressWarnings("serial") diff --git a/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java b/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java index 5bf4c106c..20dc71958 100644 --- a/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/com/jogamp/opengl/awt/GLJPanel.java @@ -98,6 +98,7 @@ import jogamp.opengl.awt.AWTTilePainter; import jogamp.opengl.awt.Java2D; import jogamp.opengl.util.glsl.GLSLTextureRaster; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.common.util.locks.LockFactory; @@ -395,7 +396,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing */ public final boolean initializeBackend(final boolean offthread) { if( offthread ) { - new Thread(getThreadName()+"-GLJPanel_Init") { + new InterruptSource.Thread(null, null, getThreadName()+"-GLJPanel_Init") { public void run() { if( !isInitialized ) { initializeBackendImpl(); diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java index 8f033a8b8..5e6338b5c 100644 --- a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java @@ -47,7 +47,7 @@ public final class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInf public Object run() { Platform.initSingleton(); - if(TempJarCache.isInitialized()) { + if( TempJarCache.isInitialized(true) ) { // only: jogl-cg.jar -> jogl-cg-natives-<os.and.arch>.jar [atomic JAR files only] JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { jogamp.opengl.cg.CgPackagePlaceholder.class }, null); } @@ -99,6 +99,16 @@ public final class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInf } @Override + public final boolean searchToolLibInSystemPath() { + return true; + } + + @Override + public final boolean searchToolLibSystemPathFirst() { + return true; + } + + @Override public final List<List<String>> getToolLibNames() { final List<List<String>> libsList = new ArrayList<List<String>>(); final List<String> libsCg = new ArrayList<String>(); diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java index 7f630f9d5..73244cb13 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.math; import java.nio.FloatBuffer; +import java.util.Locale; import com.jogamp.opengl.GLException; @@ -1738,7 +1739,6 @@ public final class FloatUtil { * @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 - * @deprecated use on of the float[] variants */ public static void multMatrix(final FloatBuffer a, final FloatBuffer b, final float[] d) { final int a_off = a.position(); @@ -1758,7 +1758,6 @@ public final class FloatUtil { * Multiply matrix: [a] = [a] x [b] * @param a 4x4 matrix in column-major order (also result) * @param b 4x4 matrix in column-major order - * @deprecated use on of the float[] variants */ public static void multMatrix(final FloatBuffer a, final FloatBuffer b) { final int a_off = a.position(); @@ -1831,7 +1830,6 @@ public final class FloatUtil { * @param m_in 4x4 matrix in column-major order * @param v_in 4-component column-vector * @param v_out m_in * v_in - * @deprecated use on of the float[] variants */ public static void multMatrixVec(final FloatBuffer m_in, final float[] v_in, final float[] v_out) { final int m_in_off = m_in.position(); @@ -1900,7 +1898,6 @@ public final class FloatUtil { * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL) * @param row row number to print * @return matrix row string representation - * @deprecated use on of the float[] variants */ public static StringBuilder matrixRowToString(StringBuilder sb, final String f, final FloatBuffer a, final int aOffset, @@ -1911,11 +1908,11 @@ public final class FloatUtil { final int a0 = aOffset + a.position(); if(rowMajorOrder) { for(int c=0; c<columns; c++) { - sb.append( String.format( f+" ", a.get( a0 + row*columns + c ) ) ); + sb.append( String.format((Locale)null, f+" ", a.get( a0 + row*columns + c ) ) ); } } else { for(int r=0; r<columns; r++) { - sb.append( String.format( f+" ", a.get( a0 + row + r*rows ) ) ); + sb.append( String.format((Locale)null, f+" ", a.get( a0 + row + r*rows ) ) ); } } return sb; @@ -1939,11 +1936,11 @@ public final class FloatUtil { } if(rowMajorOrder) { for(int c=0; c<columns; c++) { - sb.append( String.format( f+" ", a[ aOffset + row*columns + c ] ) ); + sb.append( String.format((Locale)null, f+" ", a[ aOffset + row*columns + c ] ) ); } } else { for(int r=0; r<columns; r++) { - sb.append( String.format( f+" ", a[ aOffset + row + r*rows ] ) ); + sb.append( String.format((Locale)null, f+" ", a[ aOffset + row + r*rows ] ) ); } } return sb; @@ -1959,7 +1956,6 @@ public final class FloatUtil { * @param columns * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL) * @return matrix string representation - * @deprecated use on of the float[] variants */ public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, final FloatBuffer a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) { @@ -2012,7 +2008,6 @@ public final class FloatUtil { * @param columns * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL) * @return side by side representation - * @deprecated use on of the float[] variants */ public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, final FloatBuffer a, final int aOffset, final FloatBuffer b, final int bOffset, diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 58b5bbcb9..5e90c4035 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -62,6 +62,7 @@ import jogamp.opengl.GLDrawableHelper; import jogamp.opengl.GLDrawableImpl; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Canvas; @@ -113,13 +114,12 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS private final GLCapabilitiesImmutable capsRequested; private final GLCapabilitiesChooser capsChooser; - private volatile Rectangle clientArea; + private volatile Rectangle clientAreaPixels, clientAreaWindow; private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access private volatile GLContextImpl context; // volatile: avoid locking for read-only access /* Native window surface */ private final boolean useX11GTK; - private volatile long gdkWindow; // either GDK child window .. private volatile long x11Window; // .. or X11 child window (for GL rendering) private final AbstractGraphicsScreen screen; @@ -153,7 +153,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS @Override public void run() { if (sendReshape) { - helper.reshape(GLCanvas.this, 0, 0, clientArea.width, clientArea.height); + helper.reshape(GLCanvas.this, 0, 0, clientAreaPixels.width, clientAreaPixels.height); sendReshape = false; } helper.display(GLCanvas.this); @@ -242,9 +242,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS if( 0 != x11Window) { SWTAccessor.destroyX11Window(screen.getDevice(), x11Window); x11Window = 0; - } else if( 0 != gdkWindow) { - SWTAccessor.destroyGDKWindow(gdkWindow); - gdkWindow = 0; } screen.getDevice().close(); } catch (final Throwable re) { @@ -348,7 +345,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS SWTAccessor.setRealized(this, true); - clientArea = GLCanvas.this.getClientArea(); + clientAreaPixels = SWTAccessor.getClientAreaInPixels(this); + clientAreaWindow = getClientArea(); /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). * Note: SWT is owner of the native handle, hence closing operation will be a NOP. */ @@ -376,11 +374,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS this.capsChooser = capsChooser; // post create .. when ready - gdkWindow = 0; x11Window = 0; drawable = null; context = null; + // Bug 1362 fix or workaround: Seems SWT/GTK3 at least performs lazy initialization + // Minimal action required: setBackground of the parent canvas before reparenting! + setBackground(new Color(parent.getDisplay(), 255, 255, 255)); + final Listener listener = new Listener () { @Override public void handleEvent (final Event event) { @@ -421,17 +422,17 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS @Override public final int getSurfaceWidth(final ProxySurface s) { - return clientArea.width; + return clientAreaPixels.width; } @Override public final int getSurfaceHeight(final ProxySurface s) { - return clientArea.height; + return clientAreaPixels.height; } @Override public String toString() { - return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]"; + return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientAreaPixels.width+"x"+clientAreaPixels.height+" [pixel], "+clientAreaWindow.width+"x"+clientAreaWindow.height+" [win]]"; } /** @@ -447,25 +448,27 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS }; protected final void updateSizeCheck() { - final Rectangle oClientArea = clientArea; - final Rectangle nClientArea = GLCanvas.this.getClientArea(); - if ( nClientArea != null && - ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + final Rectangle oClientAreaPixels = clientAreaPixels; + final Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this); + + if ( nClientAreaPixels != null && + ( nClientAreaPixels.width != oClientAreaPixels.width || nClientAreaPixels.height != oClientAreaPixels.height ) ) { - clientArea = nClientArea; // write back new value + clientAreaPixels = nClientAreaPixels; // write back new value + clientAreaWindow = getClientArea(); final GLDrawableImpl _drawable = drawable; final boolean drawableOK = null != _drawable && _drawable.isRealized(); if(DEBUG) { final long dh = drawableOK ? _drawable.getHandle() : 0; - System.err.println(getThreadName()+": GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - drawableHandle "+toHexString(dh)); + System.err.println(getThreadName()+": GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+" - drawableHandle "+toHexString(dh)); } if( drawableOK ) { if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { final RecursiveLock _lock = lock; _lock.lock(); try { - final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height); + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientAreaPixels.width, nClientAreaPixels.height); if(_drawable != _drawableNew) { // write back drawable = _drawableNew; @@ -476,9 +479,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS } } if(0 != x11Window) { - SWTAccessor.resizeX11Window(screen.getDevice(), clientArea, x11Window); - } else if(0 != gdkWindow) { - SWTAccessor.resizeGDKWindow(clientArea, gdkWindow); + SWTAccessor.resizeX11Window(screen.getDevice(), clientAreaPixels, x11Window); } sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock } @@ -548,7 +549,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS return res; } private final void createDrawableImpl() { - final Rectangle nClientArea = clientArea; + final Rectangle nClientArea = clientAreaPixels; if(0 >= nClientArea.width || 0 >= nClientArea.height) { if(DEBUG) { System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": drawable could not be created: size < 0x0"); @@ -573,7 +574,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS if( VisualIDHolder.VID_UNDEFINED != visualID ) { // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height); // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow); - x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientArea.width, clientArea.height); + x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientAreaPixels.width, clientAreaPixels.height); nativeWindowHandle = x11Window; } else { throw new GLException("Could not choose valid visualID: "+toHexString(visualID)+", "+this); @@ -669,12 +670,12 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS @Override public int getSurfaceWidth() { - return clientArea.width; + return clientAreaPixels.width; } @Override public int getSurfaceHeight() { - return clientArea.height; + return clientAreaPixels.height; } @Override diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java index 76d64963f..9e9cc8e44 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java @@ -56,7 +56,7 @@ import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException; class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl { // For efficient rendering of Swing components, in particular when // they overlap one another - private final List<JComponent> lightweights = new ArrayList<JComponent>(); + private final List<JComponent> lightweights = new ArrayList<JComponent>(); private final Map<RepaintManager,RepaintManager> repaintManagers = new IdentityHashMap<RepaintManager,RepaintManager>(); private final Map<JComponent,Rectangle> dirtyRegions = new IdentityHashMap<JComponent,Rectangle>(); @@ -64,34 +64,40 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl { public void display(final ArrayList<GLAutoDrawable> drawables, final boolean ignoreExceptions, final boolean printExceptions) throws UncaughtAnimatorException { - for (int i=0; i<drawables.size(); i++) { - final GLAutoDrawable drawable = drawables.get(i); - if (drawable instanceof JComponent) { - // Lightweight components need a more efficient drawing - // scheme than simply forcing repainting of each one in - // turn since drawing one can force another one to be - // drawn in turn - lightweights.add((JComponent)drawable); - } else { - try { + boolean hasException = false; + for (int i=0; !hasException && i<drawables.size(); i++) { + GLAutoDrawable drawable = null; + boolean catch1 = true; + try { + drawable = drawables.get(i); + catch1 = false; + if (drawable instanceof JComponent) { + // Lightweight components need a more efficient drawing + // scheme than simply forcing repainting of each one in + // turn since drawing one can force another one to be + // drawn in turn + lightweights.add((JComponent)drawable); + } else { drawable.display(); - } catch (final Throwable t) { - if (ignoreExceptions) { - if (printExceptions) { - t.printStackTrace(); - } - } else { - throw new UncaughtAnimatorException(drawable, t); + } + } catch (final Throwable t) { + if( catch1 && t instanceof IndexOutOfBoundsException ) { + // concurrent pulling of GLAutoDrawables .. + hasException = true; + } else if ( ignoreExceptions ) { + if ( printExceptions ) { + t.printStackTrace(); } + } else { + throw new UncaughtAnimatorException(drawable, t); } } } - if (lightweights.size() > 0) { try { SwingUtilities.invokeAndWait(drawWithRepaintManagerRunnable); - } catch (final Exception e) { - e.printStackTrace(); + } catch (final Throwable t) { + t.printStackTrace(); } lightweights.clear(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index 066709316..10b0b6b5a 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -40,6 +40,9 @@ package com.jogamp.opengl.util; +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.SourcedInterruptedException; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLException; @@ -174,6 +177,9 @@ public class Animator extends AnimatorBase { try { Animator.this.wait(); } catch (final InterruptedException e) { + caughtException = new UncaughtAnimatorException(null, SourcedInterruptedException.wrap(e)); + stopIssued = true; + break; // end pause loop } if (wasPaused) { // resume from pause -> reset counter @@ -209,8 +215,7 @@ public class Animator extends AnimatorBase { } } catch(final ThreadDeath td) { if(DEBUG) { - System.err.println("Animator caught: "+td.getClass().getName()+": "+td.getMessage()); - td.printStackTrace(); + ExceptionUtils.dumpThrowable("", td); } caughtThreadDeath = td; } @@ -222,8 +227,7 @@ public class Animator extends AnimatorBase { if( null == caughtException ) { caughtException = dre; } else { - System.err.println("Animator.setExclusiveContextThread: caught: "+dre.getMessage()); - dre.printStackTrace(); + ExceptionUtils.dumpThrowable("(setExclusiveContextThread)", dre); } } } @@ -233,8 +237,7 @@ public class Animator extends AnimatorBase { if(DEBUG) { System.err.println("Animator stop on " + animThread.getName() + ": " + toString()); if( null != caughtException ) { - System.err.println("Animator caught: "+caughtException.getMessage()); - caughtException.printStackTrace(); + ExceptionUtils.dumpThrowable("", caughtException); } } stopIssued = false; @@ -291,13 +294,7 @@ public class Animator extends AnimatorBase { runnable = new MainLoop(); } fpsCounter.resetFPSCounter(); - final String threadName = getThreadName()+"-"+baseName; - Thread thread; - if(null==threadGroup) { - thread = new Thread(runnable, threadName); - } else { - thread = new Thread(threadGroup, runnable, threadName); - } + final Thread thread = new InterruptSource.Thread(threadGroup, runnable, getThreadName()+"-"+baseName); thread.setDaemon(false); // force to be non daemon, regardless of parent thread if(DEBUG) { final Thread ct = Thread.currentThread(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java index aafdf63f8..c2da68cd9 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java @@ -33,6 +33,7 @@ import jogamp.opengl.FPSCounterImpl; import java.io.PrintStream; import java.util.ArrayList; +import java.util.Locale; import com.jogamp.opengl.GLAnimatorControl; import com.jogamp.opengl.GLAutoDrawable; @@ -40,6 +41,7 @@ import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptedRuntimeException; /** * Base implementation of GLAnimatorControl<br> @@ -150,7 +152,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { */ protected final synchronized void initImpl(final boolean force) { if( force || null == impl ) { - final String seqSuffix = String.format("#%02d", seqInstanceNumber++); + final String seqSuffix = String.format((Locale)null, "#%02d", seqInstanceNumber++); if( useAWTAnimatorImpl( modeBits ) ) { try { impl = (AnimatorImpl) awtAnimatorImplClazz.newInstance(); @@ -596,7 +598,9 @@ public abstract class AnimatorBase implements GLAnimatorControl { notifyAll(); try { wait(pollPeriod); - } catch (final InterruptedException ie) { } + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } remaining -= System.currentTimeMillis() - t1 ; nok = waitCondition.eval(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java index 6cded29d9..d8c8465d9 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java @@ -48,12 +48,19 @@ class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl { public void display(final ArrayList<GLAutoDrawable> drawables, final boolean ignoreExceptions, final boolean printExceptions) throws UncaughtAnimatorException { - for (int i=0; i<drawables.size(); i++) { - final GLAutoDrawable drawable = drawables.get(i); + boolean hasException = false; + for (int i=0; !hasException && i<drawables.size(); i++) { + boolean catch1 = true; + GLAutoDrawable drawable = null; try { + drawable = drawables.get(i); + catch1 = false; drawable.display(); } catch (final Throwable t) { - if (ignoreExceptions) { + if( catch1 && t instanceof IndexOutOfBoundsException ) { + // concurrent pulling of GLAutoDrawables .. + hasException = true; + } else if (ignoreExceptions) { if (printExceptions) { t.printStackTrace(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java index c82f63898..0e3497bd4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java @@ -262,6 +262,8 @@ public class GLPixelBuffer { case GL.GL_UNSIGNED_SHORT_5_5_5_1: pixFmt = PixelFormat.ABGR1555; break; + case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV: + // fall through intended case GL.GL_UNSIGNED_BYTE: pixFmt = PixelFormat.RGBA8888; break; @@ -280,6 +282,8 @@ public class GLPixelBuffer { case GL2GL3.GL_UNSIGNED_INT_8_8_8_8: pixFmt = PixelFormat.ARGB8888; break; + case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV: + // fall through intended case GL.GL_UNSIGNED_BYTE: pixFmt = PixelFormat.BGRA8888; break; diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java index cc3462f99..3fa856a47 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java @@ -245,8 +245,8 @@ public class GLReadBufferUtil { readTexture.updateImage(gl, readTextureData); } else { readTexture.updateSubImage(gl, readTextureData, 0, - 0, 0, // src offset - 0, 0, // dst offset + inX, inY, // dst offset + 0, 0, // src offset width, height); } readPixelBuffer.rewind(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java index 196acf9ab..5383f91be 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -920,7 +920,6 @@ public final class PMVMatrix implements GLMatrixFunc { * or {@link #glGetFrustum() Frustum get} methods. * </p> * - * @deprecated Function is exposed for debugging purposes only. * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW * @see #DIRTY_FRUSTUM @@ -941,7 +940,6 @@ public final class PMVMatrix implements GLMatrixFunc { * or {@link #glGetFrustum() Frustum get} methods. * </p> * - * @deprecated Function is exposed for debugging purposes only. * @see #clearAllUpdateRequests() * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java index f28774afa..1dded7882 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java @@ -78,7 +78,8 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect { public static PNGPixelRect read(final InputStream in, final PixelFormat ddestFmt, final boolean destDirectBuffer, final int destMinStrideInBytes, final boolean destIsGLOriented) throws IOException { - final PngReader pngr = new PngReader(new BufferedInputStream(in), null); + final BufferedInputStream bin = (in instanceof BufferedInputStream) ? (BufferedInputStream)in : new BufferedInputStream(in); + final PngReader pngr = new PngReader(bin, null); final ImageInfo imgInfo = pngr.imgInfo; final PngChunkPLTE plte = pngr.getMetadata().getPLTE(); final PngChunkTRNS trns = pngr.getMetadata().getTRNS(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java index 662cf74b7..c2de32372 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java @@ -205,22 +205,29 @@ public interface GLMediaPlayer extends TextureSequence { * {@link Uri#scheme Uri scheme} name {@value} for camera input. E.g. <code>camera:/0</code> * for the 1st camera device. * <p> - * The {@link Uri#path Uri path} is being used to identify the camera (<i>ID</i>), + * The {@link Uri#path Uri path} is being used to identify the camera (<i><id></i>), * where the root fwd-slash is being cut-off. * </p> * <p> - * The <i>ID</i> is usually an integer value indexing the camera + * The <i><id></i> is usually an integer value indexing the camera * ranging from [0..<i>max-number</i>]. * </p> * <p> + * The <i><somewhere></i> is usually empty, since it would imply a networking camera protocol. + * </p> + * <p> * The {@link Uri#query Uri query} is used to pass options to the camera * using <i>;</i> as the separator. The latter avoids trouble w/ escaping. * </p> * <pre> - * camera:/<id> - * camera://somewhere/<id> - * camera://somewhere/<id>?width=640;height=480;rate=15 - * camera://somewhere/<id>?size=640x480;rate=15 + * camera:/<id> + * camera:/<id>?width=640;height=480;rate=15 + * camera:/<id>?size=640x480;rate=15 + * camera://<somewhere>/<id> + * camera://<somewhere>/<id>?width=640;height=480;rate=15 + * camera://<somewhere>/<id>?size=640x480;rate=15 + * camera:///<id>?width=640;height=480;rate=15 + * camera:///<id>?size=640x480;rate=15 * </pre> * <pre> * Uri: [scheme:][//authority][path][?query][#fragment] 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 e6f5aaa2e..38bac06cc 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java @@ -40,6 +40,7 @@ package com.jogamp.opengl.util.awt; import com.jogamp.common.nio.Buffers; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.*; @@ -915,7 +916,7 @@ public class TextRenderer { // Run this on another thread than the AWT event queue to // make sure the call to Animator.stop() completes before // exiting - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { @Override public void run() { anim.stop(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java index e5ef3b268..532db3a7a 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java @@ -148,9 +148,9 @@ public class ShaderCode { switch (type) { case GL2ES2.GL_VERTEX_SHADER: case GL2ES2.GL_FRAGMENT_SHADER: - case GL3.GL_GEOMETRY_SHADER: - case GL3.GL_TESS_CONTROL_SHADER: - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: case GL3ES3.GL_COMPUTE_SHADER: break; default: @@ -179,9 +179,9 @@ public class ShaderCode { switch (type) { case GL2ES2.GL_VERTEX_SHADER: case GL2ES2.GL_FRAGMENT_SHADER: - case GL3.GL_GEOMETRY_SHADER: - case GL3.GL_TESS_CONTROL_SHADER: - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: case GL3ES3.GL_COMPUTE_SHADER: break; default: @@ -386,11 +386,11 @@ public class ShaderCode { return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE; case GL2ES2.GL_FRAGMENT_SHADER: return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE; - case GL3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: return binary?SUFFIX_GEOMETRY_BINARY:SUFFIX_GEOMETRY_SOURCE; - case GL3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: return binary?SUFFIX_TESS_CONTROL_BINARY:SUFFIX_TESS_CONTROL_SOURCE; - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: return binary?SUFFIX_TESS_EVALUATION_BINARY:SUFFIX_TESS_EVALUATION_SOURCE; case GL3ES3.GL_COMPUTE_SHADER: return binary?SUFFIX_COMPUTE_BINARY:SUFFIX_COMPUTE_SOURCE; @@ -785,11 +785,11 @@ public class ShaderCode { return "VERTEX_SHADER"; case GL2ES2.GL_FRAGMENT_SHADER: return "FRAGMENT_SHADER"; - case GL3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: return "GEOMETRY_SHADER"; - case GL3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: return "TESS_CONTROL_SHADER"; - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: return "TESS_EVALUATION_SHADER"; case GL3ES3.GL_COMPUTE_SHADER: return "COMPUTE_SHADER"; @@ -1098,7 +1098,15 @@ public class ShaderCode { while ((line = reader.readLine()) != null) { lineno++; if (line.startsWith("#include ")) { - final String includeFile = line.substring(9).trim(); + final String includeFile; + { + String s = line.substring(9).trim(); + // Bug 1283: Remove shader include filename quotes if exists at start and end only + if( s.startsWith("\"") && s.endsWith("\"")) { + s = s.substring(1, s.length()-1); + } + includeFile = s; + } URLConnection nextConn = null; // Try relative of current shader location @@ -1106,7 +1114,7 @@ public class ShaderCode { nextConn = IOUtil.openURL(relUri.toURL(), "ShaderCode.relativeOf "); if (nextConn == null) { // Try relative of class and absolute - nextConn = IOUtil.getResource(context, includeFile); + nextConn = IOUtil.getResource(includeFile, context.getClassLoader(), context); } if (nextConn == null) { // Fail @@ -1158,7 +1166,7 @@ public class ShaderCode { * @see IOUtil#getResource(Class, String) */ public static CharSequence readShaderSource(final Class<?> context, final String path, final boolean mutableStringBuilder) throws IOException { - final URLConnection conn = IOUtil.getResource(context, path); + final URLConnection conn = IOUtil.getResource(path, context.getClassLoader(), context); if (conn == null) { return null; } @@ -1204,7 +1212,7 @@ public class ShaderCode { * @see IOUtil#getResource(Class, String) */ public static ByteBuffer readShaderBinary(final Class<?> context, final String path) throws IOException { - final URLConnection conn = IOUtil.getResource(context, path); + final URLConnection conn = IOUtil.getResource(path, context.getClassLoader(), context); if (conn == null) { return null; } @@ -1330,9 +1338,9 @@ public class ShaderCode { // GLSL [ 1.30 .. 1.50 [ needs at least fragement float default precision! switch ( shaderType ) { case GL2ES2.GL_VERTEX_SHADER: - case GL3.GL_GEOMETRY_SHADER: - case GL3.GL_TESS_CONTROL_SHADER: - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: defaultPrecision = gl3_default_precision_vp_gp; break; case GL2ES2.GL_FRAGMENT_SHADER: defaultPrecision = gl3_default_precision_fp; break; diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java index f5dec1cab..376afb8ce 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java @@ -52,7 +52,7 @@ public abstract class CompileShader { final String justName = basename(resourceName); outName = justName.substring(0, justName.length() - suffixLen) + ShaderCode.getFileSuffix(true, type); - final URL resourceURL = IOUtil.getResource(null, resourceName).getURL(); + final URL resourceURL = IOUtil.getResource(resourceName, this.getClass().getClassLoader(), null).getURL(); final String dirName = dirname(resourceURL.getPath()); outName = dirName + File.separator + "bin" + File.separator + @@ -64,7 +64,7 @@ public abstract class CompileShader { public void processOneShader(final String resourceName, final String outName, final int type) throws IOException, UnsupportedEncodingException, InterruptedException { - final URL resourceURL = IOUtil.getResource(null, resourceName).getURL(); + final URL resourceURL = IOUtil.getResource(resourceName, this.getClass().getClassLoader(), null).getURL(); final String dirName = dirname(resourceURL.getPath()); final CharSequence shader = ShaderCode.readShaderSource(null, resourceName, false); diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageIOUtil.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageIOUtil.java deleted file mode 100644 index 12cb13b10..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageIOUtil.java +++ /dev/null @@ -1,445 +0,0 @@ -/** - * Copyright 2014 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.util.texture; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Utilities for image input and output - * - */ -public class ImageIOUtil { - - /** - * Determines the file suffix (i.e the image format) of the given InputStream. The given - * InputStream must return true from markSupported() and support a minimum of 32 bytes - * of read-ahead. - * - * @param stream stream to check - * @return the file suffix if any, otherwise <code>null</code> - * @throws java.io.IOException if an I/O exception occurred - */ - public static String getFileSuffix(InputStream stream) throws IOException { - if (stream == null) { - throw new IOException("Stream was null"); - } - if (!(stream instanceof BufferedInputStream)) { - stream = new BufferedInputStream(stream); - } - if (!stream.markSupported()) { - throw new IOException("Can not get non-destructively the image format"); - } - if (stream.available() < 32) { - throw new IOException("Not enough bytes to read in order to get the image format"); - } - try { - stream.mark(32); - final byte[] b = new byte[32]; - stream.read(b); - return getFileSuffix(b); - } finally { - stream.reset(); - } - - } - - /** - * Determines the file suffix (i.e the image format) of the given bytes from the header - * of a file. - * - * @param stream stream to check - * @return the file suffix if any, otherwise <code>null</code> - * @throws java.io.IOException if an I/O exception occurred - */ - public static String getFileSuffix(final byte[] b) { - /** - * http://www.faqs.org/faqs/jpeg-faq/part1/ - * http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=54989 - */ - if ( (b[0] == 0xff && b[1] == 0xd8 /* && b[2] == 0xff */) || - (b[0] == 0x4A && b[1] == 0x46 && b[2] == 0x49 && b[3] == 0x46)/* JFIF */ || - (b[0] == 0x45 && b[1] == 0x78 && b[2] == 0x69 && b[3] == 0x66)/* EXIF */) { - return TextureIO.JPG; - } - /** - * http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html#R.PNG-file-signature - */ - if (b[0] == 0x89 && b[1] == 0x50 && b[2] == 0x4E && b[3] == 0x47 && /* 'P' 'N' 'G', ascii code */ - b[4] == 0x0D && b[5] == 0x0A && b[6] == 0x1A && b[7] == 0x0A) { - return TextureIO.PNG; - } - /** - * Apple Icon Image - * - * 'i' 'c' 'n' 's' ascii code - */ - if (b[0] == 0x69 && b[1] == 0x63 && b[2] == 0x6E && b[3] == 0x73) { - return "icns"; - } - /** - * http://www.w3.org/Graphics/GIF/spec-gif87a.txt http://www.w3.org/Graphics/GIF/spec-gif89a.txt - * - * GIF87A or GIF89A ascii code - */ - if (b[0] == 0x47 && b[1] == 0x49 && b[2] == 0x46 && b[3] == 0x38 && (b[4] == 0x37 || b[4] == 0x39) && - b[5] == 0x61) { - return TextureIO.GIF; - } - /** - * http://www.fileformat.info/format/bmp/spec/e27073c25463436f8a64fa789c886d9c/view.htm - * - * BM ascii code - */ - if (b[0] == 0x42 && b[1] == 0x4d) { - return "bmp"; - } - if (b[0] == 0x3A && b[1] == 0xDE && b[2] == 0x68 && b[3] == 0xB1) { - return "dcx"; - } - if (b[0] == 0x0A && b[1] == 0x05 && b[2] == 0x01 && b[3] == 0x08) { - return "pcx"; - } - /** - * http://netpbm.sourceforge.net/doc/ppm.html - */ - if (b[0] == 0x50 && (b[1] == 0x33 /* plain */|| b[1] == 0x36)) { - return TextureIO.PPM; - } - if (b[0] == 0x38 && b[1] == 0x42 && b[2] == 0x50 && b[3] == 0x53 && b[4] == 0x00 && b[5] == 0x01 && - b[6] == 0x00 && b[7] == 0x00 && b[8] == 0x00 && b[9] == 0x00) { - // Adobe PhotoShop - return "psd"; - } - /** - * http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf - * - * intentionally detects only the little endian tiff images ("II" in the spec) - */ - if (b[0] == 0x49 && b[1] == 0x49 && b[2] == 0x2A && b[3] == 0x00) { - return TextureIO.TIFF; - } - /** - * http://paulbourke.net/dataformats/sgirgb/sgiversion.html - * - * "474 saved as a short" 474 = 0x01DA - */ - if (b[0] == 0x01 && b[1] == 0xDA /* && b[2] == 0x01 && b[3] == 0x01 && b[4] == 0x00 && b[5] == 0x03 */) { - return TextureIO.SGI_RGB; - } - /** - * 'D' 'D' 'S' ' ' ascii code - */ - if (b[0] == 0x44 && b[1] == 0x44 && b[2] == 0x53 && b[3] == 0x20) { - return TextureIO.DDS; - } - /** - * http://netpbm.sourceforge.net/doc/pam.html - */ - if (b[0] == 0x50 && b[1] == 0x37) { - return TextureIO.PAM; - } - /** - * http://netpbm.sourceforge.net/doc/pgm.html - */ - if (b[0] == 0x50 && (b[1] == 0x32 /* plain */|| b[1] == 0x35)) { - return "pgm"; - } - /** - * http://netpbm.sourceforge.net/doc/pbm.html - */ - if (b[0] == 0x50 && (b[1] == 0x31 /* plain */|| b[1] == 0x34)) { - return "pbm"; - } - if (b[0] == 0x3D && b[1] == 0x02) { - return "3d2"; - } - if (b[0] == 0x33 && b[1] == 0x44 && b[2] == 0x4D && b[3] == 0x46) { - return "3dmf"; - } - if (b[0] == 0x2A && b[1] == 0x2A && b[2] == 0x54 && b[3] == 0x49 && b[4] == 0x39 && b[5] == 0x32 && - b[6] == 0x2A && b[7] == 0x2A && b[8] == 0x01 && b[9] == 0x00 && b[10] == 0x58 && - b[11] == 0x6E && b[12] == 0x56 && b[13] == 0x69) { - return "92i"; - } - if (b[0] == 0x41 && b[1] == 0x4D && b[2] == 0x46 && b[3] == 0x46) { - return "amff"; - } - if (b[0] == 0x4A && b[1] == 0x47 && (b[2] == 0x03 || b[2] == 0x04) && b[3] == 0x0E && b[4] == 0x00 && - b[5] == 0x00 && b[6] == 0x00) { - return "art"; - } - if (b[0] == 0x73 && b[1] == 0x72 && b[2] == 0x63 && b[3] == 0x64 && b[4] == 0x6F && b[5] == 0x63 && - b[6] == 0x69 && b[7] == 0x64 && b[8] == 0x3A) { - return "cals"; - } - if (b[0] == 0x07 && b[1] == 0x20 && b[2] == 0x4D && b[3] == 0x4D) { - return "cam"; - } - if (b[0] == 0x20 && b[1] == 0x77 && b[2] == 0x00 && b[3] == 0x02) { - return "cbd"; - } - if (b[0] == 0x45 && b[1] == 0x59 && b[2] == 0x45 && b[3] == 0x53) { - return "ce2"; - } - if (b[0] == 0x80 && b[1] == 0x2A && b[2] == 0x5F && b[3] == 0xD7 && b[4] == 0x00 && b[5] == 0x00 && - b[6] == 0x08 && b[7] == 0x00 && b[8] == 0x00 && b[9] == 0x00 && b[10] == 0x04 && - b[11] == 0x00 && b[12] == 0x00 && b[13] == 0x00) { - return "cin"; - } - if (b[0] == 0x43 && b[1] == 0x61 && b[2] == 0x6C && b[3] == 0x69 && b[4] == 0x67 && b[5] == 0x61 && - b[6] == 0x72 && b[7] == 0x69) { - return "cob"; - } - if (b[0] == 0x43 && b[1] == 0x50 && b[2] == 0x54 && b[3] == 0x46 && b[4] == 0x49 && b[5] == 0x4C && - b[6] == 0x45) { - return "cpt"; - } - if (b[0] == 0x43 && b[1] == 0x41 && b[2] == 0x4C && b[3] == 0x41 && b[4] == 0x4D && b[5] == 0x55 && - b[6] == 0x53 && b[7] == 0x43 && b[8] == 0x56 && b[9] == 0x47) { - return "cvg"; - } - if (b[0] == 0x56 && b[1] == 0x69 && b[2] == 0x73 && b[3] == 0x74 && b[4] == 0x61 && b[5] == 0x20 && - b[6] == 0x44 && b[7] == 0x45 && b[8] == 0x4D && b[9] == 0x20 && b[10] == 0x46 && - b[11] == 0x69 && b[12] == 0x6C && b[13] == 0x65) { - return "dem"; - } - if (b[0] == 0x42 && b[1] == 0x4D && b[2] == 0x36) { - return "dib"; - } - if (b[0] == 0x53 && b[1] == 0x44 && b[2] == 0x50 && b[3] == 0x58) { - return "dpx"; - } - if (b[0] == 0x01 && b[1] == 0xFF && b[2] == 0x02 && b[3] == 0x04 && b[4] == 0x03 && b[5] == 0x02) { - return "drw"; - } - if (b[0] == 0x41 && b[1] == 0x43 && b[2] == 0x31 && b[3] == 0x30) { - return "dwg"; - } - if (b[0] == 0x65 && b[1] == 0x02 && b[2] == 0x01 && b[3] == 0x02) { - return "ecw"; - } - if (b[0] == 0x01 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x00 && b[4] == 0x58 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x00) { - return "emf"; - } - if (b[0] == 0xD0 && b[1] == 0xCF && b[2] == 0x11 && b[3] == 0xE0 && b[4] == 0xA1 && b[5] == 0xB1 && - b[6] == 0x1A && b[7] == 0xE1 && b[8] == 0x00) { - return "fpx"; - } - if (b[0] == 0x53 && b[1] == 0x49 && b[2] == 0x4D && b[3] == 0x50 && b[4] == 0x4C && b[5] == 0x45 && - b[6] == 0x20 && b[7] == 0x20 && b[8] == 0x3D) { - return "fts"; - } - if (b[0] == 0x48 && b[1] == 0x50 && b[2] == 0x48 && b[3] == 0x50 && b[4] == 0x34 && b[5] == 0x38 && - b[6] == 0x2D && b[7] == 0x45 && b[8] == 0x1E && b[9] == 0x2B) { - return "gro"; - } - if (b[0] == 0x6E && b[1] == 0x63 && b[2] == 0x6F && b[3] == 0x6C && b[4] == 0x73) { - return "hdr"; - } - if (b[0] == 0x35 && b[1] == 0x4B && b[2] == 0x50 && b[3] == 0x35 && b[4] == 0x31 && b[5] == 0x5D && - b[6] == 0x2A && b[7] == 0x67 && b[8] == 0x72 && b[9] == 0x72 && b[10] == 0x80 && - b[11] == 0x83 && b[12] == 0x85 && b[13] == 0x63) { - return "hru"; - } - if (b[0] == 0xEB && b[1] == 0x3C && b[2] == 0x90 && b[3] == 0x2A) { - return "img"; - } - if (b[0] == 0x65 && b[1] == 0x6C && b[2] == 0x6D && b[3] == 0x6F) { - return "infini-d"; - } - if (b[0] == 0x49 && b[1] == 0x57 && b[2] == 0x43 && b[3] == 0x01) { - return "iwc"; - } - if (b[0] == 0x80 && b[1] == 0x3E && b[2] == 0x44 && b[3] == 0x53 && b[4] == 0x43 && b[5] == 0x49 && - b[6] == 0x4D) { - return "j6i"; - } - if (b[0] == 0x4A && b[1] == 0x49 && b[2] == 0x46 && b[3] == 0x39 && b[4] == 0x39 && b[5] == 0x61) { - return "jif"; - } - if (b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x0C && b[4] == 0x6A && b[5] == 0x50 && - b[6] == 0x20 && b[7] == 0x20 && b[8] == 0x0D && b[9] == 0x0A && b[10] == 0x87 && - b[11] == 0x0A) { - return "jp2"; - } - if (b[0] == 0x4D && b[1] == 0x4D && b[2] == 0x00 && b[3] == 0x2A) { - return "kdc"; - } - if (b[0] == 0x36 && b[1] == 0x34 && b[2] == 0x4C && b[3] == 0x41 && b[4] == 0x4E && b[5] == 0x20 && - b[6] == 0x49 && b[7] == 0x44 && b[8] == 0x42 && b[9] == 0x4C && b[10] == 0x4F && - b[11] == 0x43 && b[12] == 0x4B) { - return "l64"; - } - if (b[0] == 0x46 && b[1] == 0x4F && b[2] == 0x52 && b[3] == 0x4D) { - return "lbm"; - } - if (b[0] == 0x49 && b[1] == 0x49 && b[2] == 0x2A && b[3] == 0x00 && b[4] == 0x08 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x00 && b[8] == 0x0E && b[9] == 0x00 && b[10] == 0x00 && - b[11] == 0x01 && b[12] == 0x04 && b[13] == 0x00) { - return "ldf"; - } - if (b[0] == 0x57 && b[1] == 0x56 && b[2] == 0x02 && b[3] == 0x00 && b[4] == 0x47 && b[5] == 0x45 && - b[6] == 0x00 && b[7] == 0x0E) { - return "lwf"; - } - if (b[0] == 0x37 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x10 && b[4] == 0x42 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x10 && b[8] == 0x00 && b[9] == 0x00 && b[10] == 0x00 && - b[11] == 0x00 && b[12] == 0x39 && b[13] == 0x64) { - return "mbm"; - } - if (b[0] == 0x4D && b[1] == 0x47 && b[2] == 0x4C) { - return "mgl"; - } - if (b[0] == 0x7B && b[1] == 0x0A && b[2] == 0x20 && b[3] == 0x20 && b[4] == 0x43 && b[5] == 0x72 && - b[6] == 0x65 && b[7] == 0x61 && b[8] == 0x74 && b[9] == 0x65 && b[10] == 0x64) { - return "mif"; - } - if (b[0] == 0x8A && b[1] == 0x4D && b[2] == 0x4E && b[3] == 0x47 && b[4] == 0x0D && b[5] == 0x0A && - b[6] == 0x1A && b[7] == 0x0A) { - return "mng"; - } - if (b[0] == 0x4D && b[1] == 0x50 && b[2] == 0x46) { - return "mpw"; - } - if (b[0] == 0x44 && b[1] == 0x61 && b[2] == 0x6E && b[3] == 0x4D) { - return "msp"; - } - if (b[0] == 0x43 && b[1] == 0x36 && b[2] == 0x34) { - return "n64"; - } - if (b[0] == 0x6E && b[1] == 0x6E && b[2] == 0x0A && b[3] == 0x00 && b[4] == 0x5E && b[5] == 0x00) { - return "ncr"; - } - if (b[0] == 0x6E && b[1] == 0x66 && b[2] == 0x66) { - return "nff"; - } - if (b[0] == 0x4E && b[1] == 0x47 && b[2] == 0x47 && b[3] == 0x00 && b[4] == 0x01 && b[5] == 0x00) { - return "ngg"; - } - if (b[0] == 0x4E && b[1] == 0x4C && b[2] == 0x4D && b[3] == 0x20 && b[4] == 0x01 && b[5] == 0x02 && - b[6] == 0x00) { - return "nlm"; - } - if (b[0] == 0x4E && b[1] == 0x4F && b[2] == 0x4C && b[3] == 0x00 && b[4] == 0x01 && b[5] == 0x00 && - b[6] == 0x06 && b[7] == 0x01 && b[8] == 0x03 && b[9] == 0x00) { - return "nol"; - } - if (b[0] == 0x41 && b[1] == 0x48) { - return "pal"; - } - if (b[0] == 0x50 && b[1] == 0x41 && b[2] == 0x58) { - return "pax"; - } - if (b[0] == 0x63 && b[1] == 0x52 && b[2] == 0x01 && b[3] == 0x01 && b[4] == 0x38 && b[5] == 0x09 && - b[6] == 0x3D && b[7] == 0x00) { - return "pcd"; - } - if (b[0] == 0x1B && b[1] == 0x45 && b[2] == 0x1B && b[3] == 0x26 && b[4] == 0x6C && b[5] == 0x30 && - b[6] == 0x4F && b[7] == 0x1B && b[8] == 0x26 && b[9] == 0x6C && b[10] == 0x30 && - b[11] == 0x45 && b[12] == 0x1B && b[13] == 0x26) { - return "pcl"; - } - if (b[0] == 0x50 && b[1] == 0x49 && b[2] == 0x58 && b[3] == 0x20) { - return "pix"; - } - if (b[0] == 0x50 && b[1] == 0x4F && b[2] == 0x4C && b[3] == 0x20 && b[4] == 0x46 && b[5] == 0x6F && - b[6] == 0x72 && b[7] == 0x6D && b[8] == 0x61 && b[9] == 0x74) { - return "pol"; - } - // Paint Shop Pro - if (b[0] == 0x7E && b[1] == 0x42 && b[2] == 0x4B && b[3] == 0x00) { - return "psp"; - } - if (b[0] == 0x50 && b[1] == 0x61 && b[2] == 0x69 && b[3] == 0x6E && b[4] == 0x74 && b[5] == 0x20 && - b[6] == 0x53 && b[7] == 0x68 && b[8] == 0x6F && b[9] == 0x70 && b[10] == 0x20 && - b[11] == 0x50 && b[12] == 0x72 && b[13] == 0x6F && b[14] == 0x20 && b[15] == 0x49 && - b[16] == 0x6D && b[17] == 0x61 && b[18] == 0x67 && b[19] == 0x65 && b[20] == 0x20 && - b[21] == 0x46 && b[22] == 0x69 && b[23] == 0x6C && b[24] == 0x65) { - return "psp"; - } - if (b[0] == 0x51 && b[1] == 0x4C && b[2] == 0x49 && b[3] == 0x49 && b[4] == 0x46 && b[5] == 0x41 && - b[6] == 0x58) { - return "qfx"; - } - if (b[0] == 0x6D && b[1] == 0x6F && b[2] == 0x6F && b[3] == 0x76) { - return "qtm"; - } - if (b[0] == 0x46 && b[1] == 0x4F && b[2] == 0x52 && b[3] == 0x4D && b[4] == 0x41 && b[5] == 0x54 && - b[6] == 0x3D) { - return "rad"; - } - if (b[0] == 0x59 && b[1] == 0xA6 && b[2] == 0x6A && b[3] == 0x95) { - return "ras"; - } - if (b[0] == 0x52 && b[1] == 0x49 && b[2] == 0x58 && b[3] == 0x33) { - return "rix"; - } - if (b[0] == 0x23 && b[1] == 0x20 && b[2] == 0x24 && b[3] == 0x49 && b[4] == 0x64 && b[5] == 0x3A && - b[6] == 0x20) { - return "sid"; - } - if (b[0] == 0x41 && b[1] == 0x75 && b[2] == 0x74 && b[3] == 0x6F && b[4] == 0x43 && b[5] == 0x41 && - b[6] == 0x44 && b[7] == 0x20 && b[8] == 0x53 && b[9] == 0x6C && b[10] == 0x69 && - b[11] == 0x64 && b[12] == 0x65) { - return "sld"; - } - if (b[0] == 0x53 && b[1] == 0x74 && b[2] == 0x6F && b[3] == 0x72 && b[4] == 0x6D && b[5] == 0x33 && - b[6] == 0x44) { - return "sod"; - } - if (b[0] == 0xFA && b[1] == 0xDE && b[2] == 0xBA && b[3] == 0xBE && b[4] == 0x01 && b[5] == 0x01) { - return "wic"; - } - if (b[0] == 0xD3 && b[1] == 0x23 && b[2] == 0x00 && b[3] == 0x00 && b[4] == 0x03 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x00) { - return "wlm"; - } - if (b[0] == 0xD7 && b[1] == 0xCD && b[2] == 0xC6 && b[3] == 0x9A) { - return "wmf"; - } - if (b[0] == 0xFF && b[1] == 0x57 && b[2] == 0x50 && b[3] == 0x43 && b[4] == 0x10) { - return "wpg"; - } - if (b[0] == 0x23 && b[1] == 0x56 && b[2] == 0x52 && b[3] == 0x4D && b[4] == 0x4C && b[5] == 0x20 && - b[6] == 0x56 && b[7] == 0x32 && b[8] == 0x2E && b[9] == 0x30) { - return "wrl"; - } - if (b[0] == 0x23 && b[1] == 0x64 && b[2] == 0x65 && b[3] == 0x66 && b[4] == 0x69 && b[5] == 0x6E && - b[6] == 0x65) { - return "xbm"; - } - if (b[0] == 0x2F && b[1] == 0x2A && b[2] == 0x20 && b[3] == 0x58 && b[4] == 0x50 && b[5] == 0x4D && - b[6] == 0x20 && b[7] == 0x2A && b[8] == 0x2F) { - return "xpm"; - } - return null; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java index 0f51c2e14..e485e5452 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java @@ -77,7 +77,7 @@ public class ImageSequence implements TextureSequence { } public final void addFrame(final GL gl, final Class<?> context, final String imageResourcePath, final String imageSuffix) throws IOException { - final URLConnection urlConn = IOUtil.getResource(context, imageResourcePath); + final URLConnection urlConn = IOUtil.getResource(imageResourcePath, context.getClassLoader(), context); if(null != urlConn) { final TextureData texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, imageSuffix); final Texture tex = new Texture(getTextureTarget()); diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageType.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageType.java new file mode 100644 index 000000000..8a3bae554 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageType.java @@ -0,0 +1,1579 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util.texture; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Image type classification. + * <p> + * Allows to classify the {@link ImageType} of an {@link InputStream} via {@link #ImageType(InputStream)} + * or to simply define one {@link ImageType} via {@link #ImageType(String)}. + * </p> + * @since 2.3.2 + */ +public class ImageType { + /** + * Minimum number of bytes to determine the image data type, i.e. {@value} bytes. + */ + public static final int MAGIC_MAX_SIZE = 25; + + /** + * Constant which can be used as a file suffix to indicate a JPEG stream, value {@value}. + * <ul> + * <li>{@code http://www.faqs.org/faqs/jpeg-faq/part1/}</li> + * <li>{@code http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=54989}</li> + * </ul> + */ + public static final String T_JPG = "jpg"; + + /** + * Constant which can be used as a file suffix to indicate a PNG stream, value {@value}. + * <ul> + * <li>{@code http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html#R.PNG-file-signature}</li> + * </ul> + */ + public static final String T_PNG = "png"; + + /** + * Constant which can be used as a file suffix to indicate an Apple Icon Image stream, value {@value}. + * <p> + * {@code 'i' 'c' 'n' 's' ascii code} + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_ICNS = "icns"; + + /** + * Constant which can be used as a file suffix to indicate a Microsoft Windows Icon stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code https://msdn.microsoft.com/en-us/library/ms997538.aspx}</li> + * </ul> + */ + public static final String T_ICO = "ico"; + + /** + * Constant which can be used as a file suffix to indicate a Microsoft Windows Cursor stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CUR = "cur"; + + /** + * Constant which can be used as a file suffix to indicate a GIF stream, value {@value}. + * <p> + * {@code GIF87A or GIF89A ascii code} + * </p> + * <ul> + * <li>{@code http://www.w3.org/Graphics/GIF/spec-gif87a.txt http://www.w3.org/Graphics/GIF/spec-gif89a.txt}</li> + * </ul> + */ + public static final String T_GIF = "gif"; + + /** + * Constant which can be used as a file suffix to indicate a GIF stream, value {@value}. + * <p> + * {@code BM ascii code} + * </p> + * <p> + * FIXME: Collision or supertype of {@link #T_DIB}? + * </p> + * <ul> + * <li>{@code http://www.fileformat.info/format/bmp/spec/e27073c25463436f8a64fa789c886d9c/view.htm}</li> + * </ul> + */ + public static final String T_BMP = "bmp"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or subtype of {@link #T_BMP}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DIB = "dib"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DCX = "dcx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PCX = "pcx"; + + /** + * Constant which can be used as a file suffix to indicate a PAM stream, NetPbm magic 6 - binary RGB. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/ppm.html}</li> + * </ul> + */ + public static final String T_PPM = "ppm"; + + /** + * Constant which can be used as a file suffix to indicate a Adobe PhotoShop stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PSD = "psd"; + + /** + * Constant which can be used as a file suffix to indicate a TIFF stream, value {@value}. + * <p> + * Intentionally detects only the little endian tiff images ("II" in the spec). + * </p> + * <p> + * FIXME: Collision or supertype of {@link #T_LDF}? + * </p> + * <ul> + * <li>{@code http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf}</li> + * </ul> + */ + public static final String T_TIFF = "tiff"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or subtype of {@link #T_TIFF}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_LDF = "ldf"; + + /** + * Constant which can be used as a file suffix to indicate an SGI RGB stream, value {@value}. + * <p> + * "474 saved as a short" 474 = 0x01DA + * </p> + * <ul> + * <li>{@code http://paulbourke.net/dataformats/sgirgb/sgiversion.html}</li> + * </ul> + */ + public static final String T_SGI_RGB = "rgb"; + + /** + * Constant which can be used as a file suffix to indicate a DirectDraw Surface stream, value {@value}. + * <p> + * 'D' 'D' 'S' ' ' ascii code + * </p> + * <ul> + * <li>{@code https://msdn.microsoft.com/en-us/library/windows/desktop/bb943991%28v=vs.85%29.aspx#File_Layout1}</li> + * </ul> + */ + public static final String T_DDS = "dds"; + + /** + * Constant which can be used as a file suffix to indicate a Portable Arbitrary Map stream, NetPbm magic 7 - binary RGB and RGBA. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/pam.html}</li> + * </ul> + */ + public static final String T_PAM = "pam"; + + /** + * Constant which can be used as a file suffix to indicate a PGM stream, NetPbm magic 5 - binary grayscale. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/pgm.html}</li> + * </ul> + */ + public static final String T_PGM = "pgm"; + + /** + * Constant which can be used as a file suffix to indicate a PGM stream, NetPbm magic 4 - binary monochrome. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/pbm.html}</li> + * </ul> + */ + public static final String T_PBM = "pbm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_3D2 = "3d2"; + + /** + * Constant which can be used as a file suffix to indicate an Apple QuickDraw 3D 3DMF stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_3DMF = "3dmf"; + + /** + * Constant which can be used as a file suffix to indicate a Texas Instruments TI-92 Bitmap stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_92I = "92i"; + + /** + * Constant which can be used as a file suffix to indicate an Amiga metafile stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_AMFF = "amff"; + + /** + * Constant which can be used as a file suffix to indicate an America Online Art stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_ART = "art"; + + /** + * Constant which can be used as a file suffix to indicate a United States Department of Defence Continuous Acquisition and Life-cycle Support Raster stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code http://www.fileformat.info/format/cals/egff.htm}</li> + * </ul> + */ + public static final String T_CALS = "cals"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CAM = "cam"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CBD = "cbd"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CE2 = "ce2"; + + /** + * Constant which can be used as a file suffix to indicate a Kodak Cineon System stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code http://www.cineon.com/ff_draft.php}</li> + * </ul> + */ + public static final String T_CIN = "cin"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_COB = "cob"; + + /** + * Constant which can be used as a file suffix to indicate a Corel Photo Paint stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CPT = "cpt"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CVG = "cvg"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DEM = "dem"; + + /** + * Constant which can be used as a file suffix to indicate a Digital Picture Exchange stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DPX = "dpx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DRW = "drw"; + + /** + * Constant which can be used as a file suffix to indicate a Autocad drawing stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DWG = "dwg"; + + /** + * Constant which can be used as a file suffix to indicate a Hexagon Geospatial Enhanced Compression Wavelet stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_ECW = "ecw"; + + /** + * Constant which can be used as a file suffix to indicate a Microsoft Windows Enhanced metafile stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_EMF = "emf"; + + /** + * Constant which can be used as a file suffix to indicate a FlashPix stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_FPX = "fpx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_FTS = "fts"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_GRO = "gro"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_HDR = "hdr"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_HRU = "hru"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_IMG = "img"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_INFINI_D = "infini-d"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_IWC = "iwc"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_J6I = "j6i"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_JIF = "jif"; + + /** + * Constant which can be used as a file suffix to indicate a JPEG-2000 stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_JP2 = "jp2"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_KDC = "kdc"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_L64 = "l64"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or supertype of {@link #T_RAD}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_LBM = "lbm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or subtype of {@link #T_LBM}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_RAD = "rad"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_LWF = "lwf"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MBM = "mbm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MGL = "mgl"; + + /** + * Constant which can be used as a file suffix to indicate an Imagemagick stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MIF = "mif"; + + /** + * Constant which can be used as a file suffix to indicate a Multiple-image Network Graphics stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MNG = "mng"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MPW = "mpw"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MSP = "msp"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_N64 = "n64"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NCR = "ncr"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NFF = "nff"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NGG = "ngg"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NLM = "nlm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NOL = "nol"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PAL = "pal"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PAX = "pax"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PCD = "pcd"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PCL = "pcl"; + + /** + * Constant which can be used as a file suffix to indicate a Softimage pic stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code http://paulbourke.net/dataformats/softimagepic/}</li> + * </ul> + */ + public static final String T_PIC = "pic"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PIX = "pix"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_POL = "pol"; + + /** + * Constant which can be used as a file suffix to indicate a PaintShop Pro stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PSP = "psp"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_QFX = "qfx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_QTM = "qtm"; + + /** + * Constant which can be used as a file suffix to indicate a Sun Raster stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_RAS = "ras"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_RIX = "rix"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_SID = "sid"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_SLD = "sld"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_SOD = "sod"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WIC = "wic"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WLM = "wlm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WMF = "wmf"; + + /** + * Constant which can be used as a file suffix to indicate a Wordperfect Graphics vectors stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WPG = "wpg"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WRL = "wrl"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_XBM = "xbm"; + + /** + * Constant which can be used as a file suffix to indicate a X PixMap stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_XPM = "xpm"; + + /** + * Constant which can be used as a file suffix to indicate a Targa stream, value {@value}. + * <ul> + * <li>{@code }</li> + * </ul> + */ + public static final String T_TGA = "tga"; + + /** + * The determined unique type, e.g. {@link #T_PNG}, {@link #T_JPG}, etc. + * <p> + * Maybe {@code null} if undetermined, i.e. {@link #isDefined()} returns {@code false}. + * </p> + */ + public final String type; + + /** + * The optionally read header of size {@link #MAGIC_MAX_SIZE} bytes as used to determine the {@link #type}, + * i.e. {@link #ImageType(InputStream)}. + * <p> + * May be {@code null}, if {@link #type} has been determined otherwise, i.e {@link #ImageType(String)}. + * </p> + * <p> + * The header is <i>not</i> being used for {@link #hashCode()} and {@link #equals(Object)}! + * </p> + */ + public final byte[] header; + + private final int hash; + + /** + * Creates instance based on given stream. + * @param stream stream to parse, {@link InputStream#available()} must be ≥ {@link #MAGIC_MAX_SIZE} + * @throws java.io.IOException if an I/O exception occurred + */ + public ImageType(final InputStream stream) throws IOException { + final byte[] _header = new byte[MAGIC_MAX_SIZE]; + type = Util.getFileSuffix(stream, _header); + this.header = _header; + this.hash = null != this.type ? this.type.hashCode() : 0; + } + /** + * Creates instance based on the given type. + * @param type must be one of {@link #T_PNG}, {@link #T_JPG}, etc. + */ + public ImageType(final String type) { + this.header = null; + this.type = type; + this.hash = this.type.hashCode(); + } + /** Returns {@code true} if {@link #type} is determined, i.e. not {@code null}, otherwise {@code false}. */ + public final boolean isDefined() { return null != type; } + + @Override + public final int hashCode() { + return hash; + } + @Override + public boolean equals(final Object o) { + if( o == this ) { + return true; + } else if( o instanceof ImageType ) { + final ImageType t = (ImageType)o; + return this.type.equals(t.type); + } else { + return false; + } + } + @Override + public String toString() { return "ImageType["+type+"]"; } + + /** + * Static utility functions for {@link ImageType} + * to determine the {@link ImageType#type}. + * @since 2.3.2 + */ + public static class Util { + /** + * Determines the file suffix (i.e the image format) of the given InputStream. The given + * InputStream must return true from markSupported() and support a minimum of {@link #MAGIC_MAX_SIZE} bytes + * of read-ahead. + * + * @param stream stream to parse, {@link InputStream#available()} must be ≥ {@link #MAGIC_MAX_SIZE} + * @return the file suffix if any, otherwise <code>null</code> + * @throws java.io.IOException if an I/O exception occurred + */ + public static String getFileSuffix(final InputStream stream) throws IOException { + return getFileSuffix(stream, new byte[MAGIC_MAX_SIZE]); + } + /** + * Determines the file suffix (i.e the image format) of the given InputStream. The given + * InputStream must return true from markSupported() and support a minimum of {@link #MAGIC_MAX_SIZE} bytes + * of read-ahead. + * + * @param stream stream to parse, {@link InputStream#available()} must be ≥ {@link #MAGIC_MAX_SIZE} + * @param b byte array sink, size must be ≥ {@link #MAGIC_MAX_SIZE} + * @return the file suffix if any, otherwise <code>null</code> + * @throws java.io.IOException if an I/O exception occurred + */ + public static String getFileSuffix(InputStream stream, final byte[] b) throws IOException { + if (stream == null) { + throw new IOException("Stream was null"); + } + if (!(stream instanceof BufferedInputStream)) { + stream = new BufferedInputStream(stream); + } + if (!stream.markSupported()) { + throw new IOException("Mark not supported"); + } + if (stream.available() < MAGIC_MAX_SIZE) { + throw new IOException("Requires "+MAGIC_MAX_SIZE+" bytes, has "+stream.available()+" bytes"); + } + try { + stream.mark(MAGIC_MAX_SIZE); + final int bytesRead = stream.read(b); + if( MAGIC_MAX_SIZE > bytesRead ) { + throw new IOException("Could not read "+MAGIC_MAX_SIZE+" bytes, read "+bytesRead+" bytes"); + } + return getFileSuffix(b); + } finally { + stream.reset(); + } + + } + + /** + * Determines the file suffix (i.e the image format) of the given bytes from the header + * of a file. + * + * @param b byte array to parse, size must be ≥ {@link #MAGIC_MAX_SIZE} + * @return the file suffix if any, otherwise <code>null</code> + * @throws java.io.IOException if an I/O exception occurred + */ + public static String getFileSuffix(final byte[] b) { + if( b.length < MAGIC_MAX_SIZE ) { + throw new IllegalArgumentException("byte array must be >= "+MAGIC_MAX_SIZE+", has "+b.length); + } + final byte b0 = b[0]; + final byte b1 = b[1]; + final byte b2 = b[2]; + final byte b3 = b[3]; + final byte b4 = b[4]; + final byte b5 = b[5]; + + // T_TGA: NO Signature! + + if (b0 == (byte)0x00) { + if (b1 == (byte)0x00 && b2 == (byte)0x00 && b3 == (byte)0x0C && + b4 == (byte)0x6A && b5 == (byte)0x50 && + b[6] == (byte)0x20 && b[7] == (byte)0x20 && b[8] == (byte)0x0D && b[9] == (byte)0x0A && b[10] == (byte)0x87 && + b[11] == (byte)0x0A) { + return T_JP2; + } + else if (b1 == (byte)0x01) { + return T_ICO; + } + else if (b1 == (byte)0x02) { + return T_CUR; + } + } + else if (b0 == (byte)0x01) { + if (b1 == (byte)0xDA /* && b2 == (byte)0x01 && b3 == (byte)0x01 && b4 == (byte)0x00 && b5 == (byte)0x03 */) { + return T_SGI_RGB; + } + else if (b1 == (byte)0xFF && b2 == (byte)0x02 && b3 == (byte)0x04 && + b4 == (byte)0x03 && b5 == (byte)0x02) { + return T_DRW; + } + else if (b1 == (byte)0x00 && b2 == (byte)0x00 && b3 == (byte)0x00 && + b4 == (byte)0x58 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x00) { + return T_EMF; + } + } + else if (b0 == (byte)0x07 && b1 == (byte)0x20 && b2 == (byte)0x4D && b3 == (byte)0x4D) { + return T_CAM; + } + else if (b0 == (byte)0x0A && b1 == (byte)0x05 && b2 == (byte)0x01 && b3 == (byte)0x08) { + return T_PCX; + } + else if (b0 == (byte)0x1B && b1 == (byte)0x45 && b2 == (byte)0x1B && b3 == (byte)0x26 && + b4 == (byte)0x6C && b5 == (byte)0x30 && + b[6] == (byte)0x4F && b[7] == (byte)0x1B && b[8] == (byte)0x26 && b[9] == (byte)0x6C && b[10] == (byte)0x30 && + b[11] == (byte)0x45 && b[12] == (byte)0x1B && b[13] == (byte)0x26) { + return T_PCL; + } + else if (b0 == (byte)0x20 && b1 == (byte)0x77 && b2 == (byte)0x00 && b3 == (byte)0x02) { + return T_CBD; + } + else if (b0 == (byte)0x23) { + if (b1 == (byte)0x20 && b2 == (byte)0x24 && b3 == (byte)0x49 && + b4 == (byte)0x64 && b5 == (byte)0x3A && + b[6] == (byte)0x20) { + return T_SID; + } + else if (b1 == (byte)0x56 && b2 == (byte)0x52 && b3 == (byte)0x4D && + b4 == (byte)0x4C && b5 == (byte)0x20 && + b[6] == (byte)0x56 && b[7] == (byte)0x32 && b[8] == (byte)0x2E && b[9] == (byte)0x30) { + return T_WRL; + } + else if (b1 == (byte)0x64 && b2 == (byte)0x65 && b3 == (byte)0x66 && + b4 == (byte)0x69 && b5 == (byte)0x6E && + b[6] == (byte)0x65) { + return T_XBM; + } + } + else if (b0 == (byte)0x2A && b1 == (byte)0x2A && b2 == (byte)0x54 && b3 == (byte)0x49 && + b4 == (byte)0x39 && b5 == (byte)0x32 && + b[6] == (byte)0x2A && b[7] == (byte)0x2A && b[8] == (byte)0x01 && b[9] == (byte)0x00 && b[10] == (byte)0x58 && + b[11] == (byte)0x6E && b[12] == (byte)0x56 && b[13] == (byte)0x69) { + return T_92I; + } + else if (b0 == (byte)0x2F && b1 == (byte)0x2A && b2 == (byte)0x20 && b3 == (byte)0x58 && + b4 == (byte)0x50 && b5 == (byte)0x4D && + b[6] == (byte)0x20 && b[7] == (byte)0x2A && b[8] == (byte)0x2F) { + return T_XPM; + } + else if (b0 == (byte)0x33 && b1 == (byte)0x44 && b2 == (byte)0x4D && b3 == (byte)0x46) { + return T_3DMF; + } + else if (b0 == (byte)0x35 && b1 == (byte)0x4B && b2 == (byte)0x50 && b3 == (byte)0x35 && + b4 == (byte)0x31 && b5 == (byte)0x5D && + b[6] == (byte)0x2A && b[7] == (byte)0x67 && b[8] == (byte)0x72 && b[9] == (byte)0x72 && b[10] == (byte)0x80 && + b[11] == (byte)0x83 && b[12] == (byte)0x85 && b[13] == (byte)0x63) { + return T_HRU; + } + else if (b0 == (byte)0x36 && b1 == (byte)0x34 && b2 == (byte)0x4C && b3 == (byte)0x41 && + b4 == (byte)0x4E && b5 == (byte)0x20 && + b[6] == (byte)0x49 && b[7] == (byte)0x44 && b[8] == (byte)0x42 && b[9] == (byte)0x4C && b[10] == (byte)0x4F && + b[11] == (byte)0x43 && b[12] == (byte)0x4B) { + return T_L64; + } + else if (b0 == (byte)0x37 && b1 == (byte)0x00 && b2 == (byte)0x00 && b3 == (byte)0x10 && + b4 == (byte)0x42 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x10 && b[8] == (byte)0x00 && b[9] == (byte)0x00 && b[10] == (byte)0x00 && + b[11] == (byte)0x00 && b[12] == (byte)0x39 && b[13] == (byte)0x64) { + return T_MBM; + } + else if (b0 == (byte)0x38 && b1 == (byte)0x42 && b2 == (byte)0x50 && b3 == (byte)0x53 && + b4 == (byte)0x00 && b5 == (byte)0x01 && + b[6] == (byte)0x00 && b[7] == (byte)0x00 && b[8] == (byte)0x00 && b[9] == (byte)0x00) { + return T_PSD; + } + else if (b0 == (byte)0x3A && b1 == (byte)0xDE && b2 == (byte)0x68 && b3 == (byte)0xB1) { + return T_DCX; + } + else if (b0 == (byte)0x3D && b1 == (byte)0x02) { + return T_3D2; + } + else if (b0 == (byte)0x41) { + if (b1 == (byte)0x43 && b2 == (byte)0x31 && b3 == (byte)0x30) { + return T_DWG; + } + else if (b1 == (byte)0x48) { + return T_PAL; + } + else if (b1 == (byte)0x4D && b2 == (byte)0x46 && b3 == (byte)0x46) { + return T_AMFF; + } + else if (b1 == (byte)0x75 && b2 == (byte)0x74 && b3 == (byte)0x6F && + b4 == (byte)0x43 && b5 == (byte)0x41 && + b[6] == (byte)0x44 && b[7] == (byte)0x20 && b[8] == (byte)0x53 && b[9] == (byte)0x6C && b[10] == (byte)0x69 && + b[11] == (byte)0x64 && b[12] == (byte)0x65) { + return T_SLD; + } + } + else if (b0 == (byte)0x42 && b1 == (byte)0x4D) { + if (b2 == (byte)0x36) { + // FIXME: Collision or subtype of T_BMP? + return T_DIB; + } else { + return T_BMP; + } + } + else if (b0 == (byte)0x43) { + if (b1 == (byte)0x36 && b2 == (byte)0x34) { + return T_N64; + } + else if (b1 == (byte)0x41 && b2 == (byte)0x4C && b3 == (byte)0x41 && + b4 == (byte)0x4D && b5 == (byte)0x55 && + b[6] == (byte)0x53 && b[7] == (byte)0x43 && b[8] == (byte)0x56 && b[9] == (byte)0x47) { + return T_CVG; + } + else if (b1 == (byte)0x50 && b2 == (byte)0x54 && b3 == (byte)0x46 && + b4 == (byte)0x49 && b5 == (byte)0x4C && + b[6] == (byte)0x45) { + return T_CPT; + } + else if (b1 == (byte)0x61 && b2 == (byte)0x6C && b3 == (byte)0x69 && + b4 == (byte)0x67 && b5 == (byte)0x61 && + b[6] == (byte)0x72 && b[7] == (byte)0x69) { + return T_COB; + } + } + else if (b0 == (byte)0x44) { + if (b1 == (byte)0x44 && b2 == (byte)0x53 && b3 == (byte)0x20) { + return T_DDS; + } + else if (b1 == (byte)0x61 && b2 == (byte)0x6E && b3 == (byte)0x4D) { + return T_MSP; + } + } + else if (b0 == (byte)0x45) { + if (b1 == (byte)0x59 && b2 == (byte)0x45 && b3 == (byte)0x53) { + return T_CE2; + } + else if (b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) { /* EXIF */ + /** + * (b0 == (byte)0x45 && b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) || // EXIF + * (b0 == (byte)0x4A && b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) || // JFIF + * (b0 == (byte)0xff && b1 == (byte)0xd8 ) // && b2 == (byte)0xff + */ + return T_JPG; + } + } + else if (b0 == (byte)0x46 && b1 == (byte)0x4F && b2 == (byte)0x52 && b3 == (byte)0x4D) { + if (b4 == (byte)0x41 && b5 == (byte)0x54 && b[6] == (byte)0x3D) { + // FIXME: Collision or subtype of T_LBM? + return T_RAD; + } else { + return T_LBM; + } + } + else if (b0 == (byte)0x47 && b1 == (byte)0x49 && b2 == (byte)0x46 && b3 == (byte)0x38 && + (b4 == (byte)0x37 || b4 == (byte)0x39) && b5 == (byte)0x61) { + return T_GIF; + } + else if (b0 == (byte)0x48 && b1 == (byte)0x50 && b2 == (byte)0x48 && b3 == (byte)0x50 && + b4 == (byte)0x34 && b5 == (byte)0x38 && + b[6] == (byte)0x2D && b[7] == (byte)0x45 && b[8] == (byte)0x1E && b[9] == (byte)0x2B) { + return T_GRO; + } + else if (b0 == (byte)0x49) { + if (b1 == (byte)0x49 && b2 == (byte)0x2A && b3 == (byte)0x00) { + if (b4 == (byte)0x08 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x00 && b[8] == (byte)0x0E && b[9] == (byte)0x00 && b[10] == (byte)0x00 && + b[11] == (byte)0x01 && b[12] == (byte)0x04 && b[13] == (byte)0x00) { + // FIXME: Collision or subtype of T_TIFF? + return T_LDF; + } else { + return T_TIFF; + } + } + else if (b1 == (byte)0x57 && b2 == (byte)0x43 && b3 == (byte)0x01) { + return T_IWC; + } + } + else if (b0 == (byte)0x4A) { + if (b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) { /* JFIF */ + /** + * (b0 == (byte)0x45 && b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) || // EXIF + * (b0 == (byte)0x4A && b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) || // JFIF + * (b0 == (byte)0xff && b1 == (byte)0xd8 ) // && b2 == (byte)0xff + */ + return T_JPG; + } + else if (b1 == (byte)0x47 && (b2 == (byte)0x03 || b2 == (byte)0x04) && b3 == (byte)0x0E && + b4 == (byte)0x00 && b5 == (byte)0x00 && + b[6] == (byte)0x00) { + return T_ART; + } + else if (b1 == (byte)0x49 && b2 == (byte)0x46 && b3 == (byte)0x39 && + b4 == (byte)0x39 && b5 == (byte)0x61) { + return T_JIF; + } + } + else if (b0 == (byte)0x4D) { + if (b1 == (byte)0x47 && b2 == (byte)0x4C) { + return T_MGL; + } + else if (b1 == (byte)0x4D && b2 == (byte)0x00 && b3 == (byte)0x2A) { + return T_KDC; + } + else if (b1 == (byte)0x50 && b2 == (byte)0x46) { + return T_MPW; + } + } + else if (b0 == (byte)0x4E) { + if (b1 == (byte)0x47 && b2 == (byte)0x47 && b3 == (byte)0x00 && + b4 == (byte)0x01 && b5 == (byte)0x00) { + return T_NGG; + } + else if (b1 == (byte)0x4C && b2 == (byte)0x4D && b3 == (byte)0x20 && + b4 == (byte)0x01 && b5 == (byte)0x02 && + b[6] == (byte)0x00) { + return T_NLM; + } + else if (b1 == (byte)0x4F && b2 == (byte)0x4C && b3 == (byte)0x00 && + b4 == (byte)0x01 && b5 == (byte)0x00 && + b[6] == (byte)0x06 && b[7] == (byte)0x01 && b[8] == (byte)0x03 && b[9] == (byte)0x00) { + return T_NOL; + } + } + else if (b0 == (byte)0x50) { + if (b1 == (byte)0x31 /* plain */|| b1 == (byte)0x34) { + return T_PBM; + } + else if (b1 == (byte)0x32 /* plain */|| b1 == (byte)0x35) { + return T_PGM; + } + else if (b1 == (byte)0x33 /* plain */|| b1 == (byte)0x36) { + return T_PPM; + } + else if (b1 == (byte)0x37) { + return T_PAM; + } + else if (b1 == (byte)0x41 && b2 == (byte)0x58) { + return T_PAX; + } + else if (b1 == (byte)0x49 && b2 == (byte)0x58 && b3 == (byte)0x20) { + return T_PIX; + } + else if (b1 == (byte)0x4F && b2 == (byte)0x4C && b3 == (byte)0x20 && + b4 == (byte)0x46 && b5 == (byte)0x6F && + b[6] == (byte)0x72 && b[7] == (byte)0x6D && b[8] == (byte)0x61 && b[9] == (byte)0x74) { + return T_POL; + } + else if (b1 == (byte)0x61 && b2 == (byte)0x69 && b3 == (byte)0x6E && + b4 == (byte)0x74 && b5 == (byte)0x20 && + b[6] == (byte)0x53 && b[7] == (byte)0x68 && b[8] == (byte)0x6F && b[9] == (byte)0x70 && b[10] == (byte)0x20 && + b[11] == (byte)0x50 && b[12] == (byte)0x72 && b[13] == (byte)0x6F && b[14] == (byte)0x20 && b[15] == (byte)0x49 && + b[16] == (byte)0x6D && b[17] == (byte)0x61 && b[18] == (byte)0x67 && b[19] == (byte)0x65 && b[20] == (byte)0x20 && + b[21] == (byte)0x46 && b[22] == (byte)0x69 && b[23] == (byte)0x6C && b[24] == (byte)0x65) { + return T_PSP; + } + } + else if (b0 == (byte)0x51 && b1 == (byte)0x4C && b2 == (byte)0x49 && b3 == (byte)0x49 && + b4 == (byte)0x46 && b5 == (byte)0x41 && + b[6] == (byte)0x58) { + return T_QFX; + } + else if (b0 == (byte)0x52 && b1 == (byte)0x49 && b2 == (byte)0x58 && b3 == (byte)0x33) { + return T_RIX; + } + else if (b0 == (byte)0x53) { + if (b1 == (byte)0x44 && b2 == (byte)0x50 && b3 == (byte)0x58) { + return T_DPX; + } + else if (b1 == (byte)0x49 && b2 == (byte)0x4D && b3 == (byte)0x50 && + b4 == (byte)0x4C && b5 == (byte)0x45 && + b[6] == (byte)0x20 && b[7] == (byte)0x20 && b[8] == (byte)0x3D) { + return T_FTS; + } + else if (b1 == (byte)0x74 && b2 == (byte)0x6F && b3 == (byte)0x72 && + b4 == (byte)0x6D && b5 == (byte)0x33 && + b[6] == (byte)0x44) { + return T_SOD; + } + else if (b1 == (byte)0x80 && b2 == (byte)0xf6 && b3 == (byte)0x34) { + return T_PIC; + } + } + else if (b0 == (byte)0x56 && b1 == (byte)0x69 && b2 == (byte)0x73 && b3 == (byte)0x74 && + b4 == (byte)0x61 && b5 == (byte)0x20 && + b[6] == (byte)0x44 && b[7] == (byte)0x45 && b[8] == (byte)0x4D && b[9] == (byte)0x20 && b[10] == (byte)0x46 && + b[11] == (byte)0x69 && b[12] == (byte)0x6C && b[13] == (byte)0x65) { + return T_DEM; + } + else if (b0 == (byte)0x57 && b1 == (byte)0x56 && b2 == (byte)0x02 && b3 == (byte)0x00 && + b4 == (byte)0x47 && b5 == (byte)0x45 && + b[6] == (byte)0x00 && b[7] == (byte)0x0E) { + return T_LWF; + } + else if (b0 == (byte)0x59 && b1 == (byte)0xA6 && b2 == (byte)0x6A && b3 == (byte)0x95) { + return T_RAS; + } + else if (b0 == (byte)0x63 && b1 == (byte)0x52 && b2 == (byte)0x01 && b3 == (byte)0x01 && + b4 == (byte)0x38 && b5 == (byte)0x09 && + b[6] == (byte)0x3D && b[7] == (byte)0x00) { + return T_PCD; + } + else if (b0 == (byte)0x65) { + if (b1 == (byte)0x02 && b2 == (byte)0x01 && b3 == (byte)0x02) { + return T_ECW; + } + else if (b1 == (byte)0x6C && b2 == (byte)0x6D && b3 == (byte)0x6F) { + return T_INFINI_D; + } + } + else if (b0 == (byte)0x69 && b1 == (byte)0x63 && b2 == (byte)0x6E && b3 == (byte)0x73) { + return T_ICNS; + } + else if (b0 == (byte)0x6D && b1 == (byte)0x6F && b2 == (byte)0x6F && b3 == (byte)0x76) { + return T_QTM; + } + else if (b0 == (byte)0x6E) { + if (b1 == (byte)0x63 && b2 == (byte)0x6F && b3 == (byte)0x6C && + b4 == (byte)0x73) { + return T_HDR; + } + else if (b1 == (byte)0x66 && b2 == (byte)0x66) { + return T_NFF; + } + else if (b1 == (byte)0x6E && b2 == (byte)0x0A && b3 == (byte)0x00 && + b4 == (byte)0x5E && b5 == (byte)0x00) { + return T_NCR; + } + } + else if (b0 == (byte)0x73 && b1 == (byte)0x72 && b2 == (byte)0x63 && b3 == (byte)0x64 && + b4 == (byte)0x6F && b5 == (byte)0x63 && + b[6] == (byte)0x69 && b[7] == (byte)0x64 && b[8] == (byte)0x3A) { + return T_CALS; + } + else if (b0 == (byte)0x7B && b1 == (byte)0x0A && b2 == (byte)0x20 && b3 == (byte)0x20 && + b4 == (byte)0x43 && b5 == (byte)0x72 && + b[6] == (byte)0x65 && b[7] == (byte)0x61 && b[8] == (byte)0x74 && b[9] == (byte)0x65 && b[10] == (byte)0x64) { + return T_MIF; + } + else if (b0 == (byte)0x7E && b1 == (byte)0x42 && b2 == (byte)0x4B && b3 == (byte)0x00) { + return T_PSP; + } + else if (b0 == (byte)0x80) { + if (b1 == (byte)0x2A && b2 == (byte)0x5F && b3 == (byte)0xD7 && + b4 == (byte)0x00 && b5 == (byte)0x00 && + b[6] == (byte)0x08 && b[7] == (byte)0x00 && b[8] == (byte)0x00 && b[9] == (byte)0x00 && b[10] == (byte)0x04 && + b[11] == (byte)0x00 && b[12] == (byte)0x00 && b[13] == (byte)0x00) { + return T_CIN; + } + else if (b1 == (byte)0x3E && b2 == (byte)0x44 && b3 == (byte)0x53 && + b4 == (byte)0x43 && b5 == (byte)0x49 && + b[6] == (byte)0x4D) { + return T_J6I; + } + } + else if (b0 == (byte)0x89 && b1 == (byte)0x50 && b2 == (byte)0x4E && b3 == (byte)0x47 && /* 'P' 'N' 'G', ascii code */ + b4 == (byte)0x0D && b5 == (byte)0x0A && b[6] == (byte)0x1A && b[7] == (byte)0x0A) { + // -119, 80, 78, 71, 13, 10, 26, 10 + return T_PNG; + } + else if (b0 == (byte)0x8A && b1 == (byte)0x4D && b2 == (byte)0x4E && b3 == (byte)0x47 && + b4 == (byte)0x0D && b5 == (byte)0x0A && + b[6] == (byte)0x1A && b[7] == (byte)0x0A) { + return T_MNG; + } + else if (b0 == (byte)0xD0 && b1 == (byte)0xCF && b2 == (byte)0x11 && b3 == (byte)0xE0 && + b4 == (byte)0xA1 && b5 == (byte)0xB1 && + b[6] == (byte)0x1A && b[7] == (byte)0xE1 && b[8] == (byte)0x00) { + return T_FPX; + } + else if (b0 == (byte)0xD3 && b1 == (byte)0x23 && b2 == (byte)0x00 && b3 == (byte)0x00 && + b4 == (byte)0x03 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x00) { + return T_WLM; + } + else if (b0 == (byte)0xD7 && b1 == (byte)0xCD && b2 == (byte)0xC6 && b3 == (byte)0x9A) { + return T_WMF; + } + else if (b0 == (byte)0xEB && b1 == (byte)0x3C && b2 == (byte)0x90 && b3 == (byte)0x2A) { + return T_IMG; + } + else if (b0 == (byte)0xFA && b1 == (byte)0xDE && b2 == (byte)0xBA && b3 == (byte)0xBE && + b4 == (byte)0x01 && b5 == (byte)0x01) { + return T_WIC; + } + else if (b0 == (byte)0xFF) { + if (b1 == (byte)0xD8 /* && b2 == (byte)0xff */) { + /** + * (b0 == (byte)0x45 && b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) || // EXIF + * (b0 == (byte)0x4A && b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) || // JFIF + * (b0 == (byte)0xff && b1 == (byte)0xd8 ) // && b2 == (byte)0xff + */ + return T_JPG; + } + else if (b1 == (byte)0x57 && b2 == (byte)0x50 && b3 == (byte)0x43 && b4 == (byte)0x10) { + return T_WPG; + } + } + return null; + } + } +} 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 18a7527b6..bdaa2d792 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -163,8 +163,10 @@ import com.jogamp.opengl.util.texture.spi.*; * @author Chris Campbell, Kenneth Russell, et.al. */ public class Texture { - /** The GL target type. */ + /** The GL target type for this texture. */ private int target; + /** The image GL target type for this texture, or its sub-components if cubemap. */ + private int imageTarget; /** The GL texture ID. */ private int texID; /** The width of the texture. */ @@ -190,7 +192,8 @@ public class Texture { @Override public String toString() { - return "Texture[target 0x"+Integer.toHexString(target)+", name "+texID+", "+ + final String targetS = target == imageTarget ? Integer.toHexString(target) : Integer.toHexString(target) + " - image "+Integer.toHexString(imageTarget); + return "Texture[target "+targetS+", name "+texID+", "+ imgWidth+"/"+texWidth+" x "+imgHeight+"/"+texHeight+", y-flip "+mustFlipVertically+ ", "+estimatedMemorySize+" bytes]"; } @@ -206,7 +209,9 @@ public class Texture { private static final boolean disableTexRect = Debug.isPropertyDefined("jogl.texture.notexrect", true); public Texture(final GL gl, final TextureData data) throws GLException { - texID = 0; + this.texID = 0; + this.target = 0; + this.imageTarget = 0; updateImage(gl, data); } @@ -217,8 +222,9 @@ public class Texture { * GL2.GL_TEXTURE_RECTANGLE */ public Texture(final int target) { - texID = 0; + this.texID = 0; this.target = target; + this.imageTarget = target; } /** @@ -250,11 +256,14 @@ public class Texture { final boolean mustFlipVertically) { this.texID = textureID; this.target = target; + this.imageTarget = target; this.mustFlipVertically = mustFlipVertically; this.texWidth = texWidth; this.texHeight = texHeight; - aspectRatio = (float) imgWidth / (float) imgHeight; - setImageSize(imgWidth, imgHeight, target); + this.aspectRatio = (float) imgWidth / (float) imgHeight; + this.imgWidth = imgWidth; + this.imgHeight = imgHeight; + this.updateTexCoords(); } /** @@ -344,8 +353,6 @@ public class Texture { /** * Returns the OpenGL "target" of this texture. - * - * @return the OpenGL target of this texture * @see com.jogamp.opengl.GL#GL_TEXTURE_2D * @see com.jogamp.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB */ @@ -354,6 +361,15 @@ public class Texture { } /** + * Returns the image OpenGL "target" of this texture, or its sub-components if cubemap. + * @see com.jogamp.opengl.GL#GL_TEXTURE_2D + * @see com.jogamp.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB + */ + public int getImageTarget() { + return imageTarget; + } + + /** * Returns the width of the allocated OpenGL texture in pixels. * Note that the texture width will be greater than or equal to the * width of the image contained within. @@ -438,7 +454,7 @@ public class Texture { * @return the texture coordinates corresponding to the specified sub-image */ public TextureCoords getSubImageTexCoords(final int x1, final int y1, final int x2, final int y2) { - if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { + if (GL2.GL_TEXTURE_RECTANGLE_ARB == imageTarget) { if (mustFlipVertically) { return new TextureCoords(x1, texHeight - y1, x2, texHeight - y2); } else { @@ -616,17 +632,17 @@ public class Texture { texHeight = nextPowerOfTwo(imgHeight); texTarget = GL.GL_TEXTURE_2D; } - texParamTarget = texTarget; - setImageSize(imgWidth, imgHeight, texTarget); + imageTarget = texTarget; + updateTexCoords(); if (targetOverride != 0) { // Allow user to override auto detection and skip bind step (for // cubemap construction) - texTarget = targetOverride; if (this.target == 0) { throw new GLException("Override of target failed; no target specified yet"); } + texTarget = targetOverride; texParamTarget = this.target; gl.glBindTexture(texParamTarget, texID); } else { @@ -977,17 +993,8 @@ public class Texture { return ret; } - /** - * Updates the actual image dimensions; usually only called from - * <code>updateImage</code>. - */ - private void setImageSize(final int width, final int height, final int target) { - imgWidth = width; - imgHeight = height; - updateTexCoords(); - } private void updateTexCoords() { - if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { + if ( GL2.GL_TEXTURE_RECTANGLE_ARB == imageTarget ) { if (mustFlipVertically) { coords = new TextureCoords(0, imgHeight, imgWidth, 0); } else { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java index 615d8c24f..5799f95a6 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -83,6 +83,9 @@ public class TextureData { protected GLProfile glProfile; protected ColorSpace pixelCS = ColorSpace.RGB; + // TODO: final, and set via ctor for 2.4.X + /* pp */ ImageType srcImageType; + /** * Constructs a new TextureData object with the specified parameters * and data contained in the given Buffer. The optional Flusher can @@ -341,6 +344,14 @@ public class TextureData { /** Used only by subclasses */ protected TextureData(final GLProfile glp) { this.glProfile = glp; this.pixelAttributes = GLPixelAttributes.UNDEF; } + /** + * Returns the source {@link ImageType} if applicable and known, otherwise {@code null}. + * @since 2.3.2 + */ + public final ImageType getSourceImageType() { + return srcImageType; + } + /** Returns the width in pixels of the texture data. */ public int getWidth() { return width; } /** Returns the height in pixels of the texture data. */ @@ -501,8 +512,9 @@ public class TextureData { @Override public String toString() { + final String optImageType = null != srcImageType ? ", "+srcImageType : ""; return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", "+ - pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; + pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength+optImageType; } //---------------------------------------------------------------------- diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java index 80b195642..2ac7c796d 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -52,8 +52,10 @@ import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.DimensionImmutable; @@ -72,6 +74,7 @@ import com.jogamp.common.util.IOUtil; import com.jogamp.opengl.util.GLPixelStorageModes; import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.ImageType; import com.jogamp.opengl.util.texture.spi.DDSImage; import com.jogamp.opengl.util.texture.spi.JPEGImage; import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter; @@ -134,44 +137,60 @@ import com.jogamp.opengl.util.texture.spi.TextureWriter; public class TextureIO { /** Constant which can be used as a file suffix to indicate a - DirectDraw Surface file. */ - public static final String DDS = "dds"; + DirectDraw Surface file, value {@value}. + <p>Alias for {@link ImageType#T_DDS}.</p> + */ + public static final String DDS = ImageType.T_DDS; - /** Constant which can be used as a file suffix to indicate an SGI - RGB file. */ + /** + * Constant which can be used as a file suffix to indicate an SGI RGB file, value {@value}. + * <p> + * Same semantics as {@link ImageType#SGI_RGB} and {@link #SGI_RGB}. + * </p> + */ public static final String SGI = "sgi"; - /** Constant which can be used as a file suffix to indicate an SGI - RGB file. */ - public static final String SGI_RGB = "rgb"; + /** Constant which can be used as a file suffix to indicate an SGI RGB file, value {@value}. + <p>Alias for {@link ImageType#T_SGI_RGB}. </p> + */ + public static final String SGI_RGB = ImageType.T_SGI_RGB; - /** Constant which can be used as a file suffix to indicate a GIF - file. */ - public static final String GIF = "gif"; + /** Constant which can be used as a file suffix to indicate a GIF file, value {@value}. + <p>Alias for {@link ImageType#T_GIF}.</p> + */ + public static final String GIF = ImageType.T_GIF; - /** Constant which can be used as a file suffix to indicate a JPEG - file. */ - public static final String JPG = "jpg"; + /** Constant which can be used as a file suffix to indicate a JPEG file, value {@value}. + <p>Alias for {@link ImageType#T_JPG}.</p> + */ + public static final String JPG = ImageType.T_JPG; - /** Constant which can be used as a file suffix to indicate a PNG - file. */ - public static final String PNG = "png"; + /** Constant which can be used as a file suffix to indicate a PNG file, value {@value}. + <p>Alias for {@link ImageType#T_PNG}.</p> + */ + public static final String PNG = ImageType.T_PNG; - /** Constant which can be used as a file suffix to indicate a Targa - file. */ - public static final String TGA = "tga"; + /** Constant which can be used as a file suffix to indicate a Targa file, value {@value}. + <p>Alias for {@link ImageType#T_TGA}.</p> + */ + public static final String TGA = ImageType.T_TGA; - /** Constant which can be used as a file suffix to indicate a TIFF - file. */ - public static final String TIFF = "tiff"; + /** Constant which can be used as a file suffix to indicate a TIFF file, value {@value}. + <p>Alias for {@link ImageType#T_TIFF}.</p> + */ + public static final String TIFF = ImageType.T_TIFF; /** Constant which can be used as a file suffix to indicate a PAM - file, NetPbm magic 7 - binary RGB and RGBA. Write support only. */ - public static final String PAM = "pam"; + file, NetPbm magic 7 - binary RGB and RGBA. Write support only, value {@value}. + <p>Alias for {@link ImageType#T_PAM}.</p> + */ + public static final String PAM = ImageType.T_PAM; /** Constant which can be used as a file suffix to indicate a PAM - file, NetPbm magic 6 - binary RGB. Write support only. */ - public static final String PPM = "ppm"; + file, NetPbm magic 6 - binary RGB. Write support only, value {@value}. + <p>Alias for {@link ImageType#T_PPM}.</p> + */ + public static final String PPM = ImageType.T_PPM; private static final boolean DEBUG = Debug.debug("TextureIO"); @@ -677,16 +696,27 @@ public class TextureIO { // /** - * Adds a TextureProvider to support reading of a new file format. + * Adds a {@link TextureProvider} to support reading of a new file format. * <p> * The last provider added, will be the first provider to be tested. * </p> + * <p> + * The {@link TextureProvider} is being mapped to its supporting {@link ImageType}s + * allowing an O(1) association, if {@link TextureProvider#} + * </p> */ public static void addTextureProvider(final TextureProvider provider) { // Must always add at the front so the ImageIO provider is last, // so we don't accidentally use it instead of a user's possibly // more optimal provider textureProviders.add(0, provider); + + final ImageType[] imageTypes = provider.getImageTypes(); + if( null != imageTypes ) { + for(int i=0; i<imageTypes.length; i++) { + imageType2TextureProvider.put(imageTypes[i], provider); + } + } } /** @@ -736,6 +766,7 @@ public class TextureIO { // private static List<TextureProvider> textureProviders = new ArrayList<TextureProvider>(); + private static Map<ImageType,TextureProvider> imageType2TextureProvider = new HashMap<ImageType,TextureProvider>(); private static List<TextureWriter> textureWriters = new ArrayList<TextureWriter>(); static { @@ -787,32 +818,6 @@ public class TextureIO { } // Implementation methods - private static TextureData newTextureDataImpl(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - String fileSuffix) throws IOException { - if (file == null) { - throw new IOException("File was null"); - } - - fileSuffix = toLowerCase(fileSuffix); - - for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) { - final TextureProvider provider = iter.next(); - final TextureData data = provider.newTextureData(glp, file, - internalFormat, - pixelFormat, - mipmap, - fileSuffix); - if (data != null) { - return data; - } - } - - throw new IOException("No suitable reader for given file "+file.getAbsolutePath()); - } - private static TextureData newTextureDataImpl(final GLProfile glp, InputStream stream, final int internalFormat, final int pixelFormat, @@ -822,70 +827,97 @@ public class TextureIO { throw new IOException("Stream was null"); } - fileSuffix = toLowerCase(fileSuffix); - // Note: use of BufferedInputStream works around 4764639/4892246 if (!(stream instanceof BufferedInputStream)) { stream = new BufferedInputStream(stream); } + // First attempt to use an ImageType mapped TextureProvider for O(1) + // using stream parsed data, ignoring the given fileSuffix! + try { + final ImageType imageType = new ImageType(stream); + if( imageType.isDefined() ) { + final TextureProvider mappedProvider = imageType2TextureProvider.get(imageType); + if( null != mappedProvider ) { + final TextureData data = mappedProvider.newTextureData(glp, stream, + internalFormat, + pixelFormat, + mipmap, + imageType.type); + if (data != null) { + data.srcImageType = imageType; + return data; + } + } + } + } catch (final IOException ioe) { + if(DEBUG) { + System.err.println("Caught "+ioe.getMessage()); + ioe.printStackTrace(); + } + } + + fileSuffix = toLowerCase(fileSuffix); + for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) { final TextureProvider provider = iter.next(); final TextureData data = provider.newTextureData(glp, stream, - internalFormat, - pixelFormat, - mipmap, - fileSuffix); + internalFormat, + pixelFormat, + mipmap, + fileSuffix); if (data != null) { + final ImageType[] imageTypes = provider.getImageTypes(); + data.srcImageType = null != imageTypes ? imageTypes[0] : null; return data; } } throw new IOException("No suitable reader for given stream"); } - + private static TextureData newTextureDataImpl(final GLProfile glp, final File file, + final int internalFormat, + final int pixelFormat, + final boolean mipmap, + final String fileSuffix) throws IOException { + if (file == null) { + throw new IOException("File was null"); + } + final InputStream stream = new BufferedInputStream(new FileInputStream(file)); + try { + return newTextureDataImpl( glp, stream, internalFormat, pixelFormat, mipmap, + (fileSuffix != null) ? fileSuffix : IOUtil.getFileSuffix(file) ); + } catch(final IOException ioe) { + throw new IOException(ioe.getMessage()+", given file "+file.getAbsolutePath(), ioe); + } finally { + stream.close(); + } + } private static TextureData newTextureDataImpl(final GLProfile glp, final URL url, final int internalFormat, final int pixelFormat, final boolean mipmap, - String fileSuffix) throws IOException { + final String fileSuffix) throws IOException { if (url == null) { throw new IOException("URL was null"); } - - fileSuffix = toLowerCase(fileSuffix); - - for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) { - final TextureProvider provider = iter.next(); - final TextureData data = provider.newTextureData(glp, url, - internalFormat, - pixelFormat, - mipmap, - fileSuffix); - if (data != null) { - return data; - } + final InputStream stream = new BufferedInputStream(url.openStream()); + try { + return newTextureDataImpl(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } catch(final IOException ioe) { + throw new IOException(ioe.getMessage()+", given URL "+url, ioe); + } finally { + stream.close(); } - - throw new IOException("No suitable reader for given URL "+url); } //---------------------------------------------------------------------- - // DDS provider -- supports files only for now + // DDS image provider static class DDSTextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_DDS) }; @Override - public TextureData newTextureData(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - if (DDS.equals(fileSuffix) || - DDS.equals(IOUtil.getFileSuffix(file))) { - final DDSImage image = DDSImage.read(file); - return newTextureData(glp, image, internalFormat, pixelFormat, mipmap); - } - - return null; + public final ImageType[] getImageTypes() { + return imageTypes; } @Override @@ -894,8 +926,8 @@ public class TextureIO { final int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (DDS.equals(fileSuffix) || - DDS.equals(ImageIOUtil.getFileSuffix(stream))) { + if (ImageType.T_DDS.equals(fileSuffix) || + ImageType.T_DDS.equals(ImageType.Util.getFileSuffix(stream))) { final byte[] data = IOUtil.copyStream2ByteArray(stream); final ByteBuffer buf = ByteBuffer.wrap(data); final DDSImage image = DDSImage.read(buf); @@ -905,20 +937,6 @@ public class TextureIO { return null; } - @Override - public TextureData newTextureData(final GLProfile glp, final URL url, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream stream = new BufferedInputStream(url.openStream()); - try { - return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); - } finally { - stream.close(); - } - } - private TextureData newTextureData(final GLProfile glp, final DDSImage image, int internalFormat, int pixelFormat, @@ -1003,47 +1021,14 @@ public class TextureIO { } //---------------------------------------------------------------------- - // Base class for SGI RGB and TGA image providers - static abstract class StreamBasedTextureProvider implements TextureProvider { - @Override - public TextureData newTextureData(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream inStream = new BufferedInputStream(new FileInputStream(file)); - try { - // The SGIImage and TGAImage implementations use InputStreams - // anyway so there isn't much point in having a separate code - // path for files - return newTextureData(glp, inStream, - internalFormat, - pixelFormat, - mipmap, - ((fileSuffix != null) ? fileSuffix : IOUtil.getFileSuffix(file))); - } finally { - inStream.close(); - } - } - + // SGI RGB image provider + static class SGITextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_SGI_RGB) }; @Override - public TextureData newTextureData(final GLProfile glp, final URL url, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream stream = new BufferedInputStream(url.openStream()); - try { - return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); - } finally { - stream.close(); - } + public final ImageType[] getImageTypes() { + return imageTypes; } - } - //---------------------------------------------------------------------- - // SGI RGB image provider - static class SGITextureProvider extends StreamBasedTextureProvider { @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, @@ -1051,9 +1036,9 @@ public class TextureIO { final boolean mipmap, final String fileSuffix) throws IOException { if (SGI.equals(fileSuffix) || - SGI_RGB.equals(fileSuffix) || - SGI.equals(ImageIOUtil.getFileSuffix(stream)) || - SGI_RGB.equals(ImageIOUtil.getFileSuffix(stream))) { + ImageType.T_SGI_RGB.equals(fileSuffix) || + SGI.equals(ImageType.Util.getFileSuffix(stream)) || + ImageType.T_SGI_RGB.equals(ImageType.Util.getFileSuffix(stream))) { final SGIImage image = SGIImage.read(stream); if (pixelFormat == 0) { pixelFormat = image.getFormat(); @@ -1080,14 +1065,20 @@ public class TextureIO { //---------------------------------------------------------------------- // TGA (Targa) image provider - static class TGATextureProvider extends StreamBasedTextureProvider { + static class TGATextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_TGA) }; + @Override + public final ImageType[] getImageTypes() { + return imageTypes; + } + @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (TGA.equals(fileSuffix)) { + if (ImageType.T_TGA.equals(fileSuffix)) { final TGAImage image = TGAImage.read(glp, stream); if (pixelFormat == 0) { pixelFormat = image.getGLFormat(); @@ -1118,15 +1109,21 @@ public class TextureIO { //---------------------------------------------------------------------- // PNG image provider - static class PNGTextureProvider extends StreamBasedTextureProvider { + static class PNGTextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_PNG) }; + @Override + public final ImageType[] getImageTypes() { + return imageTypes; + } + @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (PNG.equals(fileSuffix) || - PNG.equals(ImageIOUtil.getFileSuffix(stream))) { + if (ImageType.T_PNG.equals(fileSuffix) || + ImageType.T_PNG.equals(ImageType.Util.getFileSuffix(stream))) { final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); final GLPixelAttributes glpa = new GLPixelAttributes(glp, image.getPixelformat(), false /* pack */); if ( 0 == pixelFormat ) { @@ -1159,15 +1156,21 @@ public class TextureIO { //---------------------------------------------------------------------- // JPEG image provider - static class JPGTextureProvider extends StreamBasedTextureProvider { + static class JPGTextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_JPG) }; + @Override + public final ImageType[] getImageTypes() { + return imageTypes; + } + @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (JPG.equals(fileSuffix) || - JPG.equals(ImageIOUtil.getFileSuffix(stream))) { + if (ImageType.T_JPG.equals(fileSuffix) || + ImageType.T_JPG.equals(ImageType.Util.getFileSuffix(stream))) { final JPEGImage image = JPEGImage.read(/*glp, */ stream); if (pixelFormat == 0) { pixelFormat = image.getGLFormat(); @@ -1203,7 +1206,7 @@ public class TextureIO { @Override public boolean write(final File file, final TextureData data) throws IOException { - if (DDS.equals(IOUtil.getFileSuffix(file))) { + if (ImageType.T_DDS.equals(IOUtil.getFileSuffix(file))) { // See whether the DDS writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; @@ -1256,7 +1259,7 @@ public class TextureIO { final TextureData data) throws IOException { final String fileSuffix = IOUtil.getFileSuffix(file); if (SGI.equals(fileSuffix) || - SGI_RGB.equals(fileSuffix)) { + ImageType.T_SGI_RGB.equals(fileSuffix)) { // See whether the SGI writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; @@ -1300,7 +1303,7 @@ public class TextureIO { @Override public boolean write(final File file, final TextureData data) throws IOException { - if (TGA.equals(IOUtil.getFileSuffix(file))) { + if (ImageType.T_TGA.equals(IOUtil.getFileSuffix(file))) { // See whether the TGA writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; @@ -1350,7 +1353,7 @@ public class TextureIO { static class PNGTextureWriter implements TextureWriter { @Override public boolean write(final File file, final TextureData data) throws IOException { - if (PNG.equals(IOUtil.getFileSuffix(file))) { + if (ImageType.T_PNG.equals(IOUtil.getFileSuffix(file))) { // See whether the PNG writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java index 36c44a409..246676aae 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java @@ -53,8 +53,7 @@ import java.nio.channels.FileChannel; import com.jogamp.opengl.GL; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; -import com.jogamp.opengl.util.GLBuffers; -import com.jogamp.opengl.util.texture.ImageIOUtil; +import com.jogamp.opengl.util.texture.ImageType; /** A reader and writer for DirectDraw Surface (.dds) files, which are used to describe textures. These files can contain multiple mipmap @@ -238,38 +237,6 @@ public class DDSImage { return image; } - /** Determines from the magic number whether the given InputStream - points to a DDS image. The given InputStream must return true - from markSupported() and support a minimum of four bytes of - read-ahead. - - @param in Stream to check - @return true if input stream is DDS image or false otherwise - @throws java.io.IOException if an I/O exception occurred - @deprecated rather call {@link ImageIOUtil#getFileSuffix(InputStream)} - */ - @Deprecated - public static boolean isDDSImage(InputStream in) throws IOException { - if (!(in instanceof BufferedInputStream)) { - in = new BufferedInputStream(in); - } - if (!in.markSupported()) { - throw new IOException("Can not test non-destructively whether given InputStream is a DDS image"); - } - in.mark(4); - int magic = 0; - for (int i = 0; i < 4; i++) { - final int tmp = in.read(); - if (tmp < 0) { - in.reset(); - return false; - } - magic = ((magic >>> 8) | (tmp << 24)); - } - in.reset(); - return (magic == MAGIC); - } - /** * Writes this DDSImage to the specified file name. * @param filename File name to write to diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java index ff8167bb0..47e40e367 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java @@ -42,7 +42,7 @@ package com.jogamp.opengl.util.texture.spi; import java.io.*; import com.jogamp.opengl.*; -import com.jogamp.opengl.util.texture.ImageIOUtil; +import com.jogamp.opengl.util.texture.ImageType; import com.jogamp.common.util.IOUtil; /** <p> Reads and writes SGI RGB/RGBA images. </p> @@ -191,28 +191,6 @@ public class SGIImage { return image; } - /** - * Determines from the magic number whether the given InputStream points to - * an SGI RGB image. The given InputStream must return true from - * markSupported() and support a minimum of two bytes of read-ahead. - * - * @deprecated rather call {@link ImageIOUtil#getFileSuffix(InputStream)} - */ - @Deprecated - public static boolean isSGIImage(InputStream in) throws IOException { - if (!(in instanceof BufferedInputStream)) { - in = new BufferedInputStream(in); - } - if (!in.markSupported()) { - throw new IOException("Can not test non-destructively whether given InputStream is an SGI RGB image"); - } - final DataInputStream dIn = new DataInputStream(in); - dIn.mark(4); - final short magic = dIn.readShort(); - dIn.reset(); - return (magic == MAGIC); - } - /** Returns the width of the image. */ public int getWidth() { return header.xsize; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java index e84f300e2..485a1b82d 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2015 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,11 +40,13 @@ package com.jogamp.opengl.util.texture.spi; -import java.io.*; -import java.net.*; +import java.io.IOException; +import java.io.InputStream; + import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.util.texture.ImageType; +import com.jogamp.opengl.util.texture.TextureData; -import com.jogamp.opengl.util.texture.*; /** Plug-in interface to TextureIO to support reading OpenGL textures from new file formats. For all methods, either internalFormat or @@ -54,43 +57,24 @@ import com.jogamp.opengl.util.texture.*; public interface TextureProvider { /** - * Produces a TextureData object from a file, or returns null if the - * file format was not supported by this TextureProvider. Does not - * do any OpenGL-related work. The resulting TextureData can be - * converted into an OpenGL texture in a later step. - * - * @param glp the OpenGL Profile this texture data should be - * created for. - * @param file the file from which to read the texture data - * - * @param internalFormat the OpenGL internal format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param pixelFormat the OpenGL pixel format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param mipmap whether mipmaps should be produced for this - * texture either by autogenerating them or - * reading them from the file. Some file formats - * support multiple mipmaps in a single file in - * which case those mipmaps will be used rather - * than generating them. - * - * @param fileSuffix the file suffix to be used as a hint to the - * provider to more quickly decide whether it - * can handle the file, or null if the - * provider should infer the type from the - * file's contents - * - * @throws IOException if an error occurred while reading the file + * Optional additional interface for {@link TextureProvider} implementation + * exposing the supported {@link ImageType}s. + * <p> + * Use case: Mapping of {@link ImageType}s to {@link TextureProvider}. + * </p> */ - public TextureData newTextureData(GLProfile glp, File file, - int internalFormat, - int pixelFormat, - boolean mipmap, - String fileSuffix) throws IOException; + public static interface SupportsImageTypes { + /** Returns the supported {@link ImageType}s. */ + ImageType[] getImageTypes(); + } + + /** + * Returns the known supported {@link ImageType}s, or {@code null} if unknown. + * <p> + * Use case: Mapping of {@link ImageType}s to {@link TextureProvider}. + * </p> + */ + ImageType[] getImageTypes(); /** * Produces a TextureData object from a stream, or returns null if @@ -130,43 +114,4 @@ public interface TextureProvider { int pixelFormat, boolean mipmap, String fileSuffix) throws IOException; - - /** - * Produces a TextureData object from a URL, or returns null if the - * file format was not supported by this TextureProvider. Does not - * do any OpenGL-related work. The resulting TextureData can be - * converted into an OpenGL texture in a later step. - * - * @param glp the OpenGL Profile this texture data should be - * created for. - * @param url the URL from which to read the texture data - * - * @param internalFormat the OpenGL internal format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param pixelFormat the OpenGL pixel format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param mipmap whether mipmaps should be produced for this - * texture either by autogenerating them or - * reading them from the file. Some file formats - * support multiple mipmaps in a single file in - * which case those mipmaps will be used rather - * than generating them. - * - * @param fileSuffix the file suffix to be used as a hint to the - * provider to more quickly decide whether it - * can handle the file, or null if the - * provider should infer the type from the - * file's contents - * - * @throws IOException if an error occurred while reading the URL - */ - public TextureData newTextureData(GLProfile glp, URL url, - int internalFormat, - int pixelFormat, - boolean mipmap, - String fileSuffix) throws IOException; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java index ba762baf3..8ee54899c 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2015 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 @@ -36,39 +37,29 @@ * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ - +// package com.jogamp.opengl.util.texture.spi.awt; -import java.awt.Graphics; -import java.awt.image.*; -import java.io.*; -import java.net.*; -import javax.imageio.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.util.texture.ImageType; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.awt.AWTTextureData; +import com.jogamp.opengl.util.texture.spi.TextureProvider; import jogamp.opengl.Debug; -import com.jogamp.opengl.util.texture.*; -import com.jogamp.opengl.util.texture.awt.*; -import com.jogamp.opengl.util.texture.spi.*; public class IIOTextureProvider implements TextureProvider { private static final boolean DEBUG = Debug.debug("TextureIO"); @Override - public TextureData newTextureData(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final BufferedImage img = ImageIO.read(file); - if (img == null) { - return null; - } - if (DEBUG) { - System.out.println("TextureIO.newTextureData(): BufferedImage type for " + file + " = " + - img.getType()); - } - return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); + public final ImageType[] getImageTypes() { + return null; } @Override @@ -87,18 +78,4 @@ public class IIOTextureProvider implements TextureProvider { } return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); } - - @Override - public TextureData newTextureData(final GLProfile glp, final URL url, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream stream = url.openStream(); - try { - return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); - } finally { - stream.close(); - } - } } |