diff options
Diffstat (limited to 'src')
355 files changed, 14415 insertions, 5159 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(); - } - } } diff --git a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java index e4b0cb2a8..78140df6f 100644 --- a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java +++ b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java @@ -52,7 +52,6 @@ public class UbuntuFontLoader implements FontSet { private static final Uri.Encoded jarSubDir = Uri.Encoded.cast("atomic/"); private static final Uri.Encoded jarName = Uri.Encoded.cast("jogl-fonts-p0.jar"); - private static final String relFontPath = "fonts/ubuntu/" ; private static final String absFontPath = "jogamp/graph/font/fonts/ubuntu/" ; private static final FontSet fontLoader = new UbuntuFontLoader(); @@ -137,7 +136,7 @@ public class UbuntuFontLoader implements FontSet { if( !attemptedJARLoading ) { attemptedJARLoading = true; Platform.initSingleton(); - if( TempJarCache.isInitialized() ) { + if( TempJarCache.isInitialized(false) ) { try { final Uri uri = JarUtil.getRelativeOf(UbuntuFontLoader.class, jarSubDir, jarName); final Exception e0 = AccessController.doPrivileged(new PrivilegedAction<Exception>() { @@ -160,15 +159,14 @@ public class UbuntuFontLoader implements FontSet { } } } - final String path = useTempJARCache ? absFontPath : relFontPath; try { - final Font f = abspathImpl(path+fname, family, style); + final Font f = abspathImpl(absFontPath+fname, family, style); if( null != f ) { return f; } - throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname)); + throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, absFontPath, fname)); } catch(final Exception e) { - throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname), e); + throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, absFontPath, fname), e); } } private Font abspathImpl(final String fname, final int family, final int style) throws IOException { @@ -190,7 +188,7 @@ public class UbuntuFontLoader implements FontSet { throw new IOException(privErr[0]); } } else { - final URLConnection urlConn = IOUtil.getResource(UbuntuFontLoader.class, fname); + final URLConnection urlConn = IOUtil.getResource(fname, getClass().getClassLoader(), null); stream = null != urlConn ? urlConn.getInputStream() : null; } if(null != stream) { diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java index 6025b45ff..5eb429774 100644 --- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java +++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java @@ -48,7 +48,7 @@ public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper { gluLibNames.add("libGLU.so"); // unix gluLibNames.add("GLU32"); // windows gluLibNames.add("GLU"); // generic - gluLib = loadFirstAvailable(gluLibNames, null, true); + gluLib = loadFirstAvailable(gluLibNames, true, true, null, true); if(null != gluLib) { nativeLibraries.add(gluLib); } diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java index 331414869..b28b79418 100644 --- a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java +++ b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java @@ -45,7 +45,6 @@ import java.util.StringTokenizer; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES3; -import com.jogamp.opengl.GL2GL3; import com.jogamp.opengl.GLContext; import com.jogamp.common.util.VersionNumber; @@ -138,9 +137,9 @@ final class ExtensionAvailabilityCache { boolean useGetStringi = false; - // Use 'glGetStringi' only for ARB GL3 context, + // Use 'glGetStringi' only for ARB GL3 and ES3 context, // on GL2 platforms the function might be available, but not working. - if ( context.isGL3() ) { + if ( context.isGL3() || context.isGLES3() ) { if ( ! context.isFunctionAvailable("glGetStringi") ) { if(DEBUG) { System.err.println("GLContext: GL >= 3.1 usage, but no glGetStringi"); @@ -156,16 +155,16 @@ final class ExtensionAvailabilityCache { } if(useGetStringi) { - final GL2GL3 gl2gl3 = gl.getGL2GL3(); + final GL2ES3 gl2es3 = (GL2ES3)gl; // validated via context - OK! final int count; { final int[] val = { 0 } ; - gl2gl3.glGetIntegerv(GL2ES3.GL_NUM_EXTENSIONS, val, 0); + gl2es3.glGetIntegerv(GL2ES3.GL_NUM_EXTENSIONS, val, 0); count = val[0]; } final StringBuilder sb = new StringBuilder(); for (int i = 0; i < count; i++) { - final String ext = gl2gl3.glGetStringi(GL.GL_EXTENSIONS, i); + final String ext = gl2es3.glGetStringi(GL.GL_EXTENSIONS, i); if( null == availableExtensionCache.put(ext, ext) ) { // new one if( 0 < i ) { diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 19fd6c7e1..9d1490300 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -51,6 +51,7 @@ import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.GLSharedContextSetter; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.GLEventListenerState; @@ -598,6 +599,44 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe return helper.getExclusiveContextThread(); } + /** + * Invokes given {@code runnable} on current thread outside of a probable claimed exclusive thread, + * i.e. releases the exclusive thread, executes the runnable and reclaims it. + * FIXME: Promote to GLAutoDrawable! + * + * @param runnable the {@link Runnable} to execute on the new thread. + * The runnable <b>must exit</b>, i.e. not loop forever. + * + * @see #setExclusiveContextThread(Thread, GLContext) + * + * @since 2.3.2 + */ + public final void invokeOnCurrentThread(final Runnable runnable) { + helper.runOutsideOfExclusiveContextThread(context, runnable); + } + /** + * Invokes given {@code runnable} on current thread outside of a probable claimed exclusive thread, + * i.e. releases the exclusive thread, executes the runnable and reclaims it. + * FIXME: Promote to GLAutoDrawable! + * + * @param tg the {@link ThreadGroup} for the new thread, maybe <code>null</code> + * @param waitUntilDone if <code>true</code>, waits until <code>runnable</code> execution is completed, otherwise returns immediately. + * @param runnable the {@link Runnable} to execute on the new thread. + * The runnable <b>must exit</b>, i.e. not loop forever. + * @return {@link RunnableTask} instance with execution details + * + * @see #setExclusiveContextThread(Thread, GLContext) + * + * @since 2.3.2 + */ + public final RunnableTask invokeOnNewThread(final ThreadGroup tg, final boolean waitUntilDone, final Runnable runnable) { + return RunnableTask.invokeOnNewThread(tg, null, waitUntilDone, + new Runnable() { + public final void run() { + helper.runOutsideOfExclusiveContextThread(context, runnable); + } }); + } + @Override public final boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException { return helper.invoke(this, wait, glRunnable); diff --git a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java index 2aa4c4297..a5bd85eb1 100644 --- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java +++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java @@ -40,9 +40,13 @@ package jogamp.opengl; -import com.jogamp.opengl.*; import com.jogamp.common.util.IntIntHashMap; import com.jogamp.common.util.PropertyAccess; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES3; +import com.jogamp.opengl.GL3ES3; +import com.jogamp.opengl.GL4; +import com.jogamp.opengl.GLException; /** * Tracks as closely as possible which OpenGL buffer object is bound @@ -119,6 +123,8 @@ public class GLBufferStateTracker { * GL_ELEMENT_ARRAY_BUFFER​, * GL_PIXEL_PACK_BUFFER​, * GL_PIXEL_UNPACK_BUFFER​, + * GL_QUERY_BUFFER, + * GL_PARAMETER_BUFFER_ARB, * GL_SHADER_STORAGE_BUFFER​, * GL_TEXTURE_BUFFER​, * GL_TRANSFORM_FEEDBACK_BUFFER​ or @@ -139,8 +145,9 @@ public class GLBufferStateTracker { case GL2ES3.GL_PIXEL_PACK_BUFFER: return GL2ES3.GL_PIXEL_PACK_BUFFER_BINDING; case GL2ES3.GL_PIXEL_UNPACK_BUFFER: return GL2ES3.GL_PIXEL_UNPACK_BUFFER_BINDING; case GL4.GL_QUERY_BUFFER: return GL4.GL_QUERY_BUFFER_BINDING; + case GL4.GL_PARAMETER_BUFFER_ARB: return GL4.GL_PARAMETER_BUFFER_BINDING_ARB; // ARB_indirect_parameters case GL3ES3.GL_SHADER_STORAGE_BUFFER: return GL3ES3.GL_SHADER_STORAGE_BUFFER_BINDING; - case GL2GL3.GL_TEXTURE_BUFFER: return GL2GL3.GL_TEXTURE_BINDING_BUFFER; + case GL2ES3.GL_TEXTURE_BUFFER: return GL2ES3.GL_TEXTURE_BINDING_BUFFER; case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER: return GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER_BINDING; case GL2ES3.GL_UNIFORM_BUFFER: return GL2ES3.GL_UNIFORM_BUFFER_BINDING; @@ -162,8 +169,9 @@ public class GLBufferStateTracker { case GL2ES3.GL_PIXEL_PACK_BUFFER: case GL2ES3.GL_PIXEL_UNPACK_BUFFER: case GL4.GL_QUERY_BUFFER: + case GL4.GL_PARAMETER_BUFFER_ARB: // ARB_indirect_parameters case GL3ES3.GL_SHADER_STORAGE_BUFFER: - case GL2GL3.GL_TEXTURE_BUFFER: + case GL2ES3.GL_TEXTURE_BUFFER: case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER: case GL2ES3.GL_UNIFORM_BUFFER: diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 8f4105f98..6866374bc 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -45,7 +45,10 @@ import java.nio.IntBuffer; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.os.DynamicLookupHelper; @@ -59,12 +62,12 @@ import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.GLRendererQuirks; - import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.AbstractGraphicsDevice; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.nativewindow.ProxySurface; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GL2ES3; @@ -126,11 +129,13 @@ public abstract class GLContextImpl extends GLContext { * If GL >= 3.0 (ES or desktop) and not having {@link GLRendererQuirks#NoSurfacelessCtx}, * being evaluated if not surface-handle is null and not yet set at makeCurrent(..). */ - private boolean surfacelessOK = false; + private boolean isSurfaceless = false; private boolean pixelDataEvaluated; private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType; + private int currentSwapInterval; + protected GL gl; protected static final Object mappedContextTypeObjectLock; @@ -207,8 +212,9 @@ public abstract class GLContextImpl extends GLContext { boundFBOTarget[1] = 0; // read } - surfacelessOK = false; + isSurfaceless = false; pixelDataEvaluated = false; + currentSwapInterval = 0; super.resetStates(isInit); } @@ -536,7 +542,7 @@ public abstract class GLContextImpl extends GLContext { //---------------------------------------------------------------------- // - protected final boolean isSurfacelessOK() { return surfacelessOK; } + protected final boolean isSurfaceless() { return isSurfaceless; } /** * {@inheritDoc} @@ -607,7 +613,7 @@ public abstract class GLContextImpl extends GLContext { if ( drawable.isRealized() ) { lock.lock(); try { - if ( 0 == drawable.getHandle() && !surfacelessOK ) { + if ( 0 == drawable.getHandle() && !isSurfaceless ) { if( DEBUG ) { System.err.println(getThreadName() +": GLContext.makeCurrent: Surfaceless evaluate"); } @@ -671,7 +677,7 @@ public abstract class GLContextImpl extends GLContext { } if ( CONTEXT_NOT_CURRENT != res ) { // still locked! - if( 0 == drawable.getHandle() && !surfacelessOK ) { + if( 0 == drawable.getHandle() && !isSurfaceless ) { if( hasRendererQuirk(GLRendererQuirks.NoSurfacelessCtx) ) { throw new GLException(String.format("Surfaceless not supported due to quirk %s: %s", GLRendererQuirks.toString(GLRendererQuirks.NoSurfacelessCtx), toString())); @@ -679,15 +685,15 @@ public abstract class GLContextImpl extends GLContext { if( DEBUG ) { System.err.println(getThreadName() +": GLContext.makeCurrent: Surfaceless OK - validated"); } - surfacelessOK = true; + isSurfaceless = true; } setCurrent(this); if( CONTEXT_CURRENT_NEW == res ) { // check if the drawable's and the GL's GLProfile are equal // throws an GLException if not - drawable.getGLProfile().verifyEquality(gl.getGLProfile()); + // FIXME: drawable.getGLProfile().verifyEquality(gl.getGLProfile()); - glDebugHandler.init( isGL2GL3() && isGLDebugEnabled() ); + glDebugHandler.init( isGLDebugEnabled() ); if(DEBUG_GL) { setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ); @@ -802,28 +808,28 @@ public abstract class GLContextImpl extends GLContext { reqProfile = GLContext.CTX_PROFILE_COMPAT; isCompat = true; } - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + final MappedGLVersion me = mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); // Perform all required profile mappings if( isCompat ) { // COMPAT via non ARB - GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); if( reqMajor >= 4 ) { - GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - GLContext.mapAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 3, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); + mapAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); } if( reqMajor >= 3 ) { - GLContext.mapAvailableGLVersion(device, 2, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 2, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); } } else { // CORE via non ARB, unlikely, however .. if( reqMajor >= 4 ) { - GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 3, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); } } GLContext.setAvailableGLVersionsSet(device, true); if (DEBUG) { - System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + System.err.println(getThreadName() + ": createContextOLD-MapGLVersions HAVE: " + me); } } } @@ -947,13 +953,13 @@ public abstract class GLContextImpl extends GLContext { { final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice device = config.getScreen().getDevice(); - if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB: mappedVersionsAvailableSet("+device.getConnection()+"): "+ - GLContext.getAvailableGLVersionsSet(device)); - } final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final GLProfile glp = glCaps.getGLProfile(); + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions is SET ("+device.getConnection()+"): "+ + GLContext.getAvailableGLVersionsSet(device)); + } if ( !GLContext.getAvailableGLVersionsSet(device) ) { if( !mapGLVersions(device) ) { // none of the ARB context creation calls was successful, bail out @@ -965,7 +971,7 @@ public abstract class GLContextImpl extends GLContext { GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); if(DEBUG) { - System.err.println(getThreadName() + ": createContextARB: Requested "+glp+" -> "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[1], null)); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions Requested "+glp+" -> "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[1], null)); } final int _major[] = { 0 }; final int _minor[] = { 0 }; @@ -975,7 +981,7 @@ public abstract class GLContextImpl extends GLContext { _major, _minor, _ctp)) { _ctp[0] |= additionalCtxCreationFlags; if(DEBUG) { - System.err.println(getThreadName() + ": createContextARB: Mapped "+GLContext.getGLVersion(_major[0], _minor[0], _ctp[0], null)); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions Mapped "+GLContext.getGLVersion(_major[0], _minor[0], _ctp[0], null)); } _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { @@ -987,8 +993,156 @@ public abstract class GLContextImpl extends GLContext { return _ctx; } + //---------------------------------------------------------------------- + // + + public static class MappedGLVersion { + public final AbstractGraphicsDevice device; + public final int reqMajorVersion; + public final int reqProfile; + public final VersionNumber ctxVersion; + public final int ctxOptions; + public final GLRendererQuirks quirks; + public final VersionNumber preCtxVersion; + public final int preCtxOptions; + public MappedGLVersion(final AbstractGraphicsDevice device, final int reqMajorVersion, final int reqProfile, + final VersionNumber ctxVersion, final int ctxOptions, final GLRendererQuirks quirks, + final VersionNumber preCtxVersion, final int preCtxOptions) { + this.device = device; + this.reqMajorVersion = reqMajorVersion; + this.reqProfile = reqProfile; + this.ctxVersion = ctxVersion; + this.ctxOptions = ctxOptions; + this.quirks = quirks; + this.preCtxVersion = preCtxVersion; + this.preCtxOptions = preCtxOptions; + } + public final String toString() { + return toString(new StringBuilder(), -1, -1, -1, -1).toString(); + } + public final StringBuilder toString(final StringBuilder sb, final int minMajor, final int minMinor, final int maxMajor, final int maxMinor) { + sb.append(device.toString()).append(" ").append(reqMajorVersion).append(" ("); + GLContext.getGLProfile(sb, reqProfile).append(")"); + if( minMajor >=0 && minMinor >=0 && maxMajor >= 0 && maxMinor >= 0) { + sb.append("[").append(minMajor).append(".").append(minMinor).append(" .. ").append(maxMajor).append(".").append(maxMinor).append("]"); + } + sb.append(": ["); + if( null != preCtxVersion ) { + GLContext.getGLVersion(sb, preCtxVersion, preCtxOptions, null); + } else { + sb.append("None"); + } + sb.append("] -> ["); + GLContext.getGLVersion(sb, ctxVersion, ctxOptions, null).append("]"); + return sb; + } + } + public static interface MappedGLVersionListener { + void glVersionMapped(final MappedGLVersion e); + } + private static MappedGLVersionListener mapGLVersionListener = null; + protected static synchronized void setMappedGLVersionListener(final MappedGLVersionListener mvl) { + mapGLVersionListener = mvl; + } + + /** + * 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} + * @param resVersion the resulting version number + * @param resCtp the resulting context options + * @return the old mapped value + * + * @see #createContextARBMapVersionsAvailable + */ + protected static MappedGLVersion mapAvailableGLVersion(final AbstractGraphicsDevice device, + final int reqMajor, final int profile, + final VersionNumber resVersion, final int resCtp, + final GLRendererQuirks resQuirks) + { + final Integer preVal = mapAvailableGLVersion(device, reqMajor, profile, resVersion, resCtp); + final int[] preCtp = { 0 }; + final VersionNumber preVersion = null != preVal ? decomposeBits(preVal.intValue(), preCtp) : null; + final MappedGLVersion res = new MappedGLVersion(device, reqMajor, profile, resVersion, resCtp, resQuirks, preVersion, preCtp[0]); + if( null != mapGLVersionListener ) { + mapGLVersionListener.glVersionMapped(res); + } + return res; + } + private static Integer mapAvailableGLVersion(final AbstractGraphicsDevice device, + final int reqMajor, final int profile, final VersionNumber resVersion, int resCtp) + { + validateProfileBits(profile, "profile"); + validateProfileBits(resCtp, "resCtp"); + + if(FORCE_NO_FBO_SUPPORT) { + resCtp &= ~CTX_IMPL_FBO ; + } + if(DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions MAP "+device+": "+reqMajor+" ("+GLContext.getGLProfile(new StringBuilder(), profile).toString()+ ") -> "+ + getGLVersion(resVersion.getMajor(), resVersion.getMinor(), resCtp, null)); + } + final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile); + final Integer val = Integer.valueOf(composeBits(resVersion.getMajor(), resVersion.getMinor(), resCtp)); + synchronized(deviceVersionAvailable) { + return deviceVersionAvailable.put( objectKey, val ); + } + } + + + protected static void remapAvailableGLVersions(final AbstractGraphicsDevice fromDevice, final AbstractGraphicsDevice toDevice) { + if( fromDevice == toDevice || fromDevice.getUniqueID() == toDevice.getUniqueID() ) { + return; // NOP + } + synchronized(deviceVersionAvailable) { + if(DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions REMAP "+fromDevice+" -> "+toDevice); + } + final IdentityHashMap<String, Integer> newDeviceVersionAvailable = new IdentityHashMap<String, Integer>(); + final Set<String> keys = deviceVersionAvailable.keySet(); + for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); ) { + final String origKey = keyI.next(); + final Integer valI = deviceVersionAvailable.get(origKey); + if( null != valI ) { + if(DEBUG) { + final int[] ctp = { 0 }; + final VersionNumber version = decomposeBits(valI.intValue(), ctp); + System.err.println(" MapGLVersions REMAP OLD "+origKey+" -> "+GLContext.getGLVersion(new StringBuilder(), version, ctp[0], null).toString()); + } + newDeviceVersionAvailable.put(origKey, valI); + final int devSepIdx = origKey.lastIndexOf('-'); + if( 0 >= devSepIdx ) { + throw new InternalError("device-separator '-' at "+devSepIdx+" of "+origKey); + } + final String devUniqueID = origKey.substring(0, devSepIdx); + if( fromDevice.getUniqueID().equals(devUniqueID) ) { + final String profileReq = origKey.substring(devSepIdx); + final String newKey = (toDevice.getUniqueID()+profileReq).intern(); + if(DEBUG) { + System.err.println(" MapGLVersions REMAP NEW "+newKey+" -> (ditto)"); + } + newDeviceVersionAvailable.put(newKey, valI); + } + } + } + deviceVersionAvailable.clear(); + deviceVersionAvailable.putAll(newDeviceVersionAvailable); + GLContext.setAvailableGLVersionsSet(toDevice, true); + } + } + private final boolean mapGLVersions(final AbstractGraphicsDevice device) { synchronized (GLContext.deviceVersionAvailable) { + final boolean hasOpenGLESSupport = drawable.getFactory().hasOpenGLESSupport(); + final boolean hasOpenGLDesktopSupport = drawable.getFactory().hasOpenGLDesktopSupport(); + final boolean hasMinorVersionSupport = drawable.getFactoryImpl().hasMajorMinorCreateContextARB(); + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions START (GLDesktop "+hasOpenGLDesktopSupport+", GLES "+hasOpenGLESSupport+", minorVersion "+hasMinorVersionSupport+") on "+device); + } final long t0 = ( DEBUG ) ? System.nanoTime() : 0; boolean success = false; // Following GLProfile.GL_PROFILE_LIST_ALL order of profile detection { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 } @@ -997,6 +1151,43 @@ public abstract class GLContextImpl extends GLContext { boolean hasGL2 = false; boolean hasGL4 = false; boolean hasGL3 = false; + boolean hasES3 = false; + boolean hasES2 = false; + boolean hasES1 = false; + + if( hasOpenGLESSupport && !GLProfile.disableOpenGLES ) { + if( !hasES3) { + hasES3 = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_ES, hasMinorVersionSupport); // ES3 + success |= hasES3; + if( hasES3 ) { + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel ES3 to all lower core profiles: ES2 + mapAvailableGLVersion(device, 2, CTX_PROFILE_ES, ctxVersion, ctxOptions, glRendererQuirks); + if( PROFILE_ALIASING ) { + hasES2 = true; + } + } + resetStates(false); // clean context states, since creation was temporary + } + } + if( !hasES2) { + hasES2 = createContextARBMapVersionsAvailable(device, 2, CTX_PROFILE_ES, hasMinorVersionSupport); // ES2 + success |= hasES2; + if( hasES2 ) { + if( ctxVersion.getMajor() >= 3 && hasRendererQuirk(GLRendererQuirks.GLES3ViaEGLES2Config)) { + mapAvailableGLVersion(device, 3, CTX_PROFILE_ES, ctxVersion, ctxOptions, glRendererQuirks); + } + resetStates(false); // clean context states, since creation was temporary + } + } + if( !hasES1) { + hasES1 = createContextARBMapVersionsAvailable(device, 1, CTX_PROFILE_ES, hasMinorVersionSupport); // ES1 + success |= hasES1; + if( hasES1 ) { + resetStates(false); // clean context states, since creation was temporary + } + } + } // Even w/ PROFILE_ALIASING, try to use true core GL profiles // ensuring proper user behavior across platforms due to different feature sets! @@ -1006,31 +1197,31 @@ public abstract class GLContextImpl extends GLContext { /** * OSX 10.9 GLRendererQuirks.GL4NeedsGL3Request, quirk is added as usual @ setRendererQuirks(..) */ - if( !GLProfile.disableOpenGLCore && !hasGL4 && !hasGL3 ) { - hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 + if( hasOpenGLDesktopSupport && !GLProfile.disableOpenGLDesktop && !GLProfile.disableOpenGLCore && !hasGL4 && !hasGL3 ) { + hasGL3 = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_CORE, hasMinorVersionSupport); // GL3 success |= hasGL3; if( hasGL3 ) { final boolean isHWAccel = 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ); if( isHWAccel && ctxVersion.getMajor() >= 4 ) { // Gotcha: Creating a '3.2' ctx delivers a >= 4 ctx. - GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); hasGL4 = true; if(DEBUG) { - System.err.println("Quirk Triggerd: "+GLRendererQuirks.toString(GLRendererQuirks.GL4NeedsGL3Request)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions: Quirk Triggerd: "+GLRendererQuirks.toString(GLRendererQuirks.GL4NeedsGL3Request)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()); } } resetStates(false); // clean the context states, since creation was temporary } } } - if( !GLProfile.disableOpenGLCore ) { + if( hasOpenGLDesktopSupport && !GLProfile.disableOpenGLDesktop && !GLProfile.disableOpenGLCore ) { if( !hasGL4 ) { - hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4 + hasGL4 = createContextARBMapVersionsAvailable(device, 4, CTX_PROFILE_CORE, hasMinorVersionSupport); // GL4 success |= hasGL4; if( hasGL4 ) { if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { // Map hw-accel GL4 to all lower core profiles: GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); if( PROFILE_ALIASING ) { hasGL3 = true; } @@ -1039,72 +1230,74 @@ public abstract class GLContextImpl extends GLContext { } } if( !hasGL3 ) { - hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 + hasGL3 = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_CORE, hasMinorVersionSupport); // GL3 success |= hasGL3; if( hasGL3 ) { resetStates(false); // clean this context states, since creation was temporary } } } - if( !hasGL4bc ) { - hasGL4bc = createContextARBMapVersionsAvailable(4, CTX_PROFILE_COMPAT); // GL4bc - success |= hasGL4bc; - if( hasGL4bc ) { - if( !hasGL4 ) { // last chance .. ignore hw-accel - GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - hasGL4 = true; - } - if( !hasGL3 ) { // last chance .. ignore hw-accel - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - hasGL3 = true; - } - if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { - // Map hw-accel GL4bc to all lower compatible profiles: GL3bc, GL2 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(PROFILE_ALIASING) { - hasGL3bc = true; - hasGL2 = true; + if( hasOpenGLDesktopSupport && !GLProfile.disableOpenGLDesktop ) { + if( !hasGL4bc ) { + hasGL4bc = createContextARBMapVersionsAvailable(device, 4, CTX_PROFILE_COMPAT, hasMinorVersionSupport); // GL4bc + success |= hasGL4bc; + if( hasGL4bc ) { + if( !hasGL4 ) { // last chance .. ignore hw-accel + mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); + hasGL4 = true; + } + if( !hasGL3 ) { // last chance .. ignore hw-accel + mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); + hasGL3 = true; + } + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL4bc to all lower compatible profiles: GL3bc, GL2 + mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion, ctxOptions, glRendererQuirks); + mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion, ctxOptions, glRendererQuirks); + if(PROFILE_ALIASING) { + hasGL3bc = true; + hasGL2 = true; + } } + resetStates(false); // clean this context states, since creation was temporary } - resetStates(false); // clean this context states, since creation was temporary } - } - if( !hasGL3bc ) { - hasGL3bc = createContextARBMapVersionsAvailable(3, CTX_PROFILE_COMPAT); // GL3bc - success |= hasGL3bc; - if( hasGL3bc ) { - if(!hasGL3) { // last chance .. ignore hw-accel - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - hasGL3 = true; - } - if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { - // Map hw-accel GL3bc to all lower compatible profiles: GL2 - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(PROFILE_ALIASING) { - hasGL2 = true; + if( !hasGL3bc ) { + hasGL3bc = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_COMPAT, hasMinorVersionSupport); // GL3bc + success |= hasGL3bc; + if( hasGL3bc ) { + if(!hasGL3) { // last chance .. ignore hw-accel + mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); + hasGL3 = true; } + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL3bc to all lower compatible profiles: GL2 + mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion, ctxOptions, glRendererQuirks); + if(PROFILE_ALIASING) { + hasGL2 = true; + } + } + resetStates(false); // clean this context states, since creation was temporary } - resetStates(false); // clean this context states, since creation was temporary } - } - if( !hasGL2 ) { - hasGL2 = createContextARBMapVersionsAvailable(2, CTX_PROFILE_COMPAT); // GL2 - success |= hasGL2; - if( hasGL2 ) { - resetStates(false); // clean this context states, since creation was temporary + if( !hasGL2 ) { + hasGL2 = createContextARBMapVersionsAvailable(device, 2, CTX_PROFILE_COMPAT, hasMinorVersionSupport); // GL2 + success |= hasGL2; + if( hasGL2 ) { + resetStates(false); // clean this context states, since creation was temporary + } } } if(success) { // only claim GL versions set [and hence detected] if ARB context creation was successful GLContext.setAvailableGLVersionsSet(device, true); - if(DEBUG) { - final long t1 = System.nanoTime(); - System.err.println("GLContextImpl.mapGLVersions: "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms"); + } + if(DEBUG) { + final long t1 = System.nanoTime(); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions END (success "+success+") on "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms"); + if( success ) { System.err.println(GLContext.dumpAvailableGLVersions(null).toString()); } - } else if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersions NONE for :"+device); } return success; } @@ -1114,38 +1307,61 @@ public abstract class GLContextImpl extends GLContext { * Note: Since context creation is temporary, caller need to issue {@link #resetStates(boolean)}, if creation was successful, i.e. returns true. * This method does not reset the states, allowing the caller to utilize the state variables. **/ - private final boolean createContextARBMapVersionsAvailable(final int reqMajor, final int reqProfile) { + private final boolean createContextARBMapVersionsAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, + final boolean hasMinorVersionSupport) { long _context; int ctp = CTX_IS_ARB_CREATED | reqProfile; // To ensure GL profile compatibility within the JOGL application // we always try to map against the highest GL version, // so the user can always cast to the highest available one. - int majorMax, minorMax; - int majorMin, minorMin; + int maxMajor, maxMinor; + int minMajor, minMinor; final int major[] = new int[1]; final int minor[] = new int[1]; - if( CTX_PROFILE_ES == reqProfile ) { - majorMax=reqMajor; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=reqMajor; minorMin=0; + if( hasMinorVersionSupport ) { + if( CTX_PROFILE_ES == reqProfile ) { + // ES3, ES2 or ES1 + maxMajor=reqMajor; maxMinor=GLContext.getMaxMinor(ctp, maxMajor); + minMajor=reqMajor; minMinor=0; + } else { + if( 4 == reqMajor ) { + maxMajor=4; maxMinor=GLContext.getMaxMinor(ctp, maxMajor); + minMajor=4; minMinor=0; + } else if( 3 == reqMajor ) { + maxMajor=3; maxMinor=GLContext.getMaxMinor(ctp, maxMajor); + minMajor=3; minMinor=1; + } else /* if( glp.isGL2() ) */ { + // our minimum desktop OpenGL runtime requirements are 1.1, + // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts + maxMajor=3; maxMinor=0; + minMajor=2; minMinor=0; + } + } } else { - if( 4 == reqMajor ) { - majorMax=4; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=4; minorMin=0; - } else if( 3 == reqMajor ) { - majorMax=3; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=3; minorMin=1; - } else /* if( glp.isGL2() ) */ { - // our minimum desktop OpenGL runtime requirements are 1.1, - // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts - majorMax=3; minorMax=0; - majorMin=2; minorMin=0; + if( CTX_PROFILE_ES == reqProfile ) { + // ES3, ES2 or ES1 + maxMajor=reqMajor; maxMinor=0; + minMajor=reqMajor; minMinor=0; + } else { + if( 4 == reqMajor ) { + maxMajor=4; maxMinor=0; + minMajor=4; minMinor=0; + } else if( 3 == reqMajor ) { + maxMajor=3; maxMinor=1; + minMajor=3; minMinor=1; + } else /* if( glp.isGL2() ) */ { + // our minimum desktop OpenGL runtime requirements are 1.1, + // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts + maxMajor=2; maxMinor=0; + minMajor=2; minMinor=0; + } } } _context = createContextARBVersions(0, true, ctp, - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, + /* max */ maxMajor, maxMinor, + /* min */ minMajor, minMinor, /* res */ major, minor); if( 0 == _context && CTX_PROFILE_CORE == reqProfile && !PROFILE_ALIASING ) { @@ -1153,8 +1369,8 @@ public abstract class GLContextImpl extends GLContext { ctp &= ~CTX_PROFILE_CORE ; ctp |= CTX_OPTION_FORWARD ; _context = createContextARBVersions(0, true, ctp, - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, + /* max */ maxMajor, maxMinor, + /* min */ minMajor, minMinor, /* res */ major, minor); if( 0 == _context ) { // Try a compatible one .. even though not requested .. last resort @@ -1162,25 +1378,24 @@ public abstract class GLContextImpl extends GLContext { ctp &= ~CTX_OPTION_FORWARD ; ctp |= CTX_PROFILE_COMPAT ; _context = createContextARBVersions(0, true, ctp, - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, + /* max */ maxMajor, maxMinor, + /* min */ minMajor, minMinor, /* res */ major, minor); } } final boolean res; if( 0 != _context ) { - final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by // createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..) - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + final MappedGLVersion me = mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); destroyContextARBImpl(_context); if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions HAVE "+me.toString(new StringBuilder(), minMajor, minMinor, maxMajor, maxMinor).toString()); } res = true; } else { if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions NOPE "+device+", "+reqMajor+" ("+GLContext.getGLProfile(new StringBuilder(), reqProfile).toString()+ ") ["+maxMajor+"."+maxMinor+" .. "+minMajor+"."+minMinor+"]"); } res = false; } @@ -1188,11 +1403,11 @@ public abstract class GLContextImpl extends GLContext { } private final long createContextARBVersions(final long share, final boolean direct, final int ctxOptionFlags, - final int majorMax, final int minorMax, - final int majorMin, final int minorMin, + final int maxMajor, final int maxMinor, + final int minMajor, final int minMinor, final int major[], final int minor[]) { - major[0]=majorMax; - minor[0]=minorMax; + major[0]=maxMajor; + minor[0]=maxMinor; long _context=0; int i=0; @@ -1200,7 +1415,7 @@ public abstract class GLContextImpl extends GLContext { if (DEBUG) { i++; System.err.println(getThreadName() + ": createContextARBVersions."+i+": share "+share+", direct "+direct+ - ", version "+major[0]+"."+minor[0]+", major["+majorMin+".."+majorMax+"], minor["+minorMin+".."+minorMax+"]"); + ", version "+major[0]+"."+minor[0]+" ["+maxMajor+"."+maxMinor+" .. "+minMajor+"."+minMinor+"]"); } _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); @@ -1213,12 +1428,12 @@ public abstract class GLContextImpl extends GLContext { } } - } while ( ( major[0]>majorMin || major[0]==majorMin && minor[0] >minorMin ) && // #1 check whether version is above lower limit + } while ( ( major[0]>minMajor || major[0]==minMajor && minor[0] >minMinor ) && // #1 check whether version is above lower limit GLContext.decrementGLVersion(ctxOptionFlags, major, minor) // #2 decrement version ); if (DEBUG) { System.err.println(getThreadName() + ": createContextARBVersions.X: ctx "+toHexString(_context)+", share "+share+", direct "+direct+ - ", version "+major[0]+"."+minor[0]+", major["+majorMin+".."+majorMax+"], minor["+minorMin+".."+minorMax+"]"); + ", version "+major[0]+"."+minor[0]+" ["+maxMajor+"."+maxMinor+" .. "+minMajor+"."+minMinor+"]"); } return _context; } @@ -1261,11 +1476,19 @@ public abstract class GLContextImpl extends GLContext { // Helpers for various context implementations // - private final Object createInstance(final GLProfile glp, final boolean glObject, final Object[] cstrArgs) { + private final boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) { + return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix); + } + private final Object createInstance(final AbstractGraphicsDevice adevice, final int majorVersion, final int minorVersion, final int contextOption, + final boolean glObject, final Object[] cstrArgs) { + final String profileString = GLContext.getGLProfile(majorVersion, minorVersion, contextOption); + final GLProfile glp = GLProfile.get(adevice, profileString) ; return ReflectionUtil.createInstance(glp.getGLCtor(glObject), cstrArgs); } - - private final boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) { + private final boolean verifyInstance(final AbstractGraphicsDevice adevice, final int majorVersion, final int minorVersion, final int contextOption, + final String suffix, final Object instance) { + final String profileString = GLContext.getGLProfile(majorVersion, minorVersion, contextOption); + final GLProfile glp = GLProfile.get(adevice, profileString) ; return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix); } @@ -1273,8 +1496,11 @@ public abstract class GLContextImpl extends GLContext { * Create the GL instance for this context, * requires valid {@link #getGLProcAddressTable()} result! */ - private final GL createGL(final GLProfile glp) { - final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } ); + private final GL createGL(final AbstractGraphicsDevice adevice, final int majorVersion, final int minorVersion, final int contextOption) { + final String profileString = GLContext.getGLProfile(majorVersion, minorVersion, contextOption); + final GLProfile glp = GLProfile.get(adevice, profileString); + final GL gl = (GL) ReflectionUtil.createInstance(glp.getGLCtor(true), new Object[] { glp, this }); + //nal GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } ); /* FIXME: refactor dependence on Java 2D / JOGL bridge if (tracker != null) { @@ -1348,34 +1574,53 @@ public abstract class GLContextImpl extends GLContext { } protected abstract Map<String, String> getExtensionNameMap() ; + /** + * Returns the DynamicLookupHelper + */ + public final GLDynamicLookupHelper getGLDynamicLookupHelper() { + return drawable.getFactoryImpl().getGLDynamicLookupHelper( ctxVersion.getMajor(), ctxOptions ); + } + public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) { + return drawable.getFactoryImpl().getGLDynamicLookupHelper( majorVersion, contextOptions ); + } + /** Helper routine which resets a ProcAddressTable generated by the - GLEmitter by looking up anew all of its function pointers. */ - protected final void resetProcAddressTable(final ProcAddressTable table) { + GLEmitter by looking up anew all of its function pointers + using the given {@link GLDynamicLookupHelper}. */ + protected final void resetProcAddressTable(final ProcAddressTable table, final GLDynamicLookupHelper dlh) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { - table.reset(getDrawableImpl().getGLDynamicLookupHelper() ); + table.reset( dlh ); return null; } } ); } - private final PrivilegedAction<Object> privInitGLGetPtrAction = new PrivilegedAction<Object>() { - @Override - public Object run() { - final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); - glDynLookupHelper.claimAllLinkPermission(); - try { - glGetStringPtr = glDynLookupHelper.dynamicLookupFunction("glGetString"); - glGetIntegervPtr = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv"); - } finally { - glDynLookupHelper.releaseAllLinkPermission(); - } - return null; - } }; - private final boolean initGLRendererAndGLVersionStrings() { + /** + * Updates the platform's 'GLX' function cache + * @param contextFQN provides a fully qualified key of the context including device and GL profile + * @param dlh {@link GLDynamicLookupHelper} used to {@link #resetProcAddressTable(ProcAddressTable, GLDynamicLookupHelper)} instance. + */ + protected abstract void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh); + + private final boolean initGLRendererAndGLVersionStrings(final int majorVersion, final int contextOptions) { if( !glGetPtrInit ) { - AccessController.doPrivileged(privInitGLGetPtrAction); + AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override + public Object run() { + final GLDynamicLookupHelper glDynLookupHelper = getGLDynamicLookupHelper(majorVersion, contextOptions); + if( null != glDynLookupHelper ) { + glDynLookupHelper.claimAllLinkPermission(); + try { + glGetStringPtr = glDynLookupHelper.dynamicLookupFunction("glGetString"); + glGetIntegervPtr = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv"); + } finally { + glDynLookupHelper.releaseAllLinkPermission(); + } + } + return null; + } } ); glGetPtrInit = true; } if( 0 == glGetStringPtr || 0 == glGetIntegervPtr ) { @@ -1521,7 +1766,7 @@ public abstract class GLContextImpl extends GLContext { final VersionNumber reqGLVersion = new VersionNumber(major, minor, 0); final VersionNumber hasGLVersionByString; { - final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(); + final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(major, ctxProfileBits); if( !initGLRendererAndGLVersionStringsOK ) { final String errMsg = "Intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null); if( strictMatch ) { @@ -1557,50 +1802,51 @@ public abstract class GLContextImpl extends GLContext { { // Validate the requested version w/ the GL-version from an integer query, // as supported by GL [ES] >= 3.0 implementation. - final VersionNumber hasGLVersionByInt; - { - final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 }; - getGLIntVersion(glIntMajor, glIntMinor); - hasGLVersionByInt = new VersionNumber(glIntMajor[0], glIntMinor[0], 0); - } - if (DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Version verification (Int): String "+glVersion+", Number(Int) "+hasGLVersionByInt); - } - + // // Only validate integer based version if: // - ctx >= 3.0 is requested _or_ string-version >= 3.0 // - _and_ a valid int version was fetched, // otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX! // - if ( ( major >= 3 || hasGLVersionByString.compareTo(Version3_0) >= 0 ) && - GLContext.isValidGLVersion(ctxProfileBits, hasGLVersionByInt.getMajor(), hasGLVersionByInt.getMinor()) ) { - // Strict Match (GLVersionMapping): - // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! - // Otherwise: - // - fail if hasVersion < reqVersion (desktop and ES) - // - fail if ES major-version mismatch: - // - request 1, >= 3 must be equal - // - request 2 must be [2..3] - // - final int hasMajor = hasGLVersionByInt.getMajor(); - if( strictMatch && - ( ( ( isES || major >= 3 ) && hasGLVersionByInt.compareTo(reqGLVersion) < 0 ) || - ( isES && - ( - ( 2 == major && ( 2 > hasMajor || hasMajor > 3 ) ) || // 2 -> [2..3] - ( ( 1 == major || 3 <= major ) && major != hasMajor ) // 1,3,.. -> equal - ) - ) - ) ) { - if(DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByInt); + final VersionNumber hasGLVersionByInt; + if ( major >= 3 || hasGLVersionByString.compareTo(Version3_0) >= 0 ) { + final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 }; + getGLIntVersion(glIntMajor, glIntMinor); + hasGLVersionByInt = new VersionNumber(glIntMajor[0], glIntMinor[0], 0); + if (DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Version verification (Int): String "+glVersion+", Number(Int) "+hasGLVersionByInt); + } + if ( GLContext.isValidGLVersion(ctxProfileBits, hasGLVersionByInt.getMajor(), hasGLVersionByInt.getMinor()) ) { + // Strict Match (GLVersionMapping): + // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! + // Otherwise: + // - fail if hasVersion < reqVersion (desktop and ES) + // - fail if ES major-version mismatch: + // - request 1, >= 3 must be equal + // - request 2 must be [2..3] + // + final int hasMajor = hasGLVersionByInt.getMajor(); + if( strictMatch && + ( ( ( isES || major >= 3 ) && hasGLVersionByInt.compareTo(reqGLVersion) < 0 ) || + ( isES && + ( + ( 2 == major && ( 2 > hasMajor || hasMajor > 3 ) ) || // 2 -> [2..3] + ( ( 1 == major || 3 <= major ) && major != hasMajor ) // 1,3,.. -> equal + ) + ) + ) ) { + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByInt); + } + return false; } - return false; + // Use returned GL version! + major = hasGLVersionByInt.getMajor(); + minor = hasGLVersionByInt.getMinor(); + versionGL3IntOK = true; + } else { + versionGL3IntOK = false; } - // Use returned GL version! - major = hasGLVersionByInt.getMajor(); - minor = hasGLVersionByInt.getMinor(); - versionGL3IntOK = true; } else { versionGL3IntOK = false; } @@ -1668,7 +1914,8 @@ public abstract class GLContextImpl extends GLContext { } if( major < 2 ) { // there is no ES2/3-compat for a profile w/ major < 2 - ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES31_COMPAT ) ; + ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT | + GLContext.CTX_IMPL_ES31_COMPAT | GLContext.CTX_IMPL_ES32_COMPAT ) ; } if(!isCurrentContextHardwareRasterizer()) { @@ -1692,43 +1939,72 @@ public abstract class GLContextImpl extends GLContext { if (DEBUG) { System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)); } - - updateGLXProcAddressTable(); + final GLDynamicLookupHelper dynamicLookup = getGLDynamicLookupHelper(major, ctxProfileBits); + if( null == dynamicLookup ) { + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, No GLDynamicLookupHelper for request: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + } + return false; + } + updateGLXProcAddressTable(contextFQN, dynamicLookup); // // UpdateGLProcAddressTable functionality // _and_ setup GL instance, which ctor requires valid getGLProcAddressTable() result! // { - final GLProfile glp = drawable.getGLProfile(); + final GLProfile glp = drawable.getGLProfile(); // !withinGLVersionsMapping ProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { table = mappedGLProcAddress.get( contextFQN ); - if(null != table && !verifyInstance(glp, "ProcAddressTable", table)) { - throw new GLException("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ - ") -> "+ table.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()); + if(null != table) { + if( !verifyInstance(adevice, major, minor, ctxProfileBits, "ProcAddressTable", table) ) { + throw new GLException("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +" not matching "+table.getClass().getName()); + } + if( !withinGLVersionsMapping && !verifyInstance(glp, "ProcAddressTable", table) ) { + throw new GLException("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +": "+table.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()+"/"+glp); + } } } if(null != table) { glProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode())); + if( withinGLVersionsMapping ) { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +": "+table.getClass().getName()); + } else { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +": "+table.getClass().getName()+" -> "+glp.getGLImplBaseClassName()); + } } } else { - glProcAddressTable = (ProcAddressTable) createInstance(glp, false, + glProcAddressTable = (ProcAddressTable) createInstance(adevice, major, minor, ctxProfileBits, false, new Object[] { new GLProcAddressResolver() } ); - resetProcAddressTable( glProcAddressTable ); + resetProcAddressTable(glProcAddressTable, dynamicLookup); + synchronized(mappedContextTypeObjectLock) { mappedGLProcAddress.put(contextFQN, glProcAddressTable); if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(glProcAddressTable.hashCode())); + if( withinGLVersionsMapping ) { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+toHexString(glProcAddressTable.hashCode()) +": "+glProcAddressTable.getClass().getName()); + } else { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+toHexString(glProcAddressTable.hashCode()) +": "+glProcAddressTable.getClass().getName()+" -> "+glp.getGLImplBaseClassName()); + } } } } - if( null == this.gl || !verifyInstance(glp, "Impl", this.gl) ) { - setGL( createGL( glp ) ); + if( null == this.gl || !verifyInstance(adevice, major, minor, ctxProfileBits, "Impl", this.gl) ) { + setGL( createGL( adevice, major, minor, ctxProfileBits ) ); + } + if( !withinGLVersionsMapping && !verifyInstance(glp, "Impl", this.gl) ) { + throw new GLException("GLContext GL Object mismatch: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+": "+this.gl.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()+"/"+glp); } } @@ -1762,7 +2038,9 @@ public abstract class GLContextImpl extends GLContext { if( major >= 3 ) { ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ; ctxProfileBits |= CTX_IMPL_FBO; - if( minor >= 1 ) { + if( minor >= 2 ) { + ctxProfileBits |= CTX_IMPL_ES32_COMPAT | CTX_IMPL_ES31_COMPAT; + } else if( minor >= 1 ) { ctxProfileBits |= CTX_IMPL_ES31_COMPAT; } } else if( major >= 2 ) { @@ -1770,10 +2048,15 @@ public abstract class GLContextImpl extends GLContext { ctxProfileBits |= CTX_IMPL_FBO; } } else if( ( major > 4 || major == 4 && minor >= 5 ) || - ( ( major > 3 || major == 3 && minor >= 1 ) && isExtensionAvailable( GLExtensions.ARB_ES3_1_compatibility ) ) ) { - // See GLContext.isGLES31CompatibleAvailable(..)/isGLES31Compatible() - // Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_1_compatibility and GLES ≥ 3.1 ] - ctxProfileBits |= CTX_IMPL_ES31_COMPAT | CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ; + ( major > 3 || major == 3 && minor >= 1 ) ) { + // See GLContext.isGLES31CompatibleAvailable(..)/isGLES3[12]Compatible() + // Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_[12]_compatibility and GLES ≥ 3.[12] ] + if( isExtensionAvailable( GLExtensions.ARB_ES3_2_compatibility ) ) { + ctxProfileBits |= CTX_IMPL_ES32_COMPAT | CTX_IMPL_ES31_COMPAT; + } else if( isExtensionAvailable( GLExtensions.ARB_ES3_1_compatibility ) ) { + ctxProfileBits |= CTX_IMPL_ES31_COMPAT; + } + ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT; ctxProfileBits |= CTX_IMPL_FBO; } else if( ( major > 4 || major == 4 && minor >= 3 ) || ( ( major > 3 || major == 3 && minor >= 1 ) && isExtensionAvailable( GLExtensions.ARB_ES3_compatibility ) ) ) { @@ -1813,6 +2096,31 @@ public abstract class GLContextImpl extends GLContext { return true; } + private static final void addStickyQuirkAlways(final AbstractGraphicsDevice adevice, + final GLRendererQuirks quirks, + final int quirk, + final boolean withinGLVersionsMapping) { + quirks.addQuirk( quirk ); + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } else { + // FIXME: Remove when moving EGL/ES to ARB ctx creation + synchronized(GLContextImpl.class) { + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } + } + } + private static final void addStickyQuirkAtMapping(final AbstractGraphicsDevice adevice, + final GLRendererQuirks quirks, + final int quirk, + final boolean withinGLVersionsMapping) { + quirks.addQuirk( quirk ); + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } + } private final void setRendererQuirks(final AbstractGraphicsDevice adevice, final GLDrawableFactoryImpl factory, final int reqMajor, final int reqMinor, final int reqCTP, final int major, final int minor, final int ctp, final VersionNumberString vendorVersion, @@ -1822,10 +2130,10 @@ public abstract class GLContextImpl extends GLContext { final String MesaRendererIntelsp = "Intel(R)"; final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT ); final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT ); - final boolean esCtx = 0 != ( ctp & GLContext.CTX_PROFILE_ES ); + final boolean isES = 0 != ( ctp & GLContext.CTX_PROFILE_ES ); final boolean isX11 = NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true); final boolean isWindows = Platform.getOSType() == Platform.OSType.WINDOWS; - final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium "); + final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium ") || glVersion.contains(MesaSP); final boolean isDriverATICatalyst; final boolean isDriverNVIDIAGeForce; @@ -1845,22 +2153,13 @@ public abstract class GLContextImpl extends GLContext { // // General Quirks // - if( esCtx ) { + if( isES ) { if( 2 == reqMajor && 2 < major ) { final int quirk = GLRendererQuirks.GLES3ViaEGLES2Config; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } else { - // FIXME: Remove when moving EGL/ES to ARB ctx creation - synchronized(GLContextImpl.class) { - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } - } + addStickyQuirkAlways(adevice, quirks, quirk, withinGLVersionsMapping); } } if( GLProfile.disableSurfacelessContext ) { @@ -1868,32 +2167,14 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: disabled"); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } else { - // FIXME: Remove when moving EGL/ES to ARB ctx creation - synchronized(GLContextImpl.class) { - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } - } + addStickyQuirkAlways(adevice, quirks, quirk, withinGLVersionsMapping); } if( GLProfile.disableOpenGLARBContext ) { final int quirk = GLRendererQuirks.NoARBCreateContext; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: disabled"); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } else { - // FIXME: Remove when moving EGL/ES to ARB ctx creation - synchronized(GLContextImpl.class) { - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } - } + addStickyQuirkAlways(adevice, quirks, quirk, withinGLVersionsMapping); } // @@ -1922,11 +2203,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", req "+reqMajor+"."+reqMinor); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); } if( isDriverNVIDIAGeForce ) { final VersionNumber osxVersionNVFlushClean = new VersionNumber(10,7,3); // < OSX 10.7.3 w/ NV needs glFlush @@ -1984,11 +2261,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+", Renderer "+glRenderer+" and Version "+glVersion+"]"); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); } } } else if( isDriverIntel && glRenderer.equals("Intel Bear Lake B") ) { @@ -2054,6 +2327,17 @@ public abstract class GLContextImpl extends GLContext { } } } + if( isDriverNVIDIAGeForce ) { + // Bug 1200: Crash on GNU/Linux x86_64 'NVidia beta driver 355.06' @ probeSurfacelessCtx + // final VersionNumber nvSafeVersion = new VersionNumber(356, 0, 0); // FIXME: Add safe version! + if( !isES && !(adevice instanceof EGLGraphicsDevice) /* && vendorVersion.compareTo(nvSafeVersion) < 0 */ ) { + final int quirk = GLRendererQuirks.NoSurfacelessCtx; + if(DEBUG) { + System.err.print("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: !ES, !EGL, Vendor " + glVendor +", X11 Renderer " + glRenderer+", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]"); + } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); + } + } } @@ -2063,8 +2347,10 @@ public abstract class GLContextImpl extends GLContext { if( isDriverMesa ) { final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0); final VersionNumber mesaIntelBuggySharedCtx921 = new VersionNumber(9, 2, 1); + final VersionNumber mesaSafeDoubleBufferedPBuffer = new VersionNumber(18, 2, 2); // Mesa 18.2.2 + final VersionNumber mesaSafeSetSwapIntervalPostRetarget = mesaSafeDoubleBufferedPBuffer; // Mesa 18.2.2 - { + if( vendorVersion.compareTo(mesaSafeSetSwapIntervalPostRetarget) < 0 ) { final int quirk = GLRendererQuirks.NoSetSwapIntervalPostRetarget; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer); @@ -2073,11 +2359,13 @@ public abstract class GLContextImpl extends GLContext { } if( hwAccel ) { // hardware-acceleration - final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer; - if(DEBUG) { - System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer); + if( vendorVersion.compareTo(mesaSafeDoubleBufferedPBuffer) < 0 ) { + final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer); + } + quirks.addQuirk( quirk ); } - quirks.addQuirk( quirk ); } else { // software if( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // FIXME: Is it fixed in >= 8.0.0 ? @@ -2111,11 +2399,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Vendor "+glVendor); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); } if( isWindows && glRenderer.contains("SVGA3D") && vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { final int quirk = GLRendererQuirks.NoFullFBOSupport; @@ -2157,7 +2441,7 @@ public abstract class GLContextImpl extends GLContext { if( !GLRendererQuirks.areSameStickyDevice(factoryDefaultDevice, adevice) ) { GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, quirks); } - if( esCtx ) { + if( isES ) { final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice(); if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) && !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) { @@ -2233,11 +2517,6 @@ public abstract class GLContextImpl extends GLContext { return isHardwareRasterizer; } - /** - * Updates the platform's 'GLX' function cache - */ - protected abstract void updateGLXProcAddressTable(); - protected abstract StringBuilder getPlatformExtensionsStringImpl(); @Override @@ -2262,7 +2541,10 @@ public abstract class GLContextImpl extends GLContext { } // dynamic function lookup at last incl name aliasing (not cached) - final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper(); + final DynamicLookupHelper dynLookup = getGLDynamicLookupHelper(ctxVersion.getMajor(), ctxOptions); + if( null == dynLookup ) { + throw new GLException("No GLDynamicLookupHelper for "+this); + } final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true); return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override @@ -2378,6 +2660,40 @@ public abstract class GLContextImpl extends GLContext { } //---------------------------------------------------------------------- + // SwapBuffer + + @Override + public final boolean setSwapInterval(final int interval) throws GLException { + validateCurrent(); + return setSwapIntervalNC(interval); + } + protected final boolean setSwapIntervalNC(final int interval) throws GLException { + if( !drawableRetargeted || + !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) + ) + { + final Integer usedInterval = setSwapIntervalImpl2(interval); + if( null != usedInterval ) { + currentSwapInterval = usedInterval.intValue(); + return true; + } + } + return false; + } + protected abstract Integer setSwapIntervalImpl2(final int interval); + + @Override + public final int getSwapInterval() { + return currentSwapInterval; + } + @Override + protected final void setDefaultSwapInterval() { + currentSwapInterval = 0; + setSwapIntervalNC(1); + } + + + //---------------------------------------------------------------------- // Helpers for buffer object optimizations public final GLBufferObjectTracker getBufferObjectTracker() { @@ -2536,8 +2852,8 @@ public abstract class GLContextImpl extends GLContext { @Override public final void glDebugMessageControl(final int source, final int type, final int severity, final int count, final IntBuffer ids, final boolean enabled) { - if(glDebugHandler.isExtensionARB()) { - gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, enabled); + if(glDebugHandler.isExtensionKHRARB()) { + gl.getGL2ES2().glDebugMessageControl(source, type, severity, count, ids, enabled); } else if(glDebugHandler.isExtensionAMD()) { gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, enabled); } @@ -2545,8 +2861,8 @@ public abstract class GLContextImpl extends GLContext { @Override public final void glDebugMessageControl(final int source, final int type, final int severity, final int count, final int[] ids, final int ids_offset, final boolean enabled) { - if(glDebugHandler.isExtensionARB()) { - gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, ids_offset, enabled); + if(glDebugHandler.isExtensionKHRARB()) { + gl.getGL2ES2().glDebugMessageControl(source, type, severity, count, ids, ids_offset, enabled); } else if(glDebugHandler.isExtensionAMD()) { gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, ids_offset, enabled); } @@ -2555,8 +2871,8 @@ public abstract class GLContextImpl extends GLContext { @Override public final void glDebugMessageInsert(final int source, final int type, final int id, final int severity, final String buf) { final int len = (null != buf) ? buf.length() : 0; - if(glDebugHandler.isExtensionARB()) { - gl.getGL2GL3().glDebugMessageInsert(source, type, id, severity, len, buf); + if(glDebugHandler.isExtensionKHRARB()) { + gl.getGL2ES2().glDebugMessageInsert(source, type, id, severity, len, buf); } else if(glDebugHandler.isExtensionAMD()) { gl.getGL2GL3().glDebugMessageInsertAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, id, len, buf); } diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java index cd31d02fd..fb4529da4 100644 --- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java +++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java @@ -61,8 +61,9 @@ import com.jogamp.opengl.GLExtensions; public class GLDebugMessageHandler { private static final boolean DEBUG = Debug.debug("GLDebugMessageHandler"); - private static final int EXT_ARB = 1; - private static final int EXT_AMD = 2; + private static final int EXT_KHR = 1; + private static final int EXT_ARB = 2; + private static final int EXT_AMD = 3; static { if ( !initIDs0() ) { @@ -75,6 +76,7 @@ public class GLDebugMessageHandler { // licefycle: init - EOL private String extName; + private String extSuffix; private int extType; private long glDebugMessageCallbackProcAddress; private boolean extAvailable; @@ -92,6 +94,7 @@ public class GLDebugMessageHandler { this.listenerImpl = new ListenerSyncedImplStub<GLDebugListener>(); this.glDebugMessageCallbackProcAddress = 0; this.extName = null; + this.extSuffix = null; this.extType = 0; this.extAvailable = false; this.handle = 0; @@ -143,43 +146,68 @@ public class GLDebugMessageHandler { } return; } - if( ctx.isExtensionAvailable(GLExtensions.ARB_debug_output) ) { + if( ctx.isExtensionAvailable(GLExtensions.GL_KHR_debug) ) { + extName = GLExtensions.GL_KHR_debug; + extSuffix = ctx.isGLES() ? "KHR" : ""; // See SPEC! + extType = EXT_KHR; + } else if( ctx.isExtensionAvailable(GLExtensions.ARB_debug_output) ) { extName = GLExtensions.ARB_debug_output; + extSuffix = "ARB"; extType = EXT_ARB; } else if( ctx.isExtensionAvailable(GLExtensions.AMD_debug_output) ) { extName = GLExtensions.AMD_debug_output; + extSuffix = "AMD"; extType = EXT_AMD; } - if(DEBUG) { - System.err.println("GLDebugMessageHandler: Using extension: <"+extName+">"); + + // Validate GL Profile, just to be sure + switch(extType) { + case EXT_KHR: + if( !ctx.isGL2ES2() ) { + if(DEBUG) { + System.err.println("Non GL2ES2 context not supported, has "+ctx.getGLVersion()); + } + extType = 0; + } + break; + case EXT_ARB: + // fall through intended + case EXT_AMD: + if( !ctx.isGL2GL3() ) { + if(DEBUG) { + System.err.println("Non GL2GL3 context not supported, has "+ctx.getGLVersion()); + } + extType = 0; + } + break; } if(0 == extType) { + extName = null; + extSuffix = null; if(DEBUG) { System.err.println("GLDebugMessageHandler: No extension available! "+ctx.getGLVersion()); System.err.println("GL_EXTENSIONS "+ctx.getGLExtensionCount()); System.err.println(ctx.getGLExtensionsString()); } return; + } else if(DEBUG) { + System.err.println("GLDebugMessageHandler: Using extension: <"+extName+"> with suffix <"+extSuffix+">"); } final ProcAddressTable procAddressTable = ctx.getGLProcAddressTable(); - if( !ctx.isGLES1() && !ctx.isGLES2() ) { - switch(extType) { - case EXT_ARB: - glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackARB"); - break; - case EXT_AMD: - glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackAMD"); - break; - } - } else { - glDebugMessageCallbackProcAddress = 0; - if(DEBUG) { - System.err.println("Non desktop context not supported"); - } + switch(extType) { + case EXT_KHR: + glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallback"+extSuffix); + break; + case EXT_ARB: + glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallback"+extSuffix); + break; + case EXT_AMD: + glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallback"+extSuffix); + break; } - extAvailable = 0 < extType && null != extName && 0 != glDebugMessageCallbackProcAddress; + extAvailable = 0 < extType && null != extName && null != extSuffix && 0 != glDebugMessageCallbackProcAddress; if(DEBUG) { System.err.println("GLDebugMessageHandler: extAvailable: "+extAvailable+", glDebugMessageCallback* : 0x"+Long.toHexString(glDebugMessageCallbackProcAddress)); @@ -203,12 +231,20 @@ public class GLDebugMessageHandler { return extName; } + public final boolean isExtensionKHRARB() { + return EXT_KHR == extType || EXT_ARB == extType; + } + + public final boolean isExtensionKHR() { + return EXT_KHR == extType; + } + public final boolean isExtensionARB() { - return extName == GLExtensions.ARB_debug_output; + return EXT_ARB == extType; } public final boolean isExtensionAMD() { - return extName == GLExtensions.AMD_debug_output; + return EXT_AMD == extType; } /** @@ -226,7 +262,7 @@ public class GLDebugMessageHandler { } } private final void setSynchronousImpl() { - if(isExtensionARB()) { + if(isExtensionKHRARB()) { if(synchronous) { ctx.getGL().glEnable(GL2ES2.GL_DEBUG_OUTPUT_SYNCHRONOUS); } else { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index b7f861e13..dfe6bdd9f 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -230,6 +230,15 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } /** + * Method returns {@code true} if underlying {@link #createContextARBImpl(long, boolean, int, int, int) <i>ARB context creation</i>} + * supports {@code major} and {@code minor} version number. + * <p> + * Otherwise only the {@code major} version number is supported for context creation. + * </p> + */ + public abstract boolean hasMajorMinorCreateContextARB(); + + /** * Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, * either a preexisting or newly created, or <code>null</code> if creation failed or not supported.<br> * Creation of the shared context is tried only once. @@ -245,12 +254,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } /** - * Returns the GLDynamicLookupHelper - * @param profileName if EGL/ES, profile <code>1</code> refers to ES1 and <code>2</code> to ES2, - * otherwise the profile is ignored. - * @throws GLException if no DynamicLookupHelper is installed + * Returns the GLDynamicLookupHelper if installed, otherwise {@code null}. + * @param majorVersion the major OpenGL profile version + * @param contextOptions the context profile options */ - public abstract GLDynamicLookupHelper getGLDynamicLookupHelper(final String profileName) throws GLException; + public abstract GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions); //--------------------------------------------------------------------------- // Dispatching GLDrawable construction in respect to the NativeSurface Capabilities diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index e9ee46a51..e4b5eae5c 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -61,6 +61,7 @@ import com.jogamp.opengl.GLFBODrawable; import com.jogamp.opengl.GLRunnable; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.PropertyAccess; /** Encapsulates the implementation of most of the GLAutoDrawable's @@ -75,6 +76,8 @@ public class GLDrawableHelper { } protected static final boolean DEBUG = GLDrawableImpl.DEBUG; + private static final boolean DEBUG_SETCLEAR = GLContext.DEBUG_GL || DEBUG; + private final Object listenersLock = new Object(); private final ArrayList<GLEventListener> listeners = new ArrayList<GLEventListener>(); private final HashSet<GLEventListener> listenersToBeInit = new HashSet<GLEventListener>(); @@ -637,10 +640,10 @@ public class GLDrawableHelper { } } - private final void init(final GLEventListener l, final GLAutoDrawable drawable, final boolean sendReshape, final boolean setViewport) { + private final void init(final GLEventListener l, final GLAutoDrawable drawable, final boolean sendReshape) { l.init(drawable); if(sendReshape) { - reshape(l, drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), setViewport, false /* checkInit */); + l.reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); } } @@ -649,6 +652,7 @@ public class GLDrawableHelper { * @param sendReshape set to true if the subsequent display call won't reshape, otherwise false to avoid double reshape. **/ public final void init(final GLAutoDrawable drawable, final boolean sendReshape) { + setViewportAndClear(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); synchronized(listenersLock) { final ArrayList<GLEventListener> _listeners = listeners; final int listenerCount = _listeners.size(); @@ -660,11 +664,8 @@ public class GLDrawableHelper { // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), // hence it must be called unconditional, always. listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init - init( listener, drawable, sendReshape, 0==i /* setViewport */); + init(listener, drawable, sendReshape); } - } else { - // Expose same GL initialization if not using any GLEventListener - drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); } } } @@ -686,7 +687,7 @@ public class GLDrawableHelper { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable if( listenersToBeInit.remove(listener) ) { - init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ ); + init( listener, drawable, true /* sendReshape */ ); } listener.display(drawable); } @@ -711,41 +712,43 @@ public class GLDrawableHelper { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable if( listenersToBeInit.remove(listener) ) { - init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ ); + init( listener, drawable, true /* sendReshape */ ); } action.run(drawable, listener); } } } - private final void reshape(final GLEventListener listener, final GLAutoDrawable drawable, - final int x, final int y, final int width, final int height, final boolean setViewport, final boolean checkInit) { - if(checkInit) { - // GLEventListener may need to be init, - // in case this one is added after the realization of the GLAutoDrawable - synchronized(listenersLock) { - if( listenersToBeInit.remove(listener) ) { - listener.init(drawable); - } - } - } - if(setViewport) { - if( GLContext.DEBUG_GL || DEBUG ) { - final int glerr0 = drawable.getGL().glGetError(); - if( GL.GL_NO_ERROR != glerr0 ) { - System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0)); - ExceptionUtils.dumpStack(System.err); - } - } - drawable.getGL().glViewport(x, y, width, height); - } - listener.reshape(drawable, x, y, width, height); + /** + * Bug 1206: Security: Clear exposed framebuffer after creation and before visibility + * - Clear framebuffer after setting viewport + * - Since we only attempt to help against leaking un-initialized framebuffer content + * not against user-app faults, we do not clear a 2nd-buffer (double-buffering). + */ + private final void setViewportAndClear(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + final GL gl = drawable.getGL(); + if( DEBUG_SETCLEAR ) { + final int glerr0 = gl.glGetError(); + if( GL.GL_NO_ERROR != glerr0 ) { + System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0)); + ExceptionUtils.dumpStack(System.err); + } + } + gl.glViewport(x, y, width, height); + gl.glClear(GL.GL_COLOR_BUFFER_BIT); } public final void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + setViewportAndClear(drawable, x, y, width, height); synchronized(listenersLock) { for (int i=0; i < listeners.size(); i++) { - reshape(listeners.get(i), drawable, x, y, width, height, 0==i /* setViewport */, true /* checkInit */); + final GLEventListener l = listeners.get(i); + // GLEventListener may need to be init, + // in case this one is added after the realization of the GLAutoDrawable + if( listenersToBeInit.remove(l) ) { + l.init(drawable); + } + l.reshape(drawable, x, y, width, height); } } } @@ -874,9 +877,8 @@ public class GLDrawableHelper { return false; } - GLRunnableTask rTask = null; + final GLRunnableTask rTask; final Object rTaskLock = new Object(); - Throwable throwable = null; synchronized(rTaskLock) { boolean deferredHere; synchronized(glRunnablesLock) { @@ -910,13 +912,13 @@ public class GLDrawableHelper { drawable.display(); } else if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { throw new RuntimeException(throwable); } @@ -941,9 +943,8 @@ public class GLDrawableHelper { } final int count = newGLRunnables.size(); - GLRunnableTask rTask = null; + final GLRunnableTask rTask; final Object rTaskLock = new Object(); - Throwable throwable = null; synchronized(rTaskLock) { boolean deferredHere; synchronized(glRunnablesLock) { @@ -981,13 +982,13 @@ public class GLDrawableHelper { drawable.display(); } else if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { throw new RuntimeException(throwable); } @@ -1082,6 +1083,21 @@ public class GLDrawableHelper { return exclusiveContextThread; } + /** + * Runs given {@code runnable} outside of a probable claimed exclusive thread, + * i.e. releases the exclusive thread, executes the runnable and reclaims it. + * @see #setExclusiveContextThread(Thread, GLContext) + * @since 2.3.2 + */ + public final void runOutsideOfExclusiveContextThread(final GLContext context, final Runnable runnable) { + final Thread t = setExclusiveContextThread(null, context); + try { + runnable.run(); + } finally { + setExclusiveContextThread(t, context); + } + } + private static final ThreadLocal<WeakReference<Runnable>> perThreadInitAction = new ThreadLocal<WeakReference<Runnable>>(); private static final Runnable getLastInitAction() { final WeakReference<Runnable> lastInitActionWR = perThreadInitAction.get(); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 849a08623..98a0a0948 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -67,14 +67,6 @@ public abstract class GLDrawableImpl implements GLDrawable { this.requestedCapabilities = requestedCapabilities; } - /** - * Returns the DynamicLookupHelper - * @throws GLException if no DynamicLookupHelper is installed - */ - public final GLDynamicLookupHelper getGLDynamicLookupHelper() throws GLException { - return getFactoryImpl().getGLDynamicLookupHelper( getGLProfile().getImplName() ); - } - public final GLDrawableFactoryImpl getFactoryImpl() { return (GLDrawableFactoryImpl) getFactory(); } diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java index 39de3200d..7c75b0615 100644 --- a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java @@ -59,6 +59,16 @@ public abstract class GLDynamicLibraryBundleInfo implements DynamicLibraryBundle public boolean shallLookupGlobal() { return false; } @Override + public final boolean searchToolLibInSystemPath() { + return true; + } + + @Override + public final boolean searchToolLibSystemPathFirst() { + return true; + } + + @Override public final RunnableExecutor getLibLoaderExecutor() { return DynamicLibraryBundle.getDefaultRunnableExecutor(); } diff --git a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java index 1a6024bfa..cfe3df95d 100644 --- a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java +++ b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java @@ -29,6 +29,7 @@ package jogamp.opengl; import com.jogamp.opengl.GLRunnable; +import com.jogamp.common.ExceptionUtils; import com.jogamp.opengl.GLAutoDrawable; /** @@ -61,7 +62,7 @@ public class GLRunnableTask implements GLRunnable { } catch (final Throwable t) { runnableException = t; if(catchExceptions) { - runnableException.printStackTrace(); + ExceptionUtils.dumpThrowable("", runnableException); } else { throw new RuntimeException(runnableException); } @@ -75,7 +76,7 @@ public class GLRunnableTask implements GLRunnable { } catch (final Throwable t) { runnableException = t; if(catchExceptions) { - runnableException.printStackTrace(); + ExceptionUtils.dumpThrowable("", runnableException); } else { throw new RuntimeException(runnableException); } diff --git a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java index c03cdea02..3d0adfc9c 100644 --- a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java +++ b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java @@ -43,6 +43,9 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.opengl.GLContext; /** Singleton thread upon which all OpenGL work is performed by @@ -78,15 +81,18 @@ public class GLWorkerThread { synchronized (GLWorkerThread.class) { if (!started) { lock = new Object(); - thread = new Thread(new WorkerRunnable(), - "JOGL-GLWorkerThread-"); + final WorkerRunnable worker = new WorkerRunnable(); + thread = new InterruptSource.Thread(null, worker, "JOGL-GLWorkerThread-"); thread.setDaemon(true); started = true; synchronized (lock) { thread.start(); try { - lock.wait(); + while(!worker.isRunning) { + lock.wait(); + } } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } } @@ -119,7 +125,7 @@ public class GLWorkerThread { // less cooperatively AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - Runtime.getRuntime().addShutdownHook(new Thread() { + Runtime.getRuntime().addShutdownHook(new InterruptSource.Thread() { public void run() { Object lockTemp = lock; if (lockTemp == null) { @@ -177,7 +183,9 @@ public class GLWorkerThread { work = runnable; lockTemp.notifyAll(); - lockTemp.wait(); + while( null != work ) { + lockTemp.wait(); + } if (exception != null) { final Throwable localException = exception; exception = null; @@ -222,10 +230,13 @@ public class GLWorkerThread { protected static String getThreadName() { return Thread.currentThread().getName(); } static class WorkerRunnable implements Runnable { + volatile boolean isRunning = false; + @Override public void run() { // Notify starting thread that we're ready synchronized (lock) { + isRunning = true; lock.notifyAll(); } @@ -238,6 +249,7 @@ public class GLWorkerThread { // Avoid race conditions with wanting to release contexts on this thread lock.wait(1000); } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } if (GLContext.getCurrent() != null) { @@ -269,8 +281,7 @@ public class GLWorkerThread { final Runnable curAsync = queue.remove(0); curAsync.run(); } catch (final Throwable t) { - System.err.println(getThreadName()+": Exception occurred on JOGL OpenGL worker thread:"); - t.printStackTrace(); + ExceptionUtils.dumpThrowable("suppressed", t); // Noncancelable } } @@ -285,6 +296,7 @@ public class GLWorkerThread { } } } + isRunning = false; } } } diff --git a/src/jogl/classes/jogamp/opengl/GLXExtensions.java b/src/jogl/classes/jogamp/opengl/GLXExtensions.java index 9325c6f68..db4757e4d 100644 --- a/src/jogl/classes/jogamp/opengl/GLXExtensions.java +++ b/src/jogl/classes/jogamp/opengl/GLXExtensions.java @@ -34,4 +34,10 @@ public class GLXExtensions { public static final String GLX_MESA_swap_control = "GLX_MESA_swap_control"; public static final String GLX_SGI_swap_control = "GLX_SGI_swap_control"; public static final String GLX_NV_swap_group = "GLX_NV_swap_group"; + + public static final String GLX_EXT_swap_control = "GLX_EXT_swap_control"; + public static final String GLX_EXT_swap_control_tear = "GLX_EXT_swap_control_tear"; + + public static final String WGL_EXT_swap_control = "WGL_EXT_swap_control"; + public static final String WGL_EXT_swap_control_tear = "WGL_EXT_swap_control_tear"; } diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java index 9b9093a87..0f6c1f875 100644 --- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java +++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java @@ -28,14 +28,19 @@ package jogamp.opengl; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import com.jogamp.nativewindow.AbstractGraphicsDevice; import com.jogamp.nativewindow.AbstractGraphicsScreen; import com.jogamp.opengl.GLProfile; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; +import com.jogamp.common.util.SourcedInterruptedException; import com.jogamp.opengl.GLRendererQuirks; public class SharedResourceRunner implements Runnable { @@ -81,6 +86,29 @@ public class SharedResourceRunner implements Runnable { /** Called within synchronized block. */ Collection<Resource> mapValues(); } + public static abstract class AImplementation implements Implementation { + private final HashMap<String /* uniqueId */, SharedResourceRunner.Resource> sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); + /** Called within synchronized block. Use w/ care! */ + public Map<String /* uniqueId */, SharedResourceRunner.Resource> getSharedMap() { + return sharedMap; + } + @Override + public final void clear() { + sharedMap.clear(); + } + @Override + public final SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { + return sharedMap.put(device.getUniqueID(), resource); + } + @Override + public final SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { + return sharedMap.get(device.getUniqueID()); + } + @Override + public final Collection<SharedResourceRunner.Resource> mapValues() { + return sharedMap.values(); + } + } final HashSet<String> devicesTried = new HashSet<String>(); final Implementation impl; @@ -93,13 +121,13 @@ public class SharedResourceRunner implements Runnable { AbstractGraphicsDevice releaseDevice; private boolean getDeviceTried(final AbstractGraphicsDevice device) { // synchronized call - return devicesTried.contains(device.getConnection()); + return devicesTried.contains(device.getUniqueID()); } private void addDeviceTried(final AbstractGraphicsDevice device) { // synchronized call - devicesTried.add(device.getConnection()); + devicesTried.add(device.getUniqueID()); } private void removeDeviceTried(final AbstractGraphicsDevice device) { // synchronized call - devicesTried.remove(device.getConnection()); + devicesTried.remove(device.getUniqueID()); } public SharedResourceRunner(final Implementation impl) { @@ -141,13 +169,18 @@ public class SharedResourceRunner implements Runnable { System.err.println("SharedResourceRunner.start() - start new Thread - "+getThreadName()); } resetState(); - thread = new Thread(this, getThreadName()+"-SharedResourceRunner"); + thread = new InterruptSource.Thread(null, this, getThreadName()+"-SharedResourceRunner"); thread.setDaemon(true); // Allow JVM to exit, even if this one is running thread.start(); - while (!running) { - try { + try { + while (!running) { this.wait(); - } catch (final InterruptedException ex) { } + } + } catch (final InterruptedException ex) { + // Cleanup + shouldRelease = true; + this.notifyAll(); + throw new InterruptedRuntimeException(ex); } } } @@ -163,11 +196,12 @@ public class SharedResourceRunner implements Runnable { synchronized (this) { shouldRelease = true; this.notifyAll(); - - while (running) { - try { + try { + while (running) { this.wait(); - } catch (final InterruptedException ex) { } + } + } catch (final InterruptedException ex) { + throw new InterruptedRuntimeException(ex); } } } @@ -188,7 +222,11 @@ public class SharedResourceRunner implements Runnable { ExceptionUtils.dumpStack(System.err); } if ( impl.isDeviceSupported(device) ) { - doAndWait(device, null); + try { + doAndWait(device, null); + } catch (final InterruptedException ex) { + throw new InterruptedRuntimeException(ex); + } sr = impl.mapGet(device); } if (DEBUG) { @@ -211,7 +249,11 @@ public class SharedResourceRunner implements Runnable { if (DEBUG) { System.err.println("SharedResourceRunner.releaseShared() " + device + ": trying - "+getThreadName()); } - doAndWait(null, device); + try { + doAndWait(null, device); + } catch (final InterruptedException ex) { + throw new InterruptedRuntimeException(ex); + } if (DEBUG) { System.err.println("SharedResourceRunner.releaseShared() " + device + ": done - "+getThreadName()); } @@ -221,7 +263,7 @@ public class SharedResourceRunner implements Runnable { return sr; } - private final void doAndWait(final AbstractGraphicsDevice initDevice, final AbstractGraphicsDevice releaseDevice) { + private final void doAndWait(final AbstractGraphicsDevice initDevice, final AbstractGraphicsDevice releaseDevice) throws InterruptedException { synchronized (this) { // wait until thread becomes ready to init new device, // pass the device and release the sync @@ -229,26 +271,41 @@ public class SharedResourceRunner implements Runnable { if (DEBUG) { System.err.println("SharedResourceRunner.doAndWait() START init: " + initDevice + ", release: "+releaseDevice+" - "+threadName); } - while (!ready && running) { - try { + try { + while (!ready && running) { this.wait(); - } catch (final InterruptedException ex) { } - } - if (DEBUG) { - System.err.println("SharedResourceRunner.doAndWait() set command: " + initDevice + ", release: "+releaseDevice+" - "+threadName); - } - this.initDevice = initDevice; - this.releaseDevice = releaseDevice; - this.notifyAll(); + } + if (DEBUG) { + System.err.println("SharedResourceRunner.doAndWait() set command: " + initDevice + ", release: "+releaseDevice+" - "+threadName); + } + this.initDevice = initDevice; + this.releaseDevice = releaseDevice; + this.notifyAll(); - // wait until thread has init/released the device - while ( running && ( !ready || null != this.initDevice || null != this.releaseDevice ) ) { - try { + // wait until thread has init/released the device + while ( running && ( !ready || null != this.initDevice || null != this.releaseDevice ) ) { this.wait(); - } catch (final InterruptedException ex) { } + } + } catch (final InterruptedException ex) { + final InterruptedException ex2 = SourcedInterruptedException.wrap(ex); + if (DEBUG) { + System.err.println("SharedResourceRunner.doAndWait() INTERRUPT init: " + initDevice + ", release: "+releaseDevice+" - "+threadName); + ExceptionUtils.dumpThrowable("", ex2); + } + // Cleanup initDevice due to exception! + final AbstractGraphicsDevice _initDevice = this.initDevice; + if( null != _initDevice ) { + if (DEBUG) { + System.err.println("SharedResourceRunner.doAndWait() Cleanup init: " + _initDevice + " -> release: "+this.releaseDevice+" - "+threadName); + } + this.releaseDevice = _initDevice; + this.initDevice = null; + this.notifyAll(); + } + throw ex2; } if (DEBUG) { - System.err.println("SharedResourceRunner.initializeAndWait END init: " + initDevice + ", release: "+releaseDevice+" - "+threadName); + System.err.println("SharedResourceRunner.doAndWait() END init: " + initDevice + ", release: "+releaseDevice+" - "+threadName); } } // done @@ -267,19 +324,18 @@ public class SharedResourceRunner implements Runnable { while (!shouldRelease) { try { - // wait for stop or init + // wait until call-thread issues stop or init/released a device ready = true; if (DEBUG) { System.err.println("SharedResourceRunner.run(): READY - " + threadName); } notifyAll(); - this.wait(); + while ( !shouldRelease && null == initDevice && null == releaseDevice ) { + this.wait(); + } } catch (final InterruptedException ex) { shouldRelease = true; - if(DEBUG) { - System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+threadName); - ex.printStackTrace(); - } + ExceptionUtils.dumpThrowable("handled", SourcedInterruptedException.wrap(ex)); // cancelable } ready = false; @@ -296,7 +352,7 @@ public class SharedResourceRunner implements Runnable { try { sr = impl.createSharedResource(initDevice); } catch (final Exception e) { - e.printStackTrace(); + ExceptionUtils.dumpThrowable("handled", e); } if (null != sr) { impl.mapPut(initDevice, sr); @@ -310,9 +366,10 @@ public class SharedResourceRunner implements Runnable { if (null != sr) { try { impl.releaseSharedResource(sr); - impl.mapPut(releaseDevice, null); } catch (final Exception e) { - e.printStackTrace(); + ExceptionUtils.dumpThrowable("handled", e); + } finally { + impl.mapPut(releaseDevice, null); } } } @@ -345,8 +402,7 @@ public class SharedResourceRunner implements Runnable { try { impl.releaseSharedResource(iter.next()); } catch (final Throwable t) { - System.err.println("Caught exception on thread "+getThreadName()); - t.printStackTrace(); + ExceptionUtils.dumpThrowable("", t); } } impl.clear(); diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java index da81922a4..09d2dfda0 100644 --- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java +++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java @@ -33,7 +33,6 @@ import java.util.List; import com.jogamp.opengl.GL; import com.jogamp.opengl.GLES2; import com.jogamp.opengl.GLException; - import com.jogamp.common.os.AndroidVersion; import com.jogamp.common.os.Platform; import com.jogamp.opengl.util.TimeFrameI; @@ -364,7 +363,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { } @Override - protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) { + protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) throws InterruptedException { int pts = TimeFrameI.INVALID_PTS; if(null != mp || null != cam) { final SurfaceTextureFrame sTexFrame = null != nextFrame ? (SurfaceTextureFrame) nextFrame : singleSTexFrame; @@ -398,12 +397,8 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl { boolean update = updateSurface; if( !update ) { synchronized(updateSurfaceLock) { - if(!updateSurface) { // volatile OK. - try { - updateSurfaceLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } + while(!updateSurface) { // volatile OK. + updateSurfaceLock.wait(); // propagates InterruptedException } update = updateSurface; updateSurface = false; diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java index 7cc009668..91573143d 100644 --- a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java +++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; +import java.util.Locale; import java.util.Set; import java.util.Map.Entry; @@ -330,7 +331,7 @@ public class AWTTilePainter { // but that's the software rendering path which is very slow anyway. final BufferedImage dstImage; if( DEBUG_TILES ) { - final String fname = String.format("file_%03d_0_tile_[%02d][%02d]_sz_%03dx%03d_pos0_%03d_%03d_yOff_%03d_pos1_%03d_%03d.png", + final String fname = String.format((Locale)null, "file_%03d_0_tile_[%02d][%02d]_sz_%03dx%03d_pos0_%03d_%03d_yOff_%03d_pos1_%03d_%03d.png", _counter, renderer.getParam(TileRenderer.TR_CURRENT_COLUMN), renderer.getParam(TileRenderer.TR_CURRENT_ROW), tWidth, tHeight, @@ -361,7 +362,7 @@ public class AWTTilePainter { dstImage = tBuffer.image; } if( DEBUG_TILES ) { - final String fname = String.format("file_%03d_1_tile_[%02d][%02d]_sz_%03dx%03d_pos0_%03d_%03d_yOff_%03d_pos1_%03d_%03d.png", + final String fname = String.format((Locale)null, "file_%03d_1_tile_[%02d][%02d]_sz_%03dx%03d_pos0_%03d_%03d_yOff_%03d_pos1_%03d_%03d.png", _counter, renderer.getParam(TileRenderer.TR_CURRENT_COLUMN), renderer.getParam(TileRenderer.TR_CURRENT_ROW), tWidth, tHeight, diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index b6a05aeeb..28448d537 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -49,9 +49,9 @@ import com.jogamp.opengl.GLProfile; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.egl.EGLExtImpl; import jogamp.opengl.egl.EGLExtProcAddressTable; -import jogamp.opengl.windows.wgl.WindowsWGLContext; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; @@ -168,19 +168,17 @@ public class EGLContext extends GLContextImpl { final long eglConfig = config.getNativeConfig(); final EGLDrawableFactory factory = (EGLDrawableFactory) drawable.getFactoryImpl(); - final boolean hasOpenGLAPISupport = factory.hasOpenGLAPISupport(); + final boolean hasFullOpenGLAPISupport = factory.hasOpenGLDesktopSupport(); final boolean useKHRCreateContext = factory.hasDefaultDeviceKHRCreateContext(); - final boolean allowOpenGLAPI = hasOpenGLAPISupport && useKHRCreateContext; - final boolean ctDesktopGL = 0 == ( GLContext.CTX_PROFILE_ES & ctp ); + final boolean ctDesktopGL = 0 == ( CTX_PROFILE_ES & ctp ); final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; if(DEBUG) { System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: Start "+getGLVersion(reqMajor, reqMinor, ctp, "@creation") - + ", hasOpenGLAPISupport "+hasOpenGLAPISupport + ", useKHRCreateContext "+useKHRCreateContext - + ", allowOpenGLAPI "+allowOpenGLAPI + + ", OpenGL API Support "+hasFullOpenGLAPISupport + ", device "+device); } if ( 0 == eglDisplay ) { @@ -203,8 +201,7 @@ public class EGLContext extends GLContextImpl { * hence it must be switched before makeCurrent w/ different APIs, see: * eglWaitClient(); */ - if( ctDesktopGL && !allowOpenGLAPI ) { - // if( ctDesktopGL && !hasOpenGLAPISupport ) { + if( ctDesktopGL && !hasFullOpenGLAPISupport ) { if(DEBUG) { System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: DesktopGL not avail "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")); } @@ -212,7 +209,7 @@ public class EGLContext extends GLContextImpl { } try { - if( allowOpenGLAPI && device.getEGLVersion().compareTo(Version1_2) >= 0 ) { + if( hasFullOpenGLAPISupport && device.getEGLVersion().compareTo(Version1_2) >= 0 ) { EGL.eglWaitClient(); // EGL >= 1.2 } if( !EGL.eglBindAPI( ctDesktopGL ? EGL.EGL_OPENGL_API : EGL.EGL_OPENGL_ES_API) ) { @@ -238,11 +235,11 @@ public class EGLContext extends GLContextImpl { int index = ctx_attribs_idx_major + 2; - /** if( ctDesktopGL && reqMinor >= 0 ) { // FIXME: No minor version probing for ES currently! + if( reqMinor >= 0 ) { attribs.put(index + 0, EGLExt.EGL_CONTEXT_MINOR_VERSION_KHR); attribs.put(index + 1, reqMinor); index += 2; - } */ + } if( ctDesktopGL && ( useMajor > 3 || useMajor == 3 && reqMinor >= 2 ) ) { attribs.put(index + 0, EGLExt.EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); @@ -364,14 +361,17 @@ public class EGLContext extends GLContextImpl { } @Override - protected final void updateGLXProcAddressTable() { + protected final void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh) { + if( null == dlh ) { + throw new GLException("No GLDynamicLookupHelper for "+this); + } final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "EGL-"+adevice.getUniqueID(); + // final String key = contextFQN; if (DEBUG) { System.err.println(getThreadName() + ": Initializing EGLextension address table: "+key); } - ProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { table = mappedGLXProcAddress.get( key ); @@ -386,7 +386,7 @@ public class EGLContext extends GLContextImpl { } } else { eglExtProcAddressTable = new EGLExtProcAddressTable(new GLProcAddressResolver()); - resetProcAddressTable(eglExtProcAddressTable); + resetProcAddressTable(eglExtProcAddressTable, dlh); synchronized(mappedContextTypeObjectLock) { mappedGLXProcAddress.put(key, eglExtProcAddressTable); if(DEBUG) { @@ -432,11 +432,21 @@ public class EGLContext extends GLContextImpl { } @Override - protected boolean setSwapIntervalImpl(final int interval) { - if( hasRendererQuirk(GLRendererQuirks.NoSetSwapInterval) ) { - return false; + protected final Integer setSwapIntervalImpl2(final int interval) { + if( !drawable.getChosenGLCapabilities().isOnscreen() || + hasRendererQuirk(GLRendererQuirks.NoSetSwapInterval) ) { + return null; + } + final int useInterval; + if( 0 > interval ) { + useInterval = Math.abs(interval); + } else { + useInterval = interval; } - return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval); + if( EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), useInterval) ) { + return Integer.valueOf(useInterval); + } + return null; } static long eglGetProcAddress(final long eglGetProcAddressHandle, final String procname) @@ -453,52 +463,32 @@ public class EGLContext extends GLContextImpl { // Accessible .. // - /* pp */ void mapCurrentAvailableGLESVersion(final AbstractGraphicsDevice device) { - mapStaticGLESVersion(device, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + /* pp */ static final boolean isGLES1(final int majorVersion, final int ctxOptions) { + return 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES ) && majorVersion == 1 ; } - /* pp */ int getContextOptions() { return ctxOptions; } - /* pp */ static void mapStaticGLESVersion(final AbstractGraphicsDevice device, final GLCapabilitiesImmutable caps) { - final GLProfile glp = caps.getGLProfile(); - final int[] reqMajorCTP = new int[2]; - GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); - if( glp.isGLES() ) { - if( reqMajorCTP[0] >= 3 ) { - reqMajorCTP[1] |= GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ; - } else if( reqMajorCTP[0] >= 2 ) { - reqMajorCTP[1] |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ; - } - } - if( !caps.getHardwareAccelerated() ) { - reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT; + /* pp */ static final boolean isGLES2ES3(final int majorVersion, final int ctxOptions) { + if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) { + return 2 == majorVersion || 3 == majorVersion; + } else { + return false; } - mapStaticGLESVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]); } - /* pp */ static void mapStaticGLESVersion(final AbstractGraphicsDevice device, final int major, final int minor, final int ctp) { - if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { - // ES1, ES2, ES3, .. - mapStaticGLESVersion(device, major /* reqMajor */, major, minor, ctp); - if( 3 == major ) { - // map ES2 -> ES3 - mapStaticGLESVersion(device, 2 /* reqMajor */, major, minor, ctp); - } - } + /* pp */ static final boolean isGLDesktop(final int ctxOptions) { + return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); } - private static void mapStaticGLESVersion(final AbstractGraphicsDevice device, final int reqMajor, final int major, final int minor, final int ctp) { - GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_ES, major, minor, ctp); - if(! ( device instanceof EGLGraphicsDevice ) ) { - final EGLGraphicsDevice eglDevice = new EGLGraphicsDevice(device.getHandle(), EGL.EGL_NO_DISPLAY, device.getConnection(), device.getUnitID(), null); - GLContext.mapAvailableGLVersion(eglDevice, reqMajor, GLContext.CTX_PROFILE_ES, major, minor, ctp); - } + protected static StringBuilder getGLProfile(final StringBuilder sb, final int ctp) { + return GLContext.getGLProfile(sb, ctp); } - protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) { - return GLContext.getGLVersion(major, minor, ctp, gl_version); + /* pp */ int getContextOptions() { return ctxOptions; } + protected static void remapAvailableGLVersions(final AbstractGraphicsDevice fromDevice, final AbstractGraphicsDevice toDevice) { + GLContextImpl.remapAvailableGLVersions(fromDevice, toDevice); } - - protected static boolean getAvailableGLVersionsSet(final AbstractGraphicsDevice device) { - return GLContext.getAvailableGLVersionsSet(device); + protected static synchronized void setMappedGLVersionListener(final MappedGLVersionListener mvl) { + GLContextImpl.setMappedGLVersionListener(mvl); } - protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device, final boolean set) { - GLContext.setAvailableGLVersionsSet(device, set); + + protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) { + return GLContext.getGLVersion(major, minor, ctp, gl_version); } protected static String toHexString(final int hex) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 3d2d03403..fcd4f54eb 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -80,10 +80,17 @@ public class EGLDisplayUtil { static EGLDisplayRef getOrCreateOpened(final long eglDisplay, final IntBuffer major, final IntBuffer minor) { final EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay); if( null == o ) { - if( EGL.eglInitialize(eglDisplay, major, minor) ) { + final boolean ok = EGL.eglInitialize(eglDisplay, major, minor); + if( DEBUG ) { + System.err.println("EGLDisplayUtil.EGL.eglInitialize 0x"+Long.toHexString(eglDisplay)+" -> "+ok); + } + if( ok ) { final EGLDisplayRef n = new EGLDisplayRef(eglDisplay); openEGLDisplays.put(eglDisplay, n); n.initRefCount++; + if( DEBUG ) { + System.err.println("EGLDisplayUtil.EGL.eglInitialize "+n); + } if( null == singletonEGLDisplay ) { singletonEGLDisplay = n; } @@ -113,7 +120,12 @@ public class EGLDisplayUtil { if( 0 < o.initRefCount ) { // no negative refCount o.initRefCount--; if( 0 == o.initRefCount ) { - res[0] = EGL.eglTerminate(eglDisplay); + final boolean ok = EGL.eglTerminate(eglDisplay); + if( DEBUG ) { + System.err.println("EGLDisplayUtil.EGL.eglTerminate 0x"+Long.toHexString(eglDisplay)+" -> "+ok); + System.err.println("EGLDisplayUtil.EGL.eglTerminate "+o); + } + res[0] = ok; if( o == singletonEGLDisplay ) { singletonEGLDisplay = null; } @@ -340,6 +352,22 @@ public class EGLDisplayUtil { * <p> * Using the default {@link ToolkitLock}, via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. * </p> + * @param adevice + * @return an uninitialized {@link EGLGraphicsDevice} + */ + public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(final AbstractGraphicsDevice aDevice) { + return new EGLGraphicsDevice(aDevice, EGL.EGL_NO_DISPLAY, eglLifecycleCallback); + } + + /** + * Returns an uninitialized {@link EGLGraphicsDevice}. User needs to issue {@link EGLGraphicsDevice#open()} before usage. + * <p> + * Using {@link #eglGetDisplayAndInitialize(long[])} for the {@link EGLGraphicsDevice#open()} implementation + * and {@link #eglTerminate(long)} for {@link EGLGraphicsDevice#close()}. + * </p> + * <p> + * Using the default {@link ToolkitLock}, via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. + * </p> * @param surface * @return an uninitialized EGLGraphicsDevice */ diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index e63a63634..ef3c96aeb 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,6 +36,7 @@ package jogamp.opengl.egl; +import com.jogamp.common.ExceptionUtils; import com.jogamp.nativewindow.ProxySurface; import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLException; @@ -82,7 +83,10 @@ public class EGLDrawable extends GLDrawableImpl { final EGLSurface eglSurf = (EGLSurface) surface; final long eglSurfHandle = eglSurf.getSurfaceHandle(); if(DEBUG) { - System.err.println(getThreadName() + ": destroyHandle of "+eglSurf); + System.err.println(getThreadName() + ": EGLDrawable: destroyHandle of "+toHexString(eglSurfHandle)); + ProxySurfaceImpl.dumpHierarchy(System.err, eglSurf); + System.err.println(getThreadName() + ": EGLSurface : "+eglSurf); + ExceptionUtils.dumpStack(System.err); } if( !eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) && EGL.EGL_NO_SURFACE == eglSurfHandle ) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 4fecafdfc..fed02f34e 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -38,10 +38,9 @@ package jogamp.opengl.egl; import java.nio.IntBuffer; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import com.jogamp.nativewindow.AbstractGraphicsConfiguration; @@ -67,6 +66,7 @@ import com.jogamp.opengl.GLProfile; import jogamp.common.os.PlatformPropsImpl; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLContextImpl.MappedGLVersion; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; @@ -78,7 +78,6 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.Platform; -import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.VersionNumber; import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; @@ -90,17 +89,20 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; // allow package access private static final boolean DEBUG_SHAREDCTX = DEBUG || GLContext.DEBUG; - /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK; - static { Debug.initSingleton(); - QUERY_EGL_ES_NATIVE_TK = PropertyAccess.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); } private static boolean eglDynamicLookupHelperInit = false; private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; private static GLDynamicLookupHelper eglGLnDynamicLookupHelper = null; + private static boolean isANGLE = false; + private static boolean hasX11 = false; + private static String defaultConnection = null; + private static EGLGraphicsDevice defaultDevice = null; + private static EGLFeatures defaultDeviceEGLFeatures = null; + private static SharedResource defaultSharedResource = null; private static final boolean isANGLE(final GLDynamicLookupHelper dl) { if(Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE) { @@ -128,7 +130,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { public EGLFeatures(final EGLGraphicsDevice device) { final long eglDisplay = device.getHandle(); vendor = EGL.eglQueryString(eglDisplay, EGL.EGL_VENDOR); - if(DEBUG) { + if(DEBUG_SHAREDCTX) { System.err.println("EGLFeatures on device "+device+", vendor "+vendor); } version = device.getEGLVersion(); @@ -139,13 +141,13 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { final String eglClientAPIStr = EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS); if( hasEGL_1_4 ) { final String[] eglClientAPIs = eglClientAPIStr.split("\\s"); - for(int i=eglClientAPIs.length-1; i>=0; i--) { + for(int i=eglClientAPIs.length-1; !_hasGLAPI && i>=0; i--) { _hasGLAPI = eglClientAPIs[i].equals("OpenGL"); } } hasGLAPI = _hasGLAPI; - if(DEBUG) { - System.err.println(" Client APIs: "+eglClientAPIStr+"; has EGL 1.4 "+hasEGL_1_4+" -> has OpenGL "+hasGLAPI); + if(DEBUG_SHAREDCTX) { + System.err.println(" Client APIs: '"+eglClientAPIStr+"'; has EGL 1.4 "+hasEGL_1_4+" -> has OpenGL "+hasGLAPI); } } { @@ -163,7 +165,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } hasKHRSurfaceless = extensions.contains("EGL_KHR_surfaceless_context"); } - if(DEBUG) { + if(DEBUG_SHAREDCTX) { System.err.println(" Extensions: "+extensions); System.err.println(" KHR_create_context: "+hasKHRCreateContext); System.err.println(" KHR_surfaceless_context: "+hasKHRSurfaceless); @@ -193,12 +195,16 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { eglDynamicLookupHelperInit = true; // Check for other underlying stuff .. - if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) { + final String nwt = NativeWindowFactory.getNativeWindowType(true); + if(NativeWindowFactory.TYPE_X11 == nwt) { hasX11 = true; try { ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader()); } catch (final Exception jre) { /* n/a .. */ } + } else { + hasX11 = false; } + defaultConnection = NativeWindowFactory.getDefaultDisplayConnection(nwt); /** * FIXME: Probably need to move EGL from a static model @@ -337,14 +343,14 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // The act of constructing them causes them to be registered EGLGraphicsConfigurationFactory.registerFactory(); - sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); - - // FIXME: defaultDevice.open() triggers eglInitialize(..) which crashed on Windows w/ Chrome/ANGLE, FF/ANGLE! - defaultDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + // Note: defaultDevice.open() triggers eglInitialize(..) which crashed on Windows w/ Chrome/ANGLE, FF/ANGLE! + // Hence opening will happen later, eventually + defaultDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, defaultConnection, AbstractGraphicsDevice.DEFAULT_UNIT); // Init shared resources off thread // Will be released via ShutdownHook - sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation()); + sharedResourceImplementation = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImplementation); sharedResourceRunner.start(); } } @@ -353,7 +359,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected final boolean isComplete() { - return null != sharedMap; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper; + return null != sharedResourceImplementation; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper || ..; } @@ -366,9 +372,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { sharedResourceRunner.stop(); sharedResourceRunner = null; } - if(null != sharedMap) { - sharedMap.clear(); - sharedMap = null; + if(null != sharedResourceImplementation) { + sharedResourceImplementation.clear(); + sharedResourceImplementation = null; } if(null != defaultDevice) { @@ -395,57 +401,63 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } private void dumpMap() { - synchronized(sharedMap) { - System.err.println("EGLDrawableFactory.map "+sharedMap.size()); + synchronized(sharedResourceImplementation) { + final Map<String /* uniqueId */, SharedResourceRunner.Resource> sharedMap = sharedResourceImplementation.getSharedMap(); + System.err.println("EGLDrawableFactory.MapGLVersion.map "+sharedMap.size()); int i=0; final Set<String> keys = sharedMap.keySet(); for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); i++) { final String key = keyI.next(); final SharedResource sr = (SharedResource) sharedMap.get(key); - System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", avail "+sr.isAvailable+ - "gln [quirks "+sr.rendererQuirksGLn+", ctp "+EGLContext.getGLVersion(3, 0, sr.ctpGLn, null)+"], "+ - "es1 [quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+ - "es2/3 [quirks "+sr.rendererQuirksES3ES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES3ES2, null)+"]"); + System.err.println("EGLDrawableFactory.MapGLVersion.map["+i+"] "+key+" -> "+sr.getDevice()+", avail "+sr.isAvailable+", "+ + "es1 [avail "+sr.isAvailableES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+ + "es2 [avail "+sr.isAvailableES2+", quirks "+sr.rendererQuirksES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES2, null)+"], "+ + "es3 [avail "+sr.isAvailableES3+", quirks "+sr.rendererQuirksES3+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES3, null)+"], "+ + "gln [avail "+sr.isAvailableGLn+", quirks "+sr.rendererQuirksGLn+", ctp "+EGLContext.getGLVersion(3, 0, sr.ctpGLn, null)+"]"); } ; } } - private boolean isANGLE = false; - private boolean hasX11 = false; - private EGLGraphicsDevice defaultDevice = null; - private EGLFeatures defaultDeviceEGLFeatures; + private SharedResourceImplementation sharedResourceImplementation; private SharedResourceRunner sharedResourceRunner; - private HashMap<String /* uniqueKey */, SharedResourceRunner.Resource> sharedMap; static class SharedResource implements SharedResourceRunner.Resource { private EGLGraphicsDevice device; - // private final EGLContext contextES1; - // private final EGLContext contextES2; - // private final EGLContext contextES3; final boolean isAvailable; - final GLRendererQuirks rendererQuirksGLn; + final boolean isAvailableES1; + final boolean isAvailableES2; + final boolean isAvailableES3; + final boolean isAvailableGLn; final GLRendererQuirks rendererQuirksES1; - final GLRendererQuirks rendererQuirksES3ES2; - final int ctpGLn; + final GLRendererQuirks rendererQuirksES2; + final GLRendererQuirks rendererQuirksES3; + final GLRendererQuirks rendererQuirksGLn; final int ctpES1; - final int ctpES3ES2; + final int ctpES2; + final int ctpES3; + final int ctpGLn; - SharedResource(final EGLGraphicsDevice dev, final boolean isAvailable, - final GLRendererQuirks rendererQuirksGLn, final int ctpGLn, - final GLRendererQuirks rendererQuirksES1, final int ctpES1, - final GLRendererQuirks rendererQuirksES3ES2, final int ctpES3ES2) { + SharedResource(final EGLGraphicsDevice dev, + final boolean isAvailableES1, final GLRendererQuirks rendererQuirksES1, final int ctpES1, + final boolean isAvailableES2, final GLRendererQuirks rendererQuirksES2, final int ctpES2, + final boolean isAvailableES3, final GLRendererQuirks rendererQuirksES3, final int ctpES3, + final boolean isAvailableGLn, final GLRendererQuirks rendererQuirksGLn, final int ctpGLn) { this.device = dev; - this.isAvailable = isAvailable; - - this.rendererQuirksGLn = rendererQuirksGLn; - this.ctpGLn = ctpGLn; + this.isAvailable = isAvailableES1 || isAvailableES2 || isAvailableES3 || isAvailableGLn; + this.isAvailableES1 = isAvailableES1; this.rendererQuirksES1 = rendererQuirksES1; this.ctpES1 = ctpES1; - - this.rendererQuirksES3ES2 = rendererQuirksES3ES2; - this.ctpES3ES2 = ctpES3ES2; + this.isAvailableES2 = isAvailableES2; + this.rendererQuirksES2 = rendererQuirksES2; + this.ctpES2 = ctpES2; + this.isAvailableES3 = isAvailableES3; + this.rendererQuirksES3 = rendererQuirksES3; + this.ctpES3 = ctpES3; + this.isAvailableGLn = isAvailableGLn; + this.rendererQuirksGLn = rendererQuirksGLn; + this.ctpGLn = ctpGLn; } @Override @@ -470,8 +482,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { @Override public GLRendererQuirks getRendererQuirks(final GLProfile glp) { if( null == glp ) { - if( null != rendererQuirksES3ES2 ) { - return rendererQuirksES3ES2; + if( null != rendererQuirksES3 ) { + return rendererQuirksES3; + } else if( null != rendererQuirksES2 ) { + return rendererQuirksES2; } else if( null != rendererQuirksES1 ) { return rendererQuirksES1; } else { @@ -481,33 +495,18 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return rendererQuirksGLn; } else if( glp.isGLES1() ) { return rendererQuirksES1; - } else { - return rendererQuirksES3ES2; + } else if( glp.isGLES2() ) { + return rendererQuirksES2; + } else /* if( glp.isGLES3() ) */ { + return rendererQuirksES3; } } } - class SharedResourceImplementation implements SharedResourceRunner.Implementation { - @Override - public void clear() { - sharedMap.clear(); - } - @Override - public SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { - return sharedMap.put(device.getConnection(), resource); - } - @Override - public SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { - return sharedMap.get(device.getConnection()); - } - @Override - public Collection<SharedResourceRunner.Resource> mapValues() { - return sharedMap.values(); - } - + class SharedResourceImplementation extends SharedResourceRunner.AImplementation { @Override public boolean isDeviceSupported(final AbstractGraphicsDevice device) { - return null != sharedMap; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper + return null != sharedResourceImplementation; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper || .. } @Override @@ -523,78 +522,128 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } private SharedResource createEGLSharedResourceImpl(final AbstractGraphicsDevice adevice) { - final GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null }; - final GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null }; - final GLRendererQuirks[] rendererQuirksGLn = new GLRendererQuirks[] { null }; - final int[] ctpES1 = new int[] { EGLContext.CTX_PROFILE_ES }; - final int[] ctpES3ES2 = new int[] { EGLContext.CTX_PROFILE_ES }; - final int[] ctpGLn = new int[] { EGLContext.CTX_PROFILE_CORE }; - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.createShared(): device "+adevice); + System.err.println("EGLDrawableFactory.MapGLVersions: device "+adevice); } - boolean madeCurrentES1 = false; - boolean madeCurrentES2 = false; - boolean madeCurrentES3 = false; - boolean madeCurrentGLn = false; - - if( null != eglGLnDynamicLookupHelper ) { - // OpenGL 3.1 core -> GL3, will utilize normal desktop profile mapping - final int[] major = { 3 }; - final int[] minor = { 1 }; // FIXME: No minor version probing for ES currently! - madeCurrentGLn = mapAvailableEGLESConfig(adevice, major, minor, - ctpGLn, rendererQuirksGLn) && 0 != major[0]; + final boolean initDefaultDevice; + if( 0 == defaultDevice.getHandle() ) { // Note: GLProfile always triggers EGL device initialization first! + initDefaultDevice = true; + defaultDevice.open(); + defaultDeviceEGLFeatures = new EGLFeatures(defaultDevice); + if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory.MapGLVersions: defaultDevice "+defaultDevice); + System.err.println("EGLDrawableFactory.MapGLVersions: defaultDevice EGLFeatures "+defaultDeviceEGLFeatures); + } + // Probe for GLRendererQuirks.SingletonEGLDisplayOnly + final boolean singletonEGLDisplayOnlyVendor, singletonEGLDisplayOnlyProbe; + if( defaultDeviceEGLFeatures.vendor.contains("NVIDIA") ) { // OpenGL ES 3.1 NVIDIA 355.06 unstable + singletonEGLDisplayOnlyVendor=true; + singletonEGLDisplayOnlyProbe=false; + } else { + singletonEGLDisplayOnlyVendor=false; + final long secondEGLDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + singletonEGLDisplayOnlyProbe = EGL.EGL_NO_DISPLAY == secondEGLDisplay; + } + if( singletonEGLDisplayOnlyVendor || singletonEGLDisplayOnlyProbe ) { + final int quirk = GLRendererQuirks.SingletonEGLDisplayOnly; + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + EGLDisplayUtil.setSingletonEGLDisplayOnly(true); + if ( DEBUG_SHAREDCTX ) { + if( singletonEGLDisplayOnlyVendor ) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Vendor: "+defaultDeviceEGLFeatures); + } else if( singletonEGLDisplayOnlyProbe ) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Second eglGetDisplay(EGL_DEFAULT_DISPLAY) failed"); + } + } + } } else { - madeCurrentGLn = false; + initDefaultDevice = false; + if( null == defaultSharedResource ) { + throw new InternalError("XXX: defaultDevice "+defaultDevice+", adevice "+adevice); + } } - EGLContext.setAvailableGLVersionsSet(adevice, true); - if( null != eglES1DynamicLookupHelper ) { - final int[] major = { 1 }; - final int[] minor = { 0 }; - madeCurrentES1 = mapAvailableEGLESConfig(adevice, major, minor, - ctpES1, rendererQuirksES1) && 1 == major[0]; - } else { - madeCurrentES1 = false; - } - if( null != eglES2DynamicLookupHelper ) { - // ES3 Query - final int[] major = { 3 }; - final int[] minor = { 0 }; - madeCurrentES3 = mapAvailableEGLESConfig(adevice, major, minor, - ctpES3ES2, rendererQuirksES3ES2) && 3 == major[0]; - if( !madeCurrentES3 ) { - // ES2 Query, may result in ES3 - major[0] = 2; - if( mapAvailableEGLESConfig(adevice, major, minor, - ctpES3ES2, rendererQuirksES3ES2) ) - { - switch( major[0] ) { - case 2: madeCurrentES2 = true; break; - case 3: madeCurrentES3 = true; break; - default: throw new InternalError("XXXX Got "+major[0]); + final boolean[] mappedToDefaultDevice = { false }; + final GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null }; + final GLRendererQuirks[] rendererQuirksES2 = new GLRendererQuirks[] { null }; + final GLRendererQuirks[] rendererQuirksES3 = new GLRendererQuirks[] { null }; + final GLRendererQuirks[] rendererQuirksGLn = new GLRendererQuirks[] { null }; + final int[] ctpES1 = new int[] { 0 }; + final int[] ctpES2 = new int[] { 0 }; + final int[] ctpES3 = new int[] { 0 }; + final int[] ctpGLn = new int[] { 0 }; + final boolean[] madeCurrentES1 = { false }; + final boolean[] madeCurrentES2 = { false }; + final boolean[] madeCurrentES3 = { false }; + final boolean[] madeCurrentGLn = { false }; + + final GLContextImpl.MappedGLVersionListener mvl = new GLContextImpl.MappedGLVersionListener() { + @Override + public void glVersionMapped(final MappedGLVersion e) { + if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory.MapGLVersions: Mapped: "+e); + } + if ( EGLContext.isGLES2ES3(e.ctxVersion.getMajor(), e.ctxOptions) ) { + if( e.ctxVersion.getMajor() == 3 ) { + madeCurrentES3[0] = true; + rendererQuirksES3[0] = e.quirks; + ctpES3[0] = e.ctxOptions; } + madeCurrentES2[0] = true; + rendererQuirksES2[0] = e.quirks; + ctpES2[0] = e.ctxOptions; + } else if ( EGLContext.isGLES1(e.ctxVersion.getMajor(), e.ctxOptions) ) { + madeCurrentES1[0] = true; + rendererQuirksES1[0] = e.quirks; + ctpES1[0] = e.ctxOptions; + } else if( EGLContext.isGLDesktop(e.ctxOptions) ) { + madeCurrentGLn[0] = true; + rendererQuirksGLn[0] = e.quirks; + ctpGLn[0] = e.ctxOptions; } } + }; + final SharedResource sr; + final EGLGraphicsDevice[] eglDevice = { null }; + final boolean mapSuccess; + EGLContext.setMappedGLVersionListener(mvl); + try { + // Query triggers profile mapping! + mapSuccess = mapAvailableEGLESConfig(adevice, mappedToDefaultDevice, eglDevice); + } finally { + EGLContext.setMappedGLVersionListener(null); } - if( hasX11 ) { - handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]); - handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]); + if( mappedToDefaultDevice[0] ) { + EGLContext.remapAvailableGLVersions(defaultDevice, adevice); + sr = defaultSharedResource; + } else { + if( hasX11 ) { + handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]); + handleDontCloseX11DisplayQuirk(rendererQuirksGLn[0]); + handleDontCloseX11DisplayQuirk(rendererQuirksES3[0]); + handleDontCloseX11DisplayQuirk(rendererQuirksES2[0]); + } + sr = new SharedResource(eglDevice[0], + madeCurrentES1[0], rendererQuirksES1[0], ctpES1[0], + madeCurrentES2[0], rendererQuirksES2[0], ctpES2[0], + madeCurrentES3[0], rendererQuirksES3[0], ctpES3[0], + madeCurrentGLn[0], rendererQuirksGLn[0], ctpGLn[0]); + if( initDefaultDevice ) { + defaultSharedResource = sr; + } } - final SharedResource sr = new SharedResource(defaultDevice, - madeCurrentGLn || madeCurrentES1 || madeCurrentES2 || madeCurrentES3, - rendererQuirksGLn[0], ctpGLn[0], - rendererQuirksES1[0], ctpES1[0], - rendererQuirksES3ES2[0], ctpES3ES2[0]); if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.createShared: devices: queried nativeTK "+QUERY_EGL_ES_NATIVE_TK+", adevice " + adevice + ", defaultDevice " + defaultDevice); - System.err.println("EGLDrawableFactory.createShared: context GLn: " + madeCurrentGLn + ", quirks "+rendererQuirksGLn[0]); - System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", quirks "+rendererQuirksES1[0]); - System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", quirks "+rendererQuirksES3ES2[0]); - System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", quirks "+rendererQuirksES3ES2[0]); + System.err.println("EGLDrawableFactory.MapGLVersions: mapSuccess "+mapSuccess+", mappedToDefaultDevice "+mappedToDefaultDevice[0]); + System.err.println("EGLDrawableFactory.MapGLVersions: defDevice : " + defaultDevice); + System.err.println("EGLDrawableFactory.MapGLVersions: adevice : " + adevice); + System.err.println("EGLDrawableFactory.MapGLVersions: eglDevice : " + sr.device); + System.err.println("EGLDrawableFactory.MapGLVersions: context ES1: " + sr.isAvailableES1 + ", quirks "+sr.rendererQuirksES1); + System.err.println("EGLDrawableFactory.MapGLVersions: context ES2: " + sr.isAvailableES2 + ", quirks "+sr.rendererQuirksES2); + System.err.println("EGLDrawableFactory.MapGLVersions: context ES3: " + sr.isAvailableES3 + ", quirks "+sr.rendererQuirksES3); + System.err.println("EGLDrawableFactory.MapGLVersions: context GLn: " + sr.isAvailableGLn + ", quirks "+sr.rendererQuirksGLn); dumpMap(); } return sr; @@ -607,200 +656,218 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } private boolean mapAvailableEGLESConfig(final AbstractGraphicsDevice adevice, - final int[] majorVersion, final int[] minorVersion, - final int[] ctxProfile, final GLRendererQuirks[] rendererQuirks) { - final String profileString = EGLContext.getGLProfile(majorVersion[0], minorVersion[0], ctxProfile[0]); + final boolean[] mapsADeviceToDefaultDevice, + final EGLGraphicsDevice[] resEGLDevice) { + final int majorVersion = 2; + final int minorVersion = 0; + final int ctxProfile = EGLContext.CTX_PROFILE_ES; + final String profileString = EGLContext.getGLProfile(majorVersion, minorVersion, ctxProfile); if ( !GLProfile.isAvailable(adevice, profileString) ) { if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice); + System.err.println("EGLDrawableFactory.MapGLVersions: "+profileString+" n/a on "+adevice); } return false; } final GLProfile glp = GLProfile.get(adevice, profileString) ; final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory(); - final boolean initDefaultDevice = 0 == defaultDevice.getHandle(); // Note: GLProfile always triggers EGL device initialization first! - final boolean mapsADeviceToDefaultDevice = !QUERY_EGL_ES_NATIVE_TK || initDefaultDevice || - null == desktopFactory; - // FIXME || adevice instanceof EGLGraphicsDevice ; + + final GLCapabilities reqCapsAny = new GLCapabilities(glp); + reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0); + reqCapsAny.setDoubleBuffered(false); + final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny); + final List<GLCapabilitiesImmutable> defaultDevicePBufferCapsL = getAvailableEGLConfigs(defaultDevice, reqCapsPBuffer); + final boolean defaultDeviceHasPBuffer = defaultDevicePBufferCapsL.size() > 0; + + final boolean useDefaultDevice = adevice == defaultDevice; + + mapsADeviceToDefaultDevice[0] = !useDefaultDevice && + null != defaultSharedResource && defaultSharedResource.isAvailable && + defaultConnection.equals(adevice.getConnection()); + if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" ( "+majorVersion[0]+" ), "+ - "mapsADeviceToDefaultDevice "+mapsADeviceToDefaultDevice+ - " (QUERY_EGL_ES_NATIVE_TK "+QUERY_EGL_ES_NATIVE_TK+", initDefaultDevice "+initDefaultDevice+", hasDesktopFactory "+(null != desktopFactory)+ + System.err.println("EGLDrawableFactory.MapGLVersions: "+profileString+" ( "+majorVersion+" ), "+ + "mapsADeviceToDefaultDevice "+mapsADeviceToDefaultDevice[0]+ + " (useDefaultDevice "+useDefaultDevice+", defaultDeviceHasPBuffer "+defaultDeviceHasPBuffer+", hasDesktopFactory "+(null != desktopFactory)+ ", isEGLGraphicsDevice "+(adevice instanceof EGLGraphicsDevice)+")"); } - boolean hasPBuffer; - EGLGraphicsDevice eglDevice = null; - EGLFeatures eglFeatures = null; - NativeSurface surface = null; - ProxySurface upstreamSurface = null; // X11, GLX, .. - ProxySurface downstreamSurface = null; // EGL + if( mapsADeviceToDefaultDevice[0] ) { + return true; + } + + final boolean defaultNoSurfacelessCtx = GLRendererQuirks.existStickyDeviceQuirk(defaultDevice, GLRendererQuirks.NoSurfacelessCtx); boolean success = false; - try { - final GLCapabilities reqCapsAny = new GLCapabilities(glp); - reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0); - reqCapsAny.setDoubleBuffered(false); - - if( mapsADeviceToDefaultDevice ) { - // In this branch, any non EGL device is mapped to EGL default shared resources (default behavior). - // Only one default shared resource instance is ever be created. - if( initDefaultDevice ) { - defaultDevice.open(); - defaultDeviceEGLFeatures = new EGLFeatures(defaultDevice); - - // Probe for GLRendererQuirks.SingletonEGLDisplayOnly - final long secondEGLDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); - if ( EGL.EGL_NO_DISPLAY == secondEGLDisplay ) { - final int quirk = GLRendererQuirks.SingletonEGLDisplayOnly; - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - EGLDisplayUtil.setSingletonEGLDisplayOnly(true); + final boolean hasKHRSurfacelessTried; + if( defaultDeviceEGLFeatures.hasKHRSurfaceless && !defaultNoSurfacelessCtx ) { + hasKHRSurfacelessTried = true; + final AbstractGraphicsDevice zdevice = useDefaultDevice ? defaultDevice : adevice; // reuse + final EGLSurface zeroSurface = createSurfacelessImpl(zdevice, false, reqCapsAny, reqCapsAny, null, 64, 64); + resEGLDevice[0] = (EGLGraphicsDevice) zeroSurface.getGraphicsConfiguration().getScreen().getDevice(); + if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory-MapGLVersions.0: "+resEGLDevice[0]); + } + EGLDrawable zeroDrawable = null; + EGLContext context = null; + boolean hasException = false; + try { + zeroDrawable = (EGLDrawable) createOnscreenDrawableImpl ( zeroSurface ); + zeroDrawable.setRealized(true); + + context = (EGLContext) zeroDrawable.createContext(null); + if (null == context) { + throw new GLException("Couldn't create shared context for drawable: "+zeroDrawable); + } + // Triggers initial mapping, if not done yet + if( GLContext.CONTEXT_NOT_CURRENT != context.makeCurrent() ) { // could cause exception + // context.isCurrent() ! + final GL gl = context.getGL(); + final String glVersionString = gl.glGetString(GL.GL_VERSION); + if(null != glVersionString) { + success = true; + } else { + setNoSurfacelessCtxQuirk(context); + } + } else if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory-MapGLVersions.0: NOT_CURRENT: "+resEGLDevice[0]+", "+context); + } + } catch (final Throwable t) { + hasException = true; + if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory-MapGLVersions.0: INFO: context create/makeCurrent failed"); + t.printStackTrace(); + } + } finally { + if( null != context ) { + try { + context.destroy(); + } catch (final GLException gle) { if ( DEBUG_SHAREDCTX ) { - System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Second eglGetDisplay(EGL_DEFAULT_DISPLAY) failed"); + System.err.println("EGLDrawableFactory-MapGLVersions.0: INFO: destroy caught exception:"); + gle.printStackTrace(); } } } - eglDevice = defaultDevice; // reuse + if( null != zeroDrawable ) { + zeroDrawable.setRealized(false); + } + if( null != zeroSurface ) { + zeroSurface.destroyNotify(); + } + if( success || hasException ) { // cont. using device if !success + if( defaultDevice != resEGLDevice[0] ) { // don't close default device + if(null != resEGLDevice[0]) { + resEGLDevice[0].close(); + } + } + } + } + if( success ) { + return true; + } + } else { // hasKHRSurfaceless + hasKHRSurfacelessTried = false; + } + EGLFeatures eglFeatures = null; + NativeSurface surface = null; + EGLDrawable drawable = null; + GLDrawable zeroDrawable = null; + EGLContext context = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + ProxySurface downstreamSurface = null; // EGL + try { + if( useDefaultDevice && defaultDeviceHasPBuffer ) { + // Map any non EGL device to EGL default shared resources (default behavior), using a pbuffer surface + resEGLDevice[0] = defaultDevice; // reuse eglFeatures = defaultDeviceEGLFeatures; if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig.0: "+eglFeatures); + System.err.println("EGLDrawableFactory-MapGLVersions.1: "+resEGLDevice[0]); + System.err.println("EGLDrawableFactory-MapGLVersions.1: "+eglFeatures); } - if( !glp.isGLES() && !eglFeatures.hasGLAPI ) { - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() OpenGL API not supported (1)"); - } - } else { - final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny); - final List<GLCapabilitiesImmutable> availablePBufferCapsL = getAvailableEGLConfigs(eglDevice, reqCapsPBuffer); - hasPBuffer = availablePBufferCapsL.size() > 0; - - // attempt to created the default shared resources .. - if( hasPBuffer ) { - // 2nd case create defaultDevice shared resource using pbuffer surface - downstreamSurface = createDummySurfaceImpl(eglDevice, false, reqCapsPBuffer, reqCapsPBuffer, null, 64, 64); // egl pbuffer offscreen - if( null != downstreamSurface ) { - downstreamSurface.createNotify(); - surface = downstreamSurface; - } - } else { - // 3rd case fake creation of defaultDevice shared resource, no pbuffer available - final List<GLCapabilitiesImmutable> capsAnyL = getAvailableEGLConfigs(eglDevice, reqCapsAny); - if(capsAnyL.size() > 0) { - final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0); - EGLContext.mapStaticGLESVersion(eglDevice, chosenCaps); - success = true; - } - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "+success); - EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err); - } - } + downstreamSurface = createDummySurfaceImpl(resEGLDevice[0], false, reqCapsPBuffer, reqCapsPBuffer, null, 64, 64); + if( null != downstreamSurface ) { + downstreamSurface.createNotify(); + surface = downstreamSurface; } - } else { - // 4th case always creates a true mapping of given device to EGL + } else if( adevice != defaultDevice ) { + // Create a true mapping of given device to EGL upstreamSurface = desktopFactory.createDummySurface(adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window if(null != upstreamSurface) { upstreamSurface.createNotify(); - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); - eglDevice.open(); - eglFeatures = new EGLFeatures(eglDevice); + resEGLDevice[0] = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); + resEGLDevice[0].open(); + eglFeatures = new EGLFeatures(resEGLDevice[0]); if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig.1: "+eglFeatures); - } - if( !glp.isGLES() && !eglFeatures.hasGLAPI ) { - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() OpenGL API not supported (2)"); - } - // disposed at finalized: eglDevice, upstreamSurface - } else { - hasPBuffer = true; - surface = upstreamSurface; + System.err.println("EGLDrawableFactory-MapGLVersions.2: "+resEGLDevice[0]); + System.err.println("EGLDrawableFactory-MapGLVersions.2: "+eglFeatures); } + surface = upstreamSurface; } } if(null != surface) { - EGLDrawable drawable = null; - GLDrawable zeroDrawable = null; - EGLContext context = null; - try { - drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); - drawable.setRealized(true); - - context = (EGLContext) drawable.createContext(null); - if (null == context) { - throw new GLException("Couldn't create shared context for drawable: "+drawable); - } + drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); + drawable.setRealized(true); - if( GLContext.CONTEXT_NOT_CURRENT != context.makeCurrent() ) { // could cause exception - // context.isCurrent() ! - final String glVersionString = context.getGL().glGetString(GL.GL_VERSION); - if(null != glVersionString) { - context.mapCurrentAvailableGLESVersion(eglDevice); - if(eglDevice != adevice) { - context.mapCurrentAvailableGLESVersion(adevice); - } + context = (EGLContext) drawable.createContext(null); + if (null == context) { + throw new GLException("Couldn't create shared context for drawable: "+drawable); + } - if( eglFeatures.hasKHRSurfaceless && - ( context.isGLES() || context.getGLVersionNumber().compareTo(GLContext.Version3_0) >= 0 ) - ) - { - if( probeSurfacelessCtx(context, false /* restoreDrawable */) ) { - zeroDrawable = context.getGLDrawable(); - } - } else { - setNoSurfacelessCtxQuirk(context); + // Triggers initial mapping, if not done yet + if( GLContext.CONTEXT_NOT_CURRENT != context.makeCurrent() ) { // could cause exception + // context.isCurrent() ! + final GL gl = context.getGL(); + final String glVersionString = gl.glGetString(GL.GL_VERSION); + if(null != glVersionString) { + success = true; + if( !hasKHRSurfacelessTried && eglFeatures.hasKHRSurfaceless && + ( context.isGLES() || context.getGLVersionNumber().compareTo(GLContext.Version3_0) >= 0 ) + ) + { + if( probeSurfacelessCtx(context, false /* restoreDrawable */) ) { + zeroDrawable = context.getGLDrawable(); } - rendererQuirks[0] = context.getRendererQuirks(); - ctxProfile[0] = context.getContextOptions(); - majorVersion[0] = context.getGLVersionNumber().getMajor(); - minorVersion[0] = context.getGLVersionNumber().getMinor(); - success = true; } else { - // Oops .. something is wrong - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); - } + setNoSurfacelessCtxQuirk(context); } + } else if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory-MapGLVersions.12: NULL VERSION: "+resEGLDevice[0]+", "+context.getGLVersion()); } - } catch (final Throwable t) { - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed"); - t.printStackTrace(); - } - } finally { - if( null != context ) { - try { - context.destroy(); - } catch (final GLException gle) { - if ( DEBUG_SHAREDCTX ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: destroy caught exception:"); - gle.printStackTrace(); - } - } - } - if( null != zeroDrawable ) { - zeroDrawable.setRealized(false); - } - if( null != drawable ) { - drawable.setRealized(false); - } + } else if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory-MapGLVersions.12: NOT_CURRENT: "+resEGLDevice[0]+", "+context); } } } catch (final Throwable t) { if ( DEBUG_SHAREDCTX ) { - System.err.println("Caught exception on thread "+getThreadName()); + System.err.println("EGLDrawableFactory-MapGLVersions.12: INFO: context create/makeCurrent failed"); t.printStackTrace(); } success = false; } finally { - if(null != downstreamSurface) { + if( null != context ) { + try { + context.destroy(); + } catch (final GLException gle) { + if ( DEBUG_SHAREDCTX ) { + System.err.println("EGLDrawableFactory-MapGLVersions.12: INFO: destroy caught exception:"); + gle.printStackTrace(); + } + } + } + if( null != zeroDrawable ) { + zeroDrawable.setRealized(false); + } + if( null != drawable ) { + drawable.setRealized(false); + } + if( null != downstreamSurface ) { downstreamSurface.destroyNotify(); } - if( defaultDevice != eglDevice ) { // don't close default device - if(null != eglDevice) { - eglDevice.close(); + if( defaultDevice != resEGLDevice[0] ) { // don't close default device + if(null != resEGLDevice[0]) { + resEGLDevice[0].close(); } } if(null != upstreamSurface) { @@ -831,8 +898,44 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { public final boolean hasDefaultDeviceKHRCreateContext() { return defaultDeviceEGLFeatures.hasKHRCreateContext; } - public final boolean hasOpenGLAPISupport() { - return defaultDeviceEGLFeatures.hasGLAPI; + /** + * {@inheritDoc} + * <p> + * This factory may support native desktop OpenGL if {@link EGL#EGL_CLIENT_APIS} contains {@code OpenGL} + * <i>and</i> if {@code EGL_KHR_create_context} extension is supported. + * </p> + */ + @Override + public final boolean hasOpenGLDesktopSupport() { + /** + * It has been experienced w/ Mesa 10.3.2 (EGL 1.4/Gallium) + * that even though initial OpenGL context can be created w/o 'EGL_KHR_create_context', + * switching the API via 'eglBindAPI(EGL_OpenGL_API)' the latter 'eglCreateContext(..)' fails w/ EGL_BAD_ACCESS. + * Hence we require both: OpenGL API support _and_ 'EGL_KHR_create_context'. + */ + return null != eglGLnDynamicLookupHelper && + defaultDeviceEGLFeatures.hasGLAPI && defaultDeviceEGLFeatures.hasKHRCreateContext; + } + + /** + * {@inheritDoc} + * <p> + * This factory always supports native GLES profiles. + * </p> + */ + @Override + public final boolean hasOpenGLESSupport() { return true; } + + /** + * {@inheritDoc} + * <p> + * Return true if {@code EGL_KHR_create_context} extension is supported, + * see {@link #hasDefaultDeviceKHRCreateContext()}. + * </p> + */ + @Override + public final boolean hasMajorMinorCreateContextARB() { + return hasDefaultDeviceKHRCreateContext(); } @Override @@ -843,7 +946,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { @Override public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) { // via mappings (X11/WGL/.. -> EGL) we shall be able to handle all types. - return null != sharedMap ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; + return null != sharedResourceImplementation ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper || ..; } private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(final EGLGraphicsDevice eglDisplay, final GLCapabilitiesImmutable caps) { @@ -885,24 +988,28 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - public GLDynamicLookupHelper getGLDynamicLookupHelper(final String esProfile) { + public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) { final GLDynamicLookupHelper res; - if ( GLProfile.GLES2 == esProfile || GLProfile.GLES3 == esProfile ) { + if ( EGLContext.isGLES2ES3(majorVersion, contextOptions) ) { res = eglES2DynamicLookupHelper; - } else if ( GLProfile.GLES1 == esProfile ) { + } else if ( EGLContext.isGLES1(majorVersion, contextOptions) ) { res = eglES1DynamicLookupHelper; - } else { + } else if( EGLContext.isGLDesktop(contextOptions) ) { res = eglGLnDynamicLookupHelper; + } else { + throw new IllegalArgumentException("neither GLES1, GLES2, GLES3 nor desktop GL has been specified: "+majorVersion+" ("+EGLContext.getGLProfile(new StringBuilder(), contextOptions).toString()); } - if( null == res ) { - throw new GLException("No lookup for esProfile "+esProfile); + if( DEBUG_SHAREDCTX ) { + if( null == res ) { + System.err.println("EGLDrawableFactory.getGLDynamicLookupHelper: NULL for profile "+majorVersion+" ("+EGLContext.getGLProfile(new StringBuilder(), contextOptions).toString()); + } } return res; } @Override protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) { - if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper + if(null == sharedResourceImplementation) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper || .. return new ArrayList<GLCapabilitiesImmutable>(); // null } return EGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); @@ -942,9 +1049,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { final GLCapabilitiesChooser chooser) { final EGLGraphicsDevice device; if( createNewDevice || ! (deviceReq instanceof EGLGraphicsDevice) ) { - final long nativeDisplayID = ( deviceReq instanceof EGLGraphicsDevice) ? - ( (EGLGraphicsDevice) deviceReq ).getNativeDisplayID() : deviceReq.getHandle() ; - device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(nativeDisplayID, deviceReq.getConnection(), deviceReq.getUnitID()); + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(deviceReq); device.open(); ownDevice[0] = true; } else { @@ -960,7 +1065,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected final ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + protected final EGLSurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) { final boolean[] ownDevice = { false }; @@ -969,14 +1074,14 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - public final ProxySurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + public final EGLSurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { chosenCaps = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(chosenCaps); // complete validation in EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(..) above return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height)); } @Override - public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + public final EGLSurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); final boolean[] ownDevice = { false }; @@ -1019,11 +1124,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, + protected EGLSurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(deviceReq); device.open(); final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java index 6c11b3bdc..890dab8f7 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java @@ -1,5 +1,6 @@ package jogamp.opengl.egl; +import com.jogamp.common.ExceptionUtils; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.ProxySurface; import com.jogamp.nativewindow.UpstreamSurfaceHook; @@ -8,6 +9,8 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.egl.EGL; +import jogamp.nativewindow.ProxySurfaceImpl; + /** Uses a PBuffer offscreen surface */ public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { /** @@ -50,6 +53,11 @@ public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize } eglDevice.lock(); try { + if( EGLDrawable.DEBUG ) { + System.err.println(EGLSurface.getThreadName()+": EGLDummyUpstreamSurfaceHook: EGL.eglDestroySurface: 0x"+Long.toHexString(s.getSurfaceHandle())); + ProxySurfaceImpl.dumpHierarchy(System.err, s); + ExceptionUtils.dumpStack(System.err); + } EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); s.setSurfaceHandle(EGL.EGL_NO_SURFACE); s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java index d37efc455..038194d58 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java @@ -31,6 +31,8 @@ package jogamp.opengl.egl; import java.util.ArrayList; import java.util.List; +import jogamp.nativewindow.BcmVCArtifacts; + /** * <p> * Covering ES3 and ES2. @@ -41,12 +43,20 @@ public final class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundl super(); } + @Override public final List<List<String>> getToolLibNames() { + final List<List<String>> libsList = new ArrayList<List<String>>(); { final List<String> libsGL = new ArrayList<String>(); + /** + * Prefer libGLESv2.so over libGLESv2.so.2 for proprietary + * Broadcom graphics when the VC4 DRM Xorg driver isn't present + */ + final boolean bcm_vc_iv_quirk = BcmVCArtifacts.guessVCIVUsed(); + // ES3: This is the default lib name, according to the spec libsGL.add("libGLESv3.so.3"); @@ -63,12 +73,18 @@ public final class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundl libsGL.add("libGLES30"); // ES2: This is the default lib name, according to the spec - libsGL.add("libGLESv2.so.2"); + if (!bcm_vc_iv_quirk) { + libsGL.add("libGLESv2.so.2"); + } // ES2: Try these as well, if spec fails libsGL.add("libGLESv2.so"); libsGL.add("GLESv2"); + if (bcm_vc_iv_quirk) { + libsGL.add("libGLESv2.so.2"); + } + // ES2: Alternative names libsGL.add("GLES20"); libsGL.add("GLESv2_CM"); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index d10263f22..5505fed52 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -242,7 +242,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact } ownEGLDisplay = false; } else { - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID()); + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice); eglDevice.open(); ownEGLDisplay = true; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java index e4e692fb2..8956bcbd9 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java @@ -35,7 +35,7 @@ import com.jogamp.nativewindow.ProxySurface; import com.jogamp.nativewindow.UpstreamSurfaceHook; import com.jogamp.opengl.GLCapabilitiesImmutable; import com.jogamp.opengl.GLException; - +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; import com.jogamp.opengl.egl.EGL; @@ -101,16 +101,22 @@ public class EGLSurface extends WrappedSurface { final boolean isPBuffer = ((GLCapabilitiesImmutable) config.getChosenCapabilities()).isPBuffer(); long eglSurface = createEGLSurfaceHandle(isPBuffer, true /* useSurfaceHandle */, config, nativeSurface); + if( DEBUG ) { + System.err.println(getThreadName() + ": EGLSurface: EGL.eglCreateSurface.0: 0x"+Long.toHexString(eglSurface)); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + if ( EGL.EGL_NO_SURFACE == eglSurface ) { final int eglError0 = EGL.eglGetError(); if( EGL.EGL_BAD_NATIVE_WINDOW == eglError0 && !isPBuffer ) { // Try window handle if available and differs (Windows HDC / HWND). // ANGLE impl. required HWND on Windows. if( hasUniqueNativeWindowHandle(nativeSurface) ) { - if(DEBUG) { + eglSurface = createEGLSurfaceHandle(isPBuffer, false /* useSurfaceHandle */, config, nativeSurface); + if( DEBUG ) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+config+", error "+GLDrawableImpl.toHexString(eglError0)+", retry w/ windowHandle"); + System.err.println(getThreadName() + ": EGLSurface: EGL.eglCreateSurface.1: 0x"+Long.toHexString(eglSurface)); } - eglSurface = createEGLSurfaceHandle(isPBuffer, false /* useSurfaceHandle */, config, nativeSurface); if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface w/ window handle failed: "+config+", "+this+", error "+GLDrawableImpl.toHexString(EGL.eglGetError())); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index d4fc0b005..995ff870e 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -63,6 +63,7 @@ import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLFBODrawableImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -85,6 +86,8 @@ public class MacOSXCGLContext extends GLContextImpl // NSOpenGL-based or CGL-based) protected interface GLBackendImpl { boolean isNSContext(); + /** Indicating CALayer, i.e. onscreen rendering using offscreen layer. */ + boolean isUsingCALayer(); long create(long share, int ctp, int major, int minor); boolean destroy(long ctx); void associateDrawable(boolean bound); @@ -108,6 +111,9 @@ public class MacOSXCGLContext extends GLContextImpl } static boolean isGLProfileSupported(final int ctp, final int major, final int minor) { + if( 0 != ( CTX_PROFILE_ES & ctp ) ) { + return false; + } final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; final boolean ctCore = 0 != ( CTX_PROFILE_CORE & ctp ) ; @@ -423,12 +429,33 @@ public class MacOSXCGLContext extends GLContextImpl } @Override - protected boolean setSwapIntervalImpl(final int interval) { - return impl.setSwapInterval(interval); + protected final Integer setSwapIntervalImpl2(final int interval) { + if( !impl.isUsingCALayer() && !drawable.getChosenGLCapabilities().isOnscreen() ) { + return null; + } + final int useInterval; + if( 0 > interval ) { + useInterval = Math.abs(interval); + } else { + useInterval = interval; + } + if( impl.setSwapInterval(useInterval) ) { + return Integer.valueOf(useInterval); + } + return null; } + /** + * {@inheritDoc} + * <p> + * Ignoring {@code contextFQN}, using {@code MacOSX}-{@link AbstractGraphicsDevice#getUniqueID()}. + * </p> + */ @Override - protected final void updateGLXProcAddressTable() { + protected final void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh) { + if( null == dlh ) { + throw new GLException("No GLDynamicLookupHelper for "+this); + } final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "MacOSX-"+adevice.getUniqueID(); @@ -446,7 +473,7 @@ public class MacOSXCGLContext extends GLContextImpl } } else { cglExtProcAddressTable = new CGLExtProcAddressTable(new GLProcAddressResolver()); - resetProcAddressTable(getCGLExtProcAddressTable()); + resetProcAddressTable(getCGLExtProcAddressTable(), dlh); synchronized(mappedContextTypeObjectLock) { mappedGLXProcAddress.put(key, getCGLExtProcAddressTable()); if(DEBUG) { @@ -521,6 +548,8 @@ public class MacOSXCGLContext extends GLContextImpl @Override public boolean isNSContext() { return true; } + @Override + public boolean isUsingCALayer() { return null != backingLayerHost; } /** Only returns a valid NSView. If !NSView, return null and mark either isPBuffer, isFBO or isSurfaceless. */ private long getNSViewHandle(final boolean[] isPBuffer, final boolean[] isFBO, final boolean[] isSurfaceless) { @@ -547,7 +576,7 @@ public class MacOSXCGLContext extends GLContextImpl nsViewHandle = OSXUtil.GetNSView(drawableHandle); } else if( isPBuffer[0] ) { nsViewHandle = 0; - } else if( isSurfacelessOK() ) { + } else if( isSurfaceless() ) { isSurfaceless[0] = true; nsViewHandle = 0; } else { @@ -1128,6 +1157,9 @@ public class MacOSXCGLContext extends GLContextImpl public boolean isNSContext() { return false; } @Override + public boolean isUsingCALayer() { return false; } + + @Override public long create(final long share, final int ctp, final int major, final int minor) { long ctx = 0; final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index ab1d56e29..871067f4c 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -148,7 +148,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - public GLDynamicLookupHelper getGLDynamicLookupHelper(final String profileName) { + public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) { return macOSXCGLDynamicLookupHelper; } @@ -335,6 +335,33 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { return null; } + /** + * {@inheritDoc} + * <p> + * This factory always supports native desktop OpenGL profiles. + * </p> + */ + @Override + public final boolean hasOpenGLDesktopSupport() { return true; } + + /** + * {@inheritDoc} + * <p> + * This factory never supports native GLES profiles. + * </p> + */ + @Override + public final boolean hasOpenGLESSupport() { return false; } + + /** + * {@inheritDoc} + * <p> + * Always returns true. + * </p> + */ + @Override + public final boolean hasMajorMinorCreateContextARB() { return true; } + @Override protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) { return MacOSXCGLGraphicsConfiguration.getAvailableCapabilities(this, device); diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java index 562d4883d..bdd9b6c95 100644 --- a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java +++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java @@ -195,11 +195,21 @@ public class ALAudioSink implements AudioSink { clearPreALError("init."+checkErrIter++); preferredAudioFormat = new AudioFormat(querySampleRate(), DefaultFormat.sampleSize, DefaultFormat.channelCount, DefaultFormat.signed, DefaultFormat.fixedP, DefaultFormat.planar, DefaultFormat.littleEndian); if( DEBUG ) { - System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(ALConstants.AL_EXTENSIONS)); + final int[] alcvers = { 0, 0 }; + System.out.println("ALAudioSink: OpenAL Version: "+al.alGetString(ALConstants.AL_VERSION)); + System.out.println("ALAudioSink: OpenAL Extensions: "+al.alGetString(ALConstants.AL_EXTENSIONS)); clearPreALError("init."+checkErrIter++); - System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALCConstants.ALC_EXTENSIONS)); + System.out.println("ALAudioSink: Null device OpenALC:"); + alc.alcGetIntegerv(null, ALCConstants.ALC_MAJOR_VERSION, 1, alcvers, 0); + alc.alcGetIntegerv(null, ALCConstants.ALC_MINOR_VERSION, 1, alcvers, 1); + System.out.println(" Version: "+alcvers[0]+"."+alcvers[1]); + System.out.println(" Extensions: "+alc.alcGetString(null, ALCConstants.ALC_EXTENSIONS)); clearPreALError("init."+checkErrIter++); - System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALCConstants.ALC_EXTENSIONS)); + System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenALC:"); + alc.alcGetIntegerv(device, ALCConstants.ALC_MAJOR_VERSION, 1, alcvers, 0); + alc.alcGetIntegerv(device, ALCConstants.ALC_MINOR_VERSION, 1, alcvers, 1); + System.out.println(" Version: "+alcvers[0]+"."+alcvers[1]); + System.out.println(" Extensions: "+alc.alcGetString(device, ALCConstants.ALC_EXTENSIONS)); System.out.println("ALAudioSink: hasSOFTBufferSamples "+hasSOFTBufferSamples); System.out.println("ALAudioSink: hasALC_thread_local_context "+hasALC_thread_local_context); System.out.println("ALAudioSink: preferredAudioFormat "+preferredAudioFormat); @@ -310,12 +320,14 @@ public class ALAudioSink implements AudioSink { final int alSrcName = null != alSource ? alSource[0] : 0; final int alBuffersLen = null != alBufferNames ? alBufferNames.length : 0; final int ctxHash = context != null ? context.hashCode() : 0; + final int alFramesAvailSize = alFramesAvail != null ? alFramesAvail.size() : 0; + final int alFramesPlayingSize = alFramesPlaying != null ? alFramesPlaying.size() : 0; return "ALAudioSink[init "+initialized+", playRequested "+playRequested+", device "+deviceSpecifier+", ctx "+toHexString(ctxHash)+", alSource "+alSrcName+ ", chosen "+chosenFormat+ ", al[chan "+ALHelpers.alChannelLayoutName(alChannelLayout)+", type "+ALHelpers.alSampleTypeName(alSampleType)+ ", fmt "+toHexString(alFormat)+", soft "+hasSOFTBufferSamples+ - "], playSpeed "+playSpeed+", buffers[total "+alBuffersLen+", avail "+alFramesAvail.size()+", "+ - "queued["+alFramesPlaying.size()+", apts "+getPTS()+", "+getQueuedTime() + " ms, " + alBufferBytesQueued+" bytes], "+ + "], playSpeed "+playSpeed+", buffers[total "+alBuffersLen+", avail "+alFramesAvailSize+", "+ + "queued["+alFramesPlayingSize+", apts "+getPTS()+", "+getQueuedTime() + " ms, " + alBufferBytesQueued+" bytes], "+ "queue[g "+frameGrowAmount+", l "+frameLimit+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index cfecbfd8d..f09d289fa 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -46,10 +46,14 @@ import com.jogamp.opengl.GLProfile; import jogamp.opengl.Debug; import com.jogamp.common.net.UriQueryProps; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.net.Uri; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.LFRingbuffer; import com.jogamp.common.util.Ringbuffer; +import com.jogamp.common.util.SourcedInterruptedException; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.TimeFrameI; import com.jogamp.opengl.util.av.AudioSink; @@ -365,7 +369,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { event_mask = addStateEventMask(event_mask, GLMediaPlayer.State.Paused); setState( State.Paused ); if( null != streamWorker ) { - streamWorker.doPause(); + streamWorker.doPause(true); } if( flush ) { resetAVPTSAndFlush(); @@ -414,7 +418,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { final State _state = state; setState( State.Paused ); if( null != streamWorker ) { - streamWorker.doPause(); + streamWorker.doPause(true); } // Adjust target .. if( msec >= duration ) { @@ -571,7 +575,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { this.vid = vid; this.aid = aid; - new Thread() { + new InterruptSource.Thread() { public void run() { try { // StreamWorker may be used, see API-doc of StreamWorker @@ -968,8 +972,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * shall be <code>null</code> for audio only. * @return the last processed video PTS value, maybe {@link TimeFrameI#INVALID_PTS} if video frame is invalid or n/a. * Will be {@link TimeFrameI#END_OF_STREAM_PTS} if end of stream reached. + * @throws InterruptedException if waiting for next frame fails */ - protected abstract int getNextTextureImpl(GL gl, TextureFrame nextFrame); + protected abstract int getNextTextureImpl(GL gl, TextureFrame nextFrame) throws InterruptedException; protected final int getNextSingleThreaded(final GL gl, final TextureFrame nextFrame, final boolean[] gotVFrame) throws InterruptedException { final int pts; @@ -1064,7 +1069,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { * {@link GLMediaPlayerImpl#updateAttributes(int, int, int, int, int, int, int, float, int, int, int, String, String) updateAttributes(..)}, * the latter decides whether StreamWorker is being used. */ - class StreamWorker extends Thread { + class StreamWorker extends InterruptSource.Thread { private volatile boolean isRunning = false; private volatile boolean isActive = false; private volatile boolean isBlocked = false; @@ -1086,13 +1091,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { setDaemon(true); synchronized(this) { start(); - while( !isRunning ) { + try { this.notifyAll(); // wake-up startup-block - try { + while( !isRunning && !shallStop ) { this.wait(); // wait until started - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } } } @@ -1140,18 +1145,20 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { sharedGLCtx.release(); } } - public final synchronized void doPause() { + public final synchronized void doPause(final boolean waitUntilDone) { if( isActive ) { shallPause = true; - if( Thread.currentThread() != this ) { + if( java.lang.Thread.currentThread() != this ) { if( isBlocked && isActive ) { this.interrupt(); } - while( isActive && isRunning ) { + if( waitUntilDone ) { try { - this.wait(); // wait until paused + while( isActive && isRunning ) { + this.wait(); // wait until paused + } } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } @@ -1160,14 +1167,16 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { public final synchronized void doResume() { if( isRunning && !isActive ) { shallPause = false; - if( Thread.currentThread() != this ) { - while( !isActive && !shallPause && isRunning ) { + if( java.lang.Thread.currentThread() != this ) { + try { this.notifyAll(); // wake-up pause-block - try { + while( !isActive && !shallPause && isRunning ) { this.wait(); // wait until resumed - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + final InterruptedException e2 = SourcedInterruptedException.wrap(e); + doPause(false); + throw new InterruptedRuntimeException(e2); } } } @@ -1175,17 +1184,17 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { public final synchronized void doStop() { if( isRunning ) { shallStop = true; - if( Thread.currentThread() != this ) { + if( java.lang.Thread.currentThread() != this ) { if( isBlocked && isRunning ) { this.interrupt(); } - while( isRunning ) { + try { this.notifyAll(); // wake-up pause-block (opt) - try { + while( isRunning ) { this.wait(); // wait until stopped - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } } } @@ -1203,48 +1212,48 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { this.notifyAll(); // wake-up ctor() } - while( !shallStop ){ - if( shallPause ) { - synchronized ( this ) { - if( sharedGLCtxCurrent ) { - postNextTextureImpl(sharedGLCtx.getGL()); - sharedGLCtx.release(); - } - while( shallPause && !shallStop ) { - isActive = false; - this.notifyAll(); // wake-up doPause() - try { - this.wait(); // wait until resumed - } catch (final InterruptedException e) { - if( !shallPause ) { - e.printStackTrace(); + while( !shallStop ) { + TextureFrame nextFrame = null; + try { + if( shallPause ) { + synchronized ( this ) { + if( sharedGLCtxCurrent ) { + postNextTextureImpl(sharedGLCtx.getGL()); + sharedGLCtx.release(); + } + while( shallPause && !shallStop ) { + isActive = false; + this.notifyAll(); // wake-up doPause() + try { + this.wait(); // wait until resumed + } catch (final InterruptedException e) { + if( !shallPause ) { + throw SourcedInterruptedException.wrap(e); + } } } + if( sharedGLCtxCurrent ) { + makeCurrent(sharedGLCtx); + preNextTextureImpl(sharedGLCtx.getGL()); + } + isActive = true; + this.notifyAll(); // wake-up doResume() } - if( sharedGLCtxCurrent ) { - makeCurrent(sharedGLCtx); - preNextTextureImpl(sharedGLCtx.getGL()); - } - isActive = true; - this.notifyAll(); // wake-up doResume() } - } - if( !sharedGLCtxCurrent && null != sharedGLCtx ) { - synchronized ( this ) { - if( null != sharedGLCtx ) { - makeCurrent( sharedGLCtx ); - preNextTextureImpl(sharedGLCtx.getGL()); - sharedGLCtxCurrent = true; - } - if( null == videoFramesFree ) { - throw new InternalError("XXX videoFramesFree is null"); + if( !sharedGLCtxCurrent && null != sharedGLCtx ) { + synchronized ( this ) { + if( null != sharedGLCtx ) { + makeCurrent( sharedGLCtx ); + preNextTextureImpl(sharedGLCtx.getGL()); + sharedGLCtxCurrent = true; + } + if( null == videoFramesFree ) { + throw new InternalError("XXX videoFramesFree is null"); + } } } - } - if( !shallStop ) { - TextureFrame nextFrame = null; - try { + if( !shallStop ) { isBlocked = true; final GL gl; if( STREAM_ID_NONE != vid ) { @@ -1260,7 +1269,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { if( TimeFrameI.INVALID_PTS != vPTS ) { if( null != nextFrame ) { if( STREAM_WORKER_DELAY > 0 ) { - Thread.sleep(STREAM_WORKER_DELAY); + java.lang.Thread.sleep(STREAM_WORKER_DELAY); } if( !videoFramesDecoded.put(nextFrame) ) { throw new InternalError("XXX: free "+videoFramesFree+", decoded "+videoFramesDecoded+", "+GLMediaPlayerImpl.this); @@ -1294,31 +1303,30 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } pauseImpl(true, GLMediaEventListener.EVENT_CHANGE_EOS); } - } catch (final InterruptedException e) { - isBlocked = false; - if( !shallStop && !shallPause ) { - streamErr = new StreamException("InterruptedException while decoding: "+GLMediaPlayerImpl.this.toString(), e); - } - } catch (final Throwable t) { - streamErr = new StreamException(t.getClass().getSimpleName()+" while decoding: "+GLMediaPlayerImpl.this.toString(), t); - } finally { - if( null != nextFrame ) { // put back - videoFramesFree.put(nextFrame); + } + } catch (final InterruptedException e) { + if( !isBlocked ) { // !shallStop && !shallPause + streamErr = new StreamException("InterruptedException while decoding: "+GLMediaPlayerImpl.this.toString(), + SourcedInterruptedException.wrap(e)); + } + isBlocked = false; + } catch (final Throwable t) { + streamErr = new StreamException(t.getClass().getSimpleName()+" while decoding: "+GLMediaPlayerImpl.this.toString(), t); + } finally { + if( null != nextFrame ) { // put back + videoFramesFree.put(nextFrame); + } + if( null != streamErr ) { + if( DEBUG ) { + ExceptionUtils.dumpThrowable("handled", streamErr); } - if( null != streamErr ) { - if( DEBUG ) { - final Throwable t = null != streamErr.getCause() ? streamErr.getCause() : streamErr; - System.err.println("Caught StreamException: "+t.getMessage()); - t.printStackTrace(); - } - // state transition incl. notification - synchronized ( this ) { - shallPause = true; - isActive = false; - this.notifyAll(); // wake-up potential do*() - } - pauseImpl(true, GLMediaEventListener.EVENT_CHANGE_ERR); + // state transition incl. notification + synchronized ( this ) { + shallPause = true; + isActive = false; + this.notifyAll(); // wake-up potential do*() } + pauseImpl(true, GLMediaEventListener.EVENT_CHANGE_ERR); } } } @@ -1379,6 +1387,16 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } } + /** + * Called initially by {@link #initStreamImpl(int, int)}, which + * is called off-thread by {@link #initStream(Uri, int, int, int)}. + * <p> + * The latter catches an occurring exception and set the state delivers the error events. + * </p> + * <p> + * Further calls are issues off-thread by the decoder implementation. + * </p> + */ protected final void updateAttributes(int vid, final int aid, final int width, final int height, final int bps_stream, final int bps_video, final int bps_audio, final float fps, final int videoFrames, final int audioFrames, final int duration, final String vcodec, final String acodec) { @@ -1413,7 +1431,12 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { this.fps = fps; if( 0 != fps ) { this.frame_duration = 1000f / fps; - this.maxNullFrameCountUntilEOS = MAX_FRAMELESS_MS_UNTIL_EOS / (int)this.frame_duration; + final int fdurI = (int)this.frame_duration; + if( 0 < fdurI ) { + this.maxNullFrameCountUntilEOS = MAX_FRAMELESS_MS_UNTIL_EOS / fdurI; + } else { + this.maxNullFrameCountUntilEOS = MAX_FRAMELESS_UNTIL_EOS_DEFAULT; + } } else { this.frame_duration = 0; this.maxNullFrameCountUntilEOS = MAX_FRAMELESS_UNTIL_EOS_DEFAULT; @@ -1524,7 +1547,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { final int decVideoFrames = null != videoFramesDecoded ? videoFramesDecoded.size() : 0; final int video_scr = video_scr_pts + (int) ( ( Platform.currentTimeMillis() - video_scr_t0 ) * playSpeed ); final String camPath = null != cameraPath ? ", camera: "+cameraPath : ""; - return "GLMediaPlayer["+state+", vSCR "+video_scr+", frames[p "+presentedFrameCount+", d "+decodedFrameCount+", t "+videoFrames+" ("+tt+" s), z "+nullFrameCount+" / "+maxNullFrameCountUntilEOS+"], "+ + return getClass().getSimpleName()+"["+state+", vSCR "+video_scr+", frames[p "+presentedFrameCount+", d "+decodedFrameCount+", t "+videoFrames+" ("+tt+" s), z "+nullFrameCount+" / "+maxNullFrameCountUntilEOS+"], "+ "speed "+playSpeed+", "+bps_stream+" bps, hasSW "+(null!=streamWorker)+ ", Texture[count "+textureCount+", free "+freeVideoFrames+", dec "+decVideoFrames+", tagt "+toHexString(textureTarget)+", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+ "Video[id "+vid+", <"+vcodec+">, "+width+"x"+height+", glOrient "+isInGLOrientation+", "+fps+" fps, "+frame_duration+" fdur, "+bps_video+" bps], "+ diff --git a/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java b/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java index 44d83e78d..db8da6157 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java +++ b/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java @@ -64,7 +64,7 @@ public enum VideoPixelFormat { XVMC_MPEG2_MC, /** */ XVMC_MPEG2_IDCT, - /** packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 */ + /** packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 ( sharing Cb and Cr w/ 2 pixels ) */ UYVY422, /** packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 */ UYYVYY411, diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java index f294d5bc0..6a4257ade 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java @@ -37,7 +37,7 @@ import java.util.List; import java.util.Set; import com.jogamp.opengl.GLProfile; - +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.os.DynamicLibraryBundle; import com.jogamp.common.os.DynamicLibraryBundleInfo; import com.jogamp.common.util.RunnableExecutor; @@ -190,7 +190,8 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { libLoaded[i] = dl.isToolLibLoaded(i); } if( !libLoaded[LIB_IDX_UTI] || !libLoaded[LIB_IDX_FMT] || !libLoaded[LIB_IDX_COD] ) { - throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+libLoaded[LIB_IDX_UTI]+", avformat "+libLoaded[LIB_IDX_FMT]+", avcodec "+libLoaded[LIB_IDX_COD]+"]"); + System.err.println("FFMPEG Tool library incomplete: [ avutil "+libLoaded[LIB_IDX_UTI]+", avformat "+libLoaded[LIB_IDX_FMT]+", avcodec "+libLoaded[LIB_IDX_COD]+"]"); + return null; } dl.claimAllLinkPermission(); try { @@ -216,7 +217,10 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { throw new InternalError("XXX0 "+symbolNames.length+" != "+symbolCount); } - AccessController.doPrivileged(privInitSymbolsAction); + final DynamicLibraryBundle dl = AccessController.doPrivileged(privInitSymbolsAction); + if( null == dl ) { + return false; + } // optional symbol name set final Set<String> optionalSymbolNameSet = new HashSet<String>(); @@ -254,7 +258,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { try { _ready = initSymbols(_versions); } catch (final Throwable t) { - t.printStackTrace(); + ExceptionUtils.dumpThrowable("", t); } libsUFCLoaded = libLoaded[LIB_IDX_UTI] && libLoaded[LIB_IDX_FMT] && libLoaded[LIB_IDX_COD]; avUtilVersion = _versions[0]; @@ -328,6 +332,16 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } @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>>(); diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java index 7df5d6a9e..b5cccdb6d 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java @@ -106,11 +106,12 @@ import jogamp.opengl.util.av.VideoPixelFormat; * <p> * Currently we are binary compatible w/: * <table border="1"> - * <tr><th>libav / ffmpeg</th><th>lavc</th><th>lavf</th><th>lavu</th><th>lavr/lswr</th> <th>FFMPEG* class</th></tr> + * <tr><th>libav / ffmpeg</th><th>lavc</th><th>lavf</th><th>lavu</th><th>lavr/lswr</th> <th>FFMPEG* class</th></tr> * <tr><td>0.8</td> <td>53</td> <td>53</td> <td>51</td> <td></td> <td>FFMPEGv08</td></tr> * <tr><td>9.0 / 1.2</td> <td>54</td> <td>54</td> <td>52</td> <td>01/00</td> <td>FFMPEGv09</td></tr> * <tr><td>10 / 2.[0-3]</td> <td>55</td> <td>55</td> <td>53/52</td> <td>01/00</td> <td>FFMPEGv10</td></tr> - * <tr><td>11 / 2.[4-x]</td> <td>56</td> <td>56</td> <td>54</td> <td>02/01</td> <td>FFMPEGv11</td></tr> + * <tr><td>11 / 2.[4-8]</td> <td>56</td> <td>56</td> <td>54</td> <td>02/01</td> <td>FFMPEGv11</td></tr> + * <tr><td>12 / 2.[9-x]</td> <td>57</td> <td>57</td> <td>55</td> <td>02/01</td> <td>TODO</td></tr> * </table> * </p> * <p> @@ -145,17 +146,28 @@ import jogamp.opengl.util.av.VideoPixelFormat; * <li>GNU/Linux: ffmpeg or libav are deployed in most distributions.</li> * <li>Windows: * <ul> + * <li>https://ffmpeg.org/download.html#build-windows</li> * <li>http://ffmpeg.zeranoe.com/builds/ (ffmpeg) <i>recommended, works w/ dshow</i></li> * <li>http://win32.libav.org/releases/ (libav)</li> * </ul></li> - * <li>MacOSX using Homebrew + * <li>MacOSX * <ul> - * <li>https://github.com/Homebrew/homebrew/wiki/Installation</li> - * <li>https://trac.ffmpeg.org/wiki/CompilationGuide/MacOSX</li> + * <li>Building using Homebrew * + * <ul> + * <li>https://github.com/Homebrew/homebrew/wiki/Installation</li> + * <li>https://trac.ffmpeg.org/wiki/CompilationGuide/MacOSX<pre> +ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +brew install ffmpeg + * </pre></li> + * </ul></li> + * <li>Builds + * <ul> + * <li>https://ffmpeg.org/download.html#build-mac</li> + * </ul></li> * </ul></li> * <li>OpenIndiana/Solaris:<pre> - * pkg set-publisher -p http://pkg.openindiana.org/sfe-encumbered. - * pkt install pkg:/video/ffmpeg +pkg set-publisher -p http://pkg.openindiana.org/sfe-encumbered. +pkt install pkg:/video/ffmpeg * </pre></li> * </ul> * </p> @@ -337,12 +349,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { resStreamLocS = dev_video_linux + cameraPath.decode(); break; case WINDOWS: - resStreamLocS = cameraPath.decode(); - break; case MACOS: case OPENKODE: default: - resStreamLocS = streamLocS; // FIXME: ?? + resStreamLocS = cameraPath.decode(); break; } if( null != cameraProps ) { @@ -436,9 +446,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } break; - case 2: if( vPixelFmt == VideoPixelFormat.YUYV422 ) { + case 2: if( vPixelFmt == VideoPixelFormat.YUYV422 || vPixelFmt == VideoPixelFormat.UYVY422 ) { // YUYV422: // < packed YUV 4:2:2, 2x 16bpp, Y0 Cb Y1 Cr - // Stuffed into RGBA half width texture + // UYVY422: // < packed YUV 4:2:2, 2x 16bpp, Cb Y0 Cr Y1 + // Both stuffed into RGBA half width texture tf = GL.GL_RGBA; tif=GL.GL_RGBA; break; } else { tf = GL2ES2.GL_RG; tif=GL2ES2.GL_RG; break; @@ -606,6 +617,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { texWidth = vTexWidth[0] + vTexWidth[1] + vTexWidth[2]; texHeight = vH; break; case YUYV422: // < packed YUV 4:2:2, 2x 16bpp, Y0 Cb Y1 Cr - stuffed into RGBA half width texture + case UYVY422: // < packed YUV 4:2:2, 2x 16bpp, Cb Y0 Cr Y1 - stuffed into RGBA half width texture case BGR24: usesTexLookupShader = true; texWidth = vTexWidth[0]; texHeight = vH; @@ -764,6 +776,29 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { " return vec4(r, g, b, 1);\n"+ "}\n" ; + case UYVY422: // < packed YUV 4:2:2, 2 x 16bpp, Cb Y0 Cr Y1 + // Stuffed into RGBA half width texture + return + "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+ + " "+ + " float y1,u,y2,v,y,r,g,b;\n"+ + " vec2 tc_halfw = vec2(texCoord.x*0.5, texCoord.y);\n"+ + " vec4 uyvy = texture2D(image, tc_halfw).rgba;\n"+ + " u = uyvy.r;\n"+ + " y1 = uyvy.g;\n"+ + " v = uyvy.b;\n"+ + " y2 = uyvy.a;\n"+ + " y = mix( y1, y2, mod(gl_FragCoord.x, 2) ); /* avoid branching! */\n"+ + " y = 1.1643*(y-0.0625);\n"+ + " u = u-0.5;\n"+ + " v = v-0.5;\n"+ + " r = y+1.5958*v;\n"+ + " g = y-0.39173*u-0.81290*v;\n"+ + " b = y+2.017*u;\n"+ + " return vec4(r, g, b, 1);\n"+ + "}\n" + ; + case BGR24: return "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+ diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp index 22dd1e61a..516aa0f6f 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp @@ -6,10 +6,10 @@ #define mgl_FragColor gl_FragColor #endif -#include es_precision.glsl +#include "es_precision.glsl" -#include mgl_uniform.glsl -#include mgl_varying.glsl +#include "mgl_uniform.glsl" +#include "mgl_varying.glsl" #include mgl_alphatest.fp diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp index 130711e19..8a610f062 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp @@ -8,14 +8,14 @@ #endif -#include es_precision.glsl -#include mgl_lightdef.glsl +#include "es_precision.glsl" +#include "mgl_lightdef.glsl" -#include mgl_const.glsl -#include mgl_uniform.glsl -#include mgl_varying.glsl +#include "mgl_const.glsl" +#include "mgl_uniform.glsl" +#include "mgl_varying.glsl" -#include mgl_alphatest.fp +#include "mgl_alphatest.fp" const float gamma = 1.5; // FIXME const vec3 igammav = vec3(1.0 / gamma); // FIXME diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index a8269ad5c..fd0db7c04 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -50,15 +50,19 @@ import com.jogamp.nativewindow.NativeSurface; import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import com.jogamp.opengl.GLExtensions; +import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.GLRendererQuirks; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLXExtensions; public class WindowsWGLContext extends GLContextImpl { static final Map<String, String> extensionNameMap; @@ -70,7 +74,8 @@ public class WindowsWGLContext extends GLContextImpl { // Table that holds the addresses of the native C-language entry points for // WGL extension functions. private WGLExtProcAddressTable wglExtProcAddressTable; - private int hasSwapIntervalSGI = 0; + /** 2 WGL_EXT_swap_control_tear, 1 WGL_EXT_swap_control, 0 undefined, -1 none */ + private int hasSwapInterval = 0; private int hasSwapGroupNV = 0; static { @@ -93,7 +98,7 @@ public class WindowsWGLContext extends GLContextImpl { wglGLReadDrawableAvailable=false; // no inner state _wglExt=null; wglExtProcAddressTable=null; - hasSwapIntervalSGI = 0; + hasSwapInterval = 0; hasSwapGroupNV = 0; super.resetStates(isInit); } @@ -198,20 +203,37 @@ public class WindowsWGLContext extends GLContextImpl { @Override protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) { + if(DEBUG) { + System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") + + ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct); + } + final boolean ctDesktopGL = 0 == ( CTX_PROFILE_ES & ctp ); + final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + if( !ctDesktopGL ) { + if(DEBUG) { + System.err.println(getThreadName() + ": WindowWGLContext.createContextARBImpl: GL ES not avail "+getGLVersion(major, minor, ctp, "@creation")); + } + return 0; // n/a + } if( null == getWGLExtProcAddressTable()) { - updateGLXProcAddressTable(); + final GLDynamicLookupHelper dlh = getGLDynamicLookupHelper(major, ctp); + if( null == dlh ) { + if(DEBUG) { + System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: Null GLDynamicLookupHelper"); + } + return 0; + } else { + updateGLXProcAddressTable(null, dlh); + } } final WGLExt _wglExt = getWGLExt(); if(DEBUG) { - System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") + - ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+ + System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: "+ ", wglCreateContextAttribsARB: "+toHexString(wglExtProcAddressTable._addressof_wglCreateContextAttribsARB)); } - final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; - final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; - final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; - long ctx=0; final int idx_flags = 4; @@ -294,6 +316,11 @@ public class WindowsWGLContext extends GLContextImpl { "], bitmap "+glCaps.isBitmap()+" -> "+createContextARBAvailable+ "], shared "+sharedCreatedWithARB+"]"); } + final GLProfile glp = glCaps.getGLProfile(); + if( glp.isGLES() ) { + throw new GLException(getThreadName()+": Unable to create OpenGL ES context on desktopDevice "+device+ + ", config "+config+", "+glp+", shareWith "+toHexString(shareWithHandle)); + } boolean createContextARBTried = false; // utilize the shared context's GLXExt in case it was using the ARB method and it already exists @@ -438,8 +465,17 @@ public class WindowsWGLContext extends GLContextImpl { } } + /** + * {@inheritDoc} + * <p> + * Ignoring {@code contextFQN}, using {@code WGL}-{@link AbstractGraphicsDevice#getUniqueID()}. + * </p> + */ @Override - protected final void updateGLXProcAddressTable() { + protected final void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh) { + if( null == dlh ) { + throw new GLException("No GLDynamicLookupHelper for "+this); + } final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "WGL-"+adevice.getUniqueID(); @@ -462,7 +498,7 @@ public class WindowsWGLContext extends GLContextImpl { } } else { wglExtProcAddressTable = new WGLExtProcAddressTable(new GLProcAddressResolver()); - resetProcAddressTable(wglExtProcAddressTable); + resetProcAddressTable(wglExtProcAddressTable, dlh); synchronized(mappedContextTypeObjectLock) { mappedGLXProcAddress.put(key, getWGLExtProcAddressTable()); if(DEBUG) { @@ -487,19 +523,42 @@ public class WindowsWGLContext extends GLContextImpl { } @Override - protected boolean setSwapIntervalImpl(final int interval) { - final WGLExt wglExt = getWGLExt(); - if(0==hasSwapIntervalSGI) { + protected final Integer setSwapIntervalImpl2(final int interval) { + if( !drawable.getChosenGLCapabilities().isOnscreen() ) { + return null; + } + if( 0 == hasSwapInterval ) { try { - hasSwapIntervalSGI = wglExt.isExtensionAvailable("WGL_EXT_swap_control")?1:-1; - } catch (final Throwable t) { hasSwapIntervalSGI=1; } + if ( isExtensionAvailable(GLXExtensions.WGL_EXT_swap_control) ) { + hasSwapInterval = 1; + if ( isExtensionAvailable(GLXExtensions.WGL_EXT_swap_control_tear) ) { + hasSwapInterval = 2; + if(DEBUG) { System.err.println("WGLContext.setSwapInterval.2 using: "+GLXExtensions.WGL_EXT_swap_control_tear + ", " + GLXExtensions.WGL_EXT_swap_control_tear); } + } else { + hasSwapInterval = 1; + if(DEBUG) { System.err.println("WGLContext.setSwapInterval.1 using: "+GLXExtensions.WGL_EXT_swap_control); } + } + } else { + hasSwapInterval = -1; + if(DEBUG) { System.err.println("WGLContext.setSwapInterval.0 N/A"); } + } + } catch (final Throwable t) { hasSwapInterval=-1; if(DEBUG) { ExceptionUtils.dumpThrowable("", t); } } } - if (hasSwapIntervalSGI>0) { + if ( 0 < hasSwapInterval ) { // 2 || 1 + final int useInterval; + if( 1 == hasSwapInterval && 0 > interval ) { + useInterval = Math.abs(interval); + } else { + useInterval = interval; + } try { - return wglExt.wglSwapIntervalEXT(interval); - } catch (final Throwable t) { hasSwapIntervalSGI=-1; } + final WGLExt wglExt = getWGLExt(); + if( wglExt.wglSwapIntervalEXT(useInterval) ) { + return Integer.valueOf(useInterval); + } + } catch (final Throwable t) { hasSwapInterval=-1; if(DEBUG) { ExceptionUtils.dumpThrowable("", t); } } } - return false; + return null; } private final int initSwapGroupImpl(final WGLExt wglExt) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index 932c81f5d..652184e7e 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -44,8 +44,6 @@ import java.nio.Buffer; import java.nio.ShortBuffer; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Collection; -import java.util.HashMap; import java.util.List; import com.jogamp.nativewindow.AbstractGraphicsConfiguration; @@ -191,11 +189,10 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } catch (final Exception jre) { /* n/a .. */ } } - sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); - // Init shared resources off thread // Will be released via ShutdownHook - sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation()); + sharedResourceImplementation = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImplementation); sharedResourceRunner.start(); } } @@ -215,9 +212,9 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { sharedResourceRunner.stop(); sharedResourceRunner = null; } - if(null != sharedMap) { - sharedMap.clear(); - sharedMap = null; + if(null != sharedResourceImplementation) { + sharedResourceImplementation.clear(); + sharedResourceImplementation = null; } defaultDevice = null; /** @@ -231,15 +228,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - public GLDynamicLookupHelper getGLDynamicLookupHelper(final String profileName) { + public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) { return windowsWGLDynamicLookupHelper; } /* pp */ static String toHexString(final long l) { return "0x"+Long.toHexString(l); } private WindowsGraphicsDevice defaultDevice; + private SharedResourceImplementation sharedResourceImplementation; private SharedResourceRunner sharedResourceRunner; - private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap; @Override protected void enterThreadCriticalZone() { @@ -300,26 +297,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { final boolean hasReadDrawable() { return hasARBReadDrawable; } } - class SharedResourceImplementation implements SharedResourceRunner.Implementation { - @Override - public void clear() { - sharedMap.clear(); - } - @Override - public SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { - return sharedMap.put(device.getConnection(), resource); - } - @Override - public SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { - return sharedMap.get(device.getConnection()); - } - @Override - public Collection<SharedResourceRunner.Resource> mapValues() { - synchronized(sharedMap) { - return sharedMap.values(); - } - } - + class SharedResourceImplementation extends SharedResourceRunner.AImplementation { @Override public boolean isDeviceSupported(final AbstractGraphicsDevice device) { return true; @@ -465,6 +443,33 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { return null; } + /** + * {@inheritDoc} + * <p> + * This factory always supports native desktop OpenGL profiles. + * </p> + */ + @Override + public final boolean hasOpenGLDesktopSupport() { return true; } + + /** + * {@inheritDoc} + * <p> + * This factory never supports native GLES profiles. + * </p> + */ + @Override + public final boolean hasOpenGLESSupport() { return false; } + + /** + * {@inheritDoc} + * <p> + * Always returns true. + * </p> + */ + @Override + public final boolean hasMajorMinorCreateContextARB() { return true; } + @Override protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) { return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index f88718d1b..4ffe6e7d1 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -171,24 +171,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio ": error code " + GDI.GetLastError()); } if( !caps.isBackgroundOpaque() ) { - final long hwnd = GDI.WindowFromDC(hdc); - final DWM_BLURBEHIND bb = DWM_BLURBEHIND.create(); - bb.setDwFlags(GDI.DWM_BB_ENABLE| GDI.DWM_BB_TRANSITIONONMAXIMIZED); - bb.setFEnable( 1 ); - boolean ok = GDI.DwmEnableBlurBehindWindow(hwnd, bb); - if( ok ) { - final MARGINS m = MARGINS.create(); - m.setCxLeftWidth(-1); - m.setCxRightWidth(-1); - m.setCyBottomHeight(-1); - m.setCyTopHeight(-1); - ok = GDI.DwmExtendFrameIntoClientArea(hwnd, m); - } - if(DEBUG) { - final boolean isUndecorated = GDIUtil.IsUndecorated(hwnd); - final boolean isChild = GDIUtil.IsChild(hwnd); - System.err.println("translucency enabled on wnd: 0x"+Long.toHexString(hwnd)+" - isUndecorated "+isUndecorated+", isChild "+isChild+", ok: "+ok); - } + GDIUtil.DwmSetupTranslucency(GDI.WindowFromDC(hdc), true); } if (DEBUG) { System.err.println("setPixelFormat: hdc "+toHexString(hdc) +", "+caps); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 21eb6b8f3..99268f13f 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -56,6 +56,7 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.GLRendererQuirks; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLGraphicsConfigurationFactory; @@ -349,7 +350,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - final boolean isOpaque = capsChosen.isBackgroundOpaque() && GDI.DwmIsCompositionEnabled(); + final boolean isOpaque = capsChosen.isBackgroundOpaque() && GDIUtil.DwmIsCompositionEnabled(); final int winattrbits = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen) & ~GLGraphicsConfigurationUtil.BITMAP_BIT; // w/o BITMAP final GLProfile glProfile = capsChosen.getGLProfile(); @@ -358,7 +359,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if(DEBUG) { System.err.println("updateGraphicsConfigurationARB: hdc "+toHexString(hdc)+", pfdIDCount(hdc) "+pfdIDCount+", capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString()); - System.err.println("\tisOpaque "+isOpaque+" (translucency requested: "+(!capsChosen.isBackgroundOpaque())+", compositioning enabled: "+GDI.DwmIsCompositionEnabled()+")"); + System.err.println("\tisOpaque "+isOpaque+" (translucency requested: "+(!capsChosen.isBackgroundOpaque())+", compositioning enabled: "+GDIUtil.DwmIsCompositionEnabled()+")"); final int pformatsNum = null != pformats ? pformats.length : -1; System.err.println("\textHDC "+extHDC+", chooser "+(null!=chooser)+", pformatsNum "+pformatsNum); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 63b0b35c0..24f2ab8dd 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -56,6 +56,7 @@ import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLXExtensions; import com.jogamp.common.ExceptionUtils; @@ -72,7 +73,7 @@ public class X11GLXContext extends GLContextImpl { // Table that holds the addresses of the native C-language entry points for // GLX extension functions. private GLXExtProcAddressTable glXExtProcAddressTable; - /** 1 MESA, 2 SGI, 0 undefined, -1 none */ + /** 3 SGI, 2 GLX_EXT_swap_control_tear, 1 GLX_EXT_swap_control, 0 undefined, -1 none */ private int hasSwapInterval = 0; private int hasSwapGroupNV = 0; @@ -224,17 +225,34 @@ public class X11GLXContext extends GLContextImpl { @Override protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) { - updateGLXProcAddressTable(); - final GLXExt _glXExt = getGLXExt(); if(DEBUG) { System.err.println(getThreadName()+": X11GLXContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") + - ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+ - ", glXCreateContextAttribsARB: "+toHexString(glXExtProcAddressTable._addressof_glXCreateContextAttribsARB)); + ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct); } - + final boolean ctDesktopGL = 0 == ( CTX_PROFILE_ES & ctp ); final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + if( !ctDesktopGL ) { + if(DEBUG) { + System.err.println(getThreadName() + ": X11GLXContext.createContextARBImpl: GL ES not avail "+getGLVersion(major, minor, ctp, "@creation")); + } + return 0; // n/a + } + final GLDynamicLookupHelper dlh = getGLDynamicLookupHelper(major, ctp); + if( null == dlh ) { + if(DEBUG) { + System.err.println(getThreadName()+" - X11GLXContext.createContextARBImpl: Null GLDynamicLookupHelper"); + } + return 0; + } else { + updateGLXProcAddressTable(null, dlh); + } + final GLXExt _glXExt = getGLXExt(); + if(DEBUG) { + System.err.println(getThreadName()+": X11GLXContext.createContextARBImpl: "+ + ", glXCreateContextAttribsARB: "+toHexString(glXExtProcAddressTable._addressof_glXCreateContextAttribsARB)); + } final IntBuffer attribs = Buffers.newDirectIntBuffer(ctx_arb_attribs_rom); attribs.put(ctx_arb_attribs_idx_major + 1, major); @@ -322,6 +340,10 @@ public class X11GLXContext extends GLContextImpl { "], fbCfg "+config.hasFBConfig()+" -> "+createContextARBAvailable+ "], shared "+sharedCreatedWithARB+"]"); } + if( glp.isGLES() ) { + throw new GLException(getThreadName()+": Unable to create OpenGL ES context on desktopDevice "+device+ + ", config "+config+", "+glp+", shareWith "+toHexString(shareWithHandle)); + } if( !config.hasFBConfig() ) { // not able to use FBConfig -> GLX 1.1 @@ -479,8 +501,17 @@ public class X11GLXContext extends GLContextImpl { // Should check for X errors and raise GLException } + /** + * {@inheritDoc} + * <p> + * Ignoring {@code contextFQN}, using {@code GLX}+{@link AbstractGraphicsDevice#getUniqueID()}. + * </p> + */ @Override - protected final void updateGLXProcAddressTable() { + protected final void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh) { + if( null == dlh ) { + throw new GLException("No GLDynamicLookupHelper for "+this); + } final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "GLX-"+adevice.getUniqueID(); @@ -498,7 +529,7 @@ public class X11GLXContext extends GLContextImpl { } } else { glXExtProcAddressTable = new GLXExtProcAddressTable(new GLProcAddressResolver()); - resetProcAddressTable(getGLXExtProcAddressTable()); + resetProcAddressTable(getGLXExtProcAddressTable(), dlh); synchronized(mappedContextTypeObjectLock) { mappedGLXProcAddress.put(key, getGLXExtProcAddressTable()); if(DEBUG) { @@ -549,39 +580,67 @@ public class X11GLXContext extends GLContextImpl { } @Override - protected boolean setSwapIntervalImpl(final int interval) { - if( !drawable.getChosenGLCapabilities().isOnscreen() ) { return false; } - - final GLXExt glXExt = getGLXExt(); - if(0==hasSwapInterval) { + protected final Integer setSwapIntervalImpl2(final int interval) { + if( !drawable.getChosenGLCapabilities().isOnscreen() ) { + return null; + } + final long displayHandle = drawable.getNativeSurface().getDisplayHandle(); + if( 0 == hasSwapInterval ) { try { - /** Same impl. .. - if( glXExt.isExtensionAvailable(GLXExtensions.GLX_MESA_swap_control) ) { - if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval using: "+GLXExtensions.GLX_MESA_swap_control); } - hasSwapInterval = 1; - } else */ - if ( glXExt.isExtensionAvailable(GLXExtensions.GLX_SGI_swap_control) ) { - if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval using: "+GLXExtensions.GLX_SGI_swap_control); } - hasSwapInterval = 2; + if ( isExtensionAvailable(GLXExtensions.GLX_EXT_swap_control) ) { + hasSwapInterval = 1; + if ( isExtensionAvailable(GLXExtensions.GLX_EXT_swap_control_tear) ) { + try { + final IntBuffer val = Buffers.newDirectIntBuffer(1); + GLX.glXQueryDrawable(displayHandle, drawable.getHandle(), GLX.GLX_LATE_SWAPS_TEAR_EXT, val); + if( 1 == val.get(0) ) { + hasSwapInterval = 2; + if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval.2 using: "+GLXExtensions.GLX_EXT_swap_control_tear + ", " + GLXExtensions.GLX_EXT_swap_control_tear); } + } else if(DEBUG) { + System.err.println("X11GLXContext.setSwapInterval.2 n/a: "+GLXExtensions.GLX_EXT_swap_control_tear+", query: "+val.get(0)); + } + } catch (final Throwable t) { if(DEBUG) { ExceptionUtils.dumpThrowable("", t); } } + } + if(DEBUG) { + if( 1 == hasSwapInterval ) { + System.err.println("X11GLXContext.setSwapInterval.1 using: "+GLXExtensions.GLX_EXT_swap_control); + } + } + } else if ( isExtensionAvailable(GLXExtensions.GLX_SGI_swap_control) ) { + hasSwapInterval = 3; + if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval.3 using: "+GLXExtensions.GLX_SGI_swap_control); } } else { hasSwapInterval = -1; + if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval.0 N/A"); } } - } catch (final Throwable t) { hasSwapInterval=-1; } + } catch (final Throwable t) { hasSwapInterval=-1; if(DEBUG) { ExceptionUtils.dumpThrowable("", t); } } } - /* try { - switch( hasSwapInterval ) { - case 1: - return 0 == glXExt.glXSwapIntervalMESA(interval); - case 2: - return 0 == glXExt.glXSwapIntervalSGI(interval); + if (3 == hasSwapInterval) { + final int useInterval; + if( 0 > interval ) { + useInterval = Math.abs(interval); + } else { + useInterval = interval; + } + try { + final GLXExt glXExt = getGLXExt(); + if( 0 == glXExt.glXSwapIntervalSGI(useInterval) ) { + return Integer.valueOf(useInterval); + } + } catch (final Throwable t) { hasSwapInterval=-1; if(DEBUG) { ExceptionUtils.dumpThrowable("", t); } } + } else if ( 0 < hasSwapInterval ) { // 2 || 1 + final int useInterval; + if( 1 == hasSwapInterval && 0 > interval ) { + useInterval = Math.abs(interval); + } else { + useInterval = interval; } - } catch (Throwable t) { hasSwapInterval = -1; } */ - if (2 == hasSwapInterval) { try { - return 0 == glXExt.glXSwapIntervalSGI(interval); - } catch (final Throwable t) { hasSwapInterval=-1; } + GLX.glXSwapIntervalEXT(displayHandle, drawable.getHandle(), useInterval); + return Integer.valueOf(useInterval); + } catch (final Throwable t) { hasSwapInterval=-1; if(DEBUG) { ExceptionUtils.dumpThrowable("", t); } } } - return false; + return null; } private final int initSwapGroupImpl(final GLXExt glXExt) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index ecaf20d86..a03ce1641 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -41,8 +41,6 @@ import java.nio.Buffer; import java.nio.ShortBuffer; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Collection; -import java.util.HashMap; import java.util.List; import com.jogamp.nativewindow.AbstractGraphicsConfiguration; @@ -126,11 +124,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { // The act of constructing them causes them to be registered X11GLXGraphicsConfigurationFactory.registerFactory(); - sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); - // Init shared resources off thread // Will be released via ShutdownHook - sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation()); + sharedResourceImplementation = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImplementation); sharedResourceRunner.start(); } } @@ -149,9 +146,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { sharedResourceRunner.stop(); sharedResourceRunner = null; } - if(null != sharedMap) { - sharedMap.clear(); - sharedMap = null; + if(null != sharedResourceImplementation) { + sharedResourceImplementation.clear(); + sharedResourceImplementation = null; } defaultDevice = null; /** @@ -163,13 +160,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override - public final GLDynamicLookupHelper getGLDynamicLookupHelper(final String profileName) { + public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) { return x11GLXDynamicLookupHelper; } private X11GraphicsDevice defaultDevice; + private SharedResourceImplementation sharedResourceImplementation; private SharedResourceRunner sharedResourceRunner; - private HashMap<String /* connection */, SharedResourceRunner.Resource> sharedMap; static class SharedResource implements SharedResourceRunner.Resource { private final String glXServerVendorName; @@ -226,24 +223,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { final boolean isGLXMultisampleAvailable() { return glXMultisampleAvailable; } } - class SharedResourceImplementation implements SharedResourceRunner.Implementation { - @Override - public void clear() { - sharedMap.clear(); - } - @Override - public SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { - return sharedMap.put(device.getConnection(), resource); - } - @Override - public SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { - return sharedMap.get(device.getConnection()); - } - @Override - public Collection<SharedResourceRunner.Resource> mapValues() { - return sharedMap.values(); - } - + class SharedResourceImplementation extends SharedResourceRunner.AImplementation { @Override public boolean isDeviceSupported(final AbstractGraphicsDevice device) { final boolean res; @@ -399,6 +379,33 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return 0; } + /** + * {@inheritDoc} + * <p> + * This factory always supports native desktop OpenGL profiles. + * </p> + */ + @Override + public final boolean hasOpenGLDesktopSupport() { return true; } + + /** + * {@inheritDoc} + * <p> + * This factory never supports native GLES profiles. + * </p> + */ + @Override + public final boolean hasOpenGLESSupport() { return false; } + + /** + * {@inheritDoc} + * <p> + * Always returns true. + * </p> + */ + @Override + public final boolean hasMajorMinorCreateContextARB() { return true; } + @Override protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) { return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index 86349b645..8f7d710cd 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -275,21 +275,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return val; } - static XRenderDirectFormat XVisual2XRenderMask(final long dpy, final long visual) { - final XRenderPictFormat renderPictFmt = X11Lib.XRenderFindVisualFormat(dpy, visual); - if(null == renderPictFmt) { - return null; - } - return renderPictFmt.getDirect(); - } - static XRenderDirectFormat XVisual2XRenderMask(final long dpy, final long visual, final XRenderPictFormat dest) { - if( !X11Lib.XRenderFindVisualFormat(dpy, visual, dest) ) { - return null; - } else { - return dest.getDirect(); - } - } - static X11GLCapabilities GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final long fbcfg, final int winattrmask, final boolean isMultisampleAvailable) { final IntBuffer tmp = Buffers.newDirectIntBuffer(1); diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c index 5c18b94b1..e524df9bf 100644 --- a/src/jogl/native/GLDebugMessageHandler.c +++ b/src/jogl/native/GLDebugMessageHandler.c @@ -17,6 +17,7 @@ #define DBG_PRINT(...) #endif +// Note: 'ARB' is also used for 'KHR'! static jmethodID glDebugMessageARB = NULL; // int source, int type, int id, int severity, String msg static jmethodID glDebugMessageAMD = NULL; // int id, int category, int severity, String msg @@ -120,7 +121,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_opengl_GLDebugMessageHandler_register0 handle->extType = extType; DBG_PRINT("GLDebugMessageHandler.register0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType); - if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) { + if(jogamp_opengl_GLDebugMessageHandler_EXT_KHR == extType || + jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) { _local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB; ptr_glDebugMessageCallbackARB = (_local_PFNGLDEBUGMESSAGECALLBACKARBPROC) (intptr_t) procAddress; ptr_glDebugMessageCallbackARB((_local_GLDEBUGPROCARB)GLDebugMessageARBCallback, handle); @@ -151,7 +153,8 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_GLDebugMessageHandler_unregister0 JoglCommon_throwNewRuntimeException(env, "wrong handle (obj doesn't match)"); } - if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == handle->extType) { + if(jogamp_opengl_GLDebugMessageHandler_EXT_KHR == handle->extType || + jogamp_opengl_GLDebugMessageHandler_EXT_ARB == handle->extType) { _local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB; ptr_glDebugMessageCallbackARB = (_local_PFNGLDEBUGMESSAGECALLBACKARBPROC) (intptr_t) procAddress; ptr_glDebugMessageCallbackARB((_local_GLDEBUGPROCARB)NULL, NULL); diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index ca283ef52..d02770eb7 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -622,6 +622,7 @@ static const char * inFmtNames[] = { "video4linux", // linux (old) "dshow", // windows "vfwcap", // windows (old) + "avfoundation", // osx "mpg", "yuv2", "mjpeg", @@ -732,6 +733,9 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) fprintf(stderr, "Camera %d not found\n", devIdx); } } + if(pAV->verbose) { + fprintf(stderr, "Camera: Filename: %s\n", filename); + } const char *sizeS = NULL != jSizeS ? (*env)->GetStringUTFChars(env, jSizeS, &iscopy) : NULL; int hasSize = 0; @@ -756,6 +760,7 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) } sp_av_dict_set(&inOpts, "framerate", buffer, 0); } + // FIXME pre-select: sp_av_dict_set(&inOpts, "pixel_format", "yuyv422", 0); } MY_MUTEX_LOCK(env, mutex_avcodec_openclose); @@ -1148,8 +1153,10 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) #endif } else { vLinesize[0] = pAV->pVFrame->linesize[0]; - if( pAV->vPixFmt == PIX_FMT_YUYV422 ) { - // Stuff 2x 16bpp (YUYV) into one RGBA pixel! + if( pAV->vPixFmt == PIX_FMT_YUYV422 || + pAV->vPixFmt == PIX_FMT_UYVY422 ) + { + // Stuff 2x 16bpp (YUYV, UYVY) into one RGBA pixel! pAV->vTexWidth[0] = pAV->pVCodecCtx->width / 2; } else { pAV->vTexWidth[0] = pAV->pVCodecCtx->width; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java index 070b6bb28..56c196132 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java @@ -45,6 +45,23 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice protected ToolkitLock toolkitLock; /** + * Return the default display connection for the given windowing toolkit type + * gathered via {@link NativeWindowFactory#getDefaultDisplayConnection()}. + * @param type + */ + public static String getDefaultDisplayConnection() { + return NativeWindowFactory.getDefaultDisplayConnection(); + } + /** + * Return the default display connection for the given windowing toolkit type + * gathered via {@link NativeWindowFactory#getDefaultDisplayConnection(String)}. + * @param type + */ + public static String getDefaultDisplayConnection(final String type) { + return NativeWindowFactory.getDefaultDisplayConnection(type); + } + + /** * Create an instance with the system default {@link ToolkitLock}, * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String)}. * @param type diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java index 63c79af55..cbf3e22da 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java @@ -42,7 +42,7 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen } public static AbstractGraphicsScreen createDefault(final String type) { - return new DefaultGraphicsScreen(new DefaultGraphicsDevice(type, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT), 0); + return new DefaultGraphicsScreen(new DefaultGraphicsDevice(type, DefaultGraphicsDevice.getDefaultDisplayConnection(type), AbstractGraphicsDevice.DEFAULT_UNIT), 0); } @Override diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java index 8f841e7ea..9dc3f2d4b 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java @@ -42,6 +42,7 @@ package com.jogamp.nativewindow; /** A generic exception for OpenGL errors used throughout the binding as a substitute for {@link RuntimeException}. */ +@SuppressWarnings("serial") public class NativeWindowException extends RuntimeException { /** Constructs a NativeWindowException object. */ public NativeWindowException() { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java index d01e3a203..323bc8c86 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java @@ -33,7 +33,6 @@ package com.jogamp.nativewindow; -import java.io.File; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; @@ -43,9 +42,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.jogamp.nativewindow.util.Point; import com.jogamp.nativewindow.util.PointImmutable; import jogamp.common.os.PlatformPropsImpl; +import jogamp.nativewindow.BcmVCArtifacts; import jogamp.nativewindow.Debug; import jogamp.nativewindow.NativeWindowFactoryImpl; import jogamp.nativewindow.ToolkitProperties; @@ -54,13 +55,16 @@ import jogamp.nativewindow.WrappedWindow; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.X11Util; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.nativewindow.awt.AWTGraphicsScreen; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; @@ -79,28 +83,28 @@ public abstract class NativeWindowFactory { protected static final boolean DEBUG; /** OpenKODE/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/ - public static final String TYPE_EGL = ".egl".intern(); + public static final String TYPE_EGL = ".egl"; /** Microsoft Windows type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_WINDOWS = ".windows".intern(); + public static final String TYPE_WINDOWS = ".windows"; /** X11 type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_X11 = ".x11".intern(); + public static final String TYPE_X11 = ".x11"; /** Broadcom VC IV/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_BCM_VC_IV = ".bcm.vc.iv".intern(); + public static final String TYPE_BCM_VC_IV = ".bcm.vc.iv"; /** Android/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/ - public static final String TYPE_ANDROID = ".android".intern(); + public static final String TYPE_ANDROID = ".android"; /** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_MACOSX = ".macosx".intern(); + public static final String TYPE_MACOSX = ".macosx"; /** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_AWT = ".awt".intern(); + public static final String TYPE_AWT = ".awt"; /** Generic DEFAULT type, where platform implementation don't care, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_DEFAULT = ".default".intern(); + public static final String TYPE_DEFAULT = ".default"; private static final String nativeWindowingTypePure; // canonical String via String.intern() private static final String nativeWindowingTypeCustom; // canonical String via String.intern() @@ -133,20 +137,6 @@ public abstract class NativeWindowFactory { protected NativeWindowFactory() { } - private static final boolean guessBroadcomVCIV() { - return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { - private final File vcliblocation = new File( - "/opt/vc/lib/libbcm_host.so"); - @Override - public Boolean run() { - if ( vcliblocation.isFile() ) { - return Boolean.TRUE; - } - return Boolean.FALSE; - } - } ).booleanValue(); - } - private static String _getNativeWindowingType() { switch(PlatformPropsImpl.OS_TYPE) { case ANDROID: @@ -163,7 +153,7 @@ public abstract class NativeWindowFactory { case SUNOS: case HPUX: default: - if( guessBroadcomVCIV() ) { + if( BcmVCArtifacts.guessVCIVUsed() ) { return TYPE_BCM_VC_IV; } return TYPE_X11; @@ -181,7 +171,7 @@ public abstract class NativeWindowFactory { _DEBUG[0] = Debug.debug("NativeWindow"); _tmp[0] = PropertyAccess.getProperty("nativewindow.ws.name", true); Runtime.getRuntime().addShutdownHook( - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { @Override public void run() { NativeWindowFactory.shutdown(true); @@ -647,6 +637,17 @@ public abstract class NativeWindowFactory { VisualIDHolder.VID_UNDEFINED != visualID ; } + public static String getDefaultDisplayConnection() { + return getDefaultDisplayConnection(NativeWindowFactory.getNativeWindowType(true)); + } + public static String getDefaultDisplayConnection(final String nwt) { + if(NativeWindowFactory.TYPE_X11 == nwt) { + return X11Util.getNullDisplayName(); + } else { + return AbstractGraphicsDevice.DEFAULT_CONNECTION; + } + } + /** * Creates a native device type, following {@link #getNativeWindowType(boolean) getNativeWindowType(true)}. * <p> @@ -673,11 +674,32 @@ public abstract class NativeWindowFactory { return new X11GraphicsDevice(displayConnection, AbstractGraphicsDevice.DEFAULT_UNIT); } } else if( NativeWindowFactory.TYPE_WINDOWS == nwt ) { - return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) { return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } else if( NativeWindowFactory.TYPE_EGL == nwt ) { - throw new UnsupportedOperationException("n/a for windowing system: "+nwt); + final EGLGraphicsDevice device; + if( own ) { + Object odev = null; + try { + // EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + odev = ReflectionUtil.callStaticMethod("jogamp.opengl.egl.EGLDisplayUtil", "eglCreateEGLGraphicsDevice", + new Class<?>[] { Long.class, String.class, Integer.class}, + new Object[] { 0L /* EGL.EGL_DEFAULT_DISPLAY */, DefaultGraphicsDevice.getDefaultDisplayConnection(nwt), AbstractGraphicsDevice.DEFAULT_UNIT }, + NativeWindowFactory.class.getClassLoader()); + } catch (final Exception e) { + throw new NativeWindowException("EGLDisplayUtil.eglCreateEGLGraphicsDevice failed", e); + } + if( odev instanceof EGLGraphicsDevice ) { + device = (EGLGraphicsDevice)odev; + device.open(); + } else { + throw new NativeWindowException("EGLDisplayUtil.eglCreateEGLGraphicsDevice failed"); + } + } else { + device = new EGLGraphicsDevice(0, 0 /* EGL.EGL_NO_DISPLAY */, displayConnection, AbstractGraphicsDevice.DEFAULT_UNIT, null); + } + return device; } else if( NativeWindowFactory.TYPE_AWT == nwt ) { throw new UnsupportedOperationException("n/a for windowing system: "+nwt); } else { @@ -712,7 +734,7 @@ public abstract class NativeWindowFactory { * FIXME: Bug 973 Needs service provider interface (SPI) for TK dependent implementation * </p> */ - public static PointImmutable getLocationOnScreen(final NativeWindow nw) { + public static Point getLocationOnScreen(final NativeWindow nw) { final String nwt = NativeWindowFactory.getNativeWindowType(true); if( NativeWindowFactory.TYPE_X11 == nwt ) { return X11Lib.GetRelativeLocation(nw.getDisplayHandle(), nw.getScreenIndex(), nw.getWindowHandle(), 0, 0, 0); @@ -731,6 +753,4 @@ public abstract class NativeWindowFactory { } throw new UnsupportedOperationException("n/a for windowing system: "+nwt); } - - } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowHolder.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowHolder.java new file mode 100644 index 000000000..8cf9bcb1a --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowHolder.java @@ -0,0 +1,41 @@ +/** + * Copyright 2019 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.nativewindow; + +/** + * Accessor interface for implementing classes with ownership of a {@link NativeWindow} + * via an <i>is-a</i> or <i>has-a</i> relation. + */ +public interface NativeWindowHolder extends NativeSurfaceHolder { + /** + * Returns the associated {@link NativeWindow} of this {@link NativeWindowHolder}, which is identical to {@link #getNativeSurface()} + */ + public NativeWindow getNativeWindow(); +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java index cc70b6b7b..84fce7fc9 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java @@ -73,27 +73,6 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple } /** - * @deprecated Use {@link #create(GraphicsConfiguration, CapabilitiesImmutable, CapabilitiesImmutable)} - * Method constructs a new {@link AWTGraphicsConfiguration} primarily based - * on the given {@link Component}'s {@link GraphicsConfiguration}. - * @param awtComp the {@link Component}, which {@link GraphicsConfiguration} is used for the resulting {@link AWTGraphicsConfiguration} - * @param capsChosen if null, <code>capsRequested</code> is copied and aligned - * with the graphics {@link Capabilities} of the AWT Component to produce the chosen {@link Capabilities}. - * Otherwise the <code>capsChosen</code> is used. - * @param capsRequested if null, default {@link Capabilities} are used, otherwise the given values. - */ - public static AWTGraphicsConfiguration create(final Component awtComp, final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested) { - if(null==awtComp) { - throw new IllegalArgumentException("Null AWT Component"); - } - final GraphicsConfiguration gc = awtComp.getGraphicsConfiguration(); - if( null == gc ) { - throw new NativeWindowException("Null AWT GraphicsConfiguration @ "+awtComp); - } - return create(gc, capsChosen, capsRequested); - } - - /** * Method constructs a new {@link AWTGraphicsConfiguration} primarily based * on the given {@link GraphicsConfiguration}. * @param gc the {@link GraphicsConfiguration} for the resulting {@link AWTGraphicsConfiguration} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java index 2026ada0f..e5dcfa1c0 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java @@ -97,24 +97,23 @@ public class AppContextInfo { * The resulting thread name will have either '-OnAppContextTG' or '-OnSystemTG' appended * @return the {@link Thread} used to invoke the <code>runnable</code>, which may be the current {@link Thread} or a newly created one, see above. */ - public Thread invokeOnAppContextThread(final boolean waitUntilDone, final Runnable runnable, final String threadBaseName) { - final Thread t; + public RunnableTask invokeOnAppContextThread(final boolean waitUntilDone, final Runnable runnable, final String threadBaseName) { + final RunnableTask rt; if( update("invoke") ) { - t = Thread.currentThread(); + rt = RunnableTask.invokeOnCurrentThread(runnable); if( DEBUG ) { - System.err.println("Bug 1004: Invoke.0 on current AppContext thread: "+t+" "+toHexString(t.hashCode())); + System.err.println("Bug 1004: Invoke.0 on current AppContext: "+rt); } - runnable.run(); } else { final ThreadGroup tg = getCachedThreadGroup(); final String tName = threadBaseName + ( null != tg ? "-OnAppContextTG" : "-OnSystemTG" ); - t = RunnableTask.invokeOnNewThread(tg, waitUntilDone, runnable, tName); + rt = RunnableTask.invokeOnNewThread(tg, tName, waitUntilDone, runnable); if( DEBUG ) { final int tgHash = null != tg ? tg.hashCode() : 0; - System.err.println("Bug 1004: Invoke.1 on new AppContext thread: "+t+" "+toHexString(t.hashCode())+", tg "+tg+" "+toHexString(tgHash)); + System.err.println("Bug 1004: Invoke.1 on new AppContext: "+rt+", tg "+tg+" "+toHexString(tgHash)); } } - return t; + return rt; } /** diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index 5d84325de..71a7602e6 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -120,7 +120,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, */ protected JAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) { if (config == null) { - throw new NativeWindowException("Error: AbstractGraphicsConfiguration is null"); + throw new IllegalArgumentException("Error: AbstractGraphicsConfiguration is null"); } if(! ( config instanceof AWTGraphicsConfiguration ) ) { throw new NativeWindowException("Error: AbstractGraphicsConfiguration is not an AWTGraphicsConfiguration: "+config); @@ -132,9 +132,13 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, this.awtConfig = (AWTGraphicsConfiguration) config; this.isApplet = false; this.offscreenSurfaceLayer = 0; + if(DEBUG) { + System.err.println(jawtStr2("ctor")); + } } private static String id(final Object obj) { return ( null!=obj ? toHexString(obj.hashCode()) : "nil" ); } - private String jawtStr() { return "JAWTWindow["+id(JAWTWindow.this)+"]"; } + private String jawtStr1() { return "JAWTWindow["+id(JAWTWindow.this)+"]"; } + private String jawtStr2(final String sub) { return jawtStr1()+"."+sub+" @ Thread "+getThreadName(); } private class JAWTComponentListener implements ComponentListener, HierarchyListener { private volatile boolean isShowing; @@ -180,7 +184,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, public void run() { isShowing = component.isShowing(); // Bug 1161: Runnable might be deferred, hence need to update if(DEBUG) { - System.err.println(jawtStr()+".attach @ Thread "+getThreadName()+": "+JAWTComponentListener.this.toString()); + System.err.println(jawtStr2("attach")+": "+JAWTComponentListener.this.toString()); } component.addComponentListener(JAWTComponentListener.this); component.addHierarchyListener(JAWTComponentListener.this); @@ -192,7 +196,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public void run() { if(DEBUG) { - System.err.println(jawtStr()+".detach @ Thread "+getThreadName()+": "+JAWTComponentListener.this.toString()); + System.err.println(jawtStr2("detach")+": "+JAWTComponentListener.this.toString()); } component.removeComponentListener(JAWTComponentListener.this); component.removeHierarchyListener(JAWTComponentListener.this); @@ -202,7 +206,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public final void componentResized(final ComponentEvent e) { if(DEBUG) { - System.err.println(jawtStr()+".componentResized: "+s(e)); + System.err.println(jawtStr2("componentResized")+": "+s(e)); } layoutSurfaceLayerIfEnabled(isShowing); } @@ -210,7 +214,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public final void componentMoved(final ComponentEvent e) { if(DEBUG) { - System.err.println(jawtStr()+".componentMoved: "+s(e)); + System.err.println(jawtStr2("componentMoved")+": "+s(e)); } layoutSurfaceLayerIfEnabled(isShowing); } @@ -218,7 +222,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public final void componentShown(final ComponentEvent e) { if(DEBUG) { - System.err.println(jawtStr()+".componentShown: "+s(e)); + System.err.println(jawtStr2("componentShown")+": "+s(e)); } layoutSurfaceLayerIfEnabled(isShowing); } @@ -226,7 +230,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public final void componentHidden(final ComponentEvent e) { if(DEBUG) { - System.err.println(jawtStr()+".componentHidden: "+s(e)); + System.err.println(jawtStr2("componentHidden")+": "+s(e)); } layoutSurfaceLayerIfEnabled(isShowing); } @@ -248,7 +252,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, final java.awt.Component changed = e.getChanged(); final boolean displayable = changed.isDisplayable(); final boolean showing = changed.isShowing(); - System.err.println(jawtStr()+".hierarchyChanged: action "+action+", displayable "+displayable+", showing [changed "+showing+", comp "+wasShowing+" -> "+isShowing+"], "+s(e)); + System.err.println(jawtStr2("hierarchyChanged")+": action "+action+", displayable "+displayable+", showing [changed "+showing+", comp "+wasShowing+" -> "+isShowing+"], "+s(e)); } } } @@ -257,7 +261,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, protected synchronized void invalidate() { if(DEBUG) { - System.err.println(jawtStr()+".invalidate() - "+jawtComponentListener.toString()); + System.err.println(jawtStr2("invalidate")+" - "+jawtComponentListener.toString()); if( isSurfaceLayerAttached() ) { System.err.println("OffscreenSurfaceLayer still attached: 0x"+Long.toHexString(offscreenSurfaceLayer)); } @@ -295,9 +299,12 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, */ public final void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) { if(DEBUG) { - System.err.println(jawtStr()+".setAWTGraphicsConfiguration(): "+this.awtConfig+" -> "+config); + System.err.println(jawtStr2("setAWTGraphicsConfiguration")+": "+this.awtConfig+" -> "+config); // Thread.dumpStack(); } + if( null == awtConfig ) { + throw new IllegalArgumentException(jawtStr2("")+": null config"); + } this.awtConfig = config; } /** @@ -395,26 +402,6 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, return hasPixelScaleChanged; } } - /** - * @deprecated Use {@link #updatePixelScale(GraphicsConfiguration, boolean)}. - */ - public final boolean updatePixelScale(final boolean clearFlag) { - return updatePixelScale(awtConfig.getAWTGraphicsConfiguration(), clearFlag); - } - - /** - * @deprecated Use {@link #updateLockedData(JAWT_Rectangle, GraphicsConfiguration)}. - */ - protected final boolean updateLockedData(final JAWT_Rectangle jawtBounds) { - throw new RuntimeException("Invalid API entry"); - } - /** - * @deprecated Use {@link #lockSurfaceImpl(GraphicsConfiguration)} - */ - protected int lockSurfaceImpl() throws NativeWindowException { - throw new RuntimeException("Invalid API entry"); - } - /** * Returns and clears the {@code hasPixelScaleChanged} flag, as set via {@link #lockSurface()}. @@ -771,6 +758,9 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public final AbstractGraphicsConfiguration getGraphicsConfiguration() { + if( null == awtConfig ) { + throw new NativeWindowException(jawtStr2("")+": null awtConfig, invalidated"); + } return awtConfig.getNativeGraphicsConfiguration(); } @@ -826,7 +816,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, surfaceLock.lock(); try { if(DEBUG) { - System.err.println(jawtStr()+".destroy @ Thread "+getThreadName()); + System.err.println(jawtStr2("destroy")); } jawtComponentListener.detach(); invalidate(); @@ -930,7 +920,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append(jawtStr()+"["); + sb.append(jawtStr1()+"["); jawt2String(sb); sb.append( ", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface+ ", attachedSurfaceLayer "+toHexString(getAttachedSurfaceLayer())+ diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index 04d304cd5..320c0ec75 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -32,9 +32,11 @@ package com.jogamp.nativewindow.egl; -import com.jogamp.nativewindow.*; - import com.jogamp.common.util.VersionNumber; +import com.jogamp.nativewindow.AbstractGraphicsDevice; +import com.jogamp.nativewindow.DefaultGraphicsDevice; +import com.jogamp.nativewindow.NativeWindowException; +import com.jogamp.nativewindow.NativeWindowFactory; /** Encapsulates a graphics device on EGL platforms. */ @@ -73,11 +75,23 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl * This constructor exist to setup a default device connection/unit.<br> */ public EGLGraphicsDevice() { - super(NativeWindowFactory.TYPE_EGL, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + super(NativeWindowFactory.TYPE_EGL, DefaultGraphicsDevice.getDefaultDisplayConnection(), AbstractGraphicsDevice.DEFAULT_UNIT); this.nativeDisplayID[0] = 0 ; // EGL.EGL_DEFAULT_DISPLAY this.eglLifecycleCallback = null; } + public EGLGraphicsDevice(final AbstractGraphicsDevice aDevice, final long eglDisplay, final EGLDisplayLifecycleCallback eglLifecycleCallback) { + super(NativeWindowFactory.TYPE_EGL, aDevice.getConnection(), aDevice.getUnitID(), eglDisplay); + final long nativeDisplayID; + if( aDevice instanceof EGLGraphicsDevice ) { + nativeDisplayID = ((EGLGraphicsDevice)aDevice).getNativeDisplayID(); + } else { + nativeDisplayID = aDevice.getHandle(); + } + this.nativeDisplayID[0] = nativeDisplayID; + this.eglLifecycleCallback = eglLifecycleCallback; + } + public EGLGraphicsDevice(final long nativeDisplayID, final long eglDisplay, final String connection, final int unitID, final EGLDisplayLifecycleCallback eglLifecycleCallback) { super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay); this.nativeDisplayID[0] = nativeDisplayID; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java new file mode 100644 index 000000000..bffabdd5a --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java @@ -0,0 +1,291 @@ +/** + * Copyright 2019 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.nativewindow.javafx; + +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import com.jogamp.nativewindow.AbstractGraphicsDevice; +import com.jogamp.nativewindow.AbstractGraphicsScreen; +import com.jogamp.nativewindow.NativeWindowException; +import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.VisualIDHolder; +import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; +import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptedRuntimeException; +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.RunnableTask; +import com.sun.javafx.tk.TKStage; + +import javafx.application.Platform; +import javafx.stage.Window; +import jogamp.nativewindow.Debug; +import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.X11Util; + +public class JFXAccessor { + private static final boolean DEBUG; + + private static final boolean jfxAvailable; + private static final Method fxUserThreadGetter; + private static final Method tkStageGetter; + private static final Method glassWindowGetter; + private static final Method nativeWindowGetter; + + private static final String nwt; + private static final boolean isOSX; + private static final boolean isWindows; + private static final boolean isX11; + + static { + final boolean[] _DEBUG = new boolean[] { true }; + + final Method[] res = AccessController.doPrivileged(new PrivilegedAction<Method[]>() { + @Override + public Method[] run() { + NativeWindowFactory.initSingleton(); // last resort .. + final Method[] res = new Method[] { null, null, null, null }; + try { + int i=0; + _DEBUG[0] = Debug.debug("JFX"); + /** + * com.sun.javafx.tk.Toolkit + */ + final Class<?> jfxToolkitClz = ReflectionUtil.getClass("com.sun.javafx.tk.Toolkit", false, JFXAccessor.class.getClassLoader()); + res[i] = jfxToolkitClz.getDeclaredMethod("getFxUserThread"); + res[i++].setAccessible(true); + + /*** + * class javafx.stage.Window + * class javafx.stage.Stage extends javafx.stage.Window + * class com.sun.javafx.tk.quantum.WindowStage extends com.sun.javafx.tk.quantum.GlassStage implements com.sun.javafx.tk.TKStage + * abstract com.sun.glass.ui.Window + * + * javafx.stage.Window: com.sun.javafx.tk.TKStage [impl_]getPeer() + * com.sun.javafx.tk.quantum.WindowStage: final com.sun.glass.ui.Window getPlatformWindow() + * com.sun.glass.ui.Window: public long getNativeWindow() + */ + final Class<?> jfxStageWindowClz = ReflectionUtil.getClass("javafx.stage.Window", false, JFXAccessor.class.getClassLoader()); + // final Class<?> jfxTkTKStageClz = ReflectionUtil.getClass("com.sun.javafx.tk.TKStage", false, JFXAccessor.class.getClassLoader()); + final Class<?> jfxTkQuWindowStageClz = ReflectionUtil.getClass("com.sun.javafx.tk.quantum.WindowStage", false, JFXAccessor.class.getClassLoader()); + final Class<?> jfxGlassUiWindowClz = ReflectionUtil.getClass("com.sun.glass.ui.Window", false, JFXAccessor.class.getClassLoader()); + + try { + // jfx 9, 11, 12, .. + res[i] = jfxStageWindowClz.getDeclaredMethod("getPeer"); + } catch (final NoSuchMethodException ex) { + // jfx 8 + res[i] = jfxStageWindowClz.getDeclaredMethod("impl_getPeer"); + } + res[i++].setAccessible(true); + + res[i] = jfxTkQuWindowStageClz.getDeclaredMethod("getPlatformWindow"); + res[i++].setAccessible(true); + res[i] = jfxGlassUiWindowClz.getDeclaredMethod("getNativeWindow"); + res[i++].setAccessible(true); + } catch (final Throwable t) { + if(_DEBUG[0]) { + ExceptionUtils.dumpThrowable("jfx-init", t); + } + } + return res; + } + }); + { + int i=0; + fxUserThreadGetter = res[i++]; + tkStageGetter = res[i++]; + glassWindowGetter = res[i++]; + nativeWindowGetter = res[i++]; + } + jfxAvailable = null != fxUserThreadGetter && null != tkStageGetter && null != glassWindowGetter && null != nativeWindowGetter; + + nwt = NativeWindowFactory.getNativeWindowType(false); + isOSX = NativeWindowFactory.TYPE_MACOSX == nwt; + isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt; + isX11 = NativeWindowFactory.TYPE_X11 == nwt; + + DEBUG = _DEBUG[0]; + if(DEBUG) { + System.err.println(Thread.currentThread().getName()+" - Info: JFXAccessor.<init> available "+jfxAvailable+", nwt "+nwt+"( x11 "+isX11+", win "+isWindows+", osx "+isOSX+")"); + } + } + + // + // Common any toolkit + // + + public static boolean isJFXAvailable() { return jfxAvailable; } + + /** + * Runs given {@code task} on the JFX Thread if it has not stopped and if caller is not already on the JFX Thread, + * otherwise execute given {@code task} on the current thread. + * @param wait + * @param task + * @see #isJFXThreadOrHasJFXThreadStopped() + */ + public static void runOnJFXThread(final boolean wait, final Runnable task) { + final Object rTaskLock = new Object(); + synchronized(rTaskLock) { // lock the task execution + if( isJFXThreadOrHasJFXThreadStopped() ) { + task.run(); + } else if( !wait ) { + Platform.runLater(task); + } else { + final RunnableTask rTask = new RunnableTask(task, + rTaskLock, + true /* always catch and report Exceptions, don't disturb EDT */, + null); + Platform.runLater(rTask); + try { + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } + final Throwable throwable = rTask.getThrowable(); + if(null!=throwable) { + if(throwable instanceof NativeWindowException) { + throw (NativeWindowException)throwable; + } + throw new RuntimeException(throwable); + } + } + } + } + + public static Thread getJFXThread() throws NativeWindowException { + try { + return (Thread) fxUserThreadGetter.invoke(null); + } catch (final Throwable e) { + throw new NativeWindowException("Error getting JFX-Thread", e); + } + } + public static String getJFXThreadName() { + final Thread t = getJFXThread(); + return null != t ? t.getName() : null; + } + /** + * @return true if the JFX Thread has stopped + */ + public static boolean hasJFXThreadStopped() { + final Thread t = getJFXThread(); + return null == t || !t.isAlive(); + } + /** + * @return true if caller is on the JFX Thread + */ + public static boolean isJFXThread() { + final Thread t = getJFXThread(); + return Thread.currentThread() == t; + } + /** + * @return true if the JFX Thread has stopped or if caller is on the JFX Thread + */ + public static boolean isJFXThreadOrHasJFXThreadStopped() { + final Thread t = getJFXThread(); + return null == t || !t.isAlive() || Thread.currentThread() == t; + } + + /** + * @param stageWindow the JavaFX top heavyweight window handle + * @return the AbstractGraphicsDevice w/ the native device handle + * @throws NativeWindowException if an exception occurs retrieving the window handle or deriving the native device + * @throws UnsupportedOperationException if the windowing system is not supported + */ + public static AbstractGraphicsDevice getDevice(final Window stageWindow) throws NativeWindowException, UnsupportedOperationException { + if( isX11 ) { + // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering + final String connection = null; + final long x11DeviceHandle = X11Util.openDisplay(connection); + if( 0 == x11DeviceHandle ) { + throw new NativeWindowException("Error creating display: "+connection); + } + return new X11GraphicsDevice(x11DeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */); + } + if( isWindows ) { + return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + } + if( isOSX ) { + return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + } + throw new UnsupportedOperationException("n/a for this windowing system: "+nwt); + } + + /** + * @param device + * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen + * @return + */ + public static AbstractGraphicsScreen getScreen(final AbstractGraphicsDevice device, final int screen) { + return NativeWindowFactory.createScreen(device, screen); + } + + public static int getNativeVisualID(final AbstractGraphicsDevice device, final long windowHandle) { + if( isX11 ) { + return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); + } + if( isWindows || isOSX ) { + return VisualIDHolder.VID_UNDEFINED; + } + throw new UnsupportedOperationException("n/a for this windowing system: "+nwt); + } + + /** + * @param stageWindow the JavaFX top heavyweight window handle + * @return the native window handle + * @throws NativeWindowException if an exception occurs retrieving the window handle + */ + public static long getWindowHandle(final Window stageWindow) throws NativeWindowException { + final long h[] = { 0 }; + runOnJFXThread(true, new Runnable() { + public void run() { + try { + final TKStage tkStage = (TKStage) tkStageGetter.invoke(stageWindow); + if( null != tkStage ) { + final Object platformWindow = glassWindowGetter.invoke(tkStage); + if( null != platformWindow ) { + final Object nativeHandle = nativeWindowGetter.invoke(platformWindow); + h[0] = ((Long) nativeHandle).longValue(); + } else if(DEBUG) { + System.err.println(Thread.currentThread().getName()+" - Info: JFXAccessor null GlassWindow"); + } + } else if(DEBUG) { + System.err.println(Thread.currentThread().getName()+" - Info: JFXAccessor null TKStage"); + } + } catch (final Throwable e) { + throw new NativeWindowException("Error getting Window handle", e); + } + } }); + return h[0]; + } +} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index c750f7651..d99519878 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -35,7 +35,9 @@ import java.security.PrivilegedAction; import org.eclipse.swt.graphics.GCData; import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.DPIUtil; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Scrollable; import com.jogamp.nativewindow.AbstractGraphicsScreen; import com.jogamp.nativewindow.NativeWindowException; @@ -51,9 +53,12 @@ import com.jogamp.nativewindow.x11.X11GraphicsDevice; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.Debug; public class SWTAccessor { - private static final boolean DEBUG = true; + private static final boolean DEBUG = Debug.debug("SWT"); + + private static final Method swt_scrollable_clientAreaInPixels; private static final Field swt_control_handle; private static final boolean swt_uses_long_handles; @@ -81,7 +86,9 @@ public class SWTAccessor { private static final String str_internal_new_GC = "internal_new_GC"; private static final String str_internal_dispose_GC = "internal_dispose_GC"; - private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS"; + private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS"; // used by earlier versions of SWT + private static final String str_GTK_gtk_class = "org.eclipse.swt.internal.gtk.GTK"; // used by later versions of SWT + private static final String str_GDK_gtk_class = "org.eclipse.swt.internal.gtk.GDK"; // used by later versions of SWT public static final Class<?> OS_gtk_class; private static final String str_OS_gtk_version = "GTK_VERSION"; public static final VersionNumber OS_gtk_version; @@ -96,6 +103,7 @@ public class SWTAccessor { private static final Method OS_gdk_x11_drawable_get_xid; private static final Method OS_gdk_x11_window_get_xid; private static final Method OS_gdk_window_set_back_pixmap; + private static final Method OS_gdk_window_set_background_pattern; private static final String str_gtk_widget_realize = "gtk_widget_realize"; private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize"; @@ -107,9 +115,11 @@ public class SWTAccessor { private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid"; private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid"; private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap"; + private static final String str_gdk_window_set_background_pattern = "gdk_window_set_background_pattern"; private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0); private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0); + private static final VersionNumber GTK_VERSION_2_90_0 = new VersionNumber(2, 90, 0); private static final VersionNumber GTK_VERSION_3_0_0 = new VersionNumber(3, 0, 0); private static VersionNumber GTK_VERSION(final int version) { @@ -133,6 +143,18 @@ public class SWTAccessor { isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt; isX11 = NativeWindowFactory.TYPE_X11 == nwt; + Method m = null; + try { + m = Scrollable.class.getDeclaredMethod("getClientAreaInPixels"); + m.setAccessible(true); + } catch (final Exception ex) { + m = null; + if( DEBUG ) { + System.err.println("getClientAreaInPixels not implemented: "+ex.getMessage()); + } + } + swt_scrollable_clientAreaInPixels = m; + Field f = null; if( !isOSX ) { try { @@ -153,7 +175,7 @@ public class SWTAccessor { // System.err.println("SWT long handles: " + swt_uses_long_handles); // System.err.println("Platform 64bit: "+Platform.is64Bit()); - Method m=null; + m=null; try { m = ReflectionUtil.getMethod(Control.class, str_internal_new_GC, new Class[] { GCData.class }); } catch (final Exception ex) { @@ -161,6 +183,7 @@ public class SWTAccessor { } swt_control_internal_new_GC = m; + m=null; try { if(swt_uses_long_handles) { m = Control.class.getDeclaredMethod(str_internal_dispose_GC, new Class[] { long.class, GCData.class }); @@ -172,41 +195,57 @@ public class SWTAccessor { } swt_control_internal_dispose_GC = m; - Class<?> c=null; + Class<?> cGTK=null; VersionNumber _gtk_version = new VersionNumber(0, 0, 0); - Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null; + Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null, mb=null; final Class<?> handleType = swt_uses_long_handles ? long.class : int.class ; if( isX11 ) { // mandatory try { - c = ReflectionUtil.getClass(str_OS_gtk_class, false, SWTAccessor.class.getClassLoader()); - final Field field_OS_gtk_version = c.getField(str_OS_gtk_version); + final ClassLoader cl = SWTAccessor.class.getClassLoader(); + cGTK = ReflectionUtil.getClass(str_OS_gtk_class, false, cl); + Field field_OS_gtk_version; + Class<?> cGDK=cGTK; // used for newer versions of SWT that have a org.eclipse.swt.internal.gtk.GDK object + try { + field_OS_gtk_version = cGTK.getField(str_OS_gtk_version); + } catch (final NoSuchFieldException ex) { + // if the GTK_VERSION field didn't exist in org.eclipse.swt.internal.gtk.OS, then look for + // it in org.eclipse.swt.internal.gtk.GTK, where it was moved in later versions of SWT + cGTK = ReflectionUtil.getClass(str_GTK_gtk_class, false, cl); + field_OS_gtk_version = cGTK.getField(str_OS_gtk_version); + cGDK = ReflectionUtil.getClass(str_GDK_gtk_class, false, cl); + } _gtk_version = GTK_VERSION(field_OS_gtk_version.getInt(null)); - m1 = c.getDeclaredMethod(str_gtk_widget_realize, handleType); + m1 = cGTK.getDeclaredMethod(str_gtk_widget_realize, handleType); if (_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) { - m4 = c.getDeclaredMethod(str_gtk_widget_get_window, handleType); + m4 = cGTK.getDeclaredMethod(str_gtk_widget_get_window, handleType); } else { - m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType); + m3 = cGTK.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType); } if (_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) { - m6 = c.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType); - m7 = c.getDeclaredMethod(str_gdk_window_get_display, handleType); + m6 = cGDK.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType); + m7 = cGDK.getDeclaredMethod(str_gdk_window_get_display, handleType); } else { - m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType); + m5 = cGTK.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType); } if (_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) { - m9 = c.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType); + m9 = cGDK.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType); + } else { + m8 = cGTK.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType); + } + + if (_gtk_version.compareTo(GTK_VERSION_2_90_0) >= 0) { + mb = cGDK.getDeclaredMethod(str_gdk_window_set_background_pattern, handleType, handleType); } else { - m8 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType); + ma = cGTK.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class); } - ma = c.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class); } catch (final Exception ex) { throw new NativeWindowException(ex); } // optional try { - m2 = c.getDeclaredMethod(str_gtk_widget_unrealize, handleType); + m2 = cGTK.getDeclaredMethod(str_gtk_widget_unrealize, handleType); } catch (final Exception ex) { } } - OS_gtk_class = c; + OS_gtk_class = cGTK; OS_gtk_version = _gtk_version; OS_gtk_widget_realize = m1; OS_gtk_widget_unrealize = m2; @@ -218,6 +257,7 @@ public class SWTAccessor { OS_gdk_x11_drawable_get_xid = m8; OS_gdk_x11_window_get_xid = m9; OS_gdk_window_set_back_pixmap = ma; + OS_gdk_window_set_background_pattern = mb; isX11GTK = isX11 && null != OS_gtk_class; @@ -237,6 +277,10 @@ public class SWTAccessor { ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) }); } + private static void callStaticMethodLL2V(final Method m, final long arg0, final long arg1) { + ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1) }); + } + private static void callStaticMethodLLZ2V(final Method m, final long arg0, final long arg1, final boolean arg3) { ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1), Boolean.valueOf(arg3) }); } @@ -309,7 +353,13 @@ public class SWTAccessor { } public static void gdk_window_set_back_pixmap(final long window, final long pixmap, final boolean parent_relative) { - callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative); + if(OS_gdk_window_set_back_pixmap != null) { + callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative); + } + // in recent GTK, can't set background to pixmap any more; this sets it relative to parent + else if(OS_gdk_window_set_background_pattern != null) { + callStaticMethodLL2V(OS_gdk_window_set_background_pattern, window, 0); + } } // @@ -317,6 +367,43 @@ public class SWTAccessor { // /** + * Returns the unscaled {@link Scrollable#getClientArea()} in pixels. + * <p> + * If the package restricted method {@link Scrollable#getClientAreaInPixels()} + * is implemented, we return its result. + * </p> + * <p> + * Fallback is to return {@link DPIUtil#autoScaleUp(Rectangle) DPIUtil#autoScaleUp}({@link Scrollable#getClientArea()}), + * reverting {@link Scrollable#getClientArea()}'s {@link DPIUtil#autoScaleDown(Rectangle)}. + * </p> + * <p> + * Note to SWT's API spec writers: You need to allow access to the unscaled value, scale properties and define what is being scaled (fonts, images, ..). + * Further more the scale should be separate for x/y coordinates, as DPI differs here. + * </p> + * <p> + * Note to Eclipse authors: Scaling up the fonts and images hardly works on GTK/SWT/Eclipse. + * GDK_SCALE, GDK_DPI_SCALE and swt.autoScale produce inconsistent results with Eclipse. + * Broken High-DPI for .. some years now. + * </p> + * + * Requires SWT >= 3.105 (DPIUtil) + * + * @param s the {@link Scrollable} instance + * @return unscaled client area in pixels, see above + * @throws NativeWindowException during invocation of the method, if any + */ + public static Rectangle getClientAreaInPixels(final Scrollable s) throws NativeWindowException { + if( null == swt_scrollable_clientAreaInPixels ) { + return DPIUtil.autoScaleUp(s.getClientArea()); + } + try { + return (Rectangle) swt_scrollable_clientAreaInPixels.invoke(s); + } catch (final Throwable e) { + throw new NativeWindowException(e); + } + } + + /** * @param swtControl the SWT Control to retrieve the native widget-handle from * @return the native widget-handle * @throws NativeWindowException if the widget handle is null @@ -386,7 +473,7 @@ public class SWTAccessor { return new X11GraphicsDevice(xdisplay0, AbstractGraphicsDevice.DEFAULT_UNIT, false /* owner */); } if( isWindows ) { - return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } if( isOSX ) { return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); @@ -510,7 +597,7 @@ public class SWTAccessor { public static long createCompatibleX11ChildWindow(final AbstractGraphicsScreen screen, final Control swtControl, final int visualID, final int width, final int height) { final long handle = getHandle(swtControl); final long parentWindow = gdk_widget_get_window( handle ); - gdk_window_set_back_pixmap (parentWindow, 0, false); + // gdk_window_set_back_pixmap(parentWindow, 0, false); final long x11ParentHandle = gdk_window_get_xwindow(parentWindow); final long x11WindowHandle = X11Lib.CreateWindow(x11ParentHandle, screen.getDevice().getHandle(), screen.getIndex(), visualID, width, height, true, true); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java index fc5465bbf..aa511b625 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java @@ -120,6 +120,18 @@ public class Point implements Cloneable, PointImmutable { /** * Translate this instance's x- and y-components, + * i.e. add the values of the given delta point to them. + * @param pd delta point + * @return this instance for scaling + */ + public final Point translate(final PointImmutable pd) { + x += pd.getX() ; + y += pd.getY() ; + return this; + } + + /** + * Translate this instance's x- and y-components, * i.e. add the given deltas to them. * @param dx delta for x * @param dy delta for y diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java index 04619962d..bcb9741d6 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java @@ -33,10 +33,15 @@ package com.jogamp.nativewindow.x11; +import com.jogamp.common.util.Bitfield; import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import jogamp.nativewindow.x11.X11Capabilities; +import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.XRenderDirectFormat; +import jogamp.nativewindow.x11.XRenderPictFormat; import jogamp.nativewindow.x11.XVisualInfo; /** Encapsulates a graphics configuration, or OpenGL pixel format, on @@ -48,6 +53,44 @@ import jogamp.nativewindow.x11.XVisualInfo; public class X11GraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { private XVisualInfo info; + // FBConfig + + protected static XRenderDirectFormat XVisual2XRenderMask(final long dpy, final long visual) { + final XRenderPictFormat xRenderPictFormat = XRenderPictFormat.create(); + return XVisual2XRenderMask(dpy, visual, xRenderPictFormat); + } + protected static XRenderDirectFormat XVisual2XRenderMask(final long dpy, final long visual, final XRenderPictFormat dest) { + if( !X11Lib.XRenderFindVisualFormat(dpy, visual, dest) ) { + return null; + } else { + return dest.getDirect(); + } + } + + public static X11Capabilities XVisualInfo2X11Capabilities(final X11GraphicsDevice device, final XVisualInfo info) { + final long display = device.getHandle(); + final X11Capabilities res = new X11Capabilities(info); + + final XRenderDirectFormat xrmask = ( null != info ) ? XVisual2XRenderMask( display, info.getVisual() ) : null ; + final int alphaMask = ( null != xrmask ) ? xrmask.getAlphaMask() : 0; + if( 0 < alphaMask ) { + res.setBackgroundOpaque(false); + res.setTransparentRedValue(xrmask.getRedMask()); + res.setTransparentGreenValue(xrmask.getGreenMask()); + res.setTransparentBlueValue(xrmask.getBlueMask()); + res.setTransparentAlphaValue(alphaMask); + } else { + res.setBackgroundOpaque(true); + } + // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples) + res.setRedBits (Bitfield.Util.bitCount((int)info.getRed_mask())); + res.setGreenBits (Bitfield.Util.bitCount((int)info.getGreen_mask())); + res.setBlueBits (Bitfield.Util.bitCount((int)info.getBlue_mask())); + res.setAlphaBits (Bitfield.Util.bitCount(alphaMask)); + + return res; + } + public X11GraphicsConfiguration(final X11GraphicsScreen screen, final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final XVisualInfo info) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/BcmVCArtifacts.java b/src/nativewindow/classes/jogamp/nativewindow/BcmVCArtifacts.java new file mode 100644 index 000000000..216c55a3a --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/BcmVCArtifacts.java @@ -0,0 +1,76 @@ +/** + * Copyright 2018 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import java.io.File; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Heuristics about Broadcom (BCM) VideoCore (VC) existence and usage + */ +public class BcmVCArtifacts { + static final boolean hasVCLib; + static final boolean hasVC4ModLocation; + static final boolean hasDriCard0File; + + static { + final File vcLibLocation = new File( + "/opt/vc/lib/libbcm_host.so"); + final File vc4ModLocation = new File( + "/sys/module/vc4"); + final File driCard0Location = new File( + "/dev/dri/card0"); + final boolean[] res = new boolean [3]; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override + public Object run() { + res[0] = vcLibLocation.isFile(); + res[1] = vc4ModLocation.isDirectory(); + res[2] = driCard0Location.isFile(); + return null; + } } ); + hasVCLib = res[0]; + hasVC4ModLocation = res[1]; + hasDriCard0File = res[2]; + } + + /** + * @return True if proprietary BCM VC IV is probably being present + */ + public static final boolean guessVCIVPresent() { + return hasVCLib; + } + /** + * @return True if proprietary BCM VC IV is probably being used and not Xorg drivers + */ + public static final boolean guessVCIVUsed() { + return hasVCLib && !hasVC4ModLocation && !hasDriCard0File; + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java b/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java index 8d0d04161..1284974bf 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java +++ b/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java @@ -43,7 +43,7 @@ public class NWJNILibLoader extends JNILibLoaderBase { public Boolean run() { Platform.initSingleton(); final String libName = "nativewindow_"+ossuffix ; - if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) { + if( TempJarCache.isInitialized(true) && null == TempJarCache.findLibrary(libName) ) { JNILibLoaderBase.addNativeJarLibsJoglCfg(new Class<?>[] { jogamp.nativewindow.Debug.class }); } return Boolean.valueOf(loadLibrary(libName, false, NWJNILibLoader.class.getClassLoader())); diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index 264bdf9d3..5a0c8a79a 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -101,14 +101,15 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() { @Override public void run() { + if( 0 != jawtSurfaceLayersHandle) { + // null rootSurfaceLayer OK + UnsetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer); + } + jawtSurfaceLayersHandle = 0; if( 0 != rootSurfaceLayer ) { - if( 0 != jawtSurfaceLayersHandle) { - UnsetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer); - } OSXUtil.DestroyCALayer(rootSurfaceLayer); rootSurfaceLayer = 0; } - jawtSurfaceLayersHandle = 0; } }); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 8ad089a56..b1bf248ce 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -31,9 +31,9 @@ import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; - import com.jogamp.common.util.Function; import com.jogamp.common.util.FunctionTask; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import jogamp.nativewindow.Debug; @@ -123,10 +123,16 @@ public class OSXUtil implements ToolkitProperties { } public static long CreateNSWindow(final int x, final int y, final int width, final int height) { - return CreateNSWindow0(x, y, width, height); + final long res[] = { 0 }; + RunOnMainThread(true, false /* kickNSApp */, new Runnable() { + @Override + public void run() { + res[0] = CreateNSWindow0(x, y, width, height); + } } ); + return res[0]; } public static void DestroyNSWindow(final long nsWindow) { - DestroyNSWindow0(nsWindow); + DestroyNSWindow0(nsWindow); } public static long GetNSView(final long nsWindow) { return GetNSView0(nsWindow); @@ -267,22 +273,21 @@ public class OSXUtil implements ToolkitProperties { } else { // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread, // otherwise we may freeze the OSX main thread. - Throwable throwable = null; final Object sync = new Object(); final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err ); synchronized(sync) { RunOnMainThread0(kickNSApp, rt); if( waitUntilDone ) { - try { - sync.wait(); - } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rt.getThrowable(); - } - if(null!=throwable) { - throw new RuntimeException(throwable); + while( rt.isInQueue() ) { + try { + sync.wait(); + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } + final Throwable throwable = rt.getThrowable(); + if(null!=throwable) { + throw new RuntimeException(throwable); + } } } } @@ -341,23 +346,22 @@ public class OSXUtil implements ToolkitProperties { } else { // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread, // otherwise we may freeze the OSX main thread. - Throwable throwable = null; final Object sync = new Object(); final FunctionTask<R,A> rt = new FunctionTask<R,A>( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err ); synchronized(sync) { rt.setArgs(args); RunOnMainThread0(kickNSApp, rt); if( waitUntilDone ) { - try { - sync.wait(); - } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rt.getThrowable(); - } - if(null!=throwable) { - throw new RuntimeException(throwable); + while( rt.isInQueue() ) { + try { + sync.wait(); + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } + final Throwable throwable = rt.getThrowable(); + if(null!=throwable) { + throw new RuntimeException(throwable); + } } } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java index bdf9630af..c0f277f09 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java @@ -32,6 +32,8 @@ import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionNumber; import jogamp.nativewindow.NWJNILibLoader; import jogamp.nativewindow.Debug; @@ -122,6 +124,107 @@ public class GDIUtil implements ToolkitProperties { return (Point) GetRelativeLocation0(src_win, dest_win, src_x, src_y); } + /** + * Windows >= 8, even if not manifested + * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx + */ + public static final VersionNumber Win8Version = new VersionNumber(6, 2, 0); + + /** + * Windows >= 10, manifested + * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx + */ + public static final VersionNumber Win10Version = new VersionNumber(10, 0, 0); + + /** + * Wrapper for {@link GDI#DwmIsCompositionEnabled()} + * taking the Windows 8 version into account. + * <p> + * If Windows version >= {@link #Win8Version} method always returns {@code true}, + * otherwise value of {@link GDI#DwmIsCompositionEnabled()} is returned. + * </p> + * @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa969518%28v=vs.85%29.aspx + */ + public static boolean DwmIsCompositionEnabled() { + final VersionNumber winVer = Platform.getOSVersionNumber(); + if( winVer.compareTo(Win8Version) >= 0 ) { + return true; + } else { + return GDI.DwmIsCompositionEnabled(); + } + } + + public static boolean DwmSetupTranslucency(final long hwnd, final boolean enable) { + if( !GDI.DwmIsExtensionAvailable() ) { + if(DEBUG) { + System.err.println("GDIUtil.DwmSetupTranslucency on wnd 0x"+Long.toHexString(hwnd)+": enable "+enable+" -> failed, extension not available"); + } + return !enable; + } + final VersionNumber winVer = Platform.getOSVersionNumber(); + final boolean isWin8 = winVer.compareTo(Win8Version) >= 0; + if( !isWin8 && !GDI.DwmIsCompositionEnabled() ) { + if(DEBUG) { + System.err.println("GDIUtil.DwmSetupTranslucency on wnd 0x"+Long.toHexString(hwnd)+": enable "+enable+" -> failed, composition disabled"); + } + return !enable; + } + final boolean hasWinCompEXT = GDI.IsWindowCompositionExtensionAvailable(); + final boolean useWinCompEXT = isWin8 && hasWinCompEXT; + final boolean isUndecorated = IsUndecorated(hwnd); + boolean ok; + if( useWinCompEXT && !isUndecorated ) { + final AccentPolicy accentPolicy = AccentPolicy.create(); + if( enable ) { + // For undecorated windows, this would also enable the Glass effect! + accentPolicy.setAccentState(GDI.ACCENT_ENABLE_BLURBEHIND); + } else { + accentPolicy.setAccentState(GDI.ACCENT_DISABLED); + } + ok = GDI.SetWindowCompositionAccentPolicy(hwnd, accentPolicy); + } else { + // Works even for >= Win8, if undecorated + final DWM_BLURBEHIND bb = DWM_BLURBEHIND.create(); + final int dwFlags = enable ? GDI.DWM_BB_ENABLE | GDI.DWM_BB_BLURREGION | GDI.DWM_BB_TRANSITIONONMAXIMIZED : GDI.DWM_BB_ENABLE; + // final int dwFlags = GDI.DWM_BB_ENABLE; + bb.setDwFlags( dwFlags ); + bb.setFEnable( enable ? 1 : 0 ); + bb.setHRgnBlur(0); + bb.setFTransitionOnMaximized(1); + ok = GDI.DwmEnableBlurBehindWindow(hwnd, bb); + if( ok ) { + final MARGINS m = MARGINS.create(); + m.setCxLeftWidth(-1); + m.setCxRightWidth(-1); + m.setCyBottomHeight(-1); + m.setCyTopHeight(-1); + ok = GDI.DwmExtendFrameIntoClientArea(hwnd, m); + } + } + /*** + * Not required .. + * + if( ok && isWin8 && !isUndecorated ) { + final IntBuffer pvAttribute = Buffers.newDirectIntBuffer(1); + if( enable ) { + // Glass Effect even if undecorated, hence not truly 100% translucent! + pvAttribute.put(0, GDI.DWMNCRP_ENABLED); + } else { + pvAttribute.put(0, GDI.DWMNCRP_DISABLED); + } + final int err = GDI.DwmSetWindowAttribute(hwnd, GDI.DWMWA_NCRENDERING_POLICY, + pvAttribute, + Buffers.sizeOfBufferElem(pvAttribute)*pvAttribute.capacity()); + ok = 0 == err; // S_OK + } */ + if(DEBUG) { + final boolean isChild = IsChild(hwnd); + System.err.println("GDIUtil.DwmSetupTranslucency on wnd 0x"+Long.toHexString(hwnd)+": enable "+enable+", isUndecorated "+isUndecorated+", isChild "+isChild+ + ", version "+winVer+", isWin8 "+isWin8+", hasWinCompEXT "+hasWinCompEXT+", useWinCompEXT "+useWinCompEXT+" -> ok: "+ok); + } + return ok; + } + public static boolean IsUndecorated(final long win) { return IsUndecorated0(win); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java index f8a11f91e..4257376a0 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java @@ -42,6 +42,7 @@ import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; import com.jogamp.nativewindow.x11.X11GraphicsConfiguration; +import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory { @@ -59,15 +60,17 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor if(!(screen instanceof X11GraphicsScreen)) { throw new NativeWindowException("Only valid X11GraphicsScreen are allowed"); } - final X11Capabilities x11CapsChosen; + final XVisualInfo x11VisualInfo; if(VisualIDHolder.VID_UNDEFINED == nativeVisualID) { - x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen)); + x11VisualInfo = getXVisualInfo(screen, capsChosen); } else { - x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, nativeVisualID)); + x11VisualInfo = getXVisualInfo(screen, nativeVisualID); } + + final X11Capabilities x11CapsChosen = X11GraphicsConfiguration.XVisualInfo2X11Capabilities((X11GraphicsDevice)screen.getDevice(), x11VisualInfo); final AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo()); if(DEBUG) { - System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl(visualID 0x"+Integer.toHexString(nativeVisualID)+", "+screen+","+capsChosen+"): "+res); + System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl(visualID 0x"+Integer.toHexString(nativeVisualID)+", "+x11VisualInfo+", "+screen+","+capsChosen+"): "+res); } return res; } @@ -85,7 +88,6 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor if(xvis==null || num[0]<1) { return null; } - return XVisualInfo.create(xvis[0]); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java index e59ff2ea8..6af5467f0 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java @@ -463,10 +463,12 @@ public class X11Util implements ToolkitProperties { if(markAllDisplaysUnclosable) { namedDpy.setUncloseable(true); } - } - if(DEBUG) { - System.err.println("X11Util.Display: openDisplay [reuse "+reused+"] "+namedDpy+". Thread "+Thread.currentThread().getName()); - // Thread.dumpStack(); + if(DEBUG) { + System.err.println("X11Util.Display: openDisplay [reuse "+reused+"] "+namedDpy+ + ". Open[reuseable "+reusableDisplayList.size()+", pending "+pendingDisplayList.size()+ + "]. Thread "+Thread.currentThread().getName()); + // Thread.dumpStack(); + } } return namedDpy.getHandle(); } diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 919108db9..c04ba786e 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -336,6 +336,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0 (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [CATransaction begin]; NSRect rect = NSMakeRect(x, y, width, height); // Allocate the window @@ -365,6 +366,7 @@ NS_ENDHANDLER // [myView lockFocus]; // [myView unlockFocus]; + [CATransaction commit]; [pool release]; return (jlong) ((intptr_t) myWindow); @@ -379,9 +381,17 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0 (JNIEnv *env, jclass unused, jlong nsWindow) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* mWin = (NSWindow*) ((intptr_t) nsWindow); + [CATransaction begin]; +NS_DURING + NSWindow* mWin = (NSWindow*) ((intptr_t) nsWindow); [mWin close]; // performs release! +NS_HANDLER + // On killing or terminating the process [NSWindow _close], rarely + // throws an NSRangeException while ordering out menu items +NS_ENDHANDLER + + [CATransaction commit]; [pool release]; } @@ -861,8 +871,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Ge NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); return 0; } - id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo; - return (jlong) ((intptr_t) surfaceLayers); + NSObject *surfaceLayersObj = (NSObject*) dsi->platformInfo; + [surfaceLayersObj retain]; // Pairs w/ Unset + DBG_PRINT("CALayer::GetJAWTSurfaceLayersHandle: surfaceLayers %p (refcnt %d)\n", surfaceLayersObj, (int)[surfaceLayersObj retainCount]); + + id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)surfaceLayersObj; + return (jlong) (intptr_t) surfaceLayers; } /* @@ -878,9 +892,11 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Set [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; - id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle; + NSObject *surfaceLayersObj = (NSObject*) (intptr_t) jawtSurfaceLayersHandle; + id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)surfaceLayersObj; MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer; DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: pre %p -> root %p (refcnt %d)\n", [surfaceLayers layer], layer, (int)[layer retainCount]); + [surfaceLayers setLayer: [layer retain]]; // Pairs w/ Unset [CATransaction commit]; @@ -902,20 +918,26 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; - id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle; + NSObject *surfaceLayersObj = (NSObject*) (intptr_t) jawtSurfaceLayersHandle; + id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)surfaceLayersObj; + DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.0: surfaceLayers %p (refcnt %d)\n", surfaceLayersObj, (int)[surfaceLayersObj retainCount]); + MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer; - if(layer != [surfaceLayers layer]) { - NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer); - return; + if(NULL != layer) { + if(layer != [surfaceLayers layer]) { + NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer); + return; + } + DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.1: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]); + [layer release]; // Pairs w/ Set + [surfaceLayers setLayer: NULL]; // Pairs w/ Set } - DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.0: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]); - [layer release]; // Pairs w/ Set - [surfaceLayers setLayer: NULL]; + [surfaceLayersObj release]; // Pairs w/ Get [CATransaction commit]; [pool release]; - DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.X: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]); + DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.X\n"); } @interface MainRunnable : NSObject diff --git a/src/nativewindow/native/win32/WindowsDWM.c b/src/nativewindow/native/win32/WindowsDWM.c index cc9ed6d8c..925ddd1d1 100644 --- a/src/nativewindow/native/win32/WindowsDWM.c +++ b/src/nativewindow/native/win32/WindowsDWM.c @@ -1,4 +1,5 @@ +#include <windows.h> #include "WindowsDWM.h" #include <stdlib.h> @@ -21,39 +22,68 @@ typedef HRESULT (WINAPI *DwmEnableCompositionPROCADDR)(UINT uCompositionAction); typedef HRESULT (WINAPI *DwmIsCompositionEnabledPROCADDR)(BOOL * pfEnabled); typedef HRESULT (WINAPI *DwmEnableBlurBehindWindowPROCADDR)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind); typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaPROCADDR)(HWND hwnd, const MARGINS *pMarInset); +typedef HRESULT (WINAPI *DwmGetWindowAttributePROCADDR)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute); +typedef HRESULT (WINAPI *DwmSetWindowAttributePROCADDR)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); +typedef BOOL (WINAPI *GetWindowCompositionAttributePROCADDR)(HWND hwnd, WINCOMPATTRDATA* pAttrData); +typedef BOOL (WINAPI *SetWindowCompositionAttributePROCADDR)(HWND hwnd, WINCOMPATTRDATA* pAttrData); -static int _init = 0; // 1: init, 2: has DWM extension +#define INIT_CALLED_MASK 1 << 0 +#define INIT_HAS_DWM_EXT_MASK 1 << 1 +#define INIT_HAS_WINCOMP_EXT_MASK 1 << 2 + +#define HAS_INIT(a) ( 0 != ( INIT_CALLED_MASK & (a) ) ) +#define HAS_DWM_EXT(a) ( 0 != ( INIT_HAS_DWM_EXT_MASK & (a) ) ) +#define HAS_WINCOMP_EXT(a) ( 0 != ( INIT_HAS_WINCOMP_EXT_MASK & (a) ) ) + +static int _init = 0; // INIT_ bits, see above static DwmEnableCompositionPROCADDR _DwmEnableComposition = NULL; static DwmIsCompositionEnabledPROCADDR _DwmIsCompositionEnabled = NULL; static DwmEnableBlurBehindWindowPROCADDR _DwmEnableBlurBehindWindow = NULL; static DwmExtendFrameIntoClientAreaPROCADDR _DwmExtendFrameIntoClientArea = NULL; +static DwmGetWindowAttributePROCADDR _DwmGetWindowAttribute = NULL; +static DwmSetWindowAttributePROCADDR _DwmSetWindowAttribute = NULL; +static GetWindowCompositionAttributePROCADDR _GetWindowCompositionAttribute = NULL; +static SetWindowCompositionAttributePROCADDR _SetWindowCompositionAttribute = NULL; static int initWindowsDWM() { - if(0 == _init) { - _init = 1; - HANDLE shell = LoadLibrary(TEXT("dwmapi.dll")); - if (shell) { - _DwmEnableComposition = (DwmEnableCompositionPROCADDR) GetProcAddressA (shell, "DwmEnableComposition"); - _DwmIsCompositionEnabled = (DwmIsCompositionEnabledPROCADDR) GetProcAddressA (shell, "DwmIsCompositionEnabled"); - _DwmEnableBlurBehindWindow = (DwmEnableBlurBehindWindowPROCADDR) GetProcAddressA (shell, "DwmEnableBlurBehindWindow"); - _DwmExtendFrameIntoClientArea = (DwmExtendFrameIntoClientAreaPROCADDR) GetProcAddressA (shell, "DwmExtendFrameIntoClientArea"); + if( !HAS_INIT(_init) ) { + _init |= INIT_CALLED_MASK; + HANDLE hDwmAPI = LoadLibrary(TEXT("dwmapi.dll")); + if (hDwmAPI) { + _DwmEnableComposition = (DwmEnableCompositionPROCADDR) GetProcAddressA (hDwmAPI, "DwmEnableComposition"); + _DwmIsCompositionEnabled = (DwmIsCompositionEnabledPROCADDR) GetProcAddressA (hDwmAPI, "DwmIsCompositionEnabled"); + _DwmEnableBlurBehindWindow = (DwmEnableBlurBehindWindowPROCADDR) GetProcAddressA (hDwmAPI, "DwmEnableBlurBehindWindow"); + _DwmExtendFrameIntoClientArea = (DwmExtendFrameIntoClientAreaPROCADDR) GetProcAddressA (hDwmAPI, "DwmExtendFrameIntoClientArea"); + _DwmGetWindowAttribute = (DwmGetWindowAttributePROCADDR) GetProcAddressA (hDwmAPI, "DwmGetWindowAttribute"); + _DwmSetWindowAttribute = (DwmSetWindowAttributePROCADDR) GetProcAddressA (hDwmAPI, "DwmSetWindowAttribute"); if(NULL != _DwmEnableComposition && NULL != _DwmIsCompositionEnabled && - NULL != _DwmEnableBlurBehindWindow && NULL != _DwmExtendFrameIntoClientArea) { - _init = 2; + NULL != _DwmEnableBlurBehindWindow && NULL != _DwmExtendFrameIntoClientArea && + NULL != _DwmGetWindowAttribute && NULL != _DwmSetWindowAttribute) { + _init |= INIT_HAS_DWM_EXT_MASK; + } + } + // FreeLibrary (hDwmAPI); + HANDLE hUser32 = LoadLibrary(TEXT("user32.dll")); + if (hUser32) { + _GetWindowCompositionAttribute = (GetWindowCompositionAttributePROCADDR) GetProcAddressA (hUser32, "GetWindowCompositionAttribute"); + _SetWindowCompositionAttribute = (SetWindowCompositionAttributePROCADDR) GetProcAddressA (hUser32, "SetWindowCompositionAttribute"); + if( NULL != _GetWindowCompositionAttribute && + NULL != _SetWindowCompositionAttribute ) { + _init |= INIT_HAS_WINCOMP_EXT_MASK; } } - // FreeLibrary (shell); - DBG_PRINT("DWM - initWindowsDWM: %d - s %p, e %p, c %p\n", _init, shell, _DwmEnableBlurBehindWindow, _DwmExtendFrameIntoClientArea); + // FreeLibrary (hUser32); + DBG_PRINT("DWM - initWindowsDWM: hasDWM %d, hasWinComp %d\n", HAS_DWM_EXT(_init), HAS_WINCOMP_EXT(_init)); } return _init; } BOOL DwmIsExtensionAvailable() { - return (2 == initWindowsDWM()) ? TRUE : FALSE; + return HAS_DWM_EXT( initWindowsDWM() ) ? TRUE : FALSE; } BOOL DwmIsCompositionEnabled( ) { - if(2 == initWindowsDWM()) { + if( HAS_DWM_EXT( initWindowsDWM() ) ) { BOOL fEnabled = FALSE; if( 0 == _DwmIsCompositionEnabled(&fEnabled) ) { DBG_PRINT("DWM - DwmIsCompositionEnabled: %d\n", fEnabled); @@ -65,14 +95,14 @@ BOOL DwmIsCompositionEnabled( ) { } BOOL DwmEnableComposition( UINT uCompositionAction ) { - if(2 == initWindowsDWM()) { + if( HAS_DWM_EXT( initWindowsDWM() ) ) { return 0 == _DwmEnableComposition(uCompositionAction) ? TRUE : FALSE; } return FALSE; } BOOL DwmEnableBlurBehindWindow(HWND hwnd, const DWM_BLURBEHIND* pBlurBehind) { - if(2 == initWindowsDWM()) { + if( HAS_DWM_EXT( initWindowsDWM() ) ) { _DwmEnableBlurBehindWindow(hwnd, pBlurBehind); DBG_PRINT("DWM - DwmEnableBlurBehindWindow: hwnd %p, f %d, on %d, %p\n", (void *)hwnd, @@ -86,10 +116,59 @@ BOOL DwmEnableBlurBehindWindow(HWND hwnd, const DWM_BLURBEHIND* pBlurBehind) { } BOOL DwmExtendFrameIntoClientArea(HWND hwnd, const MARGINS *pMarInset) { - if(2 == initWindowsDWM()) { + if( HAS_DWM_EXT( initWindowsDWM() ) ) { _DwmExtendFrameIntoClientArea(hwnd, pMarInset); return TRUE; } return FALSE; } +HRESULT DwmGetWindowAttribute(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute) { + if( HAS_DWM_EXT( initWindowsDWM() ) ) { + return _DwmGetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute); + } + return E_NOINTERFACE; +} + +HRESULT DwmSetWindowAttribute(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute) { + if( HAS_DWM_EXT( initWindowsDWM() ) ) { + return _DwmSetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute); + } + return E_NOINTERFACE; +} + +BOOL IsWindowCompositionExtensionAvailable() { + return HAS_WINCOMP_EXT( initWindowsDWM() ) ? TRUE : FALSE; +} + +BOOL GetWindowCompositionAccentPolicy(HWND hwnd, AccentPolicy* pAccentPolicy) { + if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) { + WINCOMPATTRDATA attrData = { WCA_ACCENT_POLICY, pAccentPolicy, sizeof(AccentPolicy) }; + return _GetWindowCompositionAttribute(hwnd, &attrData); + } + return FALSE; +} +BOOL SetWindowCompositionAccentPolicy(HWND hwnd, const AccentPolicy* pAccentPolicy) { + if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) { + WINCOMPATTRDATA attrData = { WCA_ACCENT_POLICY, (AccentPolicy*)pAccentPolicy, sizeof(AccentPolicy) }; + return _SetWindowCompositionAttribute(hwnd, &attrData); + } + return FALSE; +} + +#if 0 +BOOL GetWindowCompositionAttribute(HWND hwnd, WINCOMPATTRDATA* pAttrData) { + if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) { + return _GetWindowCompositionAttribute(hwnd, pAttrData); + } + return FALSE; +} + +BOOL SetWindowCompositionAttribute(HWND hwnd, WINCOMPATTRDATA* pAttrData) { + if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) { + return _SetWindowCompositionAttribute(hwnd, pAttrData); + } + return FALSE; +} +#endif + diff --git a/src/nativewindow/native/win32/WindowsDWM.h b/src/nativewindow/native/win32/WindowsDWM.h deleted file mode 100644 index 6e5160fa4..000000000 --- a/src/nativewindow/native/win32/WindowsDWM.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _WINDOWS_DWM_H_ -#define _WINDOWS_DWM_H_ - - #include <windows.h> - - #define DWM_BB_ENABLE 0x00000001 // fEnable has been specified - #define DWM_BB_BLURREGION 0x00000002 - #define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 - #define DWM_EC_DISABLECOMPOSITION 0 - #define DWM_EC_ENABLECOMPOSITION 1 - - typedef struct _DWM_BLURBEHIND - { - DWORD dwFlags; - BOOL fEnable; - HRGN hRgnBlur; - BOOL fTransitionOnMaximized; - } DWM_BLURBEHIND, *PDWM_BLURBEHIND; - - typedef struct _MARGINS - { - int cxLeftWidth; // width of left border that retains its size - int cxRightWidth; // width of right border that retains its size - int cyTopHeight; // height of top border that retains its size - int cyBottomHeight; // height of bottom border that retains its size - } MARGINS, *PMARGINS; - - BOOL DwmIsExtensionAvailable(); - BOOL DwmIsCompositionEnabled(); - BOOL DwmEnableComposition( UINT uCompositionAction ); - BOOL DwmEnableBlurBehindWindow(HWND hwnd, const DWM_BLURBEHIND* pBlurBehind); - BOOL DwmExtendFrameIntoClientArea(HWND hwnd, const MARGINS *pMarInset); - -#endif /* _WINDOWS_DWM_H_ */ diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 2ed2194d8..dd15eb3ea 100644 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -59,6 +59,7 @@ public class NewtFactory { public static final String DRIVER_DEFAULT_ROOT_PACKAGE = "jogamp.newt.driver"; private static IOUtil.ClassResources defaultWindowIcons; + private static String sysPaths = "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"; static { AccessController.doPrivileged(new PrivilegedAction<Object>() { @@ -67,12 +68,11 @@ public class NewtFactory { NativeWindowFactory.initSingleton(); // last resort .. { /** See API Doc in {@link Window} ! */ - final String[] paths = PropertyAccess.getProperty("newt.window.icons", true, "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png").split("\\s"); + final String[] paths = PropertyAccess.getProperty("newt.window.icons", true, sysPaths).split("[\\s,]"); if( paths.length < 2 ) { throw new IllegalArgumentException("Property 'newt.window.icons' did not specify at least two PNG icons, but "+Arrays.toString(paths)); } - final Class<?> clazz = NewtFactory.class; - defaultWindowIcons = new IOUtil.ClassResources(clazz, paths); + defaultWindowIcons = new IOUtil.ClassResources(paths, NewtFactory.class.getClassLoader(), null); } return null; } } ); @@ -81,7 +81,7 @@ public class NewtFactory { /** * Returns the application window icon resources to be used. * <p> - * Property <code>newt.window.icons</code> may define a list of PNG icons separated by a whitespace character. + * Property <code>newt.window.icons</code> may define a list of PNG icons separated by one whitespace or one comma character. * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution. * </p> * <p> diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index d46afd1cd..30b02cb61 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -83,16 +83,22 @@ import com.jogamp.nativewindow.util.SurfaceSize; * <a name="customwindowicons"><h5>Custom Window Icons</h5></a> * <p> * Custom window icons can be defined via system property <code>newt.window.icons</code>, - * which shall contain a space separated list of PNG icon locations from low- to high-resolution. + * which shall contain a list of PNG icon locations from low- to high-resolution, + * separated by one whitespace or one comma character. * The location must be resolvable via classpath, i.e. shall reference a location within the jar file. * Example (our default): * <pre> - * -Dnewt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png" - * -Djnlp.newt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png" + * -Dnewt.window.icons="newt/data/jogamp-16x16.png,newt/data/jogamp-32x32.png" + * -Djnlp.newt.window.icons="newt/data/jogamp-16x16.png,newt/data/jogamp-32x32.png" * </pre> * The property can also be set programmatically, which must happen before any NEWT classes are <i>touched</i>: * <pre> - * System.setProperty("newt.window.icons", "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"); + * System.setProperty("newt.window.icons", "newt/data/jogamp-16x16.png, newt/data/jogamp-32x32.png"); + * </pre> + * To disable even Jogamp's own window icons in favor of system icons, + * simply set a non-existing location, e.g.: + * <pre> + * -Dnewt.window.icons="null,null" * </pre> * </p> * @@ -216,6 +222,10 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur public static final int STATE_BIT_MAXIMIZED_HORZ = 10; // reconfig-flag /** * Set if window is in <i>fullscreen mode</i>, otherwise cleared. + * <p> + * Usually fullscreen mode implies {@link #STATE_BIT_UNDECORATED}, + * however, an implementation is allowed to ignore this if unavailable. + * </p> * <p>Bit number {@value}.</p> * <p>Defaults to {@code false}.</p> * @see #getStateMask() @@ -223,9 +233,6 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur */ public static final int STATE_BIT_FULLSCREEN = 11; // reconfig-flag - // Hidden in WindowImpl: - // static final int STATE_BIT_FULLSCREEN_SPAN = 12; - /** * Set if the <i>pointer is visible</i> when inside the window, otherwise cleared. * <p>Bit number {@value}.</p> @@ -233,7 +240,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur * @see #getStateMask() * @since 2.3.2 */ - public static final int STATE_BIT_POINTERVISIBLE = 13; + public static final int STATE_BIT_POINTERVISIBLE = 12; /** * Set if the <i>pointer is confined</i> to the window, otherwise cleared. * <p>Bit number {@value}.</p> @@ -241,7 +248,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur * @see #getStateMask() * @since 2.3.2 */ - public static final int STATE_BIT_POINTERCONFINED = 14; + public static final int STATE_BIT_POINTERCONFINED = 13; /** * Bitmask for {@link #STATE_BIT_VISIBLE}, {@value}. @@ -330,6 +337,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur /** * Returns the current status mask of this instance. + * @see #getSupportedStateMask() * @see #STATE_MASK_VISIBLE * @see #STATE_MASK_AUTOPOSITION * @see #STATE_MASK_CHILDWIN @@ -354,6 +362,52 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur */ String getStateMaskString(); + /** + * Returns the supported {@link #getStateMask() state mask} of the implementation. + * <p> + * Implementation provides supported {@link #getStateMask() state mask} values at runtime + * <i>after</i> native window creation, i.e. first visibility. + * </p> + * <p> + * Please note that a window's size shall also be allowed to change, i.e. {@link #setSize(int, int)}. + * </p> + * <p> + * Default value is {@link #STATE_MASK_VISIBLE} | {@link #STATE_MASK_FOCUSED} | {@link #STATE_MASK_FULLSCREEN}, + * i.e. the <b>minimum requirement</b> for all implementations. + * </p> + * <p> + * Before native window creation {@link #getStatePublicBitmask()} is returned, + * i.e. it is assumed all features are supported. + * </p> + * <p> + * Semantic of the supported state-mask bits (after native creation, i.e. 1st visibility): + * <ul> + * <li>{@link #STATE_MASK_VISIBLE}: {@link #setVisible(boolean) Visibility} can be toggled. <b>Minimum requirement</b>.</li> + * <li>{@link #STATE_MASK_CHILDWIN}: {@link #reparentWindow(NativeWindow, int, int, int) Native window parenting} is supported.</li> + * <li>{@link #STATE_MASK_FOCUSED}: Window {@link #requestFocus() focus management} is supported. <b>Minimum requirement</b>.</li> + * <li>{@link #STATE_MASK_UNDECORATED}: {@link #setUndecorated(boolean) Window decoration} can be toggled.</li> + * <li>{@link #STATE_MASK_ALWAYSONTOP}: Window can be set {@link #setAlwaysOnTop(boolean) always-on-top}. </li> + * <li>{@link #STATE_MASK_ALWAYSONBOTTOM}: Window can be set {@link #setAlwaysOnBottom(boolean) always-on-bottom}. </li> + * <li>{@link #STATE_MASK_STICKY}: Window can be set {@link #setSticky(boolean) sticky}.</li> + * <li>{@link #STATE_MASK_RESIZABLE}: Window {@link #setResizable(boolean) resizability} can be toggled.</li> + * <li>{@link #STATE_MASK_MAXIMIZED_VERT}: Window can be {@link #setMaximized(boolean, boolean) maximized-vertically}. </li> + * <li>{@link #STATE_MASK_MAXIMIZED_HORZ}: Window can be {@link #setMaximized(boolean, boolean) maximized-horizontally}. </li> + * <li>{@link #STATE_MASK_FULLSCREEN}: Window {@link #setFullscreen(boolean) fullscreen} can be toggled. </li> + * <li>{@link #STATE_MASK_POINTERVISIBLE}: Window {@link #setPointerVisible(boolean) pointer visibility} can be toggled. </li> + * <li>{@link #STATE_MASK_POINTERCONFINED}: Window {@link #confinePointer(boolean) pointer can be confined}. </li> + * </ul> + * </p> + * @see #getStateMask() + * @since 2.3.2 + */ + int getSupportedStateMask(); + + /** + * Returns a string representation of the {@link #getSupportedStateMask() supported state mask}. + * @since 2.3.2 + */ + String getSupportedStateMaskString(); + // // Lifecycle // @@ -697,7 +751,6 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur boolean isSticky(); /** - * <p>Operation is ignored in {@link #isFullscreen() fullscreen mode}.</p> * <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p> * @see {@link #STATE_BIT_MAXIMIZED_HORZ} * @see {@link #STATE_BIT_MAXIMIZED_VERT} diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index ae32fd164..a0083b4ea 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -49,7 +49,9 @@ import java.security.PrivilegedAction; import java.util.Set; import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.NativeWindow; +import com.jogamp.nativewindow.NativeWindowHolder; import com.jogamp.nativewindow.OffscreenLayerOption; import com.jogamp.nativewindow.WindowClosingProtocol; import com.jogamp.opengl.GLAnimatorControl; @@ -100,7 +102,7 @@ import com.jogamp.opengl.util.TileRenderer; * the underlying JAWT mechanism to composite the image, if supported. */ @SuppressWarnings("serial") -public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle { +public class NewtCanvasAWT extends java.awt.Canvas implements NativeWindowHolder, WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle { public static final boolean DEBUG = Debug.debug("Window"); private final Object sync = new Object(); @@ -110,7 +112,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private Window newtChild = null; private boolean newtChildAttached = false; private boolean isOnscreen = true; - private WindowClosingMode newtChildCloseOp; + private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE; private final AWTParentWindowAdapter awtWinAdapter; private final AWTAdapter awtMouseAdapter; private final AWTAdapter awtKeyAdapter; @@ -420,10 +422,22 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto return newtChild; } - /** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called, - * or {@link #addNotify()} hasn't been called yet.*/ + /** + * {@inheritDoc} + * @return this AWT Canvas {@link NativeWindow} representation, may be null in case {@link #removeNotify()} has been called, + * or {@link #addNotify()} hasn't been called yet. + */ + @Override public NativeWindow getNativeWindow() { return jawtWindow; } + /** + * {@inheritDoc} + * @return this AWT Canvas {@link NativeSurface} representation, may be null in case {@link #removeNotify()} has been called, + * or {@link #addNotify()} hasn't been called yet. + */ + @Override + public NativeSurface getNativeSurface() { return jawtWindow; } + @Override public WindowClosingMode getDefaultCloseOperation() { return awtWindowClosingProtocol.getDefaultCloseOperation(); diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java index cd53294a1..6bf9f41a6 100644 --- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java +++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java @@ -115,7 +115,7 @@ public class JOGLNewtApplet1Run extends Applet { String glEventListenerClazzName=null; String glProfileName=null; - int glSwapInterval=0; + int glSwapInterval=1; boolean glDebug=false; boolean glTrace=false; boolean glUndecorated=false; diff --git a/src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java b/src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java new file mode 100644 index 000000000..e04ed326d --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java @@ -0,0 +1,670 @@ +/** + * Copyright 2019 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.newt.javafx; + +import com.jogamp.common.util.PropertyAccess; +import com.jogamp.nativewindow.AbstractGraphicsConfiguration; +import com.jogamp.nativewindow.AbstractGraphicsScreen; +import com.jogamp.nativewindow.Capabilities; +import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.GraphicsConfigurationFactory; +import com.jogamp.nativewindow.NativeSurface; +import com.jogamp.nativewindow.NativeWindow; +import com.jogamp.nativewindow.NativeWindowException; +import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.NativeWindowHolder; +import com.jogamp.nativewindow.SurfaceUpdatedListener; +import com.jogamp.nativewindow.WindowClosingProtocol; +import com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode; +import com.jogamp.nativewindow.util.Insets; +import com.jogamp.nativewindow.util.InsetsImmutable; +import com.jogamp.nativewindow.util.Point; +import com.jogamp.nativewindow.util.Rectangle; +import com.jogamp.opengl.GLCapabilities; + +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.event.EventHandler; +import javafx.geometry.Bounds; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import jogamp.newt.Debug; +import jogamp.newt.javafx.JFXEDTUtil; + +import com.jogamp.nativewindow.javafx.JFXAccessor; +import com.jogamp.newt.Display; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.util.EDTUtil; + +/** + * A NEWT based JFX {@link Canvas} specialization allowing a NEWT child {@link Window} to be attached using native parenting. + * <p> + * {@link NewtCanvasJFX} allows utilizing custom {@link GLCapabilities} settings independent from the JavaFX's window + * as well as independent rendering from JavaFX's thread. + * </p> + * <p> + * {@link NewtCanvasJFX} allows native parenting operations before and after + * it's belonging Group's Scene has been attached to the JavaFX {@link javafx.stage.Window Window}'s actual native window, + * i.e. becoming fully realized and visible. + * </p> + * <p> + * Note that {@link JFXAccessor#runOnJFXThread(boolean, Runnable)} is still used to for certain + * mandatory JavaFX lifecycle operation on the JavaFX thread. + * </p> + */ +public class NewtCanvasJFX extends Canvas implements NativeWindowHolder, WindowClosingProtocol { + private static final boolean DEBUG = Debug.debug("Window"); + private static final boolean USE_JFX_EDT = PropertyAccess.getBooleanProperty("jogamp.newt.javafx.UseJFXEDT", true, true); + private volatile javafx.stage.Window parentWindow = null; + private volatile AbstractGraphicsScreen screen = null; + + private WindowClosingMode newtChildClosingMode = WindowClosingMode.DISPOSE_ON_CLOSE; + private WindowClosingMode closingMode = WindowClosingMode.DISPOSE_ON_CLOSE; + private final Rectangle clientArea = new Rectangle(); + + private volatile JFXNativeWindow nativeWindow = null; + private volatile Window newtChild = null; + private volatile boolean newtChildReady = false; // ready if JFXEDTUtil is set and newtChild parented + private volatile boolean postSetSize = false; // pending resize + private volatile boolean postSetPos = false; // pending pos + + private final EventHandler<javafx.stage.WindowEvent> windowClosingListener = new EventHandler<javafx.stage.WindowEvent>() { + public final void handle(final javafx.stage.WindowEvent e) { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.Event.DISPOSE, "+e+", closeOp "+closingMode); + } + if( WindowClosingMode.DISPOSE_ON_CLOSE == closingMode ) { + NewtCanvasJFX.this.destroy(); + } else { + // avoid JavaFX closing operation + e.consume(); + } + } }; + private final EventHandler<javafx.stage.WindowEvent> windowShownListener = new EventHandler<javafx.stage.WindowEvent>() { + public final void handle(final javafx.stage.WindowEvent e) { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.Event.SHOWN, "+e); + } + repaintAction(true); + } }; + + /** + * Instantiates a NewtCanvas with a NEWT child. + * + * <p> + * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an JFX conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + * </p> + * @param child optional preassigned {@link #Window}, maybe null + */ + public NewtCanvasJFX(final Window child) { + super(); + + updateParentWindowAndScreen(); + + final ChangeListener<Number> sizeListener = new ChangeListener<Number>() { + @Override public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.Event.Size, "+oldValue.doubleValue()+" -> "+newValue.doubleValue()+", has "+getWidth()+"x"+getHeight()); + } + updateSizeCheck((int)getWidth(), (int)getHeight()); + repaintAction(isVisible()); + } }; + this.widthProperty().addListener(sizeListener); + this.heightProperty().addListener(sizeListener); + this.visibleProperty().addListener(new ChangeListener<Boolean>() { + @Override public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.Event.Visible, "+oldValue.booleanValue()+" -> "+newValue.booleanValue()+", has "+isVisible()); + } + repaintAction(newValue.booleanValue()); + } + }); + this.sceneProperty().addListener(new ChangeListener<Scene>() { + @Override public void changed(final ObservableValue<? extends Scene> observable, final Scene oldValue, final Scene newValue) { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.Event.Scene, "+oldValue+" -> "+newValue+", has "+getScene()); + if(null != newValue) { + final javafx.stage.Window w = newValue.getWindow(); + System.err.println("NewtCanvasJFX.Event.Scene window "+w+" (showing "+(null!=w?w.isShowing():0)+")"); + } + } + if( updateParentWindowAndScreen() ) { + repaintAction(isVisible()); + } + } + }); + + if(null != child) { + setNEWTChild(child); + } + } + + private final void repaintAction(final boolean visible) { + if( visible && ( null != nativeWindow || validateNative(true /* completeReparent */) ) ) { + if( newtChildReady ) { + if( postSetSize ) { + newtChild.setSize(clientArea.getWidth(), clientArea.getHeight()); + postSetSize = false; + } + if( postSetPos ) { + newtChild.setPosition(clientArea.getX(), clientArea.getY()); + postSetPos = false; + } + newtChild.windowRepaint(0, 0, clientArea.getWidth(), clientArea.getHeight()); + } + } + } + + private final void updatePosSizeCheck() { + final Bounds b = localToScene(getBoundsInLocal()); + updatePosCheck((int)b.getMinX(), (int)b.getMinY()); + updateSizeCheck((int)getWidth(), (int)getHeight()); + } + private final void updatePosCheck(final int newX, final int newY) { + final boolean posChanged; + { + final Rectangle oClientArea = clientArea; + posChanged = newX != oClientArea.getX() || newY != oClientArea.getY(); + if( posChanged ) { + clientArea.setX(newX); + clientArea.setY(newY); + } + } + if(DEBUG) { + final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0; + System.err.println("NewtCanvasJFX.updatePosCheck: posChanged "+posChanged+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+clientArea.getX()+"/"+clientArea.getY()+" "+clientArea.getWidth()+"x"+clientArea.getHeight()+" - surfaceHandle 0x"+Long.toHexString(nsh)); + } + if( posChanged ) { + if( newtChildReady ) { + newtChild.setPosition(clientArea.getX(), clientArea.getY()); + } else { + postSetPos = true; + } + } + } + private final void updateSizeCheck(final int newWidth, final int newHeight) { + final boolean sizeChanged; + { + final Rectangle oClientArea = clientArea; + sizeChanged = newWidth != oClientArea.getWidth() || newHeight != oClientArea.getHeight(); + if( sizeChanged ) { + clientArea.setWidth(newWidth); + clientArea.setHeight(newHeight); + } + } + if(DEBUG) { + final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0; + System.err.println("NewtCanvasJFX.updateSizeCheck: sizeChanged "+sizeChanged+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+clientArea.getX()+"/"+clientArea.getY()+" "+clientArea.getWidth()+"x"+clientArea.getHeight()+" - surfaceHandle 0x"+Long.toHexString(nsh)); + } + if( sizeChanged ) { + if( newtChildReady ) { + newtChild.setSize(clientArea.getWidth(), clientArea.getHeight()); + } else { + postSetSize = true; + } + } + } + + private final ChangeListener<javafx.stage.Window> sceneWindowChangeListener = new ChangeListener<javafx.stage.Window>() { + @Override public void changed(final ObservableValue<? extends javafx.stage.Window> observable, final javafx.stage.Window oldValue, final javafx.stage.Window newValue) { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.Event.Window, "+oldValue+" -> "+newValue); + } + if( updateParentWindowAndScreen() ) { + repaintAction(isVisible()); + } + } }; + + private boolean updateParentWindowAndScreen() { + final Scene s = this.getScene(); + if( null != s ) { + final javafx.stage.Window w = s.getWindow(); + if( DEBUG ) { + System.err.println("NewtCanvasJFX.updateParentWindowAndScreen: Scene "+s+", Window "+w+" (showing "+(null!=w?w.isShowing():0)+")"); + } + if( w != parentWindow ) { + destroyImpl(false); + } + parentWindow = w; + if( null != w ) { + screen = JFXAccessor.getScreen(JFXAccessor.getDevice(parentWindow), -1 /* default */); + parentWindow.addEventHandler(javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST, windowClosingListener); + parentWindow.addEventHandler(javafx.stage.WindowEvent.WINDOW_SHOWN, windowShownListener); + return true; + } else { + s.windowProperty().addListener(sceneWindowChangeListener); + } + } else { + if( DEBUG ) { + System.err.println("NewtCanvasJFX.updateParentWindowAndScreen: Null Scene"); + } + if( null != parentWindow ) { + destroyImpl(false); + } + } + return false; + } + + /** + * Destroys this resource: + * <ul> + * <li> Make the NEWT Child invisible </li> + * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li> + * <li> Issues {@link Window#destroy()} on the NEWT Child</li> + * <li> Remove reference to the NEWT Child</li> + * </ul> + * JavaFX will issue this call when sending out the {@link javafx.stage.WindowEvent#WINDOW_CLOSE_REQUEST} automatically, + * if the user has not overridden the default {@link WindowClosingMode#DISPOSE_ON_CLOSE} to {@link WindowClosingMode#DO_NOTHING_ON_CLOSE} + * via {@link #setDefaultCloseOperation(com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode)}. + * @see Window#destroy() + * @see #setDefaultCloseOperation(com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode) + */ + public void destroy() { + destroyImpl(true); + } + private void destroyImpl(final boolean disposeNewtChild) { + if(DEBUG) { + System.err.println("NewtCanvasJFX.dispose: (has parent "+(null!=parentWindow)+", hasNative "+(null!=nativeWindow)+",\n\t"+newtChild); + } + if( null != newtChild ) { + if(DEBUG) { + System.err.println("NewtCanvasJFX.dispose.1: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + if( null != nativeWindow ) { + configureNewtChild(false); + newtChild.setVisible(false); + newtChild.reparentWindow(null, -1, -1, 0 /* hint */); + } + if( disposeNewtChild ) { + newtChild.destroy(); + newtChild = null; + } + } + if( null != parentWindow ) { + parentWindow.getScene().windowProperty().removeListener(sceneWindowChangeListener); + parentWindow.removeEventHandler(javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST, windowClosingListener); + parentWindow.removeEventHandler(javafx.stage.WindowEvent.WINDOW_SHOWN, windowShownListener); + parentWindow = null; + } + if( null != screen ) { + screen.getDevice().close(); + screen = null; + } + nativeWindow = null; + } + + private final boolean validateNative(final boolean completeReparent) { + if( null == parentWindow ) { + return false; + } + assert null == nativeWindow; + updatePosSizeCheck(); + if(0 >= clientArea.getWidth() || 0 >= clientArea.getHeight()) { + return false; + } + final long nativeWindowHandle = JFXAccessor.getWindowHandle(parentWindow); + if( 0 == nativeWindowHandle ) { + return false; + } + screen.getDevice().open(); + + /* Native handle for the control, used to associate with GLContext */ + final int visualID = JFXAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle); + final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID); + if(DEBUG) { + System.err.println("NewtCanvasJFX.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid); + } + if( visualIDValid ) { + /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). + * Note: JFX is owner of the native handle, hence no closing operation will be a NOP. */ + final CapabilitiesImmutable caps = new Capabilities(); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps); + final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID ); + if(DEBUG) { + System.err.println("NewtCanvasJFX.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config); + // Thread.dumpStack(); + } + if (null == config) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + nativeWindow = new JFXNativeWindow(config, nativeWindowHandle); + if( completeReparent ) { + reparentWindow( true ); + } + } + + return null != nativeWindow; + } + + /** + * Sets a new NEWT child, provoking reparenting. + * <p> + * A previously detached <code>newChild</code> will be released to top-level status + * and made invisible. + * </p> + * <p> + * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code> + * produced much cleaner visual results. + * </p> + * <p> + * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an JFX conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + * </p> + * @return the previous attached newt child. + */ + public Window setNEWTChild(final Window newChild) { + final Window prevChild = newtChild; + if(DEBUG) { + System.err.println("NewtCanvasJFX.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild)); + } + // remove old one + if(null != newtChild) { + reparentWindow( false ); + newtChild = null; + } + // add new one, reparent only if ready + newtChild = newChild; + if( null != newtChild && ( null != nativeWindow || validateNative(false /* completeReparent */) ) ) { + reparentWindow( true ); + } + return prevChild; + } + + private void reparentWindow(final boolean add) { + if( null == newtChild ) { + return; // nop + } + if(DEBUG) { + System.err.println("NewtCanvasJFX.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + + newtChild.setFocusAction(null); // no AWT focus traversal .. + if(add) { + assert null != nativeWindow && null != parentWindow; + updatePosSizeCheck(); + final int x = clientArea.getX(); + final int y = clientArea.getY(); + final int w = clientArea.getWidth(); + final int h = clientArea.getHeight(); + + if(USE_JFX_EDT) { + // setup JFX EDT and start it + final Display newtDisplay = newtChild.getScreen().getDisplay(); + final EDTUtil oldEDTUtil = newtDisplay.getEDTUtil(); + if( ! ( oldEDTUtil instanceof JFXEDTUtil ) ) { + final EDTUtil newEDTUtil = new JFXEDTUtil(newtDisplay); + if(DEBUG) { + System.err.println("NewtCanvasJFX.reparentWindow.1: replacing EDTUtil "+oldEDTUtil+" -> "+newEDTUtil); + } + newEDTUtil.start(); + newtDisplay.setEDTUtil( newEDTUtil ); + } + } + + newtChild.setSize(w, h); + newtChild.reparentWindow(nativeWindow, x, y, Window.REPARENT_HINT_BECOMES_VISIBLE); + newtChild.setPosition(x, y); + newtChild.setVisible(true); + configureNewtChild(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + + // force this JFX Canvas to be focus-able, + // since it is completely covered by the newtChild (z-order). + // FIXME ??? super.requestFocus(); + } else { + configureNewtChild(false); + newtChild.setVisible(false); + newtChild.reparentWindow(null, -1, -1, 0 /* hints */); + } + if(DEBUG) { + System.err.println("NewtCanvasJFX.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + } + + private void configureNewtChild(final boolean attach) { + newtChildReady = attach; + if( null != newtChild ) { + newtChild.setKeyboardFocusHandler(null); + if(attach) { + newtChildClosingMode = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); + } else { + newtChild.setFocusAction(null); + newtChild.setDefaultCloseOperation(newtChildClosingMode); + } + } + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + /** + * {@inheritDoc} + * @return this JFX Canvas {@link NativeWindow} representation, may be null in case it has not been realized + */ + @Override + public NativeWindow getNativeWindow() { return nativeWindow; } + + /** + * {@inheritDoc} + * @return this JFX Canvas {@link NativeSurface} representation, may be null in case it has not been realized + */ + @Override + public NativeSurface getNativeSurface() { return nativeWindow; } + + @Override + public WindowClosingMode getDefaultCloseOperation() { + return closingMode; + } + + @Override + public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) { + final WindowClosingMode old = closingMode; + closingMode = op; + return old; + } + + + boolean isParent() { + return null!=newtChild ; + } + + boolean isFullscreen() { + return null != newtChild && newtChild.isFullscreen(); + } + + private final void requestFocusNEWTChild() { + if( newtChildReady ) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + } + } + + @Override + public void requestFocus() { + NewtCanvasJFX.super.requestFocus(); + requestFocusNEWTChild(); + } + + private class JFXNativeWindow implements NativeWindow { + private final AbstractGraphicsConfiguration config; + private final long nativeWindowHandle; + private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX + + public JFXNativeWindow(final AbstractGraphicsConfiguration config, final long nativeWindowHandle) { + this.config = config; + this.nativeWindowHandle = nativeWindowHandle; + this.insets = new Insets(0, 0, 0, 0); + } + + @Override + public int lockSurface() throws NativeWindowException, RuntimeException { + return NativeSurface.LOCK_SUCCESS; + } + + @Override + public void unlockSurface() { } + + @Override + public boolean isSurfaceLockedByOtherThread() { + return false; + } + + @Override + public Thread getSurfaceLockOwner() { + return null; + } + + @Override + public boolean surfaceSwap() { + return false; + } + + @Override + public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) { } + + @Override + public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + } + + @Override + public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) { } + + @Override + public long getSurfaceHandle() { + return 0; + } + + @Override + public int getWidth() { + return getSurfaceWidth(); // FIXME: Use 'scale' or an actual window-width + } + + @Override + public int getHeight() { + return getSurfaceHeight(); // FIXME: Use 'scale' or an actual window-width + } + + @Override + public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) { + return pixelUnitsAndResult; // FIXME HiDPI: use 'pixelScale' + } + + @Override + public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) { + return windowUnitsAndResult; // FIXME HiDPI: use 'pixelScale' + } + + @Override + public int getSurfaceWidth() { + return clientArea.getWidth(); + } + + @Override + public int getSurfaceHeight() { + return clientArea.getHeight(); + } + + @Override + public final NativeSurface getNativeSurface() { return this; } + + @Override + public AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config; + } + + @Override + public long getDisplayHandle() { + return config.getScreen().getDevice().getHandle(); + } + + @Override + public int getScreenIndex() { + return config.getScreen().getIndex(); + } + + @Override + public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) { } + + @Override + public void destroy() { } + + @Override + public NativeWindow getParent() { + return null; + } + + @Override + public long getWindowHandle() { + return nativeWindowHandle; + } + + @Override + public InsetsImmutable getInsets() { + return insets; + } + + @Override + public int getX() { + return NewtCanvasJFX.this.clientArea.getX(); + } + + @Override + public int getY() { + return NewtCanvasJFX.this.clientArea.getY(); + } + + @Override + public Point getLocationOnScreen(final Point point) { + final Point los = NativeWindowFactory.getLocationOnScreen(this); // client window location on screen + if(null!=point) { + return point.translate(los); + } else { + return los; + } + } + + @Override + public boolean hasFocus() { + return isFocused(); + } + }; + + static String newtWinHandleToHexString(final Window w) { + return null != w ? toHexString(w.getWindowHandle()) : "nil"; + } + static String toHexString(final long l) { + return "0x"+Long.toHexString(l); + } +} + diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index f15c87beb..569780311 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -246,6 +246,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override + public final int getSupportedStateMask() { + return window.getSupportedStateMask(); + } + + @Override + public final String getSupportedStateMaskString() { + return window.getSupportedStateMaskString(); + } + + @Override public CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) { return window.setCapabilitiesChooser(chooser); } diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTDemoListener.java b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java index 68a983a27..568b5d0bb 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTDemoListener.java +++ b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java @@ -25,28 +25,62 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.util; +package com.jogamp.newt.opengl.util; import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; import com.jogamp.common.util.IOUtil; import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.nativewindow.ScalableSurface; +import com.jogamp.newt.Window; import com.jogamp.newt.Display; import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.FPSCounter; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLDrawable; +import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.util.Gamma; import com.jogamp.opengl.util.PNGPixelRect; import jogamp.newt.driver.PNGIcon; -public class NEWTDemoListener extends MouseAdapter implements KeyListener { +/** + * NEWT {@link GLWindow} Demo functionality + * <ul> + * <li>SPACE: Toggle animator {@link GLAnimatorControl#pause() pause}/{@link GLAnimatorControl#resume() resume}</li> + * <li>A: Toggle window {@link Window#setAlwaysOnTop(boolean) always on top}</li> + * <li>B: Toggle window {@link Window#setAlwaysOnBottom(boolean) always on bottom}</li> + * <li>C: Toggle different {@link Window#setPointerIcon(PointerIcon) pointer icons}</li> + * <li>D: Toggle window {@link Window#setUndecorated(boolean) decoration on/off}</li> + * <li>F: Toggle window {@link Window#setFullscreen(boolean) fullscreen on/off}</li> + * <li>Three-Finger Double-Tap: Toggle window {@link Window#setFullscreen(boolean) fullscreen on/off}</li> + * <li>G: Increase {@link Gamma#setDisplayGamma(GLDrawable, float, float, float) gamma} by 0.1, +SHIFT decrease gamma by 0.1</li> + * <li>I: Toggle {@link Window#setPointerVisible(boolean) pointer visbility}</li> + * <li>J: Toggle {@link Window#confinePointer(boolean) pointer jail (confine to window)}</li> + * <li>M: Toggle {@link Window#setMaximized(boolean, boolean) window maximized}: Y, +CTRL off, +SHIFT toggle X+Y, +ALT X</li> + * <li>P: Set window {@link Window#setPosition(int, int) position to 100/100}</li> + * <li>Q: Quit</li> + * <li>R: Toggle window {@link Window#setResizable(boolean) resizable}</li> + * <li>S: Toggle window {@link Window#setSticky(boolean) sticky}</li> + * <li>V: Toggle window {@link Window#setVisible(boolean) visibility} for 5s</li> + * <li>V: +CTRL: Rotate {@link GL#setSwapInterval(int) swap interval} -1, 0, 1</li> + * <li>W: {@link Window#warpPointer(int, int) Warp pointer} to center of window</li> + * <li>X: Toggle {@link ScalableSurface#setSurfaceScale(float[]) [{@link ScalableSurface#IDENTITY_PIXELSCALE}, {@link ScalableSurface#AUTOMAX_PIXELSCALE}]</li> + * </ul> + */ +public class NEWTDemoListener extends WindowAdapter implements KeyListener, MouseListener { protected final GLWindow glWindow; - protected final QuitAdapter quitAdapter; final PointerIcon[] pointerIcons; int pointerIconIdx = 0; float gamma = 1f; @@ -54,20 +88,16 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { float contrast = 1f; boolean confinedFixedCenter = false; - public NEWTDemoListener(final GLWindow glWin, final QuitAdapter quitAdapter, final PointerIcon[] pointerIcons) { + public NEWTDemoListener(final GLWindow glWin, final PointerIcon[] pointerIcons) { this.glWindow = glWin; - this.quitAdapter = quitAdapter; if( null != pointerIcons ) { this.pointerIcons = pointerIcons; } else { - this.pointerIcons = createPointerIcons(glWindow); + this.pointerIcons = createPointerIcons(glWindow.getScreen().getDisplay()); } } - public NEWTDemoListener(final GLWindow glWin, final PointerIcon[] pointerIcons) { - this(glWin, null, pointerIcons); - } public NEWTDemoListener(final GLWindow glWin) { - this(glWin, null, null); + this(glWin, null); } protected void printlnState(final String prelude) { @@ -76,17 +106,6 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { protected void printlnState(final String prelude, final String post) { System.err.println(prelude+": "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()+", state "+glWindow.getStateMaskString()+", "+post); } - protected void quitAdapterOff() { - if( null != quitAdapter ) { - quitAdapter.enable(false); - } - } - protected void quitAdapterOn() { - if( null != quitAdapter ) { - quitAdapter.clear(); - quitAdapter.enable(true); - } - } @Override public void keyPressed(final KeyEvent e) { @@ -97,44 +116,38 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { switch(keySymbol) { case KeyEvent.VK_SPACE: e.setConsumed(true); - new Thread() { + glWindow.invokeOnCurrentThread(new Runnable() { public void run() { if(glWindow.getAnimator().isPaused()) { glWindow.getAnimator().resume(); } else { glWindow.getAnimator().pause(); } - } - }.run(); + } } ); break; case KeyEvent.VK_A: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set alwaysontop pre]"); glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop()); printlnState("[set alwaysontop post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_B: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set alwaysonbottom pre]"); glWindow.setAlwaysOnBottom(!glWindow.isAlwaysOnBottom()); printlnState("[set alwaysonbottom post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_C: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { if( null != pointerIcons ) { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set pointer-icon pre]"); final PointerIcon currentPI = glWindow.getPointerIcon(); final PointerIcon newPI; @@ -146,28 +159,23 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { } glWindow.setPointerIcon( newPI ); printlnState("[set pointer-icon post]", currentPI+" -> "+glWindow.getPointerIcon()); - glWindow.setExclusiveContextThread(t); } - } }.start(); + } } ); break; case KeyEvent.VK_D: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); - // while( null != glWindow.getExclusiveContextThread() ) ; printlnState("[set undecorated pre]"); glWindow.setUndecorated(!glWindow.isUndecorated()); printlnState("[set undecorated post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_F: e.setConsumed(true); quitAdapterOff(); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set fullscreen pre]"); if( glWindow.isFullscreen() ) { glWindow.setFullscreen( false ); @@ -179,37 +187,33 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { } } printlnState("[set fullscreen post]"); - glWindow.setExclusiveContextThread(t); quitAdapterOn(); - } }.start(); + } } ); break; case KeyEvent.VK_G: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f ); System.err.println("[set gamma]: "+gamma+" -> "+newGamma); if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) { gamma = newGamma; } - } }.start(); + } } ); break; case KeyEvent.VK_I: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set pointer-visible pre]"); glWindow.setPointerVisible(!glWindow.isPointerVisible()); printlnState("[set pointer-visible post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_J: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set pointer-confined pre]", "warp-center: "+e.isShiftDown()); final boolean confine = !glWindow.isPointerConfined(); glWindow.confinePointer(confine); @@ -219,12 +223,11 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { } else if( !confine ) { setConfinedFixedCenter(false); } - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_M: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { // none: max-v // alt: max-h @@ -248,82 +251,102 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { vert = glWindow.isMaximizedVert(); horz = glWindow.isMaximizedHorz(); } - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set maximize pre]", "max[vert "+vert+", horz "+horz+"]"); glWindow.setMaximized(horz, vert); printlnState("[set maximize post]", "max[vert "+vert+", horz "+horz+"]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_P: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set position pre]"); glWindow.setPosition(100, 100); printlnState("[set position post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); + break; + case KeyEvent.VK_Q: + if( quitAdapterEnabled && 0 == e.getModifiers() ) { + System.err.println("QUIT Key "+Thread.currentThread()); + quitAdapterShouldQuit = true; + } break; case KeyEvent.VK_R: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set resizable pre]"); glWindow.setResizable(!glWindow.isResizable()); printlnState("[set resizable post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_S: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set sticky pre]"); glWindow.setSticky(!glWindow.isSticky()); printlnState("[set sticky post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_V: e.setConsumed(true); - new Thread() { - public void run() { - final boolean wasVisible = glWindow.isVisible(); - { - final Thread t = glWindow.setExclusiveContextThread(null); - printlnState("[set visible pre]"); - glWindow.setVisible(!wasVisible); - printlnState("[set visible post]"); - glWindow.setExclusiveContextThread(t); - } - if( wasVisible && !e.isControlDown() ) { - try { - Thread.sleep(5000); - } catch (final InterruptedException e) { - e.printStackTrace(); + if( e.isControlDown() ) { + glWindow.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = -1; break; + case -1: i = 1; break; + case 1: i = 0; break; + default: i = 1; break; } - final Thread t = glWindow.setExclusiveContextThread(null); - printlnState("[reset visible pre]"); - glWindow.setVisible(true); - printlnState("[reset visible post]"); - glWindow.setExclusiveContextThread(t); + gl.setSwapInterval(i); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + if(drawable instanceof FPSCounter) { + ((FPSCounter)drawable).resetFPSCounter(); + } + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); + return true; } - } }.start(); + }); + } else { + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + final boolean wasVisible = glWindow.isVisible(); + { + printlnState("[set visible pre]"); + glWindow.setVisible(!wasVisible); + printlnState("[set visible post]"); + } + if( wasVisible && !e.isShiftDown() ) { + try { + java.lang.Thread.sleep(5000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + printlnState("[reset visible pre]"); + glWindow.setVisible(true); + printlnState("[reset visible post]"); + } + } } ); + } break; case KeyEvent.VK_W: e.setConsumed(true); - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); printlnState("[set pointer-pos pre]"); glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2); printlnState("[set pointer-pos post]"); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); break; case KeyEvent.VK_X: e.setConsumed(true); @@ -365,7 +388,7 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { } @Override public void mouseClicked(final MouseEvent e) { - if(e.getClickCount() == 2 && e.getPointerCount() == 1) { + if(e.getClickCount() == 2 && e.getPointerCount() == 3) { glWindow.setFullscreen(!glWindow.isFullscreen()); System.err.println("setFullscreen: "+glWindow.isFullscreen()); } @@ -377,6 +400,43 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { glWindow.warpPointer(x, y); } } + @Override + public void mouseEntered(final MouseEvent e) {} + @Override + public void mouseExited(final MouseEvent e) {} + @Override + public void mousePressed(final MouseEvent e) {} + @Override + public void mouseReleased(final MouseEvent e) {} + @Override + public void mouseWheelMoved(final MouseEvent e) {} + + ///////////////////////////////////////////////////////////// + + private boolean quitAdapterShouldQuit = false; + private boolean quitAdapterEnabled = false; + private boolean quitAdapterEnabled2 = true; + + protected void quitAdapterOff() { + quitAdapterEnabled2 = false; + } + protected void quitAdapterOn() { + clearQuitAdapter(); + quitAdapterEnabled2 = true; + } + public void quitAdapterEnable(final boolean v) { quitAdapterEnabled = v; } + public void clearQuitAdapter() { quitAdapterShouldQuit = false; } + public boolean shouldQuit() { return quitAdapterShouldQuit; } + public void doQuit() { quitAdapterShouldQuit=true; } + + public void windowDestroyNotify(final WindowEvent e) { + if( quitAdapterEnabled && quitAdapterEnabled2 ) { + System.err.println("QUIT Window "+Thread.currentThread()); + quitAdapterShouldQuit = true; + } + } + + ///////////////////////////////////////////////////////////// public void setTitle() { setTitle(glWindow); @@ -389,80 +449,82 @@ public class NEWTDemoListener extends MouseAdapter implements KeyListener { final float[] sDPI = win.getPixelsPerMM(new float[2]); sDPI[0] *= 25.4f; sDPI[1] *= 25.4f; - win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); + final float[] minSurfacePixelScale = win.getMinimumSurfaceScale(new float[2]); + final float[] maxSurfacePixelScale = win.getMaximumSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale = win.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale = win.getCurrentSurfaceScale(new float[2]); + win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]+ + ", scale[min "+minSurfacePixelScale[0]+"x"+minSurfacePixelScale[1]+", max "+ + maxSurfacePixelScale[0]+"x"+maxSurfacePixelScale[1]+", req "+ + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" -> has "+ + hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+"]"); } - public static PointerIcon[] createPointerIcons(final GLWindow glWindow) { - final PointerIcon[] pointerIcons = { null, null, null, null, null }; + public static PointerIcon[] createPointerIcons(final Display disp) { + final List<PointerIcon> pointerIcons = new ArrayList<PointerIcon>(); { - final Display disp = glWindow.getScreen().getDisplay(); disp.createNative(); - int idx = 0; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/cross-grey-alpha-16x16.png" }, disp.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 8, 8); - System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + pointerIcons.add(_pointerIcon); + System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString()); } catch (final Exception e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } - pointerIcons[idx] = _pointerIcon; } - idx++; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/pointer-grey-alpha-16x24.png" }, disp.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); - System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + pointerIcons.add(_pointerIcon); + System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString()); } catch (final Exception e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } - pointerIcons[idx] = _pointerIcon; } - idx++; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-red-alpha-64x64.png" }, disp.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); - System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + pointerIcons.add(_pointerIcon); + System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString()); } catch (final Exception e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } - pointerIcons[idx] = _pointerIcon; } - idx++; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-blue-alpha-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-blue-alpha-64x64.png" }, disp.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); - System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + pointerIcons.add(_pointerIcon); + System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString()); } catch (final Exception e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } - pointerIcons[idx] = _pointerIcon; } - idx++; if( PNGIcon.isAvailable() ) { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "jogamp-pointer-64x64.png" }, disp.getClass().getClassLoader(), null); try { final URLConnection urlConn = res.resolve(0); - final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); - System.err.printf("Create PointerIcon #%02d: %s%n", idx, image.toString()); - _pointerIcon = disp.createPointerIcon(image, 32, 0); - System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); + if( null != urlConn ) { + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size()+1, image.toString()); + _pointerIcon = disp.createPointerIcon(image, 32, 0); + pointerIcons.add(_pointerIcon); + System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString()); + } } catch (final Exception e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } - pointerIcons[idx] = _pointerIcon; } - idx++; } - return pointerIcons; + return pointerIcons.toArray(new PointerIcon[pointerIcons.size()]); } - }
\ No newline at end of file diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index 186ffb162..bd5c43d6c 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -38,6 +38,7 @@ import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.NativeWindow; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.NativeWindowHolder; import com.jogamp.nativewindow.SurfaceUpdatedListener; import com.jogamp.nativewindow.WindowClosingProtocol; import com.jogamp.nativewindow.util.Insets; @@ -52,6 +53,7 @@ import jogamp.newt.Debug; import jogamp.newt.swt.SWTEDTUtil; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; @@ -70,13 +72,14 @@ import com.jogamp.newt.util.EDTUtil; * Implementation allows use of custom {@link GLCapabilities}. * </p> */ -public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { +public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("Window"); private final AbstractGraphicsScreen screen; - private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE; - private volatile Rectangle clientArea; + private WindowClosingMode newtChildClosingMode = WindowClosingMode.DISPOSE_ON_CLOSE; + private final WindowClosingMode closingMode = WindowClosingMode.DISPOSE_ON_CLOSE; + private volatile Rectangle clientAreaPixels, clientAreaWindow; private volatile SWTNativeWindow nativeWindow; private volatile Window newtChild = null; @@ -126,7 +129,8 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { SWTAccessor.setRealized(this, true); - clientArea = getClientArea(); + clientAreaPixels = SWTAccessor.getClientAreaInPixels(this); + clientAreaWindow = getClientArea(); final AbstractGraphicsDevice device = SWTAccessor.getDevice(this); screen = SWTAccessor.getScreen(device, -1 /* default */); @@ -136,6 +140,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { setNEWTChild(child); } + // 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) { @@ -147,14 +155,14 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { if( null != nativeWindow || validateNative() ) { if( newtChildReady ) { if( postSetSize ) { - newtChild.setSize(clientArea.width, clientArea.height); + newtChild.setSize(clientAreaPixels.width, clientAreaPixels.height); postSetSize = false; } if( postSetPos ) { - newtChild.setPosition(clientArea.x, clientArea.y); + newtChild.setPosition(clientAreaPixels.x, clientAreaPixels.y); postSetPos = false; } - newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height); + newtChild.windowRepaint(0, 0, clientAreaPixels.width, clientAreaPixels.height); } } break; @@ -168,7 +176,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { if( DEBUG ) { System.err.println("NewtCanvasSWT.Event.RESIZE, "+event); } - updateSizeCheck(); + updatePosSizeCheck(false); break; case SWT.Dispose: if( DEBUG ) { @@ -197,14 +205,14 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { } if( SWTAccessor.isOSX ) { // Force newtChild to update its size and position (OSX only) - updatePosSizeCheck(x, y, width, height, true /* updatePos */); + updatePosSizeCheck(true /* updatePos */); } } /** assumes nativeWindow == null ! */ protected final boolean validateNative() { - updateSizeCheck(); - final Rectangle nClientArea = clientArea; + updatePosSizeCheck(false); + final Rectangle nClientArea = clientAreaPixels; if(0 >= nClientArea.width || 0 >= nClientArea.height) { return false; } @@ -242,46 +250,34 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { return null != nativeWindow; } - protected final void updateSizeCheck() { - final Rectangle nClientArea = getClientArea(); - if( null != nClientArea ) { - updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, false /* updatePos */); - } - } - protected final void updatePosSizeCheck() { - final Rectangle nClientArea = getClientArea(); - if( null != nClientArea ) { - updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, true /* updatePos */); - } - } - protected final void updatePosSizeCheck(final int newX, final int newY, final int newWidth, final int newHeight, final boolean updatePos) { + protected final void updatePosSizeCheck(final boolean updatePos) { final boolean sizeChanged, posChanged; - final Rectangle nClientArea; + Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this); { - final Rectangle oClientArea = clientArea; - sizeChanged = newWidth != oClientArea.width || newHeight != oClientArea.height; - posChanged = newX != oClientArea.x || newY != oClientArea.y; + final Rectangle oClientAreaPixels = clientAreaPixels; + sizeChanged = nClientAreaPixels.width != oClientAreaPixels.width || nClientAreaPixels.height != oClientAreaPixels.height; + posChanged = nClientAreaPixels.x != oClientAreaPixels.x || nClientAreaPixels.y != oClientAreaPixels.y; if( sizeChanged || posChanged ) { - nClientArea = new Rectangle(updatePos ? newX : oClientArea.x, updatePos ? newY : oClientArea.y, newWidth, newHeight); - clientArea = nClientArea; + clientAreaPixels = nClientAreaPixels; + clientAreaWindow = getClientArea(); } else { - nClientArea = clientArea; + nClientAreaPixels = clientAreaPixels; } } if(DEBUG) { final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0; - System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh)); + System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+" - surfaceHandle 0x"+Long.toHexString(nsh)); } if( sizeChanged ) { if( newtChildReady ) { - newtChild.setSize(nClientArea.width, nClientArea.height); + newtChild.setSize(nClientAreaPixels.width, nClientAreaPixels.height); } else { postSetSize = true; } } if( updatePos && posChanged ) { if( newtChildReady ) { - newtChild.setPosition(nClientArea.x, nClientArea.y); + newtChild.setPosition(nClientAreaPixels.x, nClientAreaPixels.y); } else { postSetPos = true; } @@ -330,17 +326,28 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { return new Point(parentLoc[0].x, parentLoc[0].y); } - /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */ + /** + * {@inheritDoc} + * @return this SWT Canvas {@link NativeWindow} representation, may be null in case it has not been realized + */ + @Override public NativeWindow getNativeWindow() { return nativeWindow; } + /** + * {@inheritDoc} + * @return this SWT Canvas {@link NativeSurface} representation, may be null in case it has not been realized + */ + @Override + public NativeSurface getNativeSurface() { return nativeWindow; } + @Override public WindowClosingMode getDefaultCloseOperation() { - return newtChildCloseOp; // TODO: implement ?! + return closingMode; } @Override public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) { - return newtChildCloseOp = op; // TODO: implement ?! + return closingMode; // TODO: implement! } @@ -401,10 +408,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { if( null != newtChild ) { newtChild.setKeyboardFocusHandler(null); if(attach) { - newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); + newtChildClosingMode = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); } else { newtChild.setFocusAction(null); - newtChild.setDefaultCloseOperation(newtChildCloseOp); + newtChild.setDefaultCloseOperation(newtChildClosingMode); } } } @@ -419,9 +426,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { newtChild.setFocusAction(null); // no AWT focus traversal .. if(add) { - updateSizeCheck(); - final int w = clientArea.width; - final int h = clientArea.height; + updatePosSizeCheck(false); + final int w = clientAreaPixels.width; + final int h = clientAreaPixels.height; // set SWT EDT and start it { @@ -539,12 +546,12 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { @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/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index 8bf4bc20f..05df63794 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -45,6 +45,7 @@ import java.util.List; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; @@ -171,15 +172,14 @@ public class MainThread { return res; } - static class UserApp extends Thread { + static class UserApp extends InterruptSource.Thread { private final String mainClassNameShort; private final String mainClassName; private final String[] mainClassArgs; private final Method mainClassMain; - private List<Thread> nonDaemonThreadsAtStart; + private List<java.lang.Thread> nonDaemonThreadsAtStart; public UserApp(final String mainClassName, final String[] mainClassArgs) throws SecurityException, NoSuchMethodException, ClassNotFoundException { - super(); this.mainClassName=mainClassName; this.mainClassArgs=mainClassArgs; @@ -200,10 +200,10 @@ public class MainThread { @Override public void run() { nonDaemonThreadsAtStart = getNonDaemonThreads(); - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart); // start user app .. try { - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" invoke "+mainClassName); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" invoke "+mainClassName); mainClassMain.invoke(null, new Object[] { mainClassArgs } ); } catch (final InvocationTargetException ite) { ite.getTargetException().printStackTrace(); @@ -219,30 +219,30 @@ public class MainThread { while( 0 < ( ndtr = getNonDaemonThreadCount(nonDaemonThreadsAtStart) ) ) { if(DEBUG) System.err.println("MainAction.run(): post user app, non daemon threads alive: "+ndtr); try { - Thread.sleep(1000); + java.lang.Thread.sleep(1000); } catch (final InterruptedException e) { e.printStackTrace(); } } - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin: "+ndtr); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" user app fin: "+ndtr); } if ( useMainThread ) { if(isMacOSX) { try { if(DEBUG) { - System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0"); + System.err.println("MainAction.main(): "+java.lang.Thread.currentThread()+" MainAction fin - stopNSApp.0"); } ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication", null, null, MainThread.class.getClassLoader()); if(DEBUG) { - System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X"); + System.err.println("MainAction.main(): "+java.lang.Thread.currentThread()+" MainAction fin - stopNSApp.X"); } } catch (final Exception e) { e.printStackTrace(); } } else { - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainAction fin - System.exit(0)"); + if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" MainAction fin - System.exit(0)"); System.exit(0); } } diff --git a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java index cc159e6ed..c30576ff4 100644 --- a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java +++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java @@ -42,10 +42,8 @@ import com.jogamp.opengl.GLPipelineFactory; import jogamp.newt.Debug; -import com.jogamp.common.util.IOUtil; -import com.jogamp.newt.Display; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Window; -import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.MouseListener; @@ -53,13 +51,18 @@ import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; -/** Shows how to deploy an applet using JOGL. This demo must be - referenced from a web page via an <applet> tag. */ - +/** + * Shows how to deploy an applet using JOGL. + * This demo must be referenced from a web page via an <applet> tag. + * <p> + * The demo code uses {@link NEWTDemoListener} functionality. + * </p> + */ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { public static final boolean DEBUG = Debug.debug("Applet"); @@ -69,7 +72,6 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { boolean glClosable; boolean glDebug; boolean glTrace; - PointerIcon pointerIconTest = null; GLEventListener glEventListener = null; GLWindow glWindow = null; @@ -193,8 +195,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { glWindow.addKeyListener((KeyListener)glEventListener); } + glWindow.addWindowListener(reparentHomeListener); + if(!noDefaultKeyListener) { glWindow.addKeyListener(this); + final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow); + glWindow.addKeyListener(newtDemoListener); + glWindow.addMouseListener(newtDemoListener); } glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err); @@ -220,7 +227,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { null == glWindow.getParent() && null != parentWin && 0 != parentWin.getWindowHandle() ) { // we may be called directly by the native EDT - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { @Override public void run() { if( glWindow.isNativeValid() && null != parentWin && 0 != parentWin.getWindowHandle() ) { @@ -235,24 +242,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { if(isValid) { glWindow.setVisible(true); glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - if( null == pointerIconTest ) { - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } ); - final Display disp = glWindow.getScreen().getDisplay(); - try { - pointerIconTest = disp.createPointerIcon(res, 8, 8); - } catch (final Exception e) { - e.printStackTrace(); - } - } glAnimator.start(); parentWin = glWindow.getParent(); - glWindow.addWindowListener(reparentHomeListener); } } public void stop() { if(null!=glAnimator) { - glWindow.removeWindowListener(reparentHomeListener); glAnimator.stop(); glWindow.setVisible(false); } @@ -291,10 +287,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { _gl = _gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, _gl, new Object[] { System.err } ) ); } catch (final Exception e) {e.printStackTrace();} } - - if(glSwapInterval>=0) { - _gl.setSwapInterval(glSwapInterval); - } + _gl.setSwapInterval(glSwapInterval); } @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { @@ -315,27 +308,14 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { if( !e.isPrintableKey() || e.isAutoRepeat() ) { return; } - if(e.getKeyChar()=='d') { - new Thread() { - public void run() { - glWindow.setUndecorated(!glWindow.isUndecorated()); - } }.start(); - } if(e.getKeyChar()=='f') { - new Thread() { - public void run() { - glWindow.setFullscreen(!glWindow.isFullscreen()); - } }.start(); - } else if(e.getKeyChar()=='a') { - new Thread() { - public void run() { - glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop()); - } }.start(); - } else if(e.getKeyChar()=='r' && null!=parentWin) { - new Thread() { + + if(e.getKeyChar()=='r' && 0==e.getModifiers() && null!=parentWin) { + e.setConsumed(true); + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { if(null == glWindow.getParent()) { - glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */); - } else { + glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */); + } else { final InsetsImmutable insets = glWindow.getInsets(); final int x, y; if ( 0 >= insets.getTopHeight() ) { @@ -349,43 +329,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { glWindow.reparentWindow(null, x, y, 0 /* hints */); glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE ); } - } }.start(); - } else if(e.getKeyChar()=='c') { - new Thread() { - public void run() { - System.err.println("[set pointer-icon pre]"); - final PointerIcon currentPI = glWindow.getPointerIcon(); - glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest); - System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); - } }.start(); - } else if(e.getKeyChar()=='i') { - new Thread() { - public void run() { - System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible()); - glWindow.setPointerVisible(!glWindow.isPointerVisible()); - System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible()); - } }.start(); - } else if(e.getKeyChar()=='j') { - new Thread() { - public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); - System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined()); - glWindow.confinePointer(!glWindow.isPointerConfined()); - System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined()); - glWindow.setExclusiveContextThread(t); - } }.start(); - } else if(e.getKeyChar()=='w') { - new Thread() { - public void run() { - System.err.println("[set mouse pos pre]"); - glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2); - System.err.println("[set mouse pos post]"); - } }.start(); + } } ); } } @Override public void keyReleased(final KeyEvent e) { } + } diff --git a/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java b/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java index 9b9b7d532..fce43d71f 100644 --- a/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java +++ b/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java @@ -243,7 +243,7 @@ public class JOGLNewtApplet3Run implements Applet3 { } this.ctx = ctx; String glEventListenerClazzName=null; - int glSwapInterval=0; + int glSwapInterval=1; boolean glDebug=false; boolean glTrace=false; boolean glNoDefaultKeyListener = false; diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index bf46ce609..ff713410b 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -44,6 +44,8 @@ import com.jogamp.nativewindow.NativeWindowException; import jogamp.common.util.locks.LockDebugUtil; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.locks.Lock; import com.jogamp.newt.util.EDTUtil; @@ -68,7 +70,7 @@ public class DefaultEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.edt = new NEDT(threadGroup, name); + this.edt = new NEDT(threadGroup, this.name); this.edt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -169,8 +171,7 @@ public class DefaultEDTUtil implements EDTUtil { }; private final boolean invokeImpl(boolean wait, Runnable task, final boolean stop, final boolean provokeError) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -187,6 +188,7 @@ public class DefaultEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if( stop ) { edt.shouldStop = true; if( edt.tasks.size()>0 ) { @@ -230,18 +232,19 @@ public class DefaultEDTUtil implements EDTUtil { } } else { wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -268,13 +271,13 @@ public class DefaultEDTUtil implements EDTUtil { return false; } synchronized(_edt.tasks) { - while(_edt.isRunning && _edt.tasks.size()>0) { - try { + try { + while(_edt.isRunning && _edt.tasks.size()>0) { _edt.tasks.notifyAll(); _edt.tasks.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } @@ -284,12 +287,12 @@ public class DefaultEDTUtil implements EDTUtil { final public boolean waitUntilStopped() { synchronized(edtLock) { if(edt.isRunning && edt != Thread.currentThread() ) { - while( edt.isRunning ) { - try { + try { + while( edt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -298,13 +301,13 @@ public class DefaultEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; final ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -347,11 +350,11 @@ public class DefaultEDTUtil implements EDTUtil { RunnableTask task = null; synchronized(tasks) { // wait for tasks - if(!shouldStop && tasks.size()==0) { + if( !shouldStop && tasks.size()==0 ) { try { tasks.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } // execute one task, if available @@ -375,7 +378,7 @@ public class DefaultEDTUtil implements EDTUtil { } if(!task.hasWaiter() && null != task.getThrowable()) { // at least dump stack-trace in case nobody waits for result - System.err.println("DefaultEDT.run(): Caught exception occured on thread "+Thread.currentThread().getName()+": "+task.toString()); + System.err.println("DefaultEDT.run(): Caught exception occured on thread "+java.lang.Thread.currentThread().getName()+": "+task.toString()); task.getThrowable().printStackTrace(); } } diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index cc1f3d8e0..61a39c133 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -37,6 +37,7 @@ package jogamp.newt; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; @@ -117,6 +118,8 @@ public abstract class DisplayImpl extends Display { return null; } final PointerIconImpl[] res = { null }; + final Exception[] ex = { null }; + final String exStr = "Could not resolve "+pngResource.resourcePaths[0]; runOnEDTIfAvail(true, new Runnable() { public void run() { try { @@ -125,7 +128,7 @@ public abstract class DisplayImpl extends Display { } final URLConnection urlConn = pngResource.resolve(0); if( null == urlConn ) { - throw new IOException("Could not resolve "+pngResource.resourcePaths[0]); + throw new IOException(exStr); } final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), getNativePointerIconPixelFormat(), @@ -137,20 +140,32 @@ public abstract class DisplayImpl extends Display { if( DEBUG_POINTER_ICON ) { System.err.println("createPointerIconPNG.0: "+image+", handle: "+toHexString(handle)+", hot "+hotspot); } - if( 0 != handle ) { - res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle); - if( DEBUG_POINTER_ICON ) { - System.err.println("createPointerIconPNG.0: "+res[0]); - } + if( 0 == handle ) { + throw new IOException(exStr); + } + res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle); + if( DEBUG_POINTER_ICON ) { + System.err.println("createPointerIconPNG.0: "+res[0]); } } catch (final Exception e) { - e.printStackTrace(); + ex[0] = e; } } } ); - if( null != res[0] ) { - synchronized(pointerIconList) { - pointerIconList.add(res[0]); + if( null != ex[0] ) { + final Exception e = ex[0]; + if( e instanceof IllegalArgumentException) { + throw new IllegalArgumentException(e); } + if( e instanceof IllegalStateException) { + throw new IllegalStateException(e); + } + throw new IOException(e); + } + if( null == res[0] ) { + throw new IOException(exStr); + } + synchronized(pointerIconList) { + pointerIconList.add(res[0]); } return res[0]; } @@ -697,8 +712,9 @@ public abstract class DisplayImpl extends Display { } else { throw re; } + } finally { + eventTask.notifyCaller(); } - eventTask.notifyCaller(); } @Override @@ -725,7 +741,10 @@ public abstract class DisplayImpl extends Display { } if( null != _events ) { for (int i=0; i < _events.size(); i++) { - dispatchMessage(_events.get(i)); + final NEWTEventTask e = _events.get(i); + if( !e.isDispatched() ) { + dispatchMessage(e); + } } } } @@ -759,11 +778,12 @@ public abstract class DisplayImpl extends Display { haveEvents = true; eventsLock.notifyAll(); } - if( wait ) { + while( wait && !eTask.isDispatched() ) { try { lock.wait(); } catch (final InterruptedException ie) { - throw new RuntimeException(ie); + eTask.setDispatched(); // Cancels NEWTEvent .. + throw new InterruptedRuntimeException(ie); } if( null != eTask.getException() ) { throw eTask.getException(); diff --git a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java index 793fbf9b0..84e2167ee 100644 --- a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java +++ b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java @@ -53,7 +53,7 @@ public class NEWTJNILibLoader extends JNILibLoaderBase { public Boolean run() { Platform.initSingleton(); final String libName = "newt"; - if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) { + if( TempJarCache.isInitialized(true) && null == TempJarCache.findLibrary(libName) ) { JNILibLoaderBase.addNativeJarLibsJoglCfg(new Class<?>[] { jogamp.nativewindow.Debug.class, jogamp.newt.Debug.class }); } return Boolean.valueOf(loadLibrary(libName, false, NEWTJNILibLoader.class.getClassLoader())); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index 819435331..f4b8ecd42 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -42,7 +42,6 @@ import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.MutableSurface; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; import com.jogamp.newt.MonitorDevice; @@ -116,6 +115,10 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { return false; // nop } + @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask; + } @Override protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) { diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index dd1680b0f..5f03189ac 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -96,11 +96,12 @@ import com.jogamp.newt.event.WindowUpdateEvent; public abstract class WindowImpl implements Window, NEWTEventConsumer { public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE; + private static final boolean DEBUG_FREEZE_AT_VISIBILITY_FAILURE; static { Debug.initSingleton(); DEBUG_TEST_REPARENT_INCOMPATIBLE = PropertyAccess.isPropertyDefined("newt.test.Window.reparent.incompatible", true); - + DEBUG_FREEZE_AT_VISIBILITY_FAILURE = PropertyAccess.isPropertyDefined("newt.debug.Window.visibility.failure.freeze", true); ScreenImpl.initSingleton(); } @@ -148,7 +149,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse }; // - // Volatile: Multithread Mutable Access + // Volatile: Multithreaded Mutable Access // private volatile long windowHandle = 0; // lifecycle critical private volatile int pixWidth = 128, pixHeight = 128; // client-area size w/o insets in pixel units, default: may be overwritten by user @@ -181,6 +182,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private LifecycleHook lifecycleHook = null; // + // Quirks + // + + /** + * Bug 1249 and Bug 1250: Visibility issues on X11 + * <ul> + * <li>setVisible(false) IconicState not listening to _NET_WM_STATE_HIDDEN</li> + * <li>setVisible(true) not restoring from _NET_WM_STATE_HIDDEN</li> + * </ul> + * <p> + * If {@code true} fall back to traditional visibility state, + * i.e. {@code fast=true}. + * </p> + */ + protected static final int QUIRK_BIT_VISIBILITY = 0; + /** Quirk mask */ + protected static final Bitfield quirks = Bitfield.Factory.synchronize(Bitfield.Factory.create(32)); + + // // State Mask // @@ -190,37 +210,46 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @see #getStateMask() * @since 2.3.2 */ - protected static final int STATE_BIT_COUNT_ALL_PUBLIC = 15; + protected static final int STATE_BIT_COUNT_ALL_PUBLIC = STATE_BIT_POINTERCONFINED + 1; /** Bitmask for {@link #STATE_BIT_COUNT_ALL_PUBLIC} */ protected static final int STATE_MASK_ALL_PUBLIC = ( 1 << STATE_BIT_COUNT_ALL_PUBLIC ) - 1; // - // Additional private state-mask bits and mask values + // Additional private reconfigure state-mask bits and mask values // - /** - * <p>Bit number {@value}.</p> - * <p>Defaults to {@code false}.</p> - * @see #getStateMask() - * @since 2.3.2 - */ - /* pp */ static final int STATE_BIT_FULLSCREEN_SPAN = 12; - /* pp */ static final int PSTATE_BIT_MINMAXSIZE_SET = 27; - /* pp */ static final int PSTATE_BIT_FOCUS_CHANGE_BROKEN = 28; - /* pp */ static final int PSTATE_BIT_FULLSCREEN_MAINMONITOR = 29; // true - /* pp */ static final int PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP = 30; // non fullscreen alwaysOnTop setting - /* pp */ static final int PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE = 31; // non fullscreen resizable setting + protected static final int STATE_BIT_FULLSCREEN_SPAN = STATE_BIT_COUNT_ALL_PUBLIC; + + protected static final int STATE_BIT_COUNT_ALL_RECONFIG = STATE_BIT_FULLSCREEN_SPAN + 1; + /** Bitmask for {@link #STATE_BIT_COUNT_ALL_RECONFIG} */ + protected static final int STATE_MASK_ALL_RECONFIG = ( 1 << STATE_BIT_COUNT_ALL_RECONFIG ) - 1; + + protected static final int STATE_MASK_ALL_PUBLIC_SUPPORTED = STATE_MASK_ALL_PUBLIC & ~STATE_MASK_AUTOPOSITION; + + // + // Additional private non-reconfigure state-mask bits and mask values + // + + /* pp */ static final int PSTATE_BIT_FOCUS_CHANGE_BROKEN = 30; + /* pp */ static final int PSTATE_BIT_FULLSCREEN_MAINMONITOR = 31; // true /** Bitmask for {@link #STATE_BIT_FULLSCREEN_SPAN}, {@value}. */ /* pp */ static final int STATE_MASK_FULLSCREEN_SPAN = 1 << STATE_BIT_FULLSCREEN_SPAN; + /* pp */ static final int PSTATE_MASK_FOCUS_CHANGE_BROKEN = 1 << PSTATE_BIT_FOCUS_CHANGE_BROKEN; /* pp */ static final int PSTATE_MASK_FULLSCREEN_MAINMONITOR = 1 << PSTATE_BIT_FULLSCREEN_MAINMONITOR; - /* pp */ static final int PSTATE_MASK_FULLSCREEN_NFS_ALWAYSONTOP = 1 << PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP; - /* pp */ static final int PSTATE_MASK_FULLSCREEN_NFS_RESIZABLE = 1 << PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE; + + /** + * Mask covering all preserved non-fullscreen (NFS) states + * while in fullscreen mode. + */ + private static final int STATE_MASK_FULLSCREEN_NFS = STATE_MASK_ALWAYSONTOP | + STATE_MASK_RESIZABLE | + STATE_MASK_MAXIMIZED_VERT | + STATE_MASK_MAXIMIZED_HORZ; /** * Reconfig mask for createNativeImpl(..) taking out from {@link #getStateMask()}: * <ul> - * <li>{@link #STATE_MASK_VISIBLE}</li> * <li>{@link #STATE_MASK_FULLSCREEN}</li> * <li>{@link #STATE_MASK_POINTERVISIBLE}</li> * <li>{@link #STATE_MASK_POINTERCONFINED}</li> @@ -228,13 +257,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * Above taken out states are achieved from caller createNative() 'manually'. * @since 2.3.2 */ - protected final int STATE_MASK_CREATENATIVE = STATE_MASK_UNDECORATED | - STATE_MASK_ALWAYSONTOP | - STATE_MASK_ALWAYSONBOTTOM | - STATE_MASK_STICKY | - STATE_MASK_RESIZABLE | - STATE_MASK_MAXIMIZED_VERT | - STATE_MASK_MAXIMIZED_HORZ; + protected static final int STATE_MASK_CREATENATIVE = STATE_MASK_ALL_PUBLIC & + ~( STATE_MASK_FULLSCREEN | + STATE_MASK_POINTERVISIBLE | + STATE_MASK_POINTERCONFINED + ); // // Additional private state-mask mask values for reconfiguration only // (keep in sync w/ src/newt/native/Window.h) @@ -251,17 +278,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected static final int CHANGE_MASK_MAXIMIZED_HORZ = 1 << 22; protected static final int CHANGE_MASK_FULLSCREEN = 1 << 21; + /** Regular state mask */ /* pp */ final Bitfield stateMask = Bitfield.Factory.synchronize(Bitfield.Factory.create(32)); + /** Non fullscreen state mask */ + private final Bitfield stateMaskNFS = Bitfield.Factory.synchronize(Bitfield.Factory.create(32)); + + /** Default is all but {@link #STATE_MASK_FULLSCREEN_SPAN}. */ + protected int supportedReconfigStateMask = 0; + /** See {@link #getSupportedStateMask()}, i.e. {@link #STATE_MASK_VISIBLE} | {@link #STATE_MASK_FOCUSED} | {@link STATE_MASK_FULLSCREEN}. */ + protected static final int minimumReconfigStateMask = STATE_MASK_VISIBLE | STATE_MASK_FOCUSED | STATE_MASK_FULLSCREEN; + /* pp */ final void resetStateMask() { stateMask.clearField(false); - stateMask.set(STATE_BIT_AUTOPOSITION); - stateMask.put(STATE_BIT_CHILDWIN, null != parentWindow); - stateMask.set(STATE_BIT_RESIZABLE); - stateMask.set(STATE_BIT_POINTERVISIBLE); - stateMask.set(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE); - stateMask.set(PSTATE_BIT_FULLSCREEN_MAINMONITOR); + stateMask.put32(0, 32, + STATE_MASK_AUTOPOSITION | + ( null != parentWindow ? STATE_MASK_CHILDWIN : 0 ) | + STATE_MASK_RESIZABLE | + STATE_MASK_POINTERVISIBLE | + PSTATE_MASK_FULLSCREEN_MAINMONITOR); + stateMaskNFS.clearField(false); normPosSizeStored[0] = false; normPosSizeStored[1] = false; + supportedReconfigStateMask = STATE_MASK_ALL_RECONFIG; } @Override @@ -277,16 +315,29 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public final int getStateMask() { return stateMask.get32(0, STATE_BIT_COUNT_ALL_PUBLIC); } + @Override public final String getStateMaskString() { return appendStateBits(new StringBuilder(), stateMask.get32(0, STATE_BIT_COUNT_ALL_PUBLIC), false).toString(); } + @Override + public final int getSupportedStateMask() { + return supportedReconfigStateMask & STATE_MASK_ALL_PUBLIC_SUPPORTED; + } + + @Override + public final String getSupportedStateMaskString() { + return appendStateBits(new StringBuilder(), getSupportedStateMask(), true).toString(); + } + protected static StringBuilder appendStateBits(final StringBuilder sb, final int mask, final boolean showChangeFlags) { sb.append("["); - if( showChangeFlags && 0 != ( CHANGE_MASK_VISIBILITY & mask) ) { - sb.append("*"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_VISIBILITY & mask) ) { + sb.append("*"); + } if( 0 != ( CHANGE_MASK_VISIBILITY_FAST & mask) ) { sb.append("*"); } @@ -296,9 +347,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append((0 != ( STATE_MASK_AUTOPOSITION & mask))?"autopos, ":""); - if( showChangeFlags && 0 != ( CHANGE_MASK_PARENTING & mask) ) { - sb.append("*"); - sb.append((0 != ( STATE_MASK_CHILDWIN & mask))?"child":"top"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_PARENTING & mask) ) { + sb.append("*"); + } + sb.append((0 != ( STATE_MASK_CHILDWIN & mask))?"child":"toplevel"); sb.append(", "); } else if( 0 != ( STATE_MASK_CHILDWIN & mask) ) { sb.append("child"); @@ -307,8 +360,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append((0 != ( STATE_MASK_FOCUSED & mask))?"focused, ":""); - if( showChangeFlags && 0 != ( CHANGE_MASK_DECORATION & mask) ) { - sb.append("*"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_DECORATION & mask) ) { + sb.append("*"); + } sb.append((0 != ( STATE_MASK_UNDECORATED & mask))?"undecor":"decor"); sb.append(", "); } else if( 0 != ( STATE_MASK_UNDECORATED & mask) ) { @@ -316,8 +371,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append(", "); } - if( showChangeFlags && 0 != ( CHANGE_MASK_ALWAYSONTOP & mask) ) { - sb.append("*"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_ALWAYSONTOP & mask) ) { + sb.append("*"); + } sb.append((0 != ( STATE_MASK_ALWAYSONTOP & mask))?"aontop":"!aontop"); sb.append(", "); } else if( 0 != ( STATE_MASK_ALWAYSONTOP & mask) ) { @@ -325,8 +382,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append(", "); } - if( showChangeFlags && 0 != ( CHANGE_MASK_ALWAYSONBOTTOM & mask) ) { - sb.append("*"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_ALWAYSONBOTTOM & mask) ) { + sb.append("*"); + } sb.append((0 != ( STATE_MASK_ALWAYSONBOTTOM & mask))?"aonbottom":"!aonbottom"); sb.append(", "); } else if( 0 != ( STATE_MASK_ALWAYSONBOTTOM & mask) ) { @@ -334,8 +393,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append(", "); } - if( showChangeFlags && 0 != ( CHANGE_MASK_STICKY & mask) ) { - sb.append("*"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_STICKY & mask) ) { + sb.append("*"); + } sb.append((0 != ( STATE_MASK_STICKY & mask))?"sticky":"unsticky"); sb.append(", "); } else if( 0 != ( STATE_MASK_STICKY & mask) ) { @@ -343,8 +404,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append(", "); } - if( showChangeFlags && 0 != ( CHANGE_MASK_RESIZABLE & mask) ) { - sb.append("*"); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_RESIZABLE & mask) ) { + sb.append("*"); + } sb.append((0 != ( STATE_MASK_RESIZABLE & mask))?"resizable":"unresizable"); sb.append(", "); } else if( 0 == ( STATE_MASK_RESIZABLE & mask) ) { @@ -352,7 +415,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append(", "); } - if( showChangeFlags && 0 != ( ( CHANGE_MASK_MAXIMIZED_HORZ | CHANGE_MASK_MAXIMIZED_VERT ) & mask) ) { + if( showChangeFlags ) { sb.append("max["); if( 0 != ( CHANGE_MASK_MAXIMIZED_HORZ & mask) ) { sb.append("*"); @@ -381,28 +444,47 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sb.append("], "); } - if( showChangeFlags && 0 != ( CHANGE_MASK_FULLSCREEN & mask) ) { - sb.append("*"); - sb.append((0 != ( STATE_MASK_FULLSCREEN & mask))?"fullscreen":"window"); - sb.append((0 != ( STATE_MASK_FULLSCREEN_SPAN & mask))?"[span]":"[]"); - sb.append(", "); + if( showChangeFlags ) { + if( 0 != ( CHANGE_MASK_FULLSCREEN & mask) ) { + sb.append("*"); + } + sb.append("fullscreen["); + sb.append(0 != ( STATE_MASK_FULLSCREEN & mask)); + sb.append((0 != ( STATE_MASK_FULLSCREEN_SPAN & mask))?", span":""); + sb.append("], "); } else if( 0 != ( STATE_MASK_FULLSCREEN & mask) ) { sb.append("fullscreen"); sb.append(", "); } - if( 0 == ( STATE_MASK_POINTERVISIBLE & mask) || - 0 != ( STATE_MASK_POINTERCONFINED & mask) ) - { - sb.append("pointer["); - if( 0 == ( STATE_MASK_POINTERVISIBLE & mask) ) { - sb.append("invisible"); + if( showChangeFlags ) { + sb.append("pointer["); + if( 0 == ( STATE_MASK_POINTERVISIBLE & mask) ) { + sb.append("invisible"); + } else { + sb.append("visible"); + } sb.append(", "); + if( 0 != ( STATE_MASK_POINTERCONFINED & mask) ) { + sb.append("confined"); + } else { + sb.append("free"); + } + sb.append("]"); + } else { + if( 0 == ( STATE_MASK_POINTERVISIBLE & mask) || + 0 != ( STATE_MASK_POINTERCONFINED & mask) ) + { + sb.append("pointer["); + if( 0 == ( STATE_MASK_POINTERVISIBLE & mask) ) { + sb.append("invisible"); + sb.append(", "); + } + if( 0 != ( STATE_MASK_POINTERCONFINED & mask) ) { + sb.append("confined"); + } + sb.append("]"); } - if( 0 != ( STATE_MASK_POINTERCONFINED & mask) ) { - sb.append("confined"); - } - sb.append("]"); } sb.append("]"); return sb; @@ -667,15 +749,37 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } final long t0 = System.currentTimeMillis(); createNativeImpl(); + supportedReconfigStateMask = getSupportedReconfigMaskImpl() & STATE_MASK_ALL_RECONFIG; + if( DEBUG_IMPLEMENTATION) { + final boolean minimumOK = minimumReconfigStateMask == ( minimumReconfigStateMask & supportedReconfigStateMask ); + System.err.println("Supported Reconfig (minimum-ok "+minimumOK+"): "+appendStateBits(new StringBuilder(), supportedReconfigStateMask, true).toString()); + } screen.addMonitorModeListener(monitorModeListenerImpl); setTitleImpl(title); setPointerIconIntern(pointerIcon); - setPointerVisibleIntern(stateMask.get(STATE_BIT_POINTERVISIBLE)); - confinePointerImpl(stateMask.get(STATE_BIT_POINTERCONFINED)); + if( !stateMask.get(STATE_BIT_POINTERVISIBLE) ) { + // non default action + if( isReconfigureMaskSupported(STATE_MASK_POINTERVISIBLE) ) { + setPointerVisibleIntern(stateMask.get(STATE_BIT_POINTERVISIBLE)); + } else { + stateMask.set(STATE_BIT_POINTERVISIBLE); + } + } + if( stateMask.get(STATE_BIT_POINTERCONFINED) ) { + // non default action + if( isReconfigureMaskSupported(STATE_MASK_POINTERCONFINED) ) { + confinePointerImpl(true); + } else { + stateMask.clear(STATE_BIT_POINTERCONFINED); + } + } setKeyboardVisible(keyboardVisible); final long remainingV = waitForVisible(true, false); if( 0 <= remainingV ) { - if(isFullscreen()) { + if( stateMask.get(STATE_BIT_FULLSCREEN) && !isReconfigureMaskSupported(STATE_MASK_FULLSCREEN) ) { + stateMask.clear(STATE_BIT_FULLSCREEN); + } + if( stateMask.get(STATE_BIT_FULLSCREEN) ) { synchronized(fullScreenAction) { stateMask.clear(STATE_BIT_FULLSCREEN); // trigger a state change fullScreenAction.init(true); @@ -844,6 +948,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected abstract void requestFocusImpl(boolean force); /** + * Returns the reconfigure state-mask supported by the implementation. + * <p> + * Default value is {@link #STATE_MASK_VISIBLE} | {@link #STATE_MASK_FOCUSED}, + * i.e. the <b>minimum requirement</b> for all implementations. + * </p> + * @see #getSupportedStateMask() + * @see #reconfigureWindowImpl(int, int, int, int, int) + */ + protected abstract int getSupportedReconfigMaskImpl(); + + /** * The native implementation should invoke the referenced java state callbacks * to notify this Java object of state changes. * @@ -858,27 +973,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param height client-area size in window units, or <=0 if unchanged * @param flags bitfield of change and status flags * + * @see #getSupportedReconfigMaskImpl() * @see #sizeChanged(int,int) * @see #positionChanged(boolean,int, int) */ protected abstract boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags); /** - * Tests whether a single reconfigure flag is supported by implementation. - * <p> - * Default is all but {@link #STATE_MASK_FULLSCREEN_SPAN} - * </p> + * Tests whether the given reconfigure state-mask is supported by implementation. */ - protected boolean isReconfigureMaskSupported(final int changeFlags) { - return 0 == ( changeFlags & STATE_MASK_FULLSCREEN_SPAN ); + protected final boolean isReconfigureMaskSupported(final int reconfigMask) { + return reconfigMask == ( reconfigMask & supportedReconfigStateMask ); } protected int getReconfigureMask(final int changeFlags, final boolean visible) { - final int smask = stateMask.get32(0, STATE_BIT_COUNT_ALL_PUBLIC); + final int smask = stateMask.get32(0, STATE_BIT_COUNT_ALL_RECONFIG); return changeFlags - | ( smask & ~STATE_MASK_VISIBLE ) + | ( smask & ~(STATE_MASK_VISIBLE | STATE_MASK_UNDECORATED | STATE_MASK_CHILDWIN) ) | ( visible ? STATE_MASK_VISIBLE : 0 ) | ( isUndecorated(smask) ? STATE_MASK_UNDECORATED : 0 ) + | ( 0 != getParentWindowHandle() ? STATE_MASK_CHILDWIN : 0 ) ; } protected static String getReconfigStateMaskString(final int flags) { @@ -1111,9 +1225,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } reconfigureWindowImpl(x, y, width, height, mask); } + final void setVisibleActionImpl(final boolean visible) { boolean nativeWindowCreated = false; - boolean madeVisible = false; + int madeVisible = -1; final RecursiveLock _lock = windowLock; _lock.lock(); @@ -1131,16 +1246,31 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(!isNativeValid() && visible) { if( 0<getWidth()*getHeight() ) { nativeWindowCreated = createNative(); - madeVisible = nativeWindowCreated; + madeVisible = nativeWindowCreated ? 1 : -1; } // always flag visible, allowing a retry .. stateMask.set(STATE_BIT_VISIBLE); } else if(stateMask.get(STATE_BIT_VISIBLE) != visible) { if(isNativeValid()) { // Skip WM if child-window! - setVisibleImpl(visible /* visible */, isChildWindow() /* fast */, getX(), getY(), getWidth(), getHeight()); - WindowImpl.this.waitForVisible(visible, false); - madeVisible = visible; + final boolean hasVisibilityQuirk = quirks.get(QUIRK_BIT_VISIBILITY); + setVisibleImpl(visible /* visible */, hasVisibilityQuirk || isChildWindow() /* fast */, + getX(), getY(), getWidth(), getHeight()); + if( 0 > WindowImpl.this.waitForVisible(visible, false) ) { + if( !hasVisibilityQuirk ) { + quirks.set(QUIRK_BIT_VISIBILITY); + if( DEBUG_IMPLEMENTATION ) { + System.err.println("Setting VISIBILITY QUIRK, due to setVisible("+visible+") failure"); + } + setVisibleImpl(visible /* visible */, true /* fast */, + getX(), getY(), getWidth(), getHeight()); + if( 0 <= WindowImpl.this.waitForVisible(visible, false) ) { + madeVisible = visible ? 1 : 0; + } // else: still not working .. bail out + } // else: no other remedy known .. bail out + } else { + madeVisible = visible ? 1 : 0; + } } else { stateMask.set(STATE_BIT_VISIBLE); } @@ -1172,7 +1302,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } _lock.unlock(); } - if( nativeWindowCreated || madeVisible ) { + if( nativeWindowCreated || 1==madeVisible ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } @@ -1191,6 +1321,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final void setVisible(final boolean wait, final boolean visible) { + if( !isReconfigureMaskSupported(STATE_MASK_VISIBLE) && isNativeValid() ) { + return; + } if(DEBUG_IMPLEMENTATION) { System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", windowHandle "+toHexString(windowHandle)+", state "+getStateMaskString()+" -> visible "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); } @@ -1780,6 +1913,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final ReparentOperation reparentWindow(final NativeWindow newParent, final int x, final int y, final int hints) { + if( !isReconfigureMaskSupported(STATE_MASK_CHILDWIN) && isNativeValid() ) { + return ReparentOperation.ACTION_INVALID; + } final ReparentAction reparentAction = new ReparentAction(newParent, x, y, hints); runOnEDTIfAvail(true, reparentAction); return reparentAction.getOp(); @@ -1841,6 +1977,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final void setUndecorated(final boolean value) { + if( isNativeValid() ) { + if( !isReconfigureMaskSupported(STATE_MASK_UNDECORATED) ) { + return; + } + if( isFullscreen() ) { + stateMaskNFS.put(STATE_MASK_UNDECORATED, value); + return; + } + } runOnEDTIfAvail(true, new DecorationAction(value)); } @Override @@ -1864,7 +2009,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer _lock.lock(); try { if( stateMask.put(STATE_BIT_ALWAYSONTOP, alwaysOnTop) != alwaysOnTop ) { - if( isNativeValid() ) { + if( isNativeValid() && !isFullscreen() ) { // Mirror pos/size so native change notification can get overwritten final int x = getX(); final int y = getY(); @@ -1888,17 +2033,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( isChildWindow() ) { return; // ignore for child windows } - if( isFullscreen() ) { - if( value && isAlwaysOnBottom() ) { - setAlwaysOnBottom(false); + if( isNativeValid() ) { + if( !isReconfigureMaskSupported(STATE_MASK_ALWAYSONTOP) ) { + return; } - stateMask.put(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP, value); - } else { - if( value && isAlwaysOnBottom() ) { - setAlwaysOnBottom(false); + if( isFullscreen() ) { + if( value && isAlwaysOnBottom() ) { + setAlwaysOnBottom(false); + } + stateMaskNFS.put(STATE_BIT_ALWAYSONTOP, value); + return; } - runOnEDTIfAvail(true, new AlwaysOnTopAction(value)); } + if( value && isAlwaysOnBottom() ) { + setAlwaysOnBottom(false); + } + runOnEDTIfAvail(true, new AlwaysOnTopAction(value)); } @Override public final boolean isAlwaysOnTop() { @@ -1942,6 +2092,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( isChildWindow() ) { return; // ignore for child windows } + if( !isReconfigureMaskSupported(STATE_MASK_ALWAYSONBOTTOM) && isNativeValid() ) { + return; + } if( value && isAlwaysOnTop() ) { setAlwaysOnTop(false); } @@ -1989,11 +2142,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( isChildWindow() ) { return; // ignore for child windows } - if( isFullscreen() ) { - stateMask.put(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE, value); - } else { - runOnEDTIfAvail(true, new ResizableAction(value)); + if( isNativeValid() ) { + if( !isReconfigureMaskSupported(STATE_MASK_RESIZABLE) ) { + return; + } + if( isFullscreen() ) { + stateMaskNFS.put(STATE_BIT_RESIZABLE, value); + return; + } } + runOnEDTIfAvail(true, new ResizableAction(value)); } @Override public final boolean isResizable() { @@ -2037,6 +2195,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( isChildWindow() ) { return; // ignore for child windows } + if( !isReconfigureMaskSupported(STATE_MASK_STICKY) && isNativeValid() ) { + return; + } runOnEDTIfAvail(true, new StickyAction(value)); } @Override @@ -2066,6 +2227,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if( 0 != cmask ) { if( isNativeValid() ) { + final boolean focused = hasFocus(); // Mirror pos/size so native change notification can get overwritten final int x = getX(); final int y = getY(); @@ -2077,6 +2239,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer reconfigureWindowImpl(x, y, width, height, getReconfigureMask(cmask, isVisible())); display.dispatchMessagesNative(); // status up2date + + if(focused) { + requestFocusInt( 0 == parentWindowHandle /* skipFocusAction if top-level */); + } } } } finally { @@ -2086,11 +2252,24 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } @Override - public final void setMaximized(final boolean horz, final boolean vert) { - if( isChildWindow() || isFullscreen() ) { + public final void setMaximized(boolean horz, boolean vert) { + if( isNativeValid() ) { + if( horz && !isReconfigureMaskSupported(STATE_MASK_MAXIMIZED_HORZ) ) { + horz = false; + } + if( vert && !isReconfigureMaskSupported(STATE_MASK_MAXIMIZED_VERT) ) { + vert = false; + } + } + if( isChildWindow() ) { return; // ignore for child windows } - runOnEDTIfAvail(true, new MaximizeAction(horz, vert)); + if( isFullscreen() ) { + stateMaskNFS.put(STATE_BIT_MAXIMIZED_HORZ, horz); + stateMaskNFS.put(STATE_BIT_MAXIMIZED_VERT, vert); + } else { + runOnEDTIfAvail(true, new MaximizeAction(horz, vert)); + } } @Override public final boolean isMaximizedVert() { @@ -2101,13 +2280,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return stateMask.get(STATE_BIT_MAXIMIZED_HORZ); } /** Triggered by implementation's WM events to update maximized window state. */ - protected void maximizedChanged(final boolean newMaxHorz, final boolean newMaxVert) { - final String stateMask0 = DEBUG_IMPLEMENTATION ? getStateMaskString() : null; - final boolean changedHorz = stateMask.put(STATE_BIT_MAXIMIZED_HORZ, newMaxHorz) != newMaxHorz; - final boolean changedVert = stateMask.put(STATE_BIT_MAXIMIZED_VERT, newMaxVert) != newMaxVert; - if ( DEBUG_IMPLEMENTATION ) { + protected final void maximizedChanged(final boolean newMaxHorz, final boolean newMaxVert) { + if( !isFullscreen() ) { + final String stateMask0 = DEBUG_IMPLEMENTATION ? getStateMaskString() : null; + final boolean changedHorz = stateMask.put(STATE_BIT_MAXIMIZED_HORZ, newMaxHorz) != newMaxHorz; + final boolean changedVert = stateMask.put(STATE_BIT_MAXIMIZED_VERT, newMaxVert) != newMaxVert; + if ( DEBUG_IMPLEMENTATION ) { + if( changedHorz || changedVert ) { + System.err.println("Window.maximizedChanged.accepted: "+stateMask0+" -> "+getStateMaskString()); + } + } + } else if( DEBUG_IMPLEMENTATION ) { + final String stateMask0 = DEBUG_IMPLEMENTATION ? getStateMaskString() : null; + final boolean changedHorz = stateMask.get(STATE_BIT_MAXIMIZED_HORZ) != newMaxHorz; + final boolean changedVert = stateMask.get(STATE_BIT_MAXIMIZED_VERT) != newMaxVert; if( changedHorz || changedVert ) { - System.err.println("Window.maximizedChanged: "+stateMask0+" -> "+getStateMaskString()); + System.err.println("Window.maximizedChanged.ignored: "+stateMask0+" -> max["+(newMaxHorz?"":"!")+"h, "+(newMaxVert?"":"!")+"v]"); } } } @@ -2200,6 +2388,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } @Override public final void setPointerVisible(final boolean pointerVisible) { + if( !isReconfigureMaskSupported(STATE_MASK_POINTERVISIBLE) && isNativeValid() ) { + return; + } if(stateMask.get(STATE_BIT_POINTERVISIBLE) != pointerVisible) { boolean setVal = 0 == getWindowHandle(); if(!setVal) { @@ -2310,6 +2501,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } @Override public final void confinePointer(final boolean confine) { + if( !isReconfigureMaskSupported(STATE_MASK_POINTERCONFINED) && isNativeValid() ) { + return; + } if(stateMask.get(STATE_BIT_POINTERCONFINED) != confine) { boolean setVal = 0 == getWindowHandle(); if(!setVal) { @@ -2634,6 +2828,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** Internally forcing request focus on current thread */ private void requestFocusInt(final boolean skipFocusAction) { if( skipFocusAction || !focusAction() ) { + if( !isReconfigureMaskSupported(STATE_MASK_FOCUSED) ) { + return; + } if(DEBUG_IMPLEMENTATION) { System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): skipFocusAction "+ skipFocusAction+", state "+getStateMaskString()+" -> focus true - windowHandle "+ @@ -2725,8 +2922,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private boolean init(final boolean fullscreen) { if(isNativeValid()) { - this._fullscreen = fullscreen; - return isFullscreen() != fullscreen; + if( !isReconfigureMaskSupported(STATE_MASK_FULLSCREEN) ) { + return false; + } else { + this._fullscreen = fullscreen; + return isFullscreen() != fullscreen; + } } else { stateMask.put(STATE_BIT_FULLSCREEN, fullscreen); // set current state for createNative(..) return false; @@ -2745,11 +2946,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer final int oldWidth = getWidth(); final int oldHeight = getHeight(); - int x,y,w,h; + final int x,y,w,h; final RectangleImmutable sviewport = screen.getViewportInWindowUnits(); // window units final RectangleImmutable viewport; // window units final boolean alwaysOnTopChange, resizableChange; + if(_fullscreen) { if( null == fullscreenMonitors ) { if( stateMask.get(PSTATE_BIT_FULLSCREEN_MAINMONITOR) ) { @@ -2774,32 +2976,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer nfs_y = oldY; nfs_width = oldWidth; nfs_height = oldHeight; - stateMask.copy(STATE_BIT_ALWAYSONTOP, PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP); - stateMask.copy(STATE_BIT_RESIZABLE, PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE); + stateMaskNFS.put32(0, 32, stateMask.get32(0, 32) & STATE_MASK_FULLSCREEN_NFS); x = viewport.getX(); y = viewport.getY(); w = viewport.getWidth(); h = viewport.getHeight(); stateMask.clear(STATE_BIT_ALWAYSONTOP); // special aontop handling for fullscreen stateMask.set(STATE_BIT_RESIZABLE); // allow fullscreen to resize to max - alwaysOnTopChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP); - resizableChange = !stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE); + alwaysOnTopChange = stateMaskNFS.get(STATE_BIT_ALWAYSONTOP); + resizableChange = !stateMaskNFS.get(STATE_BIT_RESIZABLE); } else { + int _x,_y,_w,_h; stateMask.set(PSTATE_BIT_FULLSCREEN_MAINMONITOR); fullscreenMonitors = null; stateMask.clear(STATE_BIT_FULLSCREEN_SPAN); viewport = null; - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - alwaysOnTopChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP) != stateMask.get(STATE_BIT_ALWAYSONTOP); - // alwaysOnBottomChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONBOTTOM) != stateMask.get(STATE_BIT_ALWAYSONBOTTOM); - resizableChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE) != stateMask.get(STATE_BIT_RESIZABLE); - stateMask.copy(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP, STATE_BIT_ALWAYSONTOP); - stateMask.copy(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE, STATE_BIT_RESIZABLE); - stateMask.clear(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP); - stateMask.set(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE); + _x = nfs_x; + _y = nfs_y; + _w = nfs_width; + _h = nfs_height; + alwaysOnTopChange = stateMaskNFS.get(STATE_BIT_ALWAYSONTOP) != stateMask.get(STATE_BIT_ALWAYSONTOP); + resizableChange = stateMaskNFS.get(STATE_BIT_RESIZABLE) != stateMask.get(STATE_BIT_RESIZABLE); + stateMask.put32(0, 32, stateMaskNFS.get32(0, 32) | ( stateMask.get32(0, 32) & ~STATE_MASK_FULLSCREEN_NFS ) ); if(null!=parentWindow) { // reset position to 0/0 within parent space @@ -2807,12 +3005,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer y = 0; // refit if size is bigger than parent - if( w > parentWindow.getWidth() ) { + if( _w > parentWindow.getWidth() ) { w = parentWindow.getWidth(); + } else { + w = _w; } - if( h > parentWindow.getHeight() ) { + if( _h > parentWindow.getHeight() ) { h = parentWindow.getHeight(); + } else { + h = _h; } + } else { + x = _x; + y = _y; + w = _w; + h = _h; } } @@ -2851,7 +3058,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer final int changeMask; try { { - // Enter fullscreen - Disable alwaysOnTop/alwaysOnBottom/resizableChange + // Enter fullscreen - Disable alwaysOnTop/resizableChange int cm = 0; if( alwaysOnTopChange ) { cm = CHANGE_MASK_ALWAYSONTOP; @@ -2862,11 +3069,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer changeMask = cm; } if( _fullscreen && 0 != changeMask ) { - // Enter fullscreen - Disable alwaysOnTop/alwaysOnBottom/resizableChange + // Enter fullscreen - Disable alwaysOnTop/resizableChange reconfigureWindowImpl(oldX, oldY, oldWidth, oldHeight, getReconfigureMask(changeMask, isVisible())); } stateMask.put(STATE_BIT_FULLSCREEN, _fullscreen); + // Note CHANGE_MASK_PARENTING: STATE_MASK_CHILDWIN is refined in getReconfigureMask() + // Note CHANGE_MASK_DECORATION: STATE_MASK_UNDECORATED is refined in getReconfigureMask() reconfigureWindowImpl(x, y, w, h, getReconfigureMask( ( ( null != parentWindowLocked ) ? CHANGE_MASK_PARENTING : 0 ) | CHANGE_MASK_FULLSCREEN | CHANGE_MASK_DECORATION, isVisible()) ); @@ -3066,6 +3275,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener if(animatorPaused) { lifecycleHook.resumeRenderingAction(); + animatorPaused = false; } if( hadFocus ) { requestFocus(true); @@ -3180,7 +3390,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // public final void sendMouseEvent(final short eventType, final int modifiers, - final int x, final int y, final short button, final float rotation) { + final int x, final int y, final short button, final float rotation) { doMouseEvent(false, false, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f); } @@ -3335,7 +3545,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer final int pCount = pTypes.length; if( 0 > pActionIdx || pActionIdx >= pCount) { - throw new IllegalArgumentException("actionIdx out of bounds [0.."+(pCount-1)+"]"); + throw new IllegalArgumentException("actionIdx "+pActionIdx+" out of bounds [0.."+(pCount-1)+"]"); } if( 0 < pActionIdx ) { // swap values to make idx 0 the triggering pointer @@ -4247,14 +4457,31 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if( visible != _visible ) { final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+_visible; - if(failFast) { + if(DEBUG_FREEZE_AT_VISIBILITY_FAILURE) { + System.err.println("XXXX: "+msg); + System.err.println("XXXX: FREEZE"); + try { + while(true) { + Thread.sleep(100); + display.dispatchMessagesNative(); // status up2date + } + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("", e); + Thread.currentThread().interrupt(); // keep state + } throw new NativeWindowException(msg); - } else if (DEBUG_IMPLEMENTATION) { - System.err.println(msg); - ExceptionUtils.dumpStack(System.err); + } else { + if(failFast) { + throw new NativeWindowException(msg); + } else { + if (DEBUG_IMPLEMENTATION) { + System.err.println(msg); + ExceptionUtils.dumpStack(System.err); + } + return -1; + } } - return -1; - } else if( 0 < remaining ){ + } else if( 0 < remaining ) { return remaining; } else { return 0; @@ -4384,18 +4611,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** * Triggered by implementation's WM events to update the insets. * + * @param defer + * @param left insets, -1 ignored + * @param right insets, -1 ignored + * @param top insets, -1 ignored + * @param bottom insets, -1 ignored + * * @see #getInsets() * @see #updateInsetsImpl(Insets) */ protected void insetsChanged(final boolean defer, final int left, final int right, final int top, final int bottom) { if ( left >= 0 && right >= 0 && top >= 0 && bottom >= 0 ) { + final boolean changed = left != insets.getLeftWidth() || right != insets.getRightWidth() || + top != insets.getTopHeight() || bottom != insets.getBottomHeight(); + if( blockInsetsChange || isUndecorated() ) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.insetsChanged (defer: "+defer+"): Skip insets change "+insets+" -> "+new Insets(left, right, top, bottom)+" (blocked "+blockInsetsChange+", undecoration "+isUndecorated()+")"); + if( changed ) { + System.err.println("Window.insetsChanged (defer: "+defer+"): Skip insets change "+insets+" -> "+new Insets(left, right, top, bottom)+" (blocked "+blockInsetsChange+", undecoration "+isUndecorated()+")"); + } } - } else if ( (left != insets.getLeftWidth() || right != insets.getRightWidth() || - top != insets.getTopHeight() || bottom != insets.getBottomHeight() ) - ) { + } else if ( changed ) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.insetsChanged (defer: "+defer+"): Changed "+insets+" -> "+new Insets(left, right, top, bottom)); } @@ -4485,24 +4721,157 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Accumulated actions // - /** Triggered by implementation's WM events to update the client-area position, size and maximized flags. */ - protected void sizePosMaxInsetsChanged(final boolean defer, - final int newX, final int newY, - final int newWidth, final int newHeight, - final boolean newMaxHorz, final boolean newMaxVert, - final int left, final int right, final int top, final int bottom, - final boolean force) { - sizeChanged(defer, newWidth, newHeight, force); - positionChanged(defer, newX, newY); - maximizedChanged(newMaxHorz, newMaxVert); - insetsChanged(defer, left, right, top, bottom); - } /** Triggered by implementation. */ protected final void sendMouseEventRequestFocus(final short eventType, final int modifiers, - final int x, final int y, final short button, final float rotation) { + final int x, final int y, final short button, final float rotation) { sendMouseEvent(eventType, modifiers, x, y, button, rotation); requestFocus(false /* wait */); } + /** + * Triggered by implementation's WM events to update the visibility state and send- or enqueue one mouse event + * + * @param defer + * @param visibleChange -1 ignored, 0 invisible, > 0 visible + * @param entranceChange -1 ignored, 0 exit, > 0 enter + * @param eventType 0 ignored, > 0 [send|enqueue]MouseEvent + * @param modifiers + * @param x + * @param y + * @param button + * @param rotation + */ + protected final void visibleChangedSendMouseEvent(final boolean defer, final int visibleChange, + final short eventType, final int modifiers, + final int x, final int y, final short button, final float rotation) { + if( 0 <= visibleChange ) { // ignore visible < 0 + visibleChanged(defer, 0 < visibleChange); + } + if( 0 < eventType ) { + if( defer ) { + enqueueMouseEvent(false /* wait */, eventType, modifiers, x, y, button, rotation); + } else { + sendMouseEvent(eventType, modifiers, x, y, button, rotation); + } + } + } + /** + * Triggered by implementation's WM events to update the content + * @param defer if true sent event later, otherwise wait until processed. + * @param visibleChange -1 ignored, 0 invisible, > 0 visible + * @param x dirty-region y-pos in pixel units + * @param y dirty-region x-pos in pixel units + * @param width dirty-region width in pixel units + * @param height dirty-region height in pixel units + */ + protected final void visibleChangedWindowRepaint(final boolean defer, final int visibleChange, + final int x, final int y, final int width, final int height) { + if( 0 <= visibleChange ) { // ignore visible < 0 + visibleChanged(defer, 0 < visibleChange); + } + windowRepaint(defer, x, y, width, height); + } + /** + * Triggered by implementation's WM events to update the focus and visibility state + * + * @param defer + * @param focusChange -1 ignored, 0 unfocused, > 0 focused + * @param visibleChange -1 ignored, 0 invisible, > 0 visible + */ + protected final void focusVisibleChanged(final boolean defer, + final int focusChange, + final int visibleChange) { + if( 0 <= focusChange ) { // ignore focus < 0 + focusChanged(defer, 0 < focusChange); + } + if( 0 <= visibleChange ) { // ignore visible < 0 + visibleChanged(defer, 0 < visibleChange); + } + } + /** + * Triggered by implementation's WM events to update the client-area position, size, insets and maximized flags. + * + * @param defer + * @param left insets, -1 ignored + * @param right insets, -1 ignored + * @param top insets, -1 ignored + * @param bottom insets, -1 ignored + * @param visibleChange -1 ignored, 0 invisible, > 0 visible + */ + protected final void insetsVisibleChanged(final boolean defer, + final int left, final int right, final int top, final int bottom, + final int visibleChange) { + insetsChanged(defer, left, right, top, bottom); + if( 0 <= visibleChange ) { // ignore visible < 0 + visibleChanged(defer, 0 < visibleChange); + } + } + /** + * Triggered by implementation's WM events to update the client-area position, size, insets and maximized flags. + * + * @param defer + * @param newX + * @param newY + * @param newWidth + * @param newHeight + * @param left insets, -1 ignored + * @param right insets, -1 ignored + * @param top insets, -1 ignored + * @param bottom insets, -1 ignored + * @param focusChange -1 ignored, 0 unfocused, > 0 focused + * @param visibleChange -1 ignored, 0 invisible, > 0 visible + * @param force + */ + protected final void sizePosInsetsFocusVisibleChanged(final boolean defer, + final int newX, final int newY, + final int newWidth, final int newHeight, + final int left, final int right, final int top, final int bottom, + final int focusChange, + final int visibleChange, + final boolean force) { + sizeChanged(defer, newWidth, newHeight, force); + positionChanged(defer, newX, newY); + insetsChanged(defer, left, right, top, bottom); + if( 0 <= focusChange ) { // ignore focus < 0 + focusChanged(defer, 0 < focusChange); + } + if( 0 <= visibleChange ) { // ignore visible < 0 + visibleChanged(defer, 0 < visibleChange); + } + } + /** + * Triggered by implementation's WM events to update the client-area position, size, insets and maximized flags. + * + * @param defer + * @param newX + * @param newY + * @param newWidth + * @param newHeight + * @param maxHorzChange -1 ignored, 0 !maximized, > 0 maximized + * @param maxVertChange -1 ignored, 0 !maximized, > 0 maximized + * @param left insets, -1 ignored + * @param right insets, -1 ignored + * @param top insets, -1 ignored + * @param bottom insets, -1 ignored + * @param visibleChange -1 ignored, 0 invisible, > 0 visible + * @param force + */ + protected final void sizePosMaxInsetsVisibleChanged(final boolean defer, + final int newX, final int newY, + final int newWidth, final int newHeight, + final int maxHorzChange, final int maxVertChange, + final int left, final int right, final int top, final int bottom, + final int visibleChange, + final boolean force) { + sizeChanged(defer, newWidth, newHeight, force); + positionChanged(defer, newX, newY); + if( 0 <= maxHorzChange && 0 <= maxVertChange ) { + maximizedChanged(0 < maxHorzChange, 0 < maxVertChange); + } + insetsChanged(defer, left, right, top, bottom); + if( 0 <= visibleChange ) { // ignore visible < 0 + visibleChanged(defer, 0 < visibleChange); + } + } // // Reflection helper .. diff --git a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java index cc71fb559..4e9273e83 100644 --- a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java +++ b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java @@ -55,41 +55,6 @@ public class NewtFactoryAWT extends NewtFactory { public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); /** - * @deprecated Use {@link #getNativeWindow(java.awt.Component, AWTGraphicsConfiguration)} - * - * Wraps an AWT component into a {@link com.jogamp.nativewindow.NativeWindow} utilizing the {@link com.jogamp.nativewindow.NativeWindowFactory},<br> - * using a configuration agnostic dummy {@link com.jogamp.nativewindow.DefaultGraphicsConfiguration}.<br> - * <p> - * The actual wrapping implementation is {@link com.jogamp.nativewindow.awt.JAWTWindow}.<br></p> - * <p> - * Purpose of this wrapping is to access the AWT window handle,<br> - * not to actually render into it.<br> - * Hence the dummy configuration only.</p> - * - * @param awtCompObject must be of type java.awt.Component - */ - public static JAWTWindow getNativeWindow(final Object awtCompObject, final CapabilitiesImmutable capsRequested) { - if(null==awtCompObject) { - throw new NativeWindowException("Null AWT Component"); - } - if( ! (awtCompObject instanceof java.awt.Component) ) { - throw new NativeWindowException("AWT Component not a java.awt.Component"); - } - return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested ); - } - - /** - * @deprecated Use {@link #getNativeWindow(java.awt.Component, AWTGraphicsConfiguration)} - * @param awtComp - * @param capsRequested - * @return - */ - public static JAWTWindow getNativeWindow(final java.awt.Component awtComp, final CapabilitiesImmutable capsRequested) { - final AWTGraphicsConfiguration awtConfig = AWTGraphicsConfiguration.create(awtComp, null, capsRequested); - return getNativeWindow(awtComp, awtConfig); - } - - /** * Wraps an AWT component into a {@link com.jogamp.nativewindow.NativeWindow} utilizing the {@link com.jogamp.nativewindow.NativeWindowFactory},<br> * using the given {@link AWTGraphicsConfiguration}. * <p> diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 959e75df8..af5d08da0 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -38,7 +38,6 @@ import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.nativewindow.DefaultGraphicsScreen; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; import com.jogamp.nativewindow.util.RectangleImmutable; import com.jogamp.opengl.GLCapabilitiesChooser; @@ -455,6 +454,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask; + } + + @Override protected final boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) { boolean res = true; diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index 40e3bf85a..bdf78386a 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -60,13 +60,14 @@ import com.jogamp.newt.Window; @SuppressWarnings("serial") public class AWTCanvas extends Canvas { - private GraphicsDevice device; - private GraphicsConfiguration chosen; - private AWTGraphicsConfiguration awtConfig; - private volatile JAWTWindow jawtWindow=null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle - private CapabilitiesChooser chooser=null; + private final WindowDriver driver; private final CapabilitiesImmutable capabilities; + private final CapabilitiesChooser chooser; private final UpstreamScalable upstreamScale; + private GraphicsConfiguration chosen; + private volatile GraphicsDevice device; + private volatile AWTGraphicsConfiguration awtConfig; + private volatile JAWTWindow jawtWindow=null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle public static interface UpstreamScalable { float[] getReqPixelScale(); @@ -75,12 +76,15 @@ public class AWTCanvas extends Canvas { private boolean displayConfigChanged=false; - public AWTCanvas(final CapabilitiesImmutable capabilities, final CapabilitiesChooser chooser, final UpstreamScalable upstreamScale) { + public AWTCanvas(final WindowDriver driver, final CapabilitiesImmutable capabilities, final CapabilitiesChooser chooser, final UpstreamScalable upstreamScale) { super(); - if(null==capabilities) { throw new NativeWindowException("Capabilities null"); } + if(null==driver) { + throw new NativeWindowException("driver null"); + } + this.driver = driver; this.capabilities=capabilities; this.chooser=chooser; this.upstreamScale = upstreamScale; @@ -117,6 +121,9 @@ public class AWTCanvas extends Canvas { @Override public void addNotify() { + // before native peer is valid: X11 + disableBackgroundErase(); + /** * 'super.addNotify()' determines the GraphicsConfiguration, * while calling this class's overriden 'getGraphicsConfiguration()' method @@ -134,8 +141,7 @@ public class AWTCanvas extends Canvas { } chosen = awtConfig.getAWTGraphicsConfiguration(); - // before native peer is valid: X11 - disableBackgroundErase(); + setAWTGraphicsConfiguration(awtConfig); // issues getGraphicsConfiguration() and creates the native peer super.addNotify(); @@ -146,16 +152,20 @@ public class AWTCanvas extends Canvas { { jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig); // trigger initialization cycle - jawtWindow.setSurfaceScale(upstreamScale.getReqPixelScale() ); jawtWindow.lockSurface(); - upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new float[2])); - jawtWindow.unlockSurface(); + try { + jawtWindow.setSurfaceScale(upstreamScale.getReqPixelScale() ); + upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new float[2])); + } finally { + jawtWindow.unlockSurface(); + } } final GraphicsConfiguration gc = super.getGraphicsConfiguration(); if(null!=gc) { device = gc.getDevice(); } + driver.localCreate(); if(Window.DEBUG_IMPLEMENTATION) { System.err.println(getThreadName()+": AWTCanvas.addNotify.X"); } @@ -170,16 +180,28 @@ public class AWTCanvas extends Canvas { return null != jawtWindow ? jawtWindow.isOffscreenLayerSurfaceEnabled() : false; } + private void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) { + // Cache awtConfig + awtConfig = config; + if( null != jawtWindow ) { + // Notify JAWTWindow .. + jawtWindow.setAWTGraphicsConfiguration(config); + } + } + @Override public void removeNotify() { + if(Window.DEBUG_IMPLEMENTATION) { + System.err.println(getThreadName()+": AWTCanvas.removeNotify.0: Created Config: "+awtConfig); + } try { - dispose(); + driver.localDestroy(); } finally { super.removeNotify(); } } - private void dispose() { + void dispose() { if( null != jawtWindow ) { jawtWindow.destroy(); if(Window.DEBUG_IMPLEMENTATION) { @@ -198,6 +220,7 @@ public class AWTCanvas extends Canvas { System.err.println(getThreadName()+": AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); } } + awtConfig = null; } private String getThreadName() { return Thread.currentThread().getName(); } @@ -255,9 +278,9 @@ public class AWTCanvas extends Canvas { * block, both devices should have the same visual list, and the * same configuration should be selected here. */ - final AWTGraphicsConfiguration config = chooseGraphicsConfiguration( + final AWTGraphicsConfiguration newConfig = chooseGraphicsConfiguration( awtConfig.getChosenCapabilities(), awtConfig.getRequestedCapabilities(), chooser, gc.getDevice()); - final GraphicsConfiguration compatible = (null!=config)?config.getAWTGraphicsConfiguration():null; + final GraphicsConfiguration compatible = (null!=newConfig)?newConfig.getAWTGraphicsConfiguration():null; if(Window.DEBUG_IMPLEMENTATION) { final Exception e = new Exception("Info: Call Stack: "+Thread.currentThread().getName()); e.printStackTrace(); @@ -265,8 +288,8 @@ public class AWTCanvas extends Canvas { System.err.println("Created Config (n): THIS GC "+gc); System.err.println("Created Config (n): Choosen GC "+compatible); System.err.println("Created Config (n): HAVE CF "+awtConfig); - System.err.println("Created Config (n): Choosen CF "+config); - System.err.println("Created Config (n): EQUALS CAPS "+config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())); + System.err.println("Created Config (n): Choosen CF "+newConfig); + System.err.println("Created Config (n): EQUALS CAPS "+newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())); } if (compatible != null) { @@ -275,10 +298,10 @@ public class AWTCanvas extends Canvas { * any outside callers of this method. */ chosen = compatible; - if( !config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())) { + if( !newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())) { displayConfigChanged=true; } - awtConfig = config; + setAWTGraphicsConfiguration(newConfig); } } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 9d3121635..3d9073769 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -33,6 +33,8 @@ import java.awt.EventQueue; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.newt.util.EDTUtil; @@ -54,7 +56,7 @@ public class AWTEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; this.dispatchMessages=dispatchMessages; - this.nedt = new NEDT(threadGroup, name); + this.nedt = new NEDT(threadGroup, this.name); this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } @@ -132,8 +134,7 @@ public class AWTEDTUtil implements EDTUtil { } private final boolean invokeImpl(boolean wait, final Runnable task, final boolean stop) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -150,6 +151,7 @@ public class AWTEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if(stop) { nedt.shouldStop = true; } @@ -182,18 +184,21 @@ public class AWTEDTUtil implements EDTUtil { true /* always catch and report Exceptions, don't disturb EDT */, wait ? null : System.err); AWTEDTExecutor.singleton.invoke(false, rTask); + } else { + wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -227,12 +232,12 @@ public class AWTEDTUtil implements EDTUtil { final public boolean waitUntilStopped() { synchronized(edtLock) { if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) { - while( nedt.isRunning ) { - try { + try { + while( nedt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -241,13 +246,13 @@ public class AWTEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -286,7 +291,7 @@ public class AWTEDTUtil implements EDTUtil { try { sync.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java index 222ac8ae9..aa93dd9aa 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -74,6 +74,8 @@ public class WindowDriver extends WindowImpl { public WindowDriver(final Container container) { super(); + this.withinLocalDispose = false; + this.addWindowListener(0, new NEWTWindowListener()); this.awtContainer = container; if(container instanceof Frame) { awtFrame = (Frame) container; @@ -85,6 +87,7 @@ public class WindowDriver extends WindowImpl { /** same instance as container, just for impl. convenience */ private Frame awtFrame = null; private AWTCanvas awtCanvas; + private volatile boolean withinLocalDispose; @Override protected void requestFocusImpl(final boolean reparented) { @@ -112,64 +115,98 @@ public class WindowDriver extends WindowImpl { @Override protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead"); - } - - if(null==awtContainer) { - awtFrame = new Frame(); - awtContainer = awtFrame; - owningFrame=true; + if( withinLocalDispose ) { + setupHandleAndGC(); + definePosition(getX(), getY()); // clear AUTOPOS + visibleChanged(false, true); + withinLocalDispose = false; } else { - owningFrame=false; - defineSize(awtContainer.getWidth(), awtContainer.getHeight()); - definePosition(awtContainer.getX(), awtContainer.getY()); - } - if(null!=awtFrame) { - awtFrame.setTitle(getTitle()); - } - awtContainer.setLayout(new BorderLayout()); + if(0!=getParentWindowHandle()) { + throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead"); + } - if( null == awtCanvas ) { - awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser, upstreamScalable); + if(null==awtContainer) { + awtFrame = new Frame(); + awtContainer = awtFrame; + owningFrame=true; + } else { + owningFrame=false; + defineSize(awtContainer.getWidth(), awtContainer.getHeight()); + definePosition(awtContainer.getX(), awtContainer.getY()); + } + if(null!=awtFrame) { + awtFrame.setTitle(getTitle()); + } + awtContainer.setLayout(new BorderLayout()); + + if( null == awtCanvas ) { + awtCanvas = new AWTCanvas(this, capsRequested, WindowDriver.this.capabilitiesChooser, upstreamScalable); - // canvas.addComponentListener(listener); - awtContainer.add(awtCanvas, BorderLayout.CENTER); + // canvas.addComponentListener(listener); + awtContainer.add(awtCanvas, BorderLayout.CENTER); - // via EDT .. - new AWTMouseAdapter(this).addTo(awtCanvas); // fwd all AWT Mouse events to here - new AWTKeyAdapter(this).addTo(awtCanvas); // fwd all AWT Key events to here + // via EDT .. + new AWTMouseAdapter(this).addTo(awtCanvas); // fwd all AWT Mouse events to here + new AWTKeyAdapter(this).addTo(awtCanvas); // fwd all AWT Key events to here - // direct w/o EDT - new AWTWindowAdapter(new LocalWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here + // direct w/o EDT + new AWTWindowAdapter(new AWTWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here + } else { + awtContainer.add(awtCanvas, BorderLayout.CENTER); + } + reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY | CHANGE_MASK_DECORATION, true)); + // throws exception if failed .. + // AWTCanvas -> localCreate -> setupHandleAndGC(); } + } - reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY | CHANGE_MASK_DECORATION, true)); - // throws exception if failed .. + private void setupHandleAndGC() { + // reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY | CHANGE_MASK_DECORATION, true)); + if( null != awtCanvas ) { + final NativeWindow nw = awtCanvas.getNativeWindow(); + if( null != nw ) { + setGraphicsConfiguration( awtCanvas.getAWTGraphicsConfiguration() ); + setWindowHandle( nw.getWindowHandle() ); + } + } + } - final NativeWindow nw = awtCanvas.getNativeWindow(); - if( null != nw ) { - setGraphicsConfiguration( awtCanvas.getAWTGraphicsConfiguration() ); - setWindowHandle( nw.getWindowHandle() ); + void localCreate() { + if( withinLocalDispose ) { + setVisible(true); + } else { + setupHandleAndGC(); } } + void localDestroy() { + this.withinLocalDispose = true; + super.destroy(); + } + @Override protected void closeNativeImpl() { setWindowHandle(0); - if(null!=awtContainer) { - awtContainer.setVisible(false); - awtContainer.remove(awtCanvas); - awtContainer.setEnabled(false); - awtCanvas.setEnabled(false); - } - if(owningFrame && null!=awtFrame) { - awtFrame.dispose(); - owningFrame=false; + if( this.withinLocalDispose ) { + if(null!=awtCanvas) { + awtCanvas.dispose(); + } + } else { + if(null!=awtContainer) { + awtContainer.setVisible(false); + awtContainer.remove(awtCanvas); + awtContainer.setEnabled(false); + awtCanvas.setEnabled(false); + awtCanvas.dispose(); + } + if(owningFrame && null!=awtFrame) { + awtFrame.dispose(); + owningFrame=false; + } + awtCanvas = null; + awtFrame = null; + awtContainer = null; } - awtCanvas = null; - awtFrame = null; - awtContainer = null; } @Override @@ -225,6 +262,11 @@ public class WindowDriver extends WindowImpl { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask; + } + + @Override protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) { if(DEBUG_IMPLEMENTATION) { System.err.println("AWTWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ @@ -261,6 +303,7 @@ public class WindowDriver extends WindowImpl { if( awtContainer.getX() != x || awtContainer.getY() != y ) { awtContainer.setLocation(x, y); } + definePosition(x, y); if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) { if( 0 != ( STATE_MASK_VISIBLE & flags ) ) { @@ -275,6 +318,9 @@ public class WindowDriver extends WindowImpl { } visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags)); } + if( isVisible() ) { + windowRepaint(false, 0, 0, getSurfaceWidth(), getSurfaceHeight()); + } return true; } @@ -291,7 +337,7 @@ public class WindowDriver extends WindowImpl { return ( null != awtCanvas ) ? awtCanvas.getNativeWindow() : null; } - class LocalWindowListener implements com.jogamp.newt.event.WindowListener { + class AWTWindowListener implements com.jogamp.newt.event.WindowListener { @Override public void windowMoved(final com.jogamp.newt.event.WindowEvent e) { if(null!=awtContainer) { @@ -334,4 +380,28 @@ public class WindowDriver extends WindowImpl { } } } + class NEWTWindowListener implements com.jogamp.newt.event.WindowListener { + @Override + public void windowMoved(final com.jogamp.newt.event.WindowEvent e) { } + @Override + public void windowResized(final com.jogamp.newt.event.WindowEvent e) { } + @Override + public void windowDestroyNotify(final WindowEvent e) { + if( withinLocalDispose ) { + e.setConsumed(true); + } + } + @Override + public void windowDestroyed(final WindowEvent e) { + if( withinLocalDispose ) { + e.setConsumed(true); + } + } + @Override + public void windowGainedFocus(final WindowEvent e) { } + @Override + public void windowLostFocus(final WindowEvent e) { } + @Override + public void windowRepaint(final WindowUpdateEvent e) { } + } } diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java index f95d23364..d19618bd1 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java @@ -38,7 +38,6 @@ import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; import com.jogamp.opengl.GLCapabilitiesImmutable; @@ -94,6 +93,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask; + } + + @Override protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) { if(0!=getWindowHandle()) { if(0 != ( CHANGE_MASK_FULLSCREEN & flags)) { diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java index d111e850e..d4af1b972 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java @@ -67,10 +67,12 @@ public class DisplayDriver extends DisplayImpl { PNGPixelRect image = null; if( DisplayImpl.isPNGUtilAvailable() ) { - final IOUtil.ClassResources res = new IOUtil.ClassResources(DisplayDriver.class, new String[] { "newt/data/pointer-grey-alpha-16x24.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/pointer-grey-alpha-16x24.png" }, DisplayDriver.class.getClassLoader(), null); try { final URLConnection urlConn = res.resolve(0); - image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + if( null != urlConn ) { + image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } } catch (final Exception e) { e.printStackTrace(); } @@ -96,7 +98,11 @@ public class DisplayDriver extends DisplayImpl { aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); aDevice.open(); - defaultPointerIcon = (PointerIconImpl) createPointerIcon(defaultPointerIconImage, 0, 0); + if( null != defaultPointerIconImage ) { + defaultPointerIcon = (PointerIconImpl) createPointerIcon(defaultPointerIconImage, 0, 0); + } else { + defaultPointerIcon = null; + } if( DEBUG_POINTER_ICON ) { System.err.println("Display.PointerIcon.createDefault: "+defaultPointerIcon); } diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java index f236edd6b..b4af4045c 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java @@ -84,11 +84,11 @@ public class ScreenDriver extends ScreenImpl { props[i++] = 0; // rotated viewport x pixel-units props[i++] = 0; // rotated viewport y pixel-units props[i++] = cachedWidth; // rotated viewport width pixel-units - props[i++] = cachedWidth; // rotated viewport height pixel-units + props[i++] = cachedHeight; // rotated viewport height pixel-units props[i++] = 0; // rotated viewport x window-units props[i++] = 0; // rotated viewport y window-units props[i++] = cachedWidth; // rotated viewport width window-units - props[i++] = cachedWidth; // rotated viewport height window-units + props[i++] = cachedHeight; // rotated viewport height window-units MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java index 16b0f2ee9..b0a4ee34a 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java @@ -36,7 +36,6 @@ import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; import com.jogamp.nativewindow.util.Rectangle; import com.jogamp.nativewindow.util.RectangleImmutable; @@ -249,6 +248,20 @@ public class WindowDriver extends WindowImpl { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask | + // STATE_MASK_UNDECORATED | + // STATE_MASK_ALWAYSONTOP | + // STATE_MASK_ALWAYSONBOTTOM | + // STATE_MASK_STICKY | + // STATE_MASK_RESIZABLE | + // STATE_MASK_MAXIMIZED_VERT | + // STATE_MASK_MAXIMIZED_HORZ | + STATE_MASK_POINTERVISIBLE | + STATE_MASK_POINTERCONFINED; + } + + @Override protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) { final RectangleImmutable rect = clampRect((ScreenDriver) getScreen(), new Rectangle(x, y, width, height), false); // reconfigure0 will issue position/size changed events if required diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java index ceda0997b..b01928449 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java @@ -35,7 +35,6 @@ package jogamp.newt.driver.intel.gdl; import com.jogamp.nativewindow.*; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; public class WindowDriver extends jogamp.newt.WindowImpl { @@ -86,6 +85,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask; + } + + @Override protected boolean reconfigureWindowImpl(int x, int y, int width, int height, final int flags) { final ScreenDriver screen = (ScreenDriver) getScreen(); diff --git a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java index c18eff217..ce5d208db 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java @@ -39,7 +39,6 @@ import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; import com.jogamp.nativewindow.VisualIDHolder.VIDType; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; import com.jogamp.opengl.GLCapabilitiesImmutable; @@ -96,6 +95,11 @@ public class WindowDriver extends WindowImpl { protected void requestFocusImpl(final boolean reparented) { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask; + } + + @Override protected boolean reconfigureWindowImpl(final int x, final int y, int width, int height, final int flags) { if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) { setVisible0(eglWindowHandle, 0 != ( STATE_MASK_VISIBLE & flags)); diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java index bc0bfaa16..c3b7bff36 100644 --- a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java @@ -43,6 +43,7 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.KeyTracker; import com.jogamp.common.nio.StructAccessor; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Window; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.WindowEvent; @@ -63,7 +64,7 @@ public class LinuxEventDeviceTracker implements WindowListener, KeyTracker { static { ledt = new LinuxEventDeviceTracker(); - final Thread t = new Thread(ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager"); + final Thread t = new InterruptSource.Thread(null, ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager"); t.setDaemon(true); t.start(); } @@ -153,7 +154,7 @@ public class LinuxEventDeviceTracker implements WindowListener, KeyTracker { if(number<32&&number>=0) { if(eventDevicePollers[number]==null){ eventDevicePollers[number] = new EventDevicePoller(number); - final Thread t = new Thread(eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number); + final Thread t = new InterruptSource.Thread(null, eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number); t.setDaemon(true); t.start(); } else if(eventDevicePollers[number].stop) { diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java index f40728da0..53bb9c3a5 100644 --- a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java @@ -37,6 +37,7 @@ import java.io.InputStream; import jogamp.newt.WindowImpl; import jogamp.newt.driver.MouseTracker; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseEvent; @@ -55,7 +56,7 @@ public class LinuxMouseTracker implements WindowListener, MouseTracker { static { lmt = new LinuxMouseTracker(); - final Thread t = new Thread(lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker"); + final Thread t = new InterruptSource.Thread(null, lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker"); t.setDaemon(true); t.start(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java index c8146b85d..8ff37872b 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java @@ -70,7 +70,9 @@ public class DisplayDriver extends DisplayImpl { // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly! final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons(); final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1); - image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.RGBA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + if( null != urlConn ) { + image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.RGBA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } } catch (final Exception e) { e.printStackTrace(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 0ab400fa3..e6ae7719c 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -34,6 +34,7 @@ package jogamp.newt.driver.macosx; +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindow; @@ -41,7 +42,6 @@ import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.MutableSurface; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.nativewindow.VisualIDHolder; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.Point; import com.jogamp.nativewindow.util.PointImmutable; @@ -119,11 +119,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Called from native code */ protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float maxPixelScaleRaw) { - final long handle = getWindowHandle(); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (new), "+maxPixelScaleRaw+" (max), drop "+(0==handle)); + System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (new), "+maxPixelScaleRaw+" (max), drop "+!isNativeValid()); } - if( 0 != handle ) { + if( isNativeValid() ) { updatePixelScale(true /* sendEvent*/, defer, true /*offthread */, newPixelScaleRaw, maxPixelScaleRaw); } } @@ -197,7 +196,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } setGraphicsConfiguration(cfg); reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY, true)); - if (0 == getWindowHandle()) { + if ( !isNativeValid() ) { throw new NativeWindowException("Error creating window"); } } @@ -212,6 +211,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl surfaceHandle = 0; sscSurfaceHandle = 0; isOffscreenInstance = false; + resizeAnimatorPaused = false; if (0 != handle) { OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() { @Override @@ -269,7 +269,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); } sscSurfaceHandle = surfaceHandle; - if (isNativeValid()) { + if ( isNativeValid() ) { if (0 != sscSurfaceHandle) { OSXUtil.RunOnMainThread(false, false, new Runnable() { @Override @@ -341,15 +341,20 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( 0 != handle && !isOffscreenInstance ) { final NativeWindow parent = getParent(); final boolean useParent = useParent(parent); - final int pX=parent.getX(), pY=parent.getY(); - final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent); + final Point p0S; + if( useParent ) { + p0S = getLocationOnScreenByParent(x, y, parent); + } else { + p0S = (Point) getLocationOnScreen0(handle, x, y); + } if(DEBUG_IMPLEMENTATION) { + final int pX=parent.getX(), pY=parent.getY(); System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos"); } OSXUtil.RunOnMainThread(false, false, new Runnable() { @Override public void run() { - setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible()); + setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible()); } } ); // no native event (fullscreen, some reparenting) positionChanged(true, x, y); @@ -357,39 +362,20 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } @Override - protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) { - final long handle = getWindowHandle(); - if( 0 != handle && !isOffscreenInstance ) { - final NativeWindow parent = getParent(); - final boolean useParent = useParent(parent); - if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) { - final int x=getX(), y=getY(); - final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent); - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos"); - } - OSXUtil.RunOnMainThread(false, false, new Runnable() { - @Override - public void run() { - setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible()); - } } ); - } - } - superSizeChangedOffThread(defer, newWidth, newHeight, force); - } - private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) { - if( defer ) { - new Thread() { - public void run() { - WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); - } }.start(); - } else { - WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); - } + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask | + STATE_MASK_CHILDWIN | + STATE_MASK_UNDECORATED | + STATE_MASK_ALWAYSONTOP | + STATE_MASK_ALWAYSONBOTTOM | + STATE_MASK_STICKY | + STATE_MASK_RESIZABLE | + STATE_MASK_MAXIMIZED_VERT | + STATE_MASK_MAXIMIZED_HORZ | + STATE_MASK_POINTERVISIBLE | + STATE_MASK_POINTERCONFINED; } - private final int[] normPosSize = { 0, 0, 0, 0 }; - @Override protected boolean reconfigureWindowImpl(int _x, int _y, int _width, int _height, final int flags) { final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); @@ -400,9 +386,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl pClientLevelOnSreen = new Point(0, 0); } else { final NativeWindow parent = getParent(); - final boolean useParent = useParent(parent); - if( useParent ) { - pClientLevelOnSreen = getLocationOnScreenImpl(_x, _y, parent, useParent); + if( useParent(parent) ) { + pClientLevelOnSreen = getLocationOnScreenByParent(_x, _y, parent); } else { if( 0 != ( ( CHANGE_MASK_MAXIMIZED_HORZ | CHANGE_MASK_MAXIMIZED_VERT ) & flags ) ) { final int[] posSize = { _x, _y, _width, _height }; @@ -424,7 +409,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration(); final NativeWindow pWin = getParent(); final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null; - System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+ + System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPosOnScreen "+pClientLevelOnSreen+" - "+width+"x"+height+ ", "+getReconfigStateMaskString(flags)+ ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+ ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+ @@ -449,38 +434,47 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl visibleChanged(true, false); } } - if( ( 0 == getWindowHandle() && 0 != ( STATE_MASK_VISIBLE & flags) ) || + final long oldWindowHandle = getWindowHandle(); + if( ( 0 == oldWindowHandle && 0 != ( STATE_MASK_VISIBLE & flags) ) || 0 != ( CHANGE_MASK_PARENTING & flags) || 0 != ( CHANGE_MASK_DECORATION & flags) || + 0 != ( CHANGE_MASK_ALWAYSONTOP & flags) || + 0 != ( CHANGE_MASK_ALWAYSONBOTTOM & flags) || 0 != ( CHANGE_MASK_RESIZABLE & flags) || 0 != ( CHANGE_MASK_FULLSCREEN & flags) ) { if(isOffscreenInstance) { - createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, flags); + createWindow(true, 0 != oldWindowHandle, pClientLevelOnSreen, 64, 64, flags); } else { - createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, flags); + createWindow(false, 0 != oldWindowHandle, pClientLevelOnSreen, width, height, flags); } // no native event (fullscreen, some reparenting) - positionChanged(false, x, y); updatePixelScaleByWindowHandle(false /* sendEvent */); - super.sizeChanged(false, width, height, true); + if( isOffscreenInstance) { + super.sizeChanged(false, width, height, true); + positionChanged(false, x, y); + } else { + updateSizePosInsets0(getWindowHandle(), false); + } visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags)); if( hasFocus ) { requestFocusImpl(true); } - } else { + } else if( 0 != oldWindowHandle ) { if( width>0 && height>0 ) { if( !isOffscreenInstance ) { OSXUtil.RunOnMainThread(true, false, new Runnable() { @Override public void run() { - setWindowClientTopLeftPointAndSize0(getWindowHandle(), + setWindowClientTopLeftPointAndSize0(oldWindowHandle, pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, 0 != ( STATE_MASK_VISIBLE & flags)); } } ); - } // else offscreen size is realized via recreation - // no native event (fullscreen, some reparenting) - positionChanged(true, x, y); - super.sizeChanged(true, width, height, false); + updateSizePosInsets0(oldWindowHandle, false); + } else { // else offscreen size is realized via recreation + // no native event (fullscreen, some reparenting) + super.sizeChanged(false, width, height, false); + positionChanged(false, x, y); + } } if( 0 != ( CHANGE_MASK_VISIBILITY & flags) && 0 != ( STATE_MASK_VISIBLE & flags) ) @@ -496,13 +490,11 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl visibleChanged(true, true); } } - if( !isOffscreenInstance ) { - setAlwaysOnTop0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONTOP & flags)); - setAlwaysOnBottom0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags)); - } + } else { + throw new InternalError("Null windowHandle but no re-creation triggered, check visibility: "+getStateMaskString()); } if(DEBUG_IMPLEMENTATION) { - System.err.println("MaxWindow reconfig.X: "+getLocationOnScreenImpl(0, 0)+" "+getWidth()+"x"+getHeight()+", insets "+getInsets()+", "+getStateMaskString()); + System.err.println("MacWindow reconfig.X: "+getLocationOnScreenImpl(0, 0)+" "+getWidth()+"x"+getHeight()+", insets "+getInsets()+", "+getStateMaskString()); } return true; } @@ -510,41 +502,50 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected Point getLocationOnScreenImpl(final int x, final int y) { final NativeWindow parent = getParent(); - final boolean useParent = useParent(parent); - return getLocationOnScreenImpl(x, y, parent, useParent); - } - - private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) { - if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) { - return OSXUtil.GetLocationOnScreen(surfaceHandle, x, y); + if( useParent(parent) ) { + return getLocationOnScreenByParent(x, y, parent); + } else { + final long windowHandle = getWindowHandle(); + if( !isOffscreenInstance && 0 != windowHandle ) { + return (Point) getLocationOnScreen0(windowHandle, x, y); + } else { + return new Point(x, y); + } } + } - final Point p = new Point(x, y); - if( useParent ) { - p.translate( parent.getLocationOnScreen(null) ); - } - return p; + private Point getLocationOnScreenByParent(final int x, final int y, final NativeWindow parent) { + return new Point(x, y).translate( parent.getLocationOnScreen(null) ); } /** Callback for native screen position change event of the client area. */ protected void screenPositionChanged(final boolean defer, final int newX, final int newY) { // passed coordinates are in screen position of the client area - if(getWindowHandle()!=0) { + if( isNativeValid() ) { final NativeWindow parent = getParent(); - if( null == parent || isOffscreenInstance ) { + if( !useParent(parent) || isOffscreenInstance ) { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } positionChanged(defer, newX, newY); } else { - // screen position -> rel child window position - final Point absPos = new Point(newX, newY); - final Point parentOnScreen = parent.getLocationOnScreen(null); - absPos.translate( parentOnScreen.scale(-1, -1) ); - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos); + final Runnable action = new Runnable() { + public void run() { + // screen position -> rel child window position + final Point absPos = new Point(newX, newY); + final Point parentOnScreen = parent.getLocationOnScreen(null); + absPos.translate( parentOnScreen.scale(-1, -1) ); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos); + } + positionChanged(false, absPos.getX(), absPos.getY()); + } }; + if( defer ) { + new InterruptSource.Thread(null, action).start(); + } else { + action.run(); } - positionChanged(defer, absPos.getX(), absPos.getY()); + } } else if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); @@ -552,6 +553,65 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } @Override + protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) { + if(force || getWidth() != newWidth || getHeight() != newHeight) { + if( isNativeValid() && !isOffscreenInstance ) { + final NativeWindow parent = getParent(); + final boolean useParent = useParent(parent); + if( useParent ) { + final int x=getX(), y=getY(); + final Point p0S = getLocationOnScreenByParent(x, y, parent); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos"); + } + OSXUtil.RunOnMainThread(false, false, new Runnable() { + @Override + public void run() { + setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible()); + } } ); + } + } + superSizeChangedOffThread(defer, newWidth, newHeight, force); + } + } + private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) { + if( defer ) { + new InterruptSource.Thread() { + public void run() { + WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); + } }.start(); + } else { + WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); + } + } + + // + // Accumulated actions + // + + /** Triggered by implementation's WM events to update the client-area position, size and insets. */ + protected void sizeScreenPosInsetsChanged(final boolean defer, + final int newX, final int newY, + final int newWidth, final int newHeight, + final int left, final int right, final int top, final int bottom, + final boolean force, + final boolean withinLiveResize) { + final LifecycleHook lh = getLifecycleHook(); + if( withinLiveResize && !resizeAnimatorPaused && null!=lh ) { + resizeAnimatorPaused = lh.pauseRenderingAction(); + } + sizeChanged(defer, newWidth, newHeight, force); + screenPositionChanged(defer, newX, newY); + insetsChanged(defer, left, right, top, bottom); + if( !withinLiveResize && resizeAnimatorPaused ) { + resizeAnimatorPaused = false; + if( null!=lh ) { + lh.resumeRenderingAction(); + } + } + } + + @Override protected void setPointerIconImpl(final PointerIconImpl pi) { if( !isOffscreenInstance ) { final long piHandle = null != pi ? pi.validatedHandle() : 0; @@ -655,10 +715,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl protected int getDisplayID() { if( !isOffscreenInstance ) { - final long whandle = getWindowHandle(); - if(0 != whandle) { - return getDisplayID0(whandle); - } + return getDisplayID0(getWindowHandle()); } return 0; } @@ -718,32 +775,35 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } windowStyle = ws; } - final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, - 0 != ( STATE_MASK_FULLSCREEN & flags), - windowStyle, - NSBackingStoreBuffered, surfaceHandle); - if ( newWin == 0 ) { - throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this); - } - setWindowHandle( newWin ); - - final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance; // Blocking initialization on main-thread! + final long[] newWin = { 0 }; OSXUtil.RunOnMainThread(true, false /* kickNSApp */, new Runnable() { @Override public void run() { - initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */, - isOpaque, - !offscreenInstance && 0 != ( STATE_MASK_VISIBLE & flags), - surfaceHandle); - if( offscreenInstance ) { - orderOut0(0!=parentWinHandle ? parentWinHandle : newWin); - } else { - setTitle0(newWin, getTitle()); - setAlwaysOnTop0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONTOP & flags)); - setAlwaysOnBottom0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags)); + newWin[0] = createWindow0( pS.getX(), pS.getY(), width, height, + 0 != ( STATE_MASK_FULLSCREEN & flags), + windowStyle, + NSBackingStoreBuffered, surfaceHandle); + if ( newWin[0] != 0 ) { + final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance; + initWindow0( parentWinHandle, newWin[0], pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */, + isOpaque, + !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONTOP & flags), + !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags), + !offscreenInstance && 0 != ( STATE_MASK_VISIBLE & flags), + surfaceHandle); + if( offscreenInstance ) { + orderOut0(0!=parentWinHandle ? parentWinHandle : newWin[0]); + } else { + setTitle0(newWin[0], getTitle()); + } } } }); + + if ( newWin[0] == 0 ) { + throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this); + } + setWindowHandle( newWin[0] ); } catch (final Exception ie) { ie.printStackTrace(); } @@ -754,7 +814,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view); /** Must be called on Main-Thread */ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale, - boolean opaque, boolean visible, long view); + boolean opaque, boolean atop, boolean abottom, boolean visible, long view); + private native int getDisplayID0(long window); private native void setPixelScale0(long window, long view, float reqPixelScale); private native boolean lockSurface0(long window, long view); @@ -778,10 +839,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display); /** Must be called on Main-Thread */ private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display); - /** Must be called on Main-Thread */ - private native void setAlwaysOnTop0(long window, boolean atop); - /** Must be called on Main-Thread */ - private native void setAlwaysOnBottom0(long window, boolean abottom); + /** Triggers {@link #sizeScreenPosInsetsChanged(boolean, int, int, int, int, int, int, int, int, boolean)} */ + private native void updateSizePosInsets0(long window, boolean defer); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); private static native void setPointerIcon0(long windowHandle, long handle); private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); @@ -803,5 +862,5 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private volatile long surfaceHandle = 0; private long sscSurfaceHandle = 0; private boolean isOffscreenInstance = false; - + private boolean resizeAnimatorPaused = false; } diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java index f9f1f13ad..f7d6b9f25 100644 --- a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java +++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java @@ -46,9 +46,17 @@ public class JoglUtilPNGIcon { data_size[0] = 0; for(int i=0; i<resources.resourceCount(); i++) { final URLConnection urlConn = resources.resolve(i); - final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); - data_size[0] += 2 + image.getSize().getWidth() * image.getSize().getHeight(); - images[i] = image; + if( null != urlConn ) { + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + data_size[0] += 2 + image.getSize().getWidth() * image.getSize().getHeight(); + images[i] = image; + } else { + images[i] = null; + } + } + if( 0 == data_size[0] ) { + // no image, abort + return null; } final boolean is64Bit = Platform.is64Bit(); elem_bytesize[0] = is64Bit ? Buffers.SIZEOF_LONG : Buffers.SIZEOF_INT; @@ -56,29 +64,31 @@ public class JoglUtilPNGIcon { for(int i=0; i<images.length; i++) { final PNGPixelRect image1 = images[i]; - final int width = image1.getSize().getWidth(); - final int height = image1.getSize().getHeight(); - if( is64Bit ) { - buffer.putLong(width); - buffer.putLong(height); - } else { - buffer.putInt(width); - buffer.putInt(height); - } - final ByteBuffer bb = image1.getPixels(); - final int stride = image1.getStride(); - for(int y=0; y<height; y++) { - int bbOff = y * stride; - for(int x=0; x<width; x++) { - long pixel; - pixel = ( 0xffL & bb.get(bbOff++) ); // B - pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G - pixel |= ( 0xffL & bb.get(bbOff++) ) << 16; // R - pixel |= ( 0xffL & bb.get(bbOff++) ) << 24; // A - if( is64Bit ) { - buffer.putLong(pixel); - } else { - buffer.putInt((int)pixel); + if( null != image1 ) { + final int width = image1.getSize().getWidth(); + final int height = image1.getSize().getHeight(); + if( is64Bit ) { + buffer.putLong(width); + buffer.putLong(height); + } else { + buffer.putInt(width); + buffer.putInt(height); + } + final ByteBuffer bb = image1.getPixels(); + final int stride = image1.getStride(); + for(int y=0; y<height; y++) { + int bbOff = y * stride; + for(int x=0; x<width; x++) { + long pixel; + pixel = ( 0xffL & bb.get(bbOff++) ); // B + pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G + pixel |= ( 0xffL & bb.get(bbOff++) ) << 16; // R + pixel |= ( 0xffL & bb.get(bbOff++) ) << 24; // A + if( is64Bit ) { + buffer.putLong(pixel); + } else { + buffer.putInt((int)pixel); + } } } } diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java index c44aa39f4..0bd7c5b2a 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java @@ -68,19 +68,23 @@ public class DisplayDriver extends DisplayImpl { final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons(); { final URLConnection urlConn = iconRes.resolve(0); - final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); - _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0); + if( null != urlConn ) { + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0); + } } { final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1); - final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); - _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0); + if( null != urlConn ) { + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0); + } } } catch (final Exception e) { e.printStackTrace(); } } - defaultIconHandles = _defaultIconHandle; + defaultIconHandles = _defaultIconHandle; // null is a valid value for an icon handle } sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0(), false /* useDummyDispatchThread */, defaultIconHandles[0], defaultIconHandles[1]); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java index 751ce854a..af5dad3ac 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java @@ -157,6 +157,10 @@ public class WindowDriver extends WindowImpl { if ( 0 == _windowHandle ) { throw new NativeWindowException("Error creating window"); } + if( !cfg.getChosenCapabilities().isBackgroundOpaque() ) { + GDIUtil.DwmSetupTranslucency(_windowHandle, true); + } + InitWindow0(_windowHandle, flags); setWindowHandle(_windowHandle); windowHandleClose = _windowHandle; @@ -200,6 +204,21 @@ public class WindowDriver extends WindowImpl { } @Override + protected final int getSupportedReconfigMaskImpl() { + return minimumReconfigStateMask | + STATE_MASK_CHILDWIN | + STATE_MASK_UNDECORATED | + STATE_MASK_ALWAYSONTOP | + STATE_MASK_ALWAYSONBOTTOM | + // STATE_MASK_STICKY | + STATE_MASK_RESIZABLE | + STATE_MASK_MAXIMIZED_VERT | + STATE_MASK_MAXIMIZED_HORZ | + STATE_MASK_POINTERVISIBLE | + STATE_MASK_POINTERCONFINED; + } + + @Override protected boolean reconfigureWindowImpl(int x, int y, int width, int height, final int flags) { if(DEBUG_IMPLEMENTATION) { System.err.println("WindowsWindow reconfig.0: "+x+"/"+y+" "+width+"x"+height+ @@ -220,7 +239,16 @@ public class WindowDriver extends WindowImpl { width = posSize[2]; height = posSize[3]; } + + final boolean changeDecoration = 0 != ( CHANGE_MASK_DECORATION & flags); + final boolean isTranslucent = !getChosenCapabilities().isBackgroundOpaque(); + if( changeDecoration && isTranslucent ) { + GDIUtil.DwmSetupTranslucency(getWindowHandle(), false); + } reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags); + if( changeDecoration && isTranslucent ) { + GDIUtil.DwmSetupTranslucency(getWindowHandle(), true); + } if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) { visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags)); @@ -381,6 +409,7 @@ public class WindowDriver extends WindowImpl { private native long CreateWindow0(long hInstance, String wndClassName, String wndName, int winMajor, int winMinor, long parentWindowHandle, int x, int y, int width, int height, int flags); + private native void InitWindow0(long windowHandle, int flags); private native long MonitorFromWindow0(long windowHandle); private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, int flags); diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java index 81ccdbfcd..9d89ba085 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java @@ -110,7 +110,7 @@ public class DisplayDriver extends DisplayImpl { final long handle = _aDevice.getHandle(); if(0 != handle) { DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom /*, kbdHandle */, // XKB disabled for now - randr_event_base, randr_error_base); + randr_event_base, randr_error_base, xi_opcode); } } finally { _aDevice.unlock(); @@ -122,6 +122,7 @@ public class DisplayDriver extends DisplayImpl { // protected long getKbdHandle() { return kbdHandle; } // XKB disabled for now protected int getRandREventBase() { return randr_event_base; } protected int getRandRErrorBase() { return randr_error_base; } + protected int getXiOpcode() { return xi_opcode; } /** Returns <code>null</code> if !{@link #isNativeValid()}, otherwise the Boolean value of {@link X11GraphicsDevice#isXineramaEnabled()}. */ protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; } @@ -145,12 +146,13 @@ public class DisplayDriver extends DisplayImpl { private native void CompleteDisplay0(long handle); private void displayCompleted(final long javaObjectAtom, final long windowDeleteAtom /*, long kbdHandle */, - final int randr_event_base, final int randr_error_base) { + final int randr_event_base, final int randr_error_base, final int xi_opcode) { this.javaObjectAtom=javaObjectAtom; this.windowDeleteAtom=windowDeleteAtom; // this.kbdHandle = kbdHandle; // XKB disabled for now this.randr_event_base = randr_event_base; this.randr_error_base = randr_error_base; + this.xi_opcode = xi_opcode; } private void sendRRScreenChangeNotify(final long event) { if( null != rAndR ) { @@ -163,7 +165,7 @@ public class DisplayDriver extends DisplayImpl { private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */); // XKB disabled for now private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */, // XKB disabled for now - final int randr_event_base, final int randr_error_base); + final int randr_event_base, final int randr_error_base, final int xi_opcode); private static long createPointerIcon(final long display, final Buffer pixels, final int width, final int height, final int hotX, final int hotY) { final boolean pixels_is_direct = Buffers.isDirect(pixels); @@ -185,7 +187,7 @@ public class DisplayDriver extends DisplayImpl { /** X11 Keyboard handle used on EDT */ // private long kbdHandle; // XKB disabled for now - private int randr_event_base, randr_error_base; + private int randr_event_base, randr_error_base, xi_opcode; private RandR rAndR; } diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index 5b6ea45d5..afd10f54b 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -46,7 +46,6 @@ import jogamp.newt.driver.PNGIcon; import com.jogamp.nativewindow.*; import com.jogamp.nativewindow.VisualIDHolder.VIDType; -import com.jogamp.nativewindow.util.Insets; import com.jogamp.nativewindow.util.InsetsImmutable; import com.jogamp.nativewindow.util.Point; @@ -128,13 +127,13 @@ public class WindowDriver extends WindowImpl { try { final long[] handles = CreateWindow(getParentWindowHandle(), edtDevice.getHandle(), screen.getIndex(), visualID, - display.getJavaObjectAtom(), display.getWindowDeleteAtom(), + display.getJavaObjectAtom(), display.getWindowDeleteAtom(), display.getXiOpcode(), getX(), getY(), getWidth(), getHeight(), flags, defaultIconDataSize, defaultIconData, DEBUG_IMPLEMENTATION); if (null == handles || 2 != handles.length || 0 == handles[0] || 0 == handles[1] ) { throw new NativeWindowException("Error creating window"); } - if(DEBUG_IMPLEMENTATION) { // FIXME + if(DEBUG_IMPLEMENTATION) { System.err.println("X11Window.createNativeImpl() handles "+toHexString(handles[0])+", "+toHexString(handles[1])); } setWindowHandle(handles[0]); @@ -152,7 +151,7 @@ public class WindowDriver extends WindowImpl { edtDevice.lock(); try { CloseWindow0(edtDevice.getHandle(), javaWindowHandle /* , display.getKbdHandle() */, // XKB disabled for now - display.getRandREventBase(), display.getRandRErrorBase()); + display.getRandREventBase(), display.getRandRErrorBase(), display.getXiOpcode()); } catch (final Throwable t) { if(DEBUG_IMPLEMENTATION) { final Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t); @@ -169,15 +168,9 @@ public class WindowDriver extends WindowImpl { } } - /** - * <p> - * X11 Window supports {@link #FLAG_IS_FULLSCREEN_SPAN} - * </p> - * {@inheritDoc} - */ @Override - protected boolean isReconfigureMaskSupported(final int changeFlags) { - return true; // all flags! + protected final int getSupportedReconfigMaskImpl() { + return ( minimumReconfigStateMask | GetSupportedReconfigMask0(javaWindowHandle) ) & STATE_MASK_ALL_RECONFIG; } @Override @@ -413,6 +406,19 @@ public class WindowDriver extends WindowImpl { } } + public final void sendTouchScreenEvent(final short eventType, final int modifiers, + final int pActionIdx, final int[] pNames, + final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { + final int pCount = pNames.length; + final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount]; + for(int i=0; i<pCount; i++) { + pTypes[i] = MouseEvent.PointerType.TouchScreen; + } + doPointerEvent(false /*enqueue*/, false /*wait*/, + pTypes, eventType, modifiers, pActionIdx, true /*normalPNames*/, pNames, + pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/); + } + @Override public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); @@ -435,7 +441,7 @@ public class WindowDriver extends WindowImpl { protected static native boolean initIDs0(); private long[] CreateWindow(final long parentWindowHandle, final long display, final int screen_index, - final int visualID, final long javaObjectAtom, final long windowDeleteAtom, + final int visualID, final long javaObjectAtom, final long windowDeleteAtom, final int xi_opcode, final int x, final int y, final int width, final int height, final int flags, final int pixelDataSize, final Buffer pixels, final boolean verbose) { // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly! @@ -443,22 +449,22 @@ public class WindowDriver extends WindowImpl { throw new IllegalArgumentException("data buffer is not direct "+pixels); } return CreateWindow0(parentWindowHandle, display, screen_index, - visualID, javaObjectAtom, windowDeleteAtom, + visualID, javaObjectAtom, windowDeleteAtom, xi_opcode, x, y, width, height, flags, pixelDataSize, pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */, verbose); } /** returns long[2] { X11-window-handle, JavaWindow-handle } */ private native long[] CreateWindow0(long parentWindowHandle, long display, int screen_index, - int visualID, long javaObjectAtom, long windowDeleteAtom, + int visualID, long javaObjectAtom, long windowDeleteAtom, int xi_opcode, int x, int y, int width, int height, int flags, int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct, boolean verbose); - private native long GetNativeWindowHandle0(long javaWindowHandle); + private static native int GetSupportedReconfigMask0(long javaWindowHandle); private native void CloseWindow0(long display, long javaWindowHandle /*, long kbdHandle*/, // XKB disabled for now - final int randr_event_base, final int randr_error_base); - private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long javaWindowHandle, - int x, int y, int width, int height, int flags); - private native void requestFocus0(long display, long javaWindowHandle, boolean force); + final int randr_event_base, final int randr_error_base, final int xi_opcode); + private static native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long javaWindowHandle, + int x, int y, int width, int height, int flags); + private static native void requestFocus0(long display, long javaWindowHandle, boolean force); private static native void setTitle0(long display, long javaWindowHandle, String title); diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11UnderlayTracker.java b/src/newt/classes/jogamp/newt/driver/x11/X11UnderlayTracker.java index 6e64e7025..d7e184a3c 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/X11UnderlayTracker.java +++ b/src/newt/classes/jogamp/newt/driver/x11/X11UnderlayTracker.java @@ -38,6 +38,7 @@ import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.Capabilities; import com.jogamp.nativewindow.GraphicsConfigurationFactory; import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.util.Point; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; @@ -135,19 +136,59 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl underlayWindow = (WindowImpl)s; WindowImpl overlayWindow = underlayWindowMap.get(s); - if(overlayWindow.getX()!=underlayWindow.getX() || - overlayWindow.getY()!=underlayWindow.getY()) { - overlayWindow.setPosition(underlayWindow.getX(), underlayWindow.getY()); + Point overlayOnScreen = new Point(); + Point underlayOnScreen = new Point(); + overlayWindow.getLocationOnScreen(overlayOnScreen); + underlayWindow.getLocationOnScreen(underlayOnScreen); + /* + * Apply an offset when the dimensions of over- and + * underlay don't match + */ + int dx = (overlayWindow.getScreen().getWidth() - underlayWindow.getScreen().getWidth()) / 2; + int dy = (overlayWindow.getScreen().getHeight() - underlayWindow.getScreen().getHeight()) / 2; + underlayOnScreen.translate(dx, dy); + if(overlayOnScreen.getX()!=underlayOnScreen.getX() || + overlayOnScreen.getY()!=underlayOnScreen.getY()) { + overlayWindow.setPosition(underlayOnScreen.getX(), underlayOnScreen.getY()); } } else if (overlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = (WindowImpl)s; WindowImpl underlayWindow = overlayWindowMap.get(s); - if(overlayWindow.getX()!=underlayWindow.getX() || - overlayWindow.getY()!=underlayWindow.getY()) { - //FIXME: Pressing Maximize on the underlay X11 - //with this line enabled locks-up the NEWT EDT while using the BCM.VC.IV - //underlayWindow.setPosition(overlayWindow.getX(), overlayWindow.getY()); + // FIXME: Pressing Maximize on the underlay X11 + // with these lines enabled locks-up the NEWT EDT + /* + Point overlayOnScreen = new Point(); + Point underlayOnScreen = new Point(); + overlayWindow.getLocationOnScreen(overlayOnScreen); + underlayWindow.getLocationOnScreen(underlayOnScreen); + if(overlayOnScreen.getX()!=underlayOnScreen.getX() || + overlayOnScreen.getY()!=underlayOnScreen.getY()) { + underlayWindow.setPosition(overlayOnScreen.getX(), overlayOnScreen.getY()); } + */ + /* it locks up like this + Caused by: java.lang.RuntimeException: Waited 5000ms for: <5ccc078, 45700941>[count 1, qsz 0, owner <main-Display-.x11_:0-1-EDT-1>] - <main-Display-.x11_:0-2-EDT-1> + at jogamp.common.util.locks.RecursiveLockImpl01Unfairish.lock(RecursiveLockImpl01Unfairish.java:198) + at jogamp.nativewindow.ResourceToolkitLock.lock(ResourceToolkitLock.java:56) + at com.jogamp.nativewindow.DefaultGraphicsDevice.lock(DefaultGraphicsDevice.java:126) + at jogamp.newt.DisplayImpl.runWithLockedDevice(DisplayImpl.java:780) + at jogamp.newt.DisplayImpl.runWithLockedDisplayDevice(DisplayImpl.java:793) + at jogamp.newt.driver.x11.WindowDriver.runWithLockedDisplayDevice(WindowDriver.java:425) + at jogamp.newt.driver.x11.WindowDriver.getLocationOnScreenImpl(WindowDriver.java:334) + at jogamp.newt.WindowImpl.getLocationOnScreen(WindowImpl.java:1113) + at jogamp.newt.driver.x11.X11UnderlayTracker.windowMoved(X11UnderlayTracker.java:153) + at jogamp.newt.WindowImpl.consumeWindowEvent(WindowImpl.java:4243) + at jogamp.newt.WindowImpl.sendWindowEvent(WindowImpl.java:4174) + at jogamp.newt.WindowImpl.positionChanged(WindowImpl.java:4403) + at jogamp.newt.WindowImpl.sizePosMaxInsetsChanged(WindowImpl.java:4567) + at jogamp.newt.driver.x11.DisplayDriver.DispatchMessages0(Native Method) + at jogamp.newt.driver.x11.DisplayDriver.dispatchMessagesNative(DisplayDriver.java:112) + at jogamp.newt.WindowImpl.waitForPosition(WindowImpl.java:4438) + at jogamp.newt.WindowImpl.access$2200(WindowImpl.java:96) + at jogamp.newt.WindowImpl$SetPositionAction.run(WindowImpl.java:2765) + at com.jogamp.common.util.RunnableTask.run(RunnableTask.java:150) + at jogamp.newt.DefaultEDTUtil$NEDT.run(DefaultEDTUtil.java:372) + */ } } @@ -282,7 +323,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_CLICKED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -293,7 +334,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -304,7 +345,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_EXITED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -315,7 +356,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_PRESSED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -326,7 +367,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_RELEASED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -337,7 +378,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_MOVED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -348,7 +389,7 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @@ -359,27 +400,23 @@ public class X11UnderlayTracker implements WindowListener, KeyListener, MouseLis if (underlayWindowMap.containsKey(s)) { WindowImpl overlayWindow = underlayWindowMap.get(s); overlayWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_WHEEL_MOVED, 0, - e.getX(), e.getY(), (short) 0, 0); + e.getX(), e.getY(), e.getButton(), 0); } } @Override public void keyPressed(KeyEvent e) { if (focusedWindow != null) { - // e.setConsumed(false); - // focusedWindow.consumeEvent(e); focusedWindow.sendKeyEvent(e.getEventType(), e.getModifiers(), - e.getKeyCode(), e.getKeyCode(), (char) e.getKeySymbol()); + e.getKeyCode(), e.getKeySymbol(), e.getKeyChar()); } } @Override public void keyReleased(KeyEvent e) { if (focusedWindow != null) { - // e.setConsumed(false); - // focusedWindow.consumeEvent(e); focusedWindow.sendKeyEvent(e.getEventType(), e.getModifiers(), - e.getKeyCode(), e.getKeyCode(), (char) e.getKeySymbol()); + e.getKeyCode(), e.getKeySymbol(), e.getKeyChar()); } } diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java index 2bdab2796..260a1beb4 100644 --- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java +++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java @@ -38,19 +38,27 @@ public class NEWTEventTask { private final NEWTEvent event; private final Object notifyObject; private RuntimeException exception; + private volatile boolean dispatched; public NEWTEventTask(final NEWTEvent event, final Object notifyObject) { this.event = event ; this.notifyObject = notifyObject ; this.exception = null; + this.dispatched = false; } public final NEWTEvent get() { return event; } public final void setException(final RuntimeException e) { exception = e; } public final RuntimeException getException() { return exception; } public final boolean isCallerWaiting() { return null != notifyObject; } + public final boolean isDispatched() { return dispatched; } + public final void setDispatched() { dispatched = true; } + /** + * Notifies caller after {@link #setDispatched()}. + */ public void notifyCaller() { + setDispatched(); if(null != notifyObject) { synchronized (notifyObject) { notifyObject.notifyAll(); diff --git a/src/newt/classes/jogamp/newt/javafx/JFXEDTUtil.java b/src/newt/classes/jogamp/newt/javafx/JFXEDTUtil.java new file mode 100644 index 000000000..4ee15b43d --- /dev/null +++ b/src/newt/classes/jogamp/newt/javafx/JFXEDTUtil.java @@ -0,0 +1,358 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.newt.javafx; + +import com.jogamp.nativewindow.NativeWindowException; +import com.jogamp.nativewindow.javafx.JFXAccessor; + +import jogamp.newt.Debug; + +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; +import com.jogamp.common.util.RunnableTask; +import com.jogamp.newt.util.EDTUtil; + +import javafx.application.Platform; + +/** + * Simple {@link EDTUtil} implementation utilizing the JFX UI thread + * of the given {@link Display}. + */ +public class JFXEDTUtil implements EDTUtil { + public static final boolean DEBUG = Debug.debug("EDT"); + + private final Object edtLock = new Object(); // locking the EDT start/stop state + private final ThreadGroup threadGroup; + private final String name; + private final Runnable dispatchMessages; + private NEDT nedt = null; + private int start_iter=0; + private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; + + public JFXEDTUtil(final com.jogamp.newt.Display newtDisplay) { + this.threadGroup = Thread.currentThread().getThreadGroup(); + this.name=Thread.currentThread().getName()+"-JFXDisplay-"+newtDisplay.getFQName()+"-EDT-"; + this.dispatchMessages = new Runnable() { + @Override + public void run() { + ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages(); + } }; + this.nedt = new NEDT(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. + } + + @Override + public long getPollPeriod() { + return pollPeriod; + } + + @Override + public void setPollPeriod(final long ms) { + pollPeriod = ms; // writing to static field is intended + } + + @Override + public final void start() throws IllegalStateException { + synchronized(edtLock) { + if( nedt.isRunning() ) { + final Thread curT = Thread.currentThread(); + final boolean onJFXEDT = JFXAccessor.isJFXThread(); + throw new IllegalStateException("EDT still running and not subject to stop. Curr "+curT.getName()+ + ", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", JFX-EDT "+JFXAccessor.getJFXThreadName()+", on JFX-EDT "+onJFXEDT); + } + if(DEBUG) { + System.err.println(Thread.currentThread()+": JFX-EDT reset - edt: "+nedt); + } + if( !JFXAccessor.hasJFXThreadStopped() ) { + if( nedt.getState() != Thread.State.NEW ) { + nedt = new NEDT(threadGroup, name); + nedt.setDaemon(true); // don't stop JVM from shutdown .. + } + startImpl(); + } + } + if( !JFXAccessor.hasJFXThreadStopped() ) { + if( !nedt.isRunning() ) { + throw new RuntimeException("EDT could not be started: "+nedt); + } + } else { + // FIXME: Throw exception ? + } + } + + private final void startImpl() { + if(nedt.isAlive()) { + throw new RuntimeException("JFX-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt); + } + start_iter++; + nedt.setName(name+start_iter); + if(DEBUG) { + System.err.println(Thread.currentThread()+": JFX-EDT START - edt: "+nedt+", jfxThread "+JFXAccessor.getJFXThreadName()); + // Thread.dumpStack(); + } + nedt.start(); + } + + @Override + public boolean isCurrentThreadEDT() { + return JFXAccessor.isJFXThread(); + } + + @Override + public final boolean isCurrentThreadNEDT() { + return nedt == Thread.currentThread(); + } + + @Override + public final boolean isCurrentThreadEDTorNEDT() { + return JFXAccessor.isJFXThread() || Thread.currentThread() == nedt ; + } + + @Override + public boolean isRunning() { + return nedt.isRunning(); + } + + @Override + public final boolean invokeStop(final boolean wait, final Runnable task) { + return invokeImpl(wait, task, true); + } + + @Override + public final boolean invoke(final boolean wait, final Runnable task) { + return invokeImpl(wait, task, false); + } + + private static Runnable nullTask = new Runnable() { + @Override + public void run() { } + }; + + private final boolean invokeImpl(boolean wait, final Runnable task, boolean stop) { + final RunnableTask rTask; + final Object rTaskLock = new Object(); + synchronized(rTaskLock) { // lock the optional task execution + synchronized(edtLock) { // lock the EDT status + if( nedt.shouldStop ) { + // drop task .. + if(DEBUG) { + System.err.println(Thread.currentThread()+": Warning: JFX-EDT about (1) to stop, won't enqueue new task: "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop); + ExceptionUtils.dumpStack(System.err); + } + return false; + } + final boolean hasJFXThreadStopped = JFXAccessor.hasJFXThreadStopped(); + + if( hasJFXThreadStopped ) { + stop = true; + } + + if( isCurrentThreadEDT() ) { + if(null != task) { + task.run(); + } + wait = false; // running in same thread (EDT) -> no wait + rTask = null; + if( stop ) { + nedt.shouldStop = true; + } + } else { + if( !nedt.isRunning && !hasJFXThreadStopped ) { + if( null != task ) { + if( stop ) { + System.err.println(Thread.currentThread()+": Warning: JFX-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt); + } else { + System.err.println(Thread.currentThread()+": Warning: JFX-EDT is not running, dropping task. NEDT "+nedt); + } + if(DEBUG) { + ExceptionUtils.dumpStack(System.err); + } + } + return false; + } else if( stop ) { + if( nedt.isRunning ) { + if(DEBUG) { + System.err.println(Thread.currentThread()+": JFX-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop); + } + synchronized(nedt.sync) { + nedt.shouldStop = true; + nedt.sync.notifyAll(); // stop immediate if waiting (poll freq) + } + } + if( JFXAccessor.hasJFXThreadStopped() ) { + System.err.println(Thread.currentThread()+": Warning: JFX-EDT is about (3) to stop and stopped already, dropping task. "+nedt); + if(DEBUG) { + ExceptionUtils.dumpStack(System.err); + } + return false; + } + } + + if( null != task ) { + rTask = new RunnableTask(task, + wait ? rTaskLock : null, + true /* always catch and report Exceptions, don't disturb EDT */, + wait ? null : System.err); + Platform.runLater(rTask); + } else { + wait = false; + rTask = null; + } + } + } + if( wait ) { + try { + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } + final Throwable throwable = rTask.getThrowable(); + if(null!=throwable) { + if(throwable instanceof NativeWindowException) { + throw (NativeWindowException)throwable; + } + throw new RuntimeException(throwable); + } + } + return true; + } + } + + @Override + final public boolean waitUntilIdle() { + final NEDT _nedt; + synchronized(edtLock) { + _nedt = nedt; + } + if( !_nedt.isRunning || Thread.currentThread() == _nedt || JFXAccessor.hasJFXThreadStopped() || JFXAccessor.isJFXThread() ) { + return false; + } + JFXAccessor.runOnJFXThread(true, nullTask); + return true; + } + + @Override + final public boolean waitUntilStopped() { + synchronized(edtLock) { + final Thread curT = Thread.currentThread(); + final boolean onJFXEDT = JFXAccessor.isJFXThread(); + if( nedt.isRunning && nedt != curT && !onJFXEDT ) { + try { + while( nedt.isRunning ) { + edtLock.wait(); + } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); + } + return true; + } else { + return false; + } + } + } + + class NEDT extends InterruptSource.Thread { + volatile boolean shouldStop = false; + volatile boolean isRunning = false; + Object sync = new Object(); + + public NEDT(final ThreadGroup tg, final String name) { + super(tg, null, name); + } + + final public boolean isRunning() { + return isRunning && !shouldStop; + } + + @Override + final public void start() throws IllegalThreadStateException { + isRunning = true; + super.start(); + } + + /** + * Utilizing locking only on tasks and its execution, + * not for event dispatching. + */ + @Override + final public void run() { + if(DEBUG) { + System.err.println(getName()+": JFX-EDT run() START "+ getName()); + } + RuntimeException error = null; + try { + do { + // event dispatch + if(!shouldStop) { + // EDT invoke thread is JFX-EDT, + // hence dispatching is required to run on JFX-EDT as well. + // Otherwise a deadlock may happen due to dispatched event's + // triggering a locking action. + JFXAccessor.runOnJFXThread(true, dispatchMessages); + } + // wait + synchronized(sync) { + if(!shouldStop) { + try { + sync.wait(pollPeriod); + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); + } + } + } + } while(!shouldStop) ; + } catch (final Throwable t) { + // handle errors .. + shouldStop = true; + if(t instanceof RuntimeException) { + error = (RuntimeException) t; + } else { + error = new RuntimeException("Within JFX-EDT", t); + } + } finally { + if(DEBUG) { + System.err.println(getName()+": JFX-EDT run() END "+ getName()+", "+error); + } + synchronized(edtLock) { + isRunning = false; + edtLock.notifyAll(); + } + if(DEBUG) { + System.err.println(getName()+": JFX-EDT run() EXIT "+ getName()+", exception: "+error); + } + if(null!=error) { + throw error; + } + } // finally + } // run() + } // EventDispatchThread + +} diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java index 9039b6083..9d2b41bbc 100644 --- a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java @@ -32,6 +32,8 @@ import com.jogamp.nativewindow.NativeWindowException; import jogamp.newt.Debug; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.util.EDTUtil; @@ -162,8 +164,7 @@ public class SWTEDTUtil implements EDTUtil { } private final boolean invokeImpl(boolean wait, final Runnable task, boolean stop) { - Throwable throwable = null; - RunnableTask rTask = null; + final RunnableTask rTask; final Object rTaskLock = new Object(); synchronized(rTaskLock) { // lock the optional task execution synchronized(edtLock) { // lock the EDT status @@ -184,6 +185,7 @@ public class SWTEDTUtil implements EDTUtil { task.run(); } wait = false; // running in same thread (EDT) -> no wait + rTask = null; if( stop ) { nedt.shouldStop = true; } @@ -225,18 +227,21 @@ public class SWTEDTUtil implements EDTUtil { true /* always catch and report Exceptions, don't disturb EDT */, wait ? null : System.err); swtDisplay.asyncExec(rTask); + } else { + wait = false; + rTask = null; } } } if( wait ) { try { - rTaskLock.wait(); // free lock, allow execution of rTask + while( rTask.isInQueue() ) { + rTaskLock.wait(); // free lock, allow execution of rTask + } } catch (final InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); + throw new InterruptedRuntimeException(ie); } + final Throwable throwable = rTask.getThrowable(); if(null!=throwable) { if(throwable instanceof NativeWindowException) { throw (NativeWindowException)throwable; @@ -274,12 +279,12 @@ public class SWTEDTUtil implements EDTUtil { final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null; final boolean onSWTEDT = swtT == curT; if( nedt.isRunning && nedt != curT && !onSWTEDT ) { - while( nedt.isRunning ) { - try { + try { + while( nedt.isRunning ) { edtLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); } + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); } return true; } else { @@ -288,13 +293,13 @@ public class SWTEDTUtil implements EDTUtil { } } - class NEDT extends Thread { + class NEDT extends InterruptSource.Thread { volatile boolean shouldStop = false; volatile boolean isRunning = false; Object sync = new Object(); public NEDT(final ThreadGroup tg, final String name) { - super(tg, name); + super(tg, null, name); } final public boolean isRunning() { @@ -337,7 +342,7 @@ public class SWTEDTUtil implements EDTUtil { try { sync.wait(pollPeriod); } catch (final InterruptedException e) { - e.printStackTrace(); + throw new InterruptedRuntimeException(e); } } } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index b59e19e4e..ee012add3 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -832,8 +832,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow } JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getDisplayID0(JNIEnv *env, jobject jthis, jlong window) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); + if( NULL == myWindow ) { + DBG_PRINT( "getDisplayID0 - NULL NEWT win - abort\n"); + return 0; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSScreen *screen = [myWindow screen]; int32_t displayID = (int32_t)NewtScreen_getCGDirectDisplayIDByNSScreen(screen); [pool release]; @@ -849,16 +853,16 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getDisplayID0 */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0 (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, jfloat reqPixelScale, - jboolean opaque, jboolean visible, jlong jview) + jboolean opaque, jboolean atop, jboolean abottom, jboolean visible, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); NewtView* myView = (NewtView*) (intptr_t) jview ; BOOL fullscreen = myWindow->isFullscreenWindow; - DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, fs %d, visible %d, view %p (START)\n", + DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, atop %d, abottom %d, fs %d, visible %d, view %p (START)\n", (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale, - (int) opaque, (int)fullscreen, (int)visible, myView); + (int) opaque, (int)atop, (int)abottom, (int)fullscreen, (int)visible, myView); NS_DURING // HiDPI scaling: Setup - Available >= 10.7 @@ -921,6 +925,7 @@ NS_ENDHANDLER [myWindow setOpaque: NO]; [myWindow setBackgroundColor: [NSColor clearColor]]; } + [myWindow setAlwaysOn: atop bottom:abottom]; // specify we want mouse-moved events [myWindow setAcceptsMouseMovedEvents:YES]; @@ -1035,8 +1040,12 @@ NS_ENDHANDLER JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPixelScale0 (JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window); + if( NULL == myWindow ) { + DBG_PRINT( "setPixelScale0 - NULL NEWT win - abort\n"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* myView = (NewtView*) (intptr_t) view ; #ifdef VERBOSE_ON int dbgIdx = 1; @@ -1195,8 +1204,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSur JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 (JNIEnv *env, jobject window, jlong w, jboolean force) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) w); + if( NULL == mWin ) { + DBG_PRINT( "requestFocus - NULL NEWT win - abort\n"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; #ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; #endif @@ -1220,12 +1233,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0 (JNIEnv *env, jobject window, jlong w) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) w); + if( NULL == mWin ) { + DBG_PRINT( "resignFocus0 - NULL NEWT win - abort\n"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* pWin = [mWin parentWindow]; BOOL hasFocus = [mWin isKeyWindow]; - DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + DBG_PRINT( "resignFocus0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); if( hasFocus ) { if(NULL != pWin) { // [mWin makeFirstResponder: pWin]; @@ -1234,7 +1251,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0 [pWin resignKeyWindow]; } } - DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin); + DBG_PRINT( "resignFocus0 - window: %p (END)\n", mWin); [pool release]; } @@ -1247,8 +1264,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0 JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0 (JNIEnv *env, jobject unused, jlong window) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "orderFront0 - NULL NEWT win - abort\n"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* pWin = [mWin parentWindow]; DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); @@ -1272,8 +1293,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0 JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 (JNIEnv *env, jobject unused, jlong window) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "orderOut0 - NULL NEWT win - abort\n"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* pWin = [mWin parentWindow]; DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); @@ -1297,8 +1322,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0 (JNIEnv *env, jobject unused, jlong window, jstring title) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* win = (NSWindow*) ((intptr_t) window); + if( NULL == win ) { + DBG_PRINT( "setTitle0 - NULL NEWT win - abort\n"); + return; + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "setTitle0 - window: %p (START)\n", win); @@ -1374,88 +1403,64 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContent /* * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: setWindowClientTopLeftPointAndSize0 - * Signature: (JIIIIZ)V + * Method: updateSizePosInsets0 + * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0 - (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display) +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_updateSizePosInsets0 + (JNIEnv *env, jobject jthis, jlong window, jboolean defer) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); - DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin); + DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (START)\n", mWin, (int)defer); - setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display); + [mWin updateSizePosInsets: env jwin:jthis defer:defer]; - DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin); + DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (END)\n", mWin, (int)defer); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: setWindowClientTopLeftPoint0 - * Signature: (JIIZ)V + * Method: setWindowClientTopLeftPointAndSize0 + * Signature: (JIIIIZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0 - (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display) +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0 + (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); - DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin); + DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin); - setWindowClientTopLeftPoint(mWin, x, y, display); + setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display); - DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin); + DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: setAlwaysOnTop0 - * Signature: (JZ)V + * Method: setWindowClientTopLeftPoint0 + * Signature: (JIIZ)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTop0 - (JNIEnv *env, jobject unused, jlong window, jboolean atop) +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0 + (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = (NSWindow*) ((intptr_t) window); - - DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (START)\n", win, (int)atop); - - if(atop) { - [win setLevel:NSFloatingWindowLevel]; - } else { - [win setLevel:NSNormalWindowLevel]; + NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "setWindowClientTopLeftPoint - NULL NEWT win - abort\n"); + return; } - - DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (END)\n", win, (int)atop); - - [pool release]; -} - -/* - * Class: jogamp_newt_driver_macosx_WindowDriver - * Method: setAlwaysOnBottom0 - * Signature: (JZ)V - */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnBottom0 - (JNIEnv *env, jobject unused, jlong window, jboolean abottom) -{ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = (NSWindow*) ((intptr_t) window); - DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (START)\n", win, (int)abottom); + DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin); - if(abottom) { - [win setLevel:NSScreenSaverWindowLevel]; // ?? - } else { - [win setLevel:NSNormalWindowLevel]; - } + setWindowClientTopLeftPoint(mWin, x, y, display); - DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (END)\n", win, (int)abottom); + DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin); [pool release]; } @@ -1469,6 +1474,10 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y) { NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) win; + if( NULL == mWin ) { + DBG_PRINT( "getLocationOnScreen0 - NULL NEWT win - abort\n"); + return NULL; + } if( ![mWin isKindOfClass:[NewtMacWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return NULL; @@ -1480,12 +1489,16 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocatio JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 (JNIEnv *env, jobject unused, jlong window, jlong handle) { + NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; + if( NULL == mWin ) { + DBG_PRINT( "setPointerIcon0 - NULL NEWT win - abort\n"); + return; + } NSCursor *c = (NSCursor*) (intptr_t) handle ; if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c); return; } - NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window; if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; @@ -1509,6 +1522,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVis (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "setPointerVisible0 - NULL NEWT win - abort\n"); + return; + } if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; @@ -1533,6 +1550,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointe (JNIEnv *env, jclass clazz, jlong window, jboolean confine) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "confinePointer0 - NULL NEWT win - abort\n"); + return; + } if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; @@ -1556,6 +1577,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + if( NULL == mWin ) { + DBG_PRINT( "warpPointer0 - NULL NEWT win - abort\n"); + return; + } if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 7dc5c6e19..14474bc10 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -142,6 +142,7 @@ CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen); #endif { BOOL realized; + jboolean withinLiveResize; @public BOOL hasPresentationSwitch; NSUInteger defaultPresentationOptions; @@ -164,7 +165,10 @@ CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen); - (void) setRealized: (BOOL)v; - (BOOL) isRealized; +- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom; + - (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin; +- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer; - (void) attachToParent: (NSWindow*) parent; - (void) detachFromParent: (NSWindow*) parent; @@ -189,7 +193,12 @@ CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen); - (void) windowDidBecomeKey: (NSNotification *) notification; - (void) windowDidResignKey: (NSNotification *) notification; +- (void) windowWillStartLiveResize: (NSNotification *) notification; +- (void) windowDidEndLiveResize: (NSNotification *) notification; +- (NSSize) windowWillResize: (NSWindow *)sender toSize:(NSSize)frameSize; - (void) windowDidResize: (NSNotification*) notification; +- (void) sendResizeEvent; + - (void) windowDidMove: (NSNotification*) notification; - (BOOL) windowClosingImpl: (BOOL) force; - (BOOL) windowShouldClose: (id) sender; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 7b3df391d..6024a90d4 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -54,7 +54,7 @@ static jfloat GetDelta(NSEvent *event, jint javaMods[]) { deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2); deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1); // fprintf(stderr, "WHEEL/PAD: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]); - if( fabsf(deltaX) > fabsf(deltaY) ) { + if( fabs(deltaX) > fabs(deltaY) ) { javaMods[0] |= EVENT_SHIFT_MASK; delta = deltaX; } else { @@ -179,9 +179,10 @@ static jmethodID requestFocusID = NULL; static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; +static jmethodID sizeScreenPosInsetsChangedID = NULL; static jmethodID updatePixelScaleID = NULL; static jmethodID visibleChangedID = NULL; -static jmethodID positionChangedID = NULL; +static jmethodID screenPositionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowRepaintID = NULL; @@ -649,31 +650,32 @@ static jmethodID windowRepaintID = NULL; // convert to 1-based button number (or use zero if no button is involved) // TODO: detect mouse button when mouse wheel scrolled - jshort javaButtonNum = 0; + jshort javaButtonNum; jfloat scrollDeltaY = 0.0f; switch ([event type]) { - case NSScrollWheel: { - scrollDeltaY = GetDelta(event, javaMods); - javaButtonNum = 1; - break; - } - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSLeftMouseDragged: - javaButtonNum = 1; - break; - case NSRightMouseDown: - case NSRightMouseUp: - case NSRightMouseDragged: - javaButtonNum = 3; - break; - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - javaButtonNum = 2; - break; + case NSScrollWheel: + scrollDeltaY = GetDelta(event, javaMods); + javaButtonNum = 1; + break; + case NSLeftMouseDown: + case NSLeftMouseUp: + case NSLeftMouseDragged: + javaButtonNum = 1; + break; + case NSRightMouseDown: + case NSRightMouseUp: + case NSRightMouseDragged: + javaButtonNum = 3; + break; + case NSOtherMouseDown: + case NSOtherMouseUp: + case NSOtherMouseDragged: + javaButtonNum = 2; + break; + default: + javaButtonNum = 0; + break; } - if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) { // ignore 0 increment wheel scroll events return; @@ -830,13 +832,15 @@ NS_ENDHANDLER updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); + sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V"); + screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); - if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID && - positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) + if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && + insetsChangedID && sizeScreenPosInsetsChangedID && + screenPositionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) { CKCH_CreateDictionaries(); return YES; @@ -889,6 +893,7 @@ NS_ENDHANDLER cachedInsets[3] = 0; // b realized = YES; + withinLiveResize = JNI_FALSE; DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n", res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]); return res; @@ -928,6 +933,20 @@ NS_ENDHANDLER return realized; } +- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom +{ + if( top ) { + DBG_PRINT( "*************** setAlwaysOn -> top\n"); + [self setLevel: kCGMaximumWindowLevel]; + } else if ( bottom ) { + DBG_PRINT( "*************** setAlwaysOn -> bottom\n"); + [self setLevel: kCGDesktopIconWindowLevel]; // w/ input + } else { + DBG_PRINT( "*************** setAlwaysOn -> normal\n"); + [self setLevel:NSNormalWindowLevel]; + } +} + - (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin { NSRect frameRect = [self frame]; @@ -948,6 +967,33 @@ NS_ENDHANDLER } } +- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer +{ + // update insets on every window resize for lack of better hook place + [self updateInsets: NULL jwin:NULL]; + + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; + + DBG_PRINT( "updateSize: [ w %d, h %d ], liveResize %d\n", (jint) contentRect.size.width, (jint) contentRect.size.height, (jint)withinLiveResize); + + NSPoint p0 = { 0, 0 }; + p0 = [self getLocationOnScreen: p0]; + + DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); + + if( NULL != env && NULL != javaWin ) { + (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, + (jint) p0.x, (jint) p0.y, + (jint) contentRect.size.width, (jint) contentRect.size.height, + cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], + JNI_FALSE, // force + withinLiveResize + ); + } +} + + - (void) attachToParent: (NSWindow*) parent { DBG_PRINT( "attachToParent.1\n"); @@ -1183,8 +1229,30 @@ NS_ENDHANDLER [self focusChanged: NO]; } +- (void) windowWillStartLiveResize: (NSNotification *) notification +{ + DBG_PRINT( "*************** windowWillStartLiveResize\n"); + withinLiveResize = JNI_TRUE; +} +- (void) windowDidEndLiveResize: (NSNotification *) notification +{ + DBG_PRINT( "*************** windowDidEndLiveResize\n"); + withinLiveResize = JNI_FALSE; + [self sendResizeEvent]; +} +- (NSSize) windowWillResize: (NSWindow *)sender toSize:(NSSize)frameSize +{ + DBG_PRINT( "*************** windowWillResize %lfx%lf\n", frameSize.width, frameSize.height); + return frameSize; +} - (void)windowDidResize: (NSNotification*) notification { + DBG_PRINT( "*************** windowDidResize\n"); + [self sendResizeEvent]; +} + +- (void) sendResizeEvent +{ jobject javaWindowObject = NULL; int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); @@ -1198,15 +1266,7 @@ NS_ENDHANDLER javaWindowObject = [newtView getJavaWindowObject]; } if( NULL != javaWindowObject ) { - // update insets on every window resize for lack of better hook place - [self updateInsets: env jwin:javaWindowObject]; - - NSRect frameRect = [self frame]; - NSRect contentRect = [self contentRectForFrameRect: frameRect]; - - (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_TRUE, // defer - (jint) contentRect.size.width, - (jint) contentRect.size.height, JNI_FALSE); + [self updateSizePosInsets: env jwin: javaWindowObject defer:JNI_TRUE]; } // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -1232,7 +1292,8 @@ NS_ENDHANDLER NSPoint p0 = { 0, 0 }; p0 = [self getLocationOnScreen: p0]; - (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y); + DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); + (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h index ada886d24..f6aba4c83 100644 --- a/src/newt/native/Window.h +++ b/src/newt/native/Window.h @@ -53,7 +53,9 @@ #define FLAG_IS_MAXIMIZED_VERT ( 1 << 9 ) #define FLAG_IS_MAXIMIZED_HORZ ( 1 << 10 ) #define FLAG_IS_FULLSCREEN ( 1 << 11 ) -#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 12 ) +#define FLAG_IS_POINTERVISIBLE ( 1 << 12 ) +#define FLAG_IS_POINTERCONFINED ( 1 << 13 ) +#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 14 ) #define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) #define TST_FLAG_CHANGE_VISIBILITY_FAST(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY_FAST ) ) diff --git a/src/newt/native/WindowsEDID.c b/src/newt/native/WindowsEDID.c index d84773dc6..5fc410a91 100644 --- a/src/newt/native/WindowsEDID.c +++ b/src/newt/native/WindowsEDID.c @@ -144,8 +144,14 @@ static _TCHAR* Get2ndSlashBlock(const _TCHAR* sIn, _TCHAR* sOut, size_t sOutLen) size_t len = t - s; if( len > 0 ) { if( sOutLen >= len ) { - _tcsncpy_s(sOut, sOutLen, s, len); - return sOut; + // Bug 1196: Unresolved strncpy_s (MSVCRT) on WinXP. + // Mapped: _tcsncpy_s -> strncpy_s (!UNICODE). + // On WinXP MSVCRT has no strncpy_s. + // _tcsncpy_s(sOut, sOutLen, s, len); + if( len <= sOutLen-1 ) { + _tcsncpy(sOut, s, len); + return sOut; + } } } } diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index a9a5cac10..59e054516 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -181,6 +181,7 @@ static jmethodID maximizedChangedID = NULL; static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID visibleChangedID = NULL; +static jmethodID sizePosInsetsFocusVisibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowRepaintID = NULL; static jmethodID sendMouseEventID = NULL; @@ -206,10 +207,18 @@ static int NewtEDID_avail = 0; typedef struct { JNIEnv* jenv; jobject jinstance; + /* client x-pos */ + int xpos; + /* client y-pos */ + int ypos; /* client size width */ int width; /* client size height */ int height; + /* visible state */ + BOOL visible; + /* focused state */ + BOOL focused; /* Insets left, right, top, bottom */ RECT insets; /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */ @@ -226,6 +235,10 @@ typedef struct { BOOL isMinimized; /** Bool: 0 NOP, 1 maximized */ BOOL isMaximized; + BOOL isOnBottom; + BOOL isOnTop; + /** Bug 1205: Clear Window Background -> security! */ + BOOL isInCreation; int pointerCaptured; int pointerInside; int touchDownCount; @@ -608,21 +621,41 @@ static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE s static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) { HWND pHwnd, current; + WindowUserData * wud; BOOL isEnabled = IsWindowEnabled(hwnd); pHwnd = GetParent(hwnd); current = GetFocus(); - DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d\n", - (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd); +#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 ) + wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA); +#else + wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#endif + + DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d, isOn[Top %d, Bottom %d]\n", + (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd, + wud->isOnTop, wud->isOnBottom); if( JNI_TRUE==force || current!=hwnd || !isEnabled ) { UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; if(!isEnabled) { EnableWindow(hwnd, TRUE); } - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); - SetForegroundWindow(hwnd); // Slightly Higher Priority + BOOL frontWindow; + if( wud->isOnBottom ) { + SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + frontWindow = FALSE; + } else if( wud->isOnTop ) { + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, flags); + frontWindow = TRUE; + } else { + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); + frontWindow = TRUE; + } + if( frontWindow ) { + SetForegroundWindow(hwnd); // Slightly Higher Priority + } SetFocus(hwnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window) - if(NULL!=pHwnd) { + if( frontWindow && NULL!=pHwnd ) { SetActiveWindow(hwnd); } current = GetFocus(); @@ -671,10 +704,11 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { jobject window = wud->jinstance; RECT outside; RECT inside; + int strategy = 0; if (IsIconic(hwnd)) { wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = -1; - return FALSE; + return; } wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0; @@ -688,6 +722,7 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { wud->insets.bottom = outside.bottom - inside.bottom; wud->insets.left = inside.left - outside.left; wud->insets.right = outside.right - inside.right; + strategy = 1; } else { wud->insets.top = -1; } @@ -713,18 +748,21 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { /* Add in title. */ wud->insets.top += GetSystemMetrics(SM_CYCAPTION); + strategy += 10; } else { /* undo the -1 set above */ wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0; + strategy += 20; } } - DBG_PRINT("*** WindowsWindow: UpdateInsets window %p, [l %d, r %d - t %d, b %d - %dx%d]\n", - (void*)hwnd, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom, - (int) ( wud->insets.left + wud->insets.right ), (int) (wud->insets.top + wud->insets.bottom)); - - (*env)->CallVoidMethod(env, window, insetsChangedID, JNI_FALSE, - (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom); + DBG_PRINT("*** WindowsWindow: UpdateInsets window %p, s %d, [l %d, r %d - t %d, b %d - %dx%d], at-init %d\n", + (void*)hwnd, strategy, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom, + (int) ( wud->insets.left + wud->insets.right ), (int) (wud->insets.top + wud->insets.bottom), wud->isInCreation); + if( !wud->isInCreation ) { + (*env)->CallVoidMethod(env, window, insetsChangedID, JNI_FALSE, + (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom); + } } static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) @@ -763,14 +801,16 @@ static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) wud->width = (int) ( rc.right - rc.left ); wud->height = (int) ( rc.bottom - rc.top ); - DBG_PRINT("*** WindowsWindow: WmSize.X window %p, %dx%d, isMinimized %d, isMaximized %d (changed %d), visible %d\n", - (void*)wnd, wud->width, wud->height, wud->isMinimized, wud->isMaximized, maxChanged, isVisible); + DBG_PRINT("*** WindowsWindow: WmSize.X window %p, %dx%d, isMinimized %d, isMaximized %d (changed %d), visible %d, at-init %d\n", + (void*)wnd, wud->width, wud->height, wud->isMinimized, wud->isMaximized, maxChanged, isVisible, wud->isInCreation); - if( maxChanged ) { - jboolean v = wud->isMaximized ? JNI_TRUE : JNI_FALSE; - (*env)->CallVoidMethod(env, window, maximizedChangedID, v, v); + if( !wud->isInCreation ) { + if( maxChanged ) { + jboolean v = wud->isMaximized ? JNI_TRUE : JNI_FALSE; + (*env)->CallVoidMethod(env, window, maximizedChangedID, v, v); + } + (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE); } - (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE); } #ifdef TEST_MOUSE_HOOKS @@ -896,6 +936,7 @@ static void sendTouchScreenEvent(JNIEnv *env, jobject window, jNames, jX, jY, jPressure, (jfloat)maxPressure); } +// #define DO_ERASEBKGND 1 static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT res = 0; @@ -959,11 +1000,15 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP // Bug 916 - NEWT Fullscreen Mode on Windows ALT-TAB doesn't allow Application Switching // Remedy for 'some' display drivers, i.e. Intel HD: // Explicitly push fullscreen window to BOTTOM when inactive (ALT-TAB) - UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if( inactive ) { - SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, flags); + if( inactive || wud->isOnBottom ) { + SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); } else { - SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags); + UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if( wud->isOnTop ) { + SetWindowPos(wnd, HWND_TOPMOST, 0, 0, 0, 0, flags); + } else { + SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags); + } SetForegroundWindow(wnd); // Slightly Higher Priority } } @@ -971,6 +1016,34 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP } break; + case WM_WINDOWPOSCHANGING: { + WINDOWPOS *p = (WINDOWPOS*)lParam; + BOOL isThis = wnd == p->hwnd; + BOOL isBottom = HWND_BOTTOM == p->hwndInsertAfter; + BOOL isTopMost = HWND_TOPMOST == p->hwndInsertAfter; + BOOL forceBottom = isThis && wud->isOnBottom && !isBottom; + BOOL forceTop = isThis && wud->isOnTop && !isTopMost; + #ifdef VERBOSE_ON + BOOL isNoTopMost = HWND_NOTOPMOST == p->hwndInsertAfter; + BOOL isTop = HWND_TOP == p->hwndInsertAfter; + BOOL isNoZ = 0 != ( SWP_NOZORDER & p->flags ); + DBG_PRINT("*** WindowsWindow: WM_WINDOWPOSCHANGING window %p / %p (= %d), %p[bottom %d, notop %d, top %d, topmost %d, noZ %d, force[Top %d, Bottom %d], %d/%d %dx%d 0x%X\n", + wnd, p->hwnd, isThis, + p->hwndInsertAfter, isBottom, isNoTopMost, isTop, isTopMost, isNoZ, + forceTop, forceBottom, + p->x, p->y, p->cx, p->cy, p->flags); + #endif + if( forceTop ) { + p->hwndInsertAfter = HWND_TOPMOST; + p->flags &= ~SWP_NOZORDER; + } else if( forceBottom ) { + p->hwndInsertAfter = HWND_BOTTOM; + p->flags &= ~SWP_NOZORDER; + } + useDefWindowProc = 1; + } + break; + case WM_SETTINGCHANGE: if (wParam == SPI_SETNONCLIENTMETRICS) { // make sure insets are updated, we don't need to resize the window @@ -986,33 +1059,79 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_SHOWWINDOW: - DBG_PRINT("*** WindowsWindow: WM_SHOWWINDOW window %p: %d\n", wnd, wParam==TRUE); - (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE); + DBG_PRINT("*** WindowsWindow: WM_SHOWWINDOW window %p: %d, at-init %d\n", wnd, wParam==TRUE, wud->isInCreation); + wud->visible = wParam==TRUE; + if( !wud->isInCreation ) { + (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE); + } break; case WM_MOVE: - DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam)); + wud->xpos = (int)GET_X_LPARAM(lParam); + wud->ypos = (int)GET_Y_LPARAM(lParam); + DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d, at-init %d\n", wnd, wud->xpos, wud->ypos, wud->isInCreation); + if( !wud->isInCreation ) { + (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)wud->xpos, (jint)wud->ypos); + } useDefWindowProc = 1; break; case WM_PAINT: { - RECT r; - if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) { - // clear the whole client area and issue repaint for it, w/o looping through erase background - ValidateRect(wnd, NULL); // clear all! - (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + if( wud->isInCreation ) { + #ifdef DO_ERASEBKGND + if (GetUpdateRect(wnd, NULL, TRUE /* erase background */)) { + DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n"); + // WM_ERASEBKGND sent! + #else + if (GetUpdateRect(wnd, NULL, FALSE /* do not erase background */)) { + DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n"); + ValidateRect(wnd, NULL); // clear all! + #endif + } else { + DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (clean)\n"); + } } else { - // shall not happen ? - ValidateRect(wnd, NULL); // clear all! + if (GetUpdateRect(wnd, NULL, FALSE /* do not erase background */)) { + DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (dirty)\n"); + // Let NEWT render the whole client area by issueing repaint for it, w/o looping through erase background + ValidateRect(wnd, NULL); // clear all! + (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + } else { + DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (clean)\n"); + // shall not happen ? + ValidateRect(wnd, NULL); // clear all! + } + // return 0 == done } - // return 0 == done break; } case WM_ERASEBKGND: - // ignore erase background - (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); - res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this + if( wud->isInCreation ) { + #ifdef DO_ERASEBKGND + // On Windows the initial window is clean?! + // This fill destroys translucency on Windows 10 + // (which only seem to work on undecorated windows) + PAINTSTRUCT ps; + HDC hdc; + hdc = BeginPaint(wnd, &ps); + DBG_PRINT("*** WindowsWindow: WM_ERASEBKGND.0 (erasure) l/b %d/%d r/t %d/%d\n", + ps.rcPaint.left, ps.rcPaint.bottom, ps.rcPaint.right, ps.rcPaint.top); + // FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW+1)); + // FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_APPWORKSPACE+1)); + // A black color also sets alpha to zero for translucency! + FillRect(hdc, &ps.rcPaint, (HBRUSH)GetStockObject(BLACK_PEN)); + EndPaint(wnd, &ps); + #else + ValidateRect(wnd, NULL); // clear all! + #endif + res = 1; // return 1 == done + } else { + // ignore erase background, but let NEWT render the whole client area + DBG_PRINT("*** WindowsWindow: WM_ERASEBKGND.1 (repaint)\n"); + ValidateRect(wnd, NULL); // clear all! + (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this + } break; case WM_SETCURSOR : @@ -1061,8 +1180,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_SETFOCUS: - DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p\n", wnd, (HWND)wParam); - (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); + DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p, at-init %d\n", wnd, (HWND)wParam, wud->isInCreation); + wud->focused = TRUE; + if( !wud->isInCreation ) { + (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); + } useDefWindowProc = 1; break; @@ -1075,7 +1197,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerCaptured = 0; ReleaseCapture(); } - (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); + wud->focused = FALSE; + if( !wud->isInCreation ) { + (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); + } useDefWindowProc = 1; } else { // quick focus .. we had it already, are enabled .. @@ -2003,6 +2128,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); + sizePosInsetsFocusVisibleChangedID = (*env)->GetMethodID(env, clazz, "sizePosInsetsFocusVisibleChanged", "(ZIIIIIIIIIIZ)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V"); @@ -2016,6 +2142,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 positionChangedID == NULL || focusChangedID == NULL || visibleChangedID == NULL || + sizePosInsetsFocusVisibleChangedID == NULL || windowDestroyNotifyID == NULL || windowRepaintID == NULL || sendMouseEventID == NULL || @@ -2078,6 +2205,9 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl if(visible) { wflags = SWP_SHOWWINDOW; + if( abottom ) { + wflags |= SWP_NOACTIVATE; + } } else { wflags = SWP_NOACTIVATE | SWP_NOZORDER; } @@ -2085,6 +2215,8 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl wflags |= SWP_NOSIZE; } + wud->isOnTop = atop; + wud->isOnBottom = abottom; if(atop) { SetWindowPos(hwnd, HWND_TOP, x, y, width, height, wflags); SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, wflags); @@ -2095,7 +2227,6 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, width, height, wflags); SetWindowPos(hwnd, HWND_TOP, x, y, width, height, wflags); } - // SetWindowPos(hwnd, atop ? HWND_TOPMOST : HWND_TOP, x, y, width, height, wflags); if( TST_FLAG_CHANGE_MAXIMIZED_ANY(jflags) ) { if( TST_FLAG_IS_MAXIMIZED_VERT(jflags) && TST_FLAG_IS_MAXIMIZED_HORZ(jflags) ) { @@ -2122,16 +2253,15 @@ static void NewtWindow_setVisiblePosSize(WindowUserData *wud, HWND hwnd, int jfl JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor, - jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jint flags) + jlong parent, jint jxpos, jint jypos, jint defaultWidth, jint defaultHeight, jint flags) { HWND parentWindow = (HWND) (intptr_t) parent; const TCHAR* wndClassName = NULL; const TCHAR* wndName = NULL; - DWORD windowStyle = WS_DEFAULT_STYLES | WS_VISIBLE; - int x=(int)jx, y=(int)jy; + DWORD windowStyle = WS_DEFAULT_STYLES; + int xpos=(int)jxpos, ypos=(int)jypos; int width=(int)defaultWidth, height=(int)defaultHeight; - HWND window = NULL; - int _x = x, _y = y; // pos for CreateWindow, might be tweaked + HWND hwnd = NULL; #ifdef UNICODE wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName); @@ -2147,10 +2277,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo return 0; } windowStyle |= WS_CHILD ; - } else if ( TST_FLAG_IS_UNDECORATED(flags) ) { - windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; } else { - if ( TST_FLAG_IS_RESIZABLE(flags) ) { + if ( TST_FLAG_IS_UNDECORATED(flags) ) { + windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + } else if ( TST_FLAG_IS_RESIZABLE(flags) ) { // WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); windowStyle |= WS_OVERLAPPEDWINDOW; } else { @@ -2158,31 +2288,32 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo } if( TST_FLAG_IS_AUTOPOSITION(flags) ) { // user didn't requested specific position, use WM default - _x = CW_USEDEFAULT; - _y = 0; + xpos = CW_USEDEFAULT; + ypos = 0; } } - window = CreateWindow(wndClassName, wndName, windowStyle, - _x, _y, width, height, - parentWindow, NULL, - (HINSTANCE) (intptr_t) hInstance, - NULL); + hwnd = CreateWindow(wndClassName, wndName, windowStyle, + xpos, ypos, width, height, + parentWindow, NULL, (HINSTANCE) (intptr_t) hInstance, NULL); - DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", - (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, window, x, y, width, height, + DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d -> %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", + (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, hwnd, jxpos, jypos, xpos, ypos, width, height, TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), TST_FLAG_IS_AUTOPOSITION(flags)); - if (NULL == window) { + if (NULL == hwnd) { int lastError = (int) GetLastError(); DBG_PRINT("*** WindowsWindow: CreateWindow failure: 0x%X %d\n", lastError, lastError); - return 0; } else { WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData)); wud->jinstance = (*env)->NewGlobalRef(env, obj); wud->jenv = env; + wud->xpos = xpos; + wud->ypos = ypos; wud->width = width; wud->height = height; + wud->visible = TRUE; + wud->focused = TRUE; wud->setPointerVisible = 0; wud->setPointerAction = 0; wud->defPointerHandle = LoadCursor( NULL, IDC_ARROW); @@ -2191,6 +2322,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo wud->isChildWindow = NULL!=parentWindow; wud->isMinimized = FALSE; wud->isMaximized = FALSE; + wud->isOnBottom = FALSE; + wud->isOnTop = FALSE; + wud->isInCreation = TRUE; wud->pointerCaptured = 0; wud->pointerInside = 0; wud->touchDownCount = 0; @@ -2209,32 +2343,26 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo DBG_PRINT("*** WindowsWindow: CreateWindow winTouchFuncAvail %d, supportsMTouch %d\n", WinTouch_func_avail, wud->supportsMTouch); #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 ) - SetWindowLong(window, GWL_USERDATA, (intptr_t) wud); + SetWindowLong(hwnd, GWL_USERDATA, (intptr_t) wud); #else - SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (intptr_t) wud); #endif - // gather and adjust position and size - { - RECT rc; - - ShowWindow(window, SW_SHOW); - - // send insets before visibility, allowing java code a proper sync point! - UpdateInsets(env, wud, window); - (*env)->CallVoidMethod(env, wud->jinstance, visibleChangedID, JNI_FALSE, JNI_TRUE); + // send insets before visibility, allowing java code a proper sync point! + UpdateInsets(env, wud, hwnd); - if( TST_FLAG_IS_AUTOPOSITION(flags) ) { - GetWindowRect(window, &rc); - x = rc.left + wud->insets.left; // client coords - y = rc.top + wud->insets.top; // client coords - } - DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, TST_FLAG_IS_AUTOPOSITION(flags)); - NewtWindow_setVisiblePosSize(wud, window, flags, TRUE, x, y, width, height); - } - if( wud->supportsMTouch ) { - WinTouch_RegisterTouchWindow(window, 0); + if( TST_FLAG_IS_AUTOPOSITION(flags) ) { + RECT rc; + GetWindowRect(hwnd, &rc); + xpos = rc.left + wud->insets.left; // client coords + ypos = rc.top + wud->insets.top; // client coords + wud->xpos = xpos; + wud->ypos = ypos; } + DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d -> %d/%d %dx%d (autoPosition %d)\n", + xpos, ypos, width, height, + wud->xpos, wud->ypos, wud->width, wud->height, + TST_FLAG_IS_AUTOPOSITION(flags)); } #ifdef UNICODE @@ -2251,7 +2379,49 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo DBG_PRINT("**** LLMP Hook %p, MP Hook %p\n", hookLLMP, hookMP); #endif - return (jlong) (intptr_t) window; + DBG_PRINT("*** WindowsWindow: CreateWindow done\n"); + return (jlong) (intptr_t) hwnd; +} + +/* + * Class: jogamp_newt_driver_windows_WindowDriver + * Method: InitWindow + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_InitWindow0 + (JNIEnv *env, jobject obj, jlong window, jint flags) +{ + HWND hwnd = (HWND) (intptr_t) window; + WindowUserData * wud; +#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 ) + wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA); +#else + wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#endif + + DBG_PRINT("*** WindowsWindow: InitWindow start %d/%d %dx%d, focused %d, visible %d\n", + wud->xpos, wud->ypos, wud->width, wud->height, wud->focused, wud->visible); + + NewtWindow_setVisiblePosSize(wud, hwnd, flags, TRUE, wud->xpos, wud->ypos, wud->width, wud->height); + wud->isInCreation = FALSE; + + DBG_PRINT("*** WindowsWindow: InitWindow pos/size set: %d/%d %dx%d, focused %d, visible %d\n", + wud->xpos, wud->ypos, wud->width, wud->height, wud->focused, wud->visible); + + if( wud->isMaximized ) { + (*env)->CallVoidMethod(env, wud->jinstance, maximizedChangedID, JNI_TRUE, JNI_TRUE); + } + (*env)->CallVoidMethod(env, wud->jinstance, sizePosInsetsFocusVisibleChangedID, JNI_FALSE, + (jint)wud->xpos, (jint)wud->ypos, + (jint)wud->width, (jint)wud->height, + (jint)wud->insets.left, (jint)wud->insets.right, (jint)wud->insets.top, (jint)wud->insets.bottom, + (jint)(wud->focused ? 1 : 0), + (jint)(wud->visible ? 1 : 0), + JNI_FALSE); + DBG_PRINT("*** WindowsWindow: InitWindow JNI callbacks done\n"); + + if( wud->supportsMTouch ) { + WinTouch_RegisterTouchWindow(hwnd, 0); + } } /* @@ -2283,6 +2453,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW DWORD windowStyle = WS_DEFAULT_STYLES; BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) || TST_FLAG_CHANGE_RESIZABLE(flags); + BOOL atop = TST_FLAG_IS_ALWAYSONTOP(flags); + BOOL abottom = TST_FLAG_IS_ALWAYSONBOTTOM(flags); WindowUserData * wud; #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 ) wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA); @@ -2290,12 +2462,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); #endif - DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, isChild %d, undecoration[change %d, val %d], fullscreen[change %d, val %d], alwaysOnTop[change %d, val %d], visible[change %d, val %d], resizable[change %d, val %d] -> styleChange %d, isChild %d, isMinimized %d, isMaximized %d, isFullscreen %d\n", + DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, isChild %d, undecoration[change %d, val %d], fullscreen[change %d, val %d], alwaysOnTop[change %d, val %d], alwaysOnBottom[change %d, val %d], visible[change %d, val %d], resizable[change %d, val %d] -> styleChange %d, isChild %d, isMinimized %d, isMaximized %d, isFullscreen %d\n", parent, window, x, y, width, height, TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_IS_CHILD(flags), TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags), + TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags), TST_FLAG_IS_ALWAYSONBOTTOM(flags), TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), TST_FLAG_CHANGE_RESIZABLE(flags), TST_FLAG_CHANGE_RESIZABLE(flags), styleChange, wud->isChildWindow, wud->isMinimized, wud->isMaximized, wud->isFullscreen); @@ -2305,6 +2478,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW return; } + wud->isOnTop = atop; + wud->isOnBottom = abottom; + if (NULL!=hwndP && !IsWindow(hwndP)) { DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed parent window %p is invalid\n", (void*)hwndP); return; @@ -2329,10 +2505,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW SetParent(hwnd, NULL); } - if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on - // TOP: in -> out - wud->isFullscreen = TRUE; - NewtWindows_setFullScreen(JNI_TRUE); + if( TST_FLAG_IS_FULLSCREEN(flags) ) { + if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) { // FS on + wud->isFullscreen = TRUE; + if( !abottom ) { + NewtWindows_setFullScreen(JNI_TRUE); + } + } else if( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) ) { // FS BOTTOM toggle + NewtWindows_setFullScreen( abottom ? JNI_FALSE : JNI_TRUE); + } } if ( styleChange ) { @@ -2351,7 +2532,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW } if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - // CHILD: out -> in wud->isFullscreen = FALSE; NewtWindows_setFullScreen(JNI_FALSE); } @@ -2365,9 +2545,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW if( TST_FLAG_CHANGE_VISIBILITY(flags) ) { if( TST_FLAG_IS_VISIBLE(flags) ) { - int cmd = wud->isMinimized ? SW_RESTORE : SW_SHOW; + int cmd = wud->isMinimized ? SW_RESTORE : ( abottom ? SW_SHOWNA : SW_SHOW ); wud->isMinimized = FALSE; ShowWindow(hwnd, cmd); + if( abottom ) { + SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + } } else if( !TST_FLAG_CHANGE_VISIBILITY_FAST(flags) && !TST_FLAG_IS_CHILD(flags) ) { wud->isMinimized = TRUE; ShowWindow(hwnd, SW_MINIMIZE); diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h index cdfb65d50..978cfffed 100644 --- a/src/newt/native/X11Common.h +++ b/src/newt/native/X11Common.h @@ -42,6 +42,7 @@ #include <X11/Xutil.h> #include <X11/keysym.h> #include <X11/Xatom.h> +#include <X11/extensions/XInput2.h> #include <X11/extensions/Xrandr.h> @@ -71,7 +72,15 @@ extern jclass X11NewtWindowClazz; extern jmethodID insetsChangedID; extern jmethodID visibleChangedID; -extern jmethodID sizePosMaxInsetsChanged; +extern jmethodID insetsVisibleChangedID; + +typedef struct { + int id; + int x; + int y; +} XITouchPosition; + +#define XI_TOUCHCOORD_COUNT 10 typedef struct { Window window; @@ -83,13 +92,71 @@ typedef struct { uint32_t lastDesktop; Bool maxHorz; Bool maxVert; + /** flag whether window is mapped */ + Bool isMapped; + int xiTouchDeviceId; + XITouchPosition xiTouchCoords[XI_TOUCHCOORD_COUNT]; } JavaWindow; JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning); Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return); Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom); -Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w); +Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w, uint32_t netWMState); + +#define _MASK_NET_WM_STATE ( 1 << 0 ) +#define _MASK_NET_WM_STATE_MODAL ( 1 << 1 ) +#define _MASK_NET_WM_STATE_STICKY ( 1 << 2 ) +#define _MASK_NET_WM_STATE_MAXIMIZED_VERT ( 1 << 3 ) +#define _MASK_NET_WM_STATE_MAXIMIZED_HORZ ( 1 << 4 ) +#define _MASK_NET_WM_STATE_SHADED ( 1 << 5 ) +#define _MASK_NET_WM_STATE_HIDDEN ( 1 << 8 ) +#define _MASK_NET_WM_STATE_FULLSCREEN ( 1 << 9 ) +#define _MASK_NET_WM_STATE_ABOVE ( 1 << 10 ) +#define _MASK_NET_WM_STATE_BELOW ( 1 << 11 ) +#define _MASK_NET_WM_STATE_DEMANDS_ATTENTION ( 1 << 12 ) +#define _MASK_NET_WM_STATE_FOCUSED ( 1 << 13 ) +#define _MASK_NET_WM_BYPASS_COMPOSITOR ( 1 << 14 ) +#define _MASK_NET_WM_DESKTOP ( 1 << 15 ) +#define _MASK_NET_CURRENT_DESKTOP ( 1 << 16 ) +#define _MASK_NET_WM_WINDOW_TYPE ( 1 << 17 ) +#define _MASK_NET_WM_WINDOW_TYPE_NORMAL ( 1 << 18 ) +#define _MASK_NET_WM_WINDOW_TYPE_POPUP_MENU ( 1 << 19 ) +#define _MASK_NET_FRAME_EXTENTS ( 1 << 20 ) +#define _MASK_NET_SUPPORTED ( 1 << 21 ) +#define _MASK_NET_ACTIVE_WINDOW ( 1 << 22 ) +#define _MASK_WM_CHANGE_STATE ( 1 << 23 ) +#define _MASK_MOTIF_WM_HINTS ( 1 << 24 ) + +#define _NET_WM_STATE_IDX 0 +#define _NET_WM_STATE_MODAL_IDX 1 +#define _NET_WM_STATE_STICKY_IDX 2 +#define _NET_WM_STATE_MAXIMIZED_VERT_IDX 3 +#define _NET_WM_STATE_MAXIMIZED_HORZ_IDX 4 +#define _NET_WM_STATE_SHADED_IDX 5 +#define _NET_WM_STATE_SKIP_TASKBAR_IDX 6 +#define _NET_WM_STATE_SKIP_PAGER_IDX 7 +#define _NET_WM_STATE_HIDDEN_IDX 8 +#define _NET_WM_STATE_FULLSCREEN_IDX 9 +#define _NET_WM_STATE_ABOVE_IDX 10 +#define _NET_WM_STATE_BELOW_IDX 11 +#define _NET_WM_STATE_DEMANDS_ATTENTION_IDX 12 +#define _NET_WM_STATE_FOCUSED_IDX 13 +#define _NET_WM_BYPASS_COMPOSITOR_IDX 14 +#define _NET_WM_DESKTOP_IDX 15 +#define _NET_CURRENT_DESKTOP_IDX 16 +#define _NET_WM_WINDOW_TYPE_IDX 17 +#define _NET_WM_WINDOW_TYPE_NORMAL_IDX 18 +#define _NET_WM_WINDOW_TYPE_POPUP_MENU_IDX 19 +#define _NET_FRAME_EXTENTS_IDX 20 +#define _NET_SUPPORTED_IDX 21 +#define _NET_ACTIVE_WINDOW_IDX 22 +#define _WM_CHANGE_STATE_IDX 23 +#define _MOTIF_WM_HINTS_IDX 24 + +void NewtWindows_setUrgency(Display *dpy, Window window, Bool enable); +void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable); +uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, JavaWindow *w); #endif /* _X11COMMON_H_ */ diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index 7ac6e8639..7c6741839 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -35,7 +35,7 @@ jclass X11NewtWindowClazz = NULL; jmethodID insetsChangedID = NULL; jmethodID visibleChangedID = NULL; -jmethodID sizePosMaxInsetsChangedID = NULL; +jmethodID insetsVisibleChangedID = NULL; static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver"; @@ -46,13 +46,17 @@ static jmethodID getCurrentThreadNameID = NULL; static jmethodID dumpStackID = NULL; static jmethodID sizeChangedID = NULL; static jmethodID positionChangedID = NULL; -static jmethodID focusChangedID = NULL; +static jmethodID focusVisibleChangedID = NULL; static jmethodID reparentNotifyID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowRepaintID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; static jmethodID sendMouseEventRequestFocusID = NULL; +static jmethodID visibleChangedWindowRepaintID = NULL; +static jmethodID visibleChangedSendMouseEventID = NULL; +static jmethodID sizePosMaxInsetsVisibleChangedID = NULL; +static jmethodID sendTouchScreenEventID = NULL; /** * Keycode @@ -244,22 +248,26 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 } } - // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJII)V"); // Variant using XKB - displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJII)V"); + // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJIII)V"); // Variant using XKB + displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJIII)V"); sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)V"); getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;"); dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V"); insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V"); sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZIIZ)V"); positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V"); + focusVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusVisibleChanged", "(ZII)V"); visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V"); - sizePosMaxInsetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsChanged", "(ZIIIIZZIIIIZ)V"); + insetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsVisibleChanged", "(ZIIIII)V"); + sizePosMaxInsetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsVisibleChanged", "(ZIIIIIIIIIIIZ)V"); reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); + visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V"); sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)V"); + visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)V"); + sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V"); sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V"); if (displayCompletedID == NULL || @@ -269,19 +277,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 insetsChangedID == NULL || sizeChangedID == NULL || positionChangedID == NULL || - focusChangedID == NULL || + focusVisibleChangedID == NULL || visibleChangedID == NULL || - sizePosMaxInsetsChangedID == NULL || + insetsVisibleChangedID == NULL || + sizePosMaxInsetsVisibleChangedID == NULL || reparentNotifyID == NULL || windowDestroyNotifyID == NULL || windowRepaintID == NULL || + visibleChangedWindowRepaintID == NULL || sendMouseEventID == NULL || sendMouseEventRequestFocusID == NULL || + visibleChangedSendMouseEventID == NULL || + sendTouchScreenEventID == NULL || sendKeyEventID == NULL) { return JNI_FALSE; } - return JNI_TRUE; } @@ -320,10 +331,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay int randr_event_base, randr_error_base; XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); + int xi_opcode = -1, event, error; + XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error); + DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy); (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/, // XKB disabled for now - randr_event_base, randr_error_base); + randr_event_base, randr_error_base, xi_opcode); } /* @@ -353,14 +367,96 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0 DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy); } +static int NewtWindows_updateVisibility(JNIEnv *env, Display *dpy, JavaWindow *jw, uint32_t netWMState, const char *dbgs) { + int visibleChange; + if( jw->isMapped && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) { + if( 0 != ( _MASK_NET_WM_STATE_HIDDEN & netWMState ) ) { + visibleChange = 0; + } else { + visibleChange = 1; + } + } else { + visibleChange = -1; + } + #ifdef VERBOSE_ON + XWindowAttributes xwa; + memset(&xwa, 0, sizeof(XWindowAttributes)); + XGetWindowAttributes(dpy, jw->window, &xwa); + + // map_state: IsUnmapped(0), IsUnviewable(1), IsViewable(2) + DBG_PRINT( "X11: event . %s call %p - isMapped %d, visibleChanged %d, map_state %d\n", + dbgs, (void*)jw->window, jw->isMapped, visibleChange, xwa.map_state); + #endif + return visibleChange; +} + +static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, + short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED + int modifiers, // 0! + int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event +{ + jint pointerNames[XI_TOUCHCOORD_COUNT]; + jint x[XI_TOUCHCOORD_COUNT]; + jint y[XI_TOUCHCOORD_COUNT]; + jfloat pressure[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + jint actionIdx = -1; + int i, cnt; + + for(i = 0, cnt = 0; i < XI_TOUCHCOORD_COUNT; i++) { + if( -1 != jw->xiTouchCoords[i].id ) { + x[cnt] = jw->xiTouchCoords[i].x; + y[cnt] = jw->xiTouchCoords[i].y; + pointerNames[cnt] = jw->xiTouchCoords[i].id; + if (jw->xiTouchCoords[i].id == actionId) { + actionIdx = cnt; + } + cnt++; + } + } + if( 0 > actionIdx ) { + NewtCommon_throwNewRuntimeException(env, "Internal Error: XI event (window %p) actionId %d not found in %d xiTouchCoords", + (void*)jw->window, actionId, cnt); + } + DBG_PRINT( "X11: XI event - sendTouchScreenEvent: Window %p, action-touchid[%d] %d of %d ptr: %d/%d\n", + (void*)jw->window, actionIdx, actionId, cnt, x[actionIdx], y[actionIdx]); + + jintArray jNames = (*env)->NewIntArray(env, cnt); + if (jNames == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", cnt); + } + (*env)->SetIntArrayRegion(env, jNames, 0, cnt, pointerNames); + + jintArray jX = (*env)->NewIntArray(env, cnt); + if (jX == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", cnt); + } + (*env)->SetIntArrayRegion(env, jX, 0, cnt, x); + + jintArray jY = (*env)->NewIntArray(env, cnt); + if (jY == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", cnt); + } + (*env)->SetIntArrayRegion(env, jY, 0, cnt, y); + + jfloatArray jPressure = (*env)->NewFloatArray(env, cnt); + if (jPressure == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", cnt); + } + (*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure); + + (*env)->CallVoidMethod(env, jw->jwindow, sendTouchScreenEventID, + (jshort)eventType, (jint)modifiers, (jint)actionIdx, + jNames, jX, jY, jPressure, (jfloat)1.0f); +} + /* * Class: jogamp_newt_driver_x11_DisplayDriver * Method: DispatchMessages0 - * Signature: (JJJII)V + * Signature: (JJJIII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0 (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/, - jint randr_event_base, jint randr_error_base) + jint randr_event_base, jint randr_error_base, jint xi_opcode) { Display * dpy = (Display *) (intptr_t) display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -411,17 +507,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage if( randr_event_base > 0 && RRScreenChangeNotify == ( evt.type - randr_event_base ) ) { DBG_PRINT( "X11: DispatchMessages dpy %p, Event RRScreenChangeNotify %p\n", (void*)dpy, (void*)&evt); (*env)->CallVoidMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt); - continue; + continue; // next event } if( 0==evt.xany.window ) { DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type); - continue; + continue; // next event } - // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type); + // Valid registered XI Event w/ cookie data (incl. the event Window name)? + // Here: https://www.x.org/wiki/Development/Documentation/Multitouch/ + XGenericEventCookie *evtCookie = &evt.xcookie; // hacks: https://keithp.com/blogs/Cursor_tracking/ + int isXiEvent = GenericEvent == evtCookie->type && xi_opcode == evtCookie->extension && XGetEventData(dpy, evtCookie); + XIDeviceEvent *xiDevEv; + Window windowPointer; + if( !isXiEvent ) { + xiDevEv = NULL; + windowPointer = evt.xany.window; + DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type); + } else { + xiDevEv = evtCookie->data; + windowPointer = xiDevEv->event; + } - jw = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + jw = getJavaWindowProperty(env, dpy, windowPointer, javaObjectAtom, #ifdef VERBOSE_ON True #else @@ -430,10 +539,62 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage ); if(NULL==jw) { - fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); - continue; + fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)windowPointer); + continue; // next event } - + + if ( isXiEvent ) { + if( xiDevEv->deviceid != jw->xiTouchDeviceId) { + DBG_PRINT( "X11: XI event - dpy %p, win %p, Event %d: DeviceID not matching: Window %d, this %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type, xiDevEv->deviceid, jw->xiTouchDeviceId); + } else { + int i; + switch (xiDevEv->evtype) { + case XI_TouchBegin: + for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) { + if (jw->xiTouchCoords[i].id == -1) { + jw->xiTouchCoords[i].id = xiDevEv->detail % 32767; + jw->xiTouchCoords[i].x = xiDevEv->event_x; + jw->xiTouchCoords[i].y = xiDevEv->event_y; + break; + } + } + DBG_PRINT( "X11: XI event - XI_TouchBegin Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, + i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); + sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, xiDevEv->detail % 32767); + break; + + case XI_TouchUpdate: + for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) { + if (jw->xiTouchCoords[i].id == xiDevEv->detail % 32767) { + jw->xiTouchCoords[i].x = xiDevEv->event_x; + jw->xiTouchCoords[i].y = xiDevEv->event_y; + break; + } + } + DBG_PRINT( "X11: XI event - XI_TouchUpdate: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, + i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); + sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, xiDevEv->detail % 32767); + break; + + case XI_TouchEnd: + for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) { + if (jw->xiTouchCoords[i].id == xiDevEv->detail % 32767) { + break; + } + } + DBG_PRINT( "X11: XI event - XI_TouchEnd: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, + i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); + sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, xiDevEv->detail % 32767); + if ( i < XI_TOUCHCOORD_COUNT ) { + jw->xiTouchCoords[i].id = -1; + } + break; + } + } + XFreeEventData(dpy, evtCookie); + continue; // next event, skip evt.type handling below + } + switch(evt.type) { case KeyRelease: if (XEventsQueued(dpy, QueuedAfterReading)) { @@ -538,15 +699,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage break; case EnterNotify: DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED, - modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + { + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "EnterNotify"); + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, + (jshort) EVENT_MOUSE_ENTERED, modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + } break; case LeaveNotify: DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, - modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + { + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "LeaveNotify"); + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, + (jshort) EVENT_MOUSE_EXITED, modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + } break; case MappingNotify: DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type); @@ -578,19 +747,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event); if ( evt.xconfigure.window == evt.xconfigure.event ) { // ignore child window change notification - // update insets + // insets: negative values are ignored int left=-1, right=-1, top=-1, bottom=-1; + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "ConfigureNotify"); NewtWindows_updateInsets(dpy, jw, &left, &right, &top, &bottom); - NewtWindows_updateMaximized(dpy, jw); - (*env)->CallVoidMethod(env, jw->jwindow, sizePosMaxInsetsChangedID, JNI_FALSE, + Bool maxChanged = NewtWindows_updateMaximized(dpy, jw, netWMState); + (*env)->CallVoidMethod(env, jw->jwindow, sizePosMaxInsetsVisibleChangedID, JNI_FALSE, (jint) evt.xconfigure.x, (jint) evt.xconfigure.y, (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, - (jboolean)jw->maxHorz, (jboolean)jw->maxVert, + (jint)(maxChanged ? ( jw->maxHorz ? 1 : 0 ) : -1), + (jint)(maxChanged ? ( jw->maxVert ? 1 : 0 ) : -1), (jint)left, (jint)right, (jint)top, (jint)bottom, + (jint)visibleChange, JNI_FALSE); } break; case ClientMessage: + DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, sendEvent %d\n", + (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, evt.xclient.send_event); if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom jboolean closed; DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", @@ -604,48 +779,76 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage break; case FocusIn: - DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); + DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xfocus.window); + { + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusIn"); + (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)1, (jint)visibleChange); + } break; case FocusOut: - DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); + DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xfocus.window); + { + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusOut"); + (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)0, (jint)visibleChange); + } break; + case VisibilityNotify: + DBG_PRINT( "X11: event . VisibilityNotify call %p\n", (void*)evt.xvisibility.window); + { + #if 0 + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "VisibilityNotify"); + if( 0 <= visibleChange ) { + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, 0 < visibleChange ? JNI_TRUE : JNI_FALSE); + } + #endif + } + break; + + case Expose: DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); - if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { (*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + #if 0 + uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); + int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "Expose"); + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + #endif } break; case MapNotify: - DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n", - (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect, + DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, isMapped %d -> 1, override_redirect %d, child-event: %d\n", + (void*)evt.xmap.event, (void*)evt.xmap.window, jw->isMapped, (int)evt.xmap.override_redirect, evt.xmap.event!=evt.xmap.window); if( evt.xmap.event == evt.xmap.window ) { // ignore child window notification - { - // update insets - int left, right, top, bottom; - if( NewtWindows_updateInsets(dpy, jw, &left, &right, &top, &bottom) ) { - (*env)->CallVoidMethod(env, jw->jwindow, insetsChangedID, JNI_FALSE, left, right, top, bottom); - } + jw->isMapped = True; + // insets: negative values are ignored + int left=-1, right=-1, top=-1, bottom=-1; + if( NewtWindows_updateInsets(dpy, jw, &left, &right, &top, &bottom) ) { + (*env)->CallVoidMethod(env, jw->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1); + } else { + (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); } - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); } break; case UnmapNotify: - DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n", - (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure, + DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, isMapped %d -> 0, from_configure %d, child-event: %d\n", + (void*)evt.xunmap.event, (void*)evt.xunmap.window, jw->isMapped, (int)evt.xunmap.from_configure, evt.xunmap.event!=evt.xunmap.window); if( evt.xunmap.event == evt.xunmap.window ) { // ignore child window notification + jw->isMapped = False; (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); } break; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 6fa3cc195..1c2c8e80f 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -85,53 +85,7 @@ static uintptr_t getPtrOut32Long(unsigned long * src) { #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 -#define _MASK_NET_WM_STATE ( 1 << 0 ) -#define _MASK_NET_WM_STATE_MODAL ( 1 << 1 ) -#define _MASK_NET_WM_STATE_STICKY ( 1 << 2 ) -#define _MASK_NET_WM_STATE_MAXIMIZED_VERT ( 1 << 3 ) -#define _MASK_NET_WM_STATE_MAXIMIZED_HORZ ( 1 << 4 ) -#define _MASK_NET_WM_STATE_SHADED ( 1 << 5 ) -#define _MASK_NET_WM_STATE_HIDDEN ( 1 << 8 ) -#define _MASK_NET_WM_STATE_FULLSCREEN ( 1 << 9 ) -#define _MASK_NET_WM_STATE_ABOVE ( 1 << 10 ) -#define _MASK_NET_WM_STATE_BELOW ( 1 << 11 ) -#define _MASK_NET_WM_STATE_DEMANDS_ATTENTION ( 1 << 12 ) -#define _MASK_NET_WM_STATE_FOCUSED ( 1 << 13 ) -#define _MASK_NET_WM_BYPASS_COMPOSITOR ( 1 << 14 ) -#define _MASK_NET_WM_DESKTOP ( 1 << 15 ) -#define _MASK_NET_CURRENT_DESKTOP ( 1 << 16 ) -#define _MASK_NET_WM_WINDOW_TYPE ( 1 << 17 ) -#define _MASK_NET_WM_WINDOW_TYPE_NORMAL ( 1 << 18 ) -#define _MASK_NET_WM_WINDOW_TYPE_POPUP_MENU ( 1 << 19 ) -#define _MASK_NET_FRAME_EXTENTS ( 1 << 20 ) -#define _MASK_NET_SUPPORTED ( 1 << 21 ) -#define _MASK_WM_CHANGE_STATE ( 1 << 22 ) -#define _MASK_MOTIF_WM_HINTS ( 1 << 23 ) - -#define _NET_WM_STATE_IDX 0 -#define _NET_WM_STATE_MODAL_IDX 1 -#define _NET_WM_STATE_STICKY_IDX 2 -#define _NET_WM_STATE_MAXIMIZED_VERT_IDX 3 -#define _NET_WM_STATE_MAXIMIZED_HORZ_IDX 4 -#define _NET_WM_STATE_SHADED_IDX 5 -#define _NET_WM_STATE_SKIP_TASKBAR_IDX 6 -#define _NET_WM_STATE_SKIP_PAGER_IDX 7 -#define _NET_WM_STATE_HIDDEN_IDX 8 -#define _NET_WM_STATE_FULLSCREEN_IDX 9 -#define _NET_WM_STATE_ABOVE_IDX 10 -#define _NET_WM_STATE_BELOW_IDX 11 -#define _NET_WM_STATE_DEMANDS_ATTENTION_IDX 12 -#define _NET_WM_STATE_FOCUSED_IDX 13 -#define _NET_WM_BYPASS_COMPOSITOR_IDX 14 -#define _NET_WM_DESKTOP_IDX 15 -#define _NET_CURRENT_DESKTOP_IDX 16 -#define _NET_WM_WINDOW_TYPE_IDX 17 -#define _NET_WM_WINDOW_TYPE_NORMAL_IDX 18 -#define _NET_WM_WINDOW_TYPE_POPUP_MENU_IDX 19 -#define _NET_FRAME_EXTENTS_IDX 20 -#define _NET_SUPPORTED_IDX 21 -#define _WM_CHANGE_STATE_IDX 22 -#define _MOTIF_WM_HINTS_IDX 23 +/** Sync w/ X11Common.h MASK and IDX */ static const char * _ALL_ATOM_NAMES[] = { /* 0 */ "_NET_WM_STATE", /* 1 */ "_NET_WM_STATE_MODAL", @@ -155,8 +109,9 @@ static const char * _ALL_ATOM_NAMES[] = { /* 19 */ "_NET_WM_WINDOW_TYPE_POPUP_MENU", /* 20 */ "_NET_FRAME_EXTENTS", /* 21 */ "_NET_SUPPORTED", - /* 22 */ "WM_CHANGE_STATE", - /* 23 */ "_MOTIF_WM_HINTS" + /* 22 */ "_NET_ACTIVE_WINDOW", + /* 23 */ "WM_CHANGE_STATE", + /* 24 */ "_MOTIF_WM_HINTS" }; static const uint32_t _ALL_ATOM_COUNT = (uint32_t)(sizeof(_ALL_ATOM_NAMES)/sizeof(const char *)); @@ -185,7 +140,6 @@ static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root, uint32_t res = 0; Status s; - XSync(dpy, False); if ( Success == (s = XGetWindowProperty(dpy, root, allAtoms[_NET_SUPPORTED_IDX], 0, 1024, False, AnyPropertyType, &type, &form, &props_count, &remain, (unsigned char**)&properties)) ) { if( NULL != properties ) { @@ -202,7 +156,16 @@ static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root, } return res; } -static uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, Window window, Atom * allAtoms, Bool verbose) { +uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, JavaWindow *w) { + Bool verbose = +#ifdef VERBOSE_ON + True +#else + False +#endif + ; + Window window = w->window; + Atom * allAtoms = w->allAtoms; Atom * properties = NULL; Atom type = 0; unsigned long props_count = 0, remain = 0; @@ -210,7 +173,6 @@ static uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, Window window, Atom * uint32_t res = 0; Status s; - XSync(dpy, False); if ( Success == (s = XGetWindowProperty(dpy, window, allAtoms[_NET_WM_STATE_IDX], 0, 1024, False, AnyPropertyType, &type, &form, &props_count, &remain, (unsigned char**)&properties)) ) { if( NULL != properties ) { @@ -220,7 +182,7 @@ static uint32_t NewtWindows_getNET_WM_STATE(Display *dpy, Window window, Atom * XFree(properties); } if(verbose) { - fprintf(stderr, "**************** X11: WM_STATE of %p: 0x%X\n", (void*)window, res); + fprintf(stderr, "**************** X11: WM_STATE of %p: %d props -> 0x%X\n", (void*)window, (int)props_count, res); } } else if(verbose) { fprintf(stderr, "**************** X11: WM_STATE of %p: XGetWindowProperty failed: %d\n", (void*)window, s); @@ -249,6 +211,12 @@ static JavaWindow* createJavaWindowProperty(JNIEnv *env, Display *dpy, Window ro res->lastDesktop = 0; //undef res->maxHorz = False; res->maxVert = False; + res->isMapped = False; + int i; + for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) { + res->xiTouchCoords[i].id = -1; + } + res->xiTouchDeviceId = -1; } unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long' int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) res); @@ -292,7 +260,7 @@ JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlo if ( Success != res ) { if(True==showWarning) { - fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, result 0!\n", res, nitems, bytes_after); + fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom NEWT_JAVA_OBJECT window %p property (res %d) nitems %ld, bytes_after %ld, result 0!\n", (void*)window, res, nitems, bytes_after); } return NULL; } @@ -302,8 +270,8 @@ JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlo XFree(jogl_java_object_data_pp); } if(True==showWarning) { - fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n", - res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom); + fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window %p property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n", + (void *)window, res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom); } return NULL; } @@ -352,7 +320,6 @@ static void NewtWindows_setCWAbove(Display *dpy, Window w) { memset(&xwc, 0, sizeof(XWindowChanges)); xwc.stack_mode = Above; XConfigureWindow(dpy, w, CWStackMode, &xwc); - XSync(dpy, False); } static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window w, int *x_return, int *y_return) { Window root_return; @@ -440,8 +407,7 @@ static void NewtWindows_setDecorations (Display *dpy, JavaWindow *w, Bool decora #ifdef DECOR_USE_EWMH XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); #endif - - XSync(dpy, False); + XFlush(dpy); } static Bool NewtWindows_hasDecorations (Display *dpy, JavaWindow * w) { @@ -473,7 +439,6 @@ static void NewtWindows_requestFocus (Display *dpy, JavaWindow * jw, Bool force) Window focus_return; int revert_to_return; - XSync(dpy, False); XGetInputFocus(dpy, &focus_return, &revert_to_return); DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)jw->window, force, focus_return==jw->window); @@ -488,8 +453,8 @@ static void NewtWindows_requestFocus (Display *dpy, JavaWindow * jw, Bool force) XSetInputFocus(dpy, jw->window, RevertToParent, CurrentTime); } } + XFlush(dpy); DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)jw->window, force); - XSync(dpy, False); } Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom) { @@ -513,16 +478,9 @@ Bool NewtWindows_updateInsets(Display *dpy, JavaWindow * w, int *left, int *righ return False; // Error } -Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w) { - uint32_t state = NewtWindows_getNET_WM_STATE(dpy, w->window, w->allAtoms, -#ifdef VERBOSE_ON - True -#else - False -#endif - ); - Bool maxHorz = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & state ) ; - Bool maxVert = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & state ) ; +Bool NewtWindows_updateMaximized(Display *dpy, JavaWindow * w, uint32_t netWMState) { + Bool maxHorz = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & netWMState ) ; + Bool maxVert = 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & netWMState ) ; if( w->maxHorz != maxHorz || w->maxVert != maxVert ) { w->maxHorz = maxHorz; w->maxVert = maxVert; @@ -558,11 +516,20 @@ static void NewtWindows_setWindowTypeEWMH (Display *dpy, JavaWindow * w, int typ } // else { } if( 0 != types[0] ) { XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1); - XSync(dpy, False); + XFlush(dpy); } } -static void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) { +void NewtWindows_setUrgency(Display *dpy, Window window, Bool enable) { + XWMHints wmh; + memset ( &wmh, 0, sizeof(wmh) ); + if( enable ) { + wmh.flags = XUrgencyHint; + } + XSetWMHints(dpy, window, &wmh); +} + +void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) { XEvent xev; int i=0; @@ -694,7 +661,7 @@ static void NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, JavaWin changeMaxVert ? _NET_WM_STATE_MAXIMIZED_VERT_IDX : 0, enable); } - XSync(dpy, False); + XFlush(dpy); DBG_PRINT( "X11: setStackingEWMHFlags ON %d, change[Sticky %d, Fullscreen %d, Above %d, Below %d, MaxV %d, MaxH %d]\n", enable, changeSticky, changeFullscreen, changeAbove, changeBelow, changeMaxVert, changeMaxHorz); } @@ -709,35 +676,47 @@ static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) { static void NewtWindows_setVisible(Display *dpy, Window root, JavaWindow* jw, Bool visible, Bool useWM, Bool waitForNotify) { XEvent event; - if( !visible && useWM && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) { - DBG_PRINT( "X11: setVisible -> %d, method: IconicState, wait %d, window %p\n", (int)visible, (int)waitForNotify, (void*)jw->window); - // It has been experienced that UnmapNotify is not sent for child windows when using IconicState! + DBG_PRINT( "X11: setVisible -> %d, useWM: %d, wait %d, window %p\n", (int)visible, (int)useWM, (int)waitForNotify, (void*)jw->window); + if( useWM && jw->isMapped && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) { + // It has been experienced that MapNotify/UnmapNotify is not sent for windows when using NormalState/IconicState! + // See X11Display.c::Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0 case ConfigureNotify + // NewtWindows_sendNET_WM_STATE(dpy, root, jw, _NET_WM_STATE_DEMANDS_ATTENTION_IDX, 0, True); + // NewtWindows_setUrgency(dpy, jw->window, True); XEvent xev; memset ( &xev, 0, sizeof(xev) ); - xev.type = ClientMessage; - xev.xclient.window = jw->window; - xev.xclient.message_type = jw->allAtoms[_WM_CHANGE_STATE_IDX]; - xev.xclient.format = 32; - xev.xclient.data.l[0] = IconicState; - XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); - // NewtWindows_sendNET_WM_STATE(dpy, root, jw, _NET_WM_STATE_HIDDEN_IDX, 0, !visible); - if(waitForNotify) { - XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window ); + if( visible ) { + // NormalState does not work on some WMs (Gnome, KDE) + xev.type = ClientMessage; + xev.xclient.window = jw->window; + xev.xclient.message_type = jw->allAtoms[_NET_ACTIVE_WINDOW_IDX]; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; //source indication for normal applications + xev.xclient.data.l[1] = CurrentTime; + XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); + } else { + xev.type = ClientMessage; + xev.xclient.window = jw->window; + xev.xclient.message_type = jw->allAtoms[_WM_CHANGE_STATE_IDX]; + xev.xclient.format = 32; + xev.xclient.data.l[0] = IconicState; + XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); } } else { - DBG_PRINT( "X11: setVisible -> %d, method: Map/Unmap, wait %d, window %p\n", (int)visible, (int)waitForNotify, (void*)jw->window); if( visible ) { XMapRaised(dpy, jw->window); if(waitForNotify) { XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) jw->window ); } + jw->isMapped=True; } else { XUnmapWindow(dpy, jw->window); if(waitForNotify) { XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window ); } + jw->isMapped=False; } } + XFlush(dpy); } @@ -771,7 +750,7 @@ static void NewtWindows_setPosSize(Display *dpy, JavaWindow* w, jint x, jint y, xwc.height=height; } XConfigureWindow(dpy, w->window, flags, &xwc); - XSync(dpy, False); + XFlush(dpy); } } @@ -787,7 +766,7 @@ static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const uns JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, jint visualID, - jlong javaObjectAtom, jlong windowDeleteAtom, + jlong javaObjectAtom, jlong windowDeleteAtom, jint xi_opcode, jint x, jint y, jint width, jint height, int flags, jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jboolean verbose) @@ -858,24 +837,23 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind pVisualQuery=NULL; } - attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap | - CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask ) ; + attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | + CWBackPixmap | CWBackPixel | CWBorderPixel | CWColormap | + CWOverrideRedirect | CWEventMask ) ; memset(&xswa, 0, sizeof(xswa)); - xswa.override_redirect = False; // use the window manager, always (default) - xswa.border_pixel = 0; - xswa.background_pixmap = None; xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */ xswa.backing_planes=0; /* planes to be preserved if possible */ xswa.backing_pixel=0; /* value to use in restoring planes */ + xswa.background_pixmap = None; + xswa.background_pixel = BlackPixel(dpy, scrn_idx); + xswa.border_pixel = 0; + xswa.colormap = XCreateColormap(dpy, windowParent, visual, AllocNone); + xswa.override_redirect = False; // use the window manager, always (default) xswa.event_mask = X11_MOUSE_EVENT_MASK; xswa.event_mask |= KeyPressMask | KeyReleaseMask ; - xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ; - - xswa.colormap = XCreateColormap(dpy, - windowParent, - visual, - AllocNone); + xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask; + // xswa.event_mask |= VisibilityChangeMask; { int _x = x, _y = y; // pos for CreateWindow, might be tweaked @@ -900,6 +878,7 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind NewtCommon_throwNewRuntimeException(env, "could not create Window, bail out!"); return 0; } + // XClearWindow(dpy, window); XSetWMProtocols(dpy, window, &wm_delete_atom, 1); // windowDeleteAtom javaWindow = createJavaWindowProperty(env, dpy, root, window, javaObjectAtom, windowDeleteAtom, obj, verbose); @@ -911,7 +890,8 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind // we can pre-map the window here to be able to gather the insets and position. { XEvent event; - int left=0, right=0, top=0, bottom=0; + // insets: negative values are ignored + int left=-1, right=-1, top=-1, bottom=-1; const unsigned char * pixelPtr = NULL; // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly! @@ -926,18 +906,20 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values - - XSync(dpy, False); + javaWindow->isMapped=True; if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) { (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); } // send insets before visibility, allowing java code a proper sync point! + XSync(dpy, False); if( NewtWindows_updateInsets(dpy, javaWindow, &left, &right, &top, &bottom) ) { - (*env)->CallVoidMethod(env, javaWindow->jwindow, insetsChangedID, JNI_FALSE, left, right, top, bottom); + (*env)->CallVoidMethod(env, javaWindow->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1); + } else { + (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); + left=0; right=0; top=0; bottom=0; } - (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); if( TST_FLAG_IS_AUTOPOSITION(flags) ) { // get position from WM @@ -975,6 +957,59 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind NewtWindows_setMinMaxSize(dpy, javaWindow, width, height, width, height); } } + + // Register X11 Multitouch Events for new Window + // https://www.x.org/wiki/Development/Documentation/Multitouch/ + if( 0 <= xi_opcode ) { + XIDeviceInfo *di; + int cnt = 0; + + DBG_PRINT( "X11: [CreateWindow]: XI: Window %p, Extension %d\n", (void*)window, xi_opcode); + di = XIQueryDevice(dpy, XIAllDevices, &cnt); + + if( NULL != di && 0 < cnt ) { + int devid = -1; + int i, j; + + // find the 1st XITouchClass device available + for (i = 0; i < cnt && -1 == devid; i ++) { + XIDeviceInfo *dev = &di[i]; + for (j = 0; j < dev->num_classes; j ++) { + XITouchClassInfo *class = (XITouchClassInfo*)(dev->classes[j]); + DBG_PRINT( "X11: [CreateWindow]: XI: Scan Window %p, device[%d/%d].class[%d/%d]: devid %d, type %d (is XITouchClass %d)\n", + (void*)window, (i+1), cnt, (j+1), dev->num_classes, dev->deviceid, class->type, (XITouchClass == class->type)); + if ( XITouchClass == class->type ) { + devid = dev->deviceid; + break; + } + } + } + XIFreeDeviceInfo(di); + di = NULL; + + if( -1 != devid ) { + // register 1st XITouchClass device if available + XIEventMask mask = { + .deviceid = devid, + .mask_len = XIMaskLen(XI_TouchEnd) // in bytes + }; + + mask.mask = (unsigned char*)calloc(mask.mask_len, sizeof(unsigned char)); + XISetMask(mask.mask, XI_TouchBegin); + XISetMask(mask.mask, XI_TouchUpdate); + XISetMask(mask.mask, XI_TouchEnd); + + XISelectEvents(dpy, window, &mask, 1); + + free(mask.mask); + + javaWindow->xiTouchDeviceId = devid; + DBG_PRINT( "X11: [CreateWindow]: XI: Window %p, XITouchClass devid %d\n", (void*)window, devid); + } + } + } + + XFlush(dpy); handles[0] = (jlong)(intptr_t)window; handles[1] = (jlong)(intptr_t)javaWindow; jhandles = (*env)->NewLongArray(env, 2); @@ -988,12 +1023,40 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind /* * Class: jogamp_newt_driver_x11_WindowDriver + * Method: GetSupportedReconfigMask0 + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_WindowDriver_GetSupportedReconfigMask0 + (JNIEnv *env, jclass clazz, jlong javaWindow) +{ + JavaWindow * jw = (JavaWindow*)(intptr_t)javaWindow; + uint32_t supported = jw->supportedAtoms; + return + FLAG_IS_VISIBLE | + FLAG_IS_AUTOPOSITION | + FLAG_IS_CHILD | + FLAG_IS_FOCUSED | + FLAG_IS_UNDECORATED | + ( ( 0 != ( _MASK_NET_WM_STATE_ABOVE & supported ) ) ? FLAG_IS_ALWAYSONTOP : 0 ) | + ( ( 0 != ( _MASK_NET_WM_STATE_BELOW & supported ) ) ? FLAG_IS_ALWAYSONBOTTOM : 0 ) | + ( ( 0 != ( _MASK_NET_WM_DESKTOP & supported ) ) ? FLAG_IS_STICKY : 0 ) | + FLAG_IS_RESIZABLE | + ( ( 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & supported ) ) ? FLAG_IS_MAXIMIZED_VERT : 0 ) | + ( ( 0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & supported ) ) ? FLAG_IS_MAXIMIZED_HORZ : 0 ) | + FLAG_IS_FULLSCREEN | + FLAG_IS_POINTERVISIBLE | + FLAG_IS_POINTERCONFINED | + FLAG_IS_FULLSCREEN_SPAN; +} + +/* + * Class: jogamp_newt_driver_x11_WindowDriver * Method: CloseWindow * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 (JNIEnv *env, jobject obj, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now - jint randr_event_base, jint randr_error_base) + jint randr_event_base, jint randr_error_base, jint xi_opcode) { Display * dpy = (Display *) (intptr_t) display; JavaWindow * jw, * jw0; @@ -1008,7 +1071,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 NewtCommon_FatalError(env, "invalid JavaWindow connection.."); } jw0 = getJavaWindowProperty(env, dpy, jw->window, jw->javaObjectAtom, True); - if(NULL==jw) { + if(NULL==jw0) { NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!"); return; } @@ -1026,11 +1089,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 XGetWindowAttributes(dpy, jw->window, &xwa); // prefetch colormap to be destroyed after window destruction XSelectInput(dpy, jw->window, 0); XUnmapWindow(dpy, jw->window); + jw->isMapped=False; // Drain all events related to this window .. Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, (jlong)(intptr_t)jw->javaObjectAtom, (jlong)(intptr_t)jw->windowDeleteAtom /*, kbdHandle */, // XKB disabled for now - randr_event_base, randr_error_base); + randr_event_base, randr_error_base, xi_opcode); XDestroyWindow(dpy, jw->window); if( None != xwa.colormap ) { @@ -1065,7 +1129,7 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) { * Signature: (JIJJIIIII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindow0 - (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, + (JNIEnv *env, jclass clazz, jlong jdisplay, jint screen_index, jlong jparent, jlong javaWindow, jint x, jint y, jint width, jint height, jint flags) { @@ -1121,6 +1185,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo TST_FLAG_CHANGE_STICKY(flags), TST_FLAG_IS_STICKY(flags), fsEWMHFlags); + XSync(dpy, False); + // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough. // However, we have to consider other cases like reparenting and WM which don't support it. #if 0 // Also doesn't work work properly w/ Unity WM @@ -1162,8 +1228,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window ); + #else + XSync(dpy, False); #endif - XSync(dpy, False); XSetWMProtocols(dpy, jw->window, &wm_delete_atom, 1); // windowDeleteAtom // Fix for Unity WM, i.e. _remove_ persistent previous states NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, False); @@ -1205,10 +1272,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo // CHILD: out -> in DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n"); XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call + XFlush(dpy); #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window ); + #else + XSync(dpy, False); #endif - XSync(dpy, False); } if( tempInvisible ) { @@ -1220,7 +1289,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo if( TST_FLAG_IS_VISIBLE(flags) ) { DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n"); NewtWindows_setVisible(dpy, root, jw, True /* visible */, useWM, False /* wait */); - XSync(dpy, False); if( !TST_FLAG_IS_MAXIMIZED_ANY(flags) ) { // WM may disregard pos/size XConfigureWindow requests for invisible windows! DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height); @@ -1229,7 +1297,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo } else { DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n"); NewtWindows_setVisible(dpy, root, jw, False /* visible */, useWM, False /* wait */); - XSync(dpy, False); } } @@ -1250,6 +1317,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo NewtWindows_setMinMaxSize(dpy, jw, -1, -1, -1, -1); // FIXME: .. } } + XFlush(dpy); DBG_PRINT( "X11: reconfigureWindow0 X (full)\n"); } @@ -1259,9 +1327,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo * Signature: (JJZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0 - (JNIEnv *env, jobject obj, jlong display, jlong javaWindow, jboolean force) + (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jboolean force) { - NewtWindows_requestFocus ( (Display *) (intptr_t) display, (JavaWindow*)(intptr_t)javaWindow, JNI_TRUE==force?True:False ) ; + Display * dpy = (Display *) (intptr_t) display; + XSync(dpy, False); + NewtWindows_requestFocus ( dpy, (JavaWindow*)(intptr_t)javaWindow, JNI_TRUE==force?True:False ) ; } /* diff --git a/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java b/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java index 86041b35d..4b5145ded 100644 --- a/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java +++ b/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java @@ -46,7 +46,7 @@ import java.util.*; public Object run() { Platform.initSingleton(); - if(TempJarCache.isInitialized()) { + if( TempJarCache.isInitialized(true) ) { // only: oculusvr.jar -> oculusvr-natives-<os.and.arch>.jar JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { com.jogamp.oculusvr.OVRDynamicLibraryBundleInfo.class }, null); } @@ -85,6 +85,16 @@ import java.util.*; } @Override + public final boolean searchToolLibInSystemPath() { + return true; + } + + @Override + public final boolean searchToolLibSystemPathFirst() { + return true; + } + + @Override public final List<List<String>> getToolLibNames() { return new ArrayList<List<String>>(); // None } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java index e4fabbbcc..eff2aae49 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java @@ -36,6 +36,7 @@ import com.jogamp.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.event.MonitorEvent; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; @@ -90,7 +91,7 @@ public class NEWTGearsES2Activity extends NewtBaseActivity { public void mousePressed(final MouseEvent e) { if( e.getPointerCount() == 3 ) { Log.d(TAG, "MemoryHog"); - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { public void run() { final ArrayList<Buffer> buffers = new ArrayList<Buffer>(); while(true) { diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java index 89d28c08d..7430dcd38 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java @@ -27,7 +27,7 @@ import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.GLUniformData; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; - +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; @@ -98,7 +98,7 @@ public class Bug735Inv0AppletAWT extends Applet implements Runnable { } public void start() { - thread = new Thread(this, "Animation Thread"); + thread = new InterruptSource.Thread(null, this, "Animation Thread"); thread.start(); } diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java index 5019391ad..b31a5f410 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java @@ -27,7 +27,7 @@ import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.GLUniformData; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; - +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; @@ -100,7 +100,7 @@ public class Bug735Inv1AppletAWT extends Applet implements Runnable { } public void start() { - thread = new Thread(this, "Animation Thread"); + thread = new InterruptSource.Thread(null, this, "Animation Thread"); thread.start(); } diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java index 1228f1453..d0e4448cc 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java @@ -20,7 +20,8 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.awt.GLCanvas; - +import com.jogamp.common.util.InterruptSource; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; @@ -82,7 +83,7 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { public void start() { initDraw(); - thread = new Thread(this, "Animation Thread"); + thread = new InterruptSource.Thread(null, this, "Animation Thread"); thread.start(); } @@ -219,7 +220,7 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { System.err.println("swapInterval "+SWAP_INTERVAL); System.err.println("exclusiveContext "+USE_ECT); if(waitForKey) { - UITestCase.waitForKey("Start"); + JunitTracer.waitForKey("Start"); } final GraphicsEnvironment environment = diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java index 184a2ef0f..7532ca6db 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java +++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java @@ -6,6 +6,7 @@ import java.awt.Frame; import java.awt.event.*; import java.awt.geom.*; +import com.jogamp.common.util.InterruptSource; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; @@ -49,7 +50,7 @@ public abstract class Issue344Base implements GLEventListener frame.setSize(512, 512); frame.addWindowListener(new WindowAdapter() { public void windowClosing(final WindowEvent e) { - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { public void run() { System.exit(0); } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java b/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java index 0666ec4db..38eda9adf 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java @@ -14,22 +14,22 @@ public class FontSet01 { fonts[i++] = FontFactory.get(FontFactory.UBUNTU).getDefault(); // FontSet.FAMILY_REGULAR, FontSet.STYLE_NONE fonts[i++] = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_REGULAR, FontSet.STYLE_ITALIC); fonts[i++] = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_REGULAR, FontSet.STYLE_BOLD); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeMono.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeMonoBold.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeSans.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeSansBold.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeSerif.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeSerifBold.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeSerifBoldItalic.ttf").getInputStream(), true); - fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class, - "fonts/freefont/FreeSerifItalic.ttf").getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMono.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMonoBold.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSans.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSansBold.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerif.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerifBold.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerifBoldItalic.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); + fonts[i++] = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerifItalic.ttf", + TestTextRendererNEWTBugXXXX.class.getClassLoader(), TestTextRendererNEWTBugXXXX.class).getInputStream(), true); return fonts; } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index 86b129fe1..f37f6b7e0 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -30,6 +30,7 @@ package com.jogamp.opengl.test.junit.graph; import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.Locale; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; @@ -54,6 +55,7 @@ import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.Window; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.MiscUtils; @@ -73,7 +75,7 @@ public class TestTextRendererNEWT00 extends UITestCase { static int GraphVBAASamples = 0; static int GraphMSAASamples = 0; static boolean ManualTest = false; - static int SwapInterval = 0; + static int SwapInterval = 1; static String fontFileName = null; static URL fontURL = null; @@ -213,7 +215,7 @@ public class TestTextRendererNEWT00 extends UITestCase { window.display(); System.err.println("Chosen: "+window.getChosenGLCapabilities()); if( WaitStartEnd ) { - UITestCase.waitForKey("Start"); + JunitTracer.waitForKey("Start"); } final RenderState rs = RenderState.createRenderState(SVertex.factory()); @@ -252,7 +254,7 @@ public class TestTextRendererNEWT00 extends UITestCase { }); anim.stop(); if( WaitStartEnd ) { - UITestCase.waitForKey("Stop"); + JunitTracer.waitForKey("Stop"); } destroyWindow(window); } @@ -342,7 +344,7 @@ public class TestTextRendererNEWT00 extends UITestCase { public void printScreen(final int renderModes, final GLAutoDrawable drawable, final String dir, final String objName, final boolean exportAlpha) throws GLException, IOException { final String modeS = Region.getRenderModeString(renderModes); - final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, + final String bname = String.format((Locale)null, "%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, drawable.getChosenGLCapabilities().getNumSamples(), TestTextRendererNEWT00.fontSizeFixed, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, vbaaSampleCount[0]); final String filename = dir + bname +".png"; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java index 4e66f6920..b452e091d 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java @@ -29,6 +29,7 @@ package com.jogamp.opengl.test.junit.graph; import java.io.File; import java.io.IOException; +import java.util.Locale; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; @@ -102,7 +103,7 @@ public class TestTextRendererNEWT10 extends UITestCase { forceGL3 = true; } else if(args[i].equals("-font")) { i++; - font = FontFactory.get(IOUtil.getResource(TestTextRendererNEWT10.class, args[i]).getInputStream(), true); + font = FontFactory.get(IOUtil.getResource(args[i], TestTextRendererNEWT10.class.getClassLoader(), TestTextRendererNEWT10.class).getInputStream(), true); } else if(args[i].equals("-fontSize")) { i++; fontSize = MiscUtils.atof(args[i], fontSize); @@ -242,7 +243,7 @@ public class TestTextRendererNEWT10 extends UITestCase { final String objName = getSimpleTestName(".")+"-snap"+screenshot_num; screenshot_num++; final String modeS = Region.getRenderModeString(renderModes); - final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, + final String bname = String.format((Locale)null, "%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, drawable.getChosenGLCapabilities().getNumSamples(), TestTextRendererNEWT10.fontSize, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount); final String filename = dir + bname +".png"; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java index 678361f24..e6ae83911 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java @@ -29,6 +29,7 @@ package com.jogamp.opengl.test.junit.graph; import java.io.File; import java.io.IOException; +import java.util.Locale; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; @@ -212,7 +213,7 @@ public class TestTextRendererNEWTBugXXXX extends UITestCase { final String objName = getSimpleTestName(".")+"-snap"+screenshot_num; screenshot_num++; final String modeS = Region.getRenderModeString(renderModes); - final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, + final String bname = String.format((Locale)null, "%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, drawable.getChosenGLCapabilities().getNumSamples(), TestTextRendererNEWTBugXXXX.fontSize, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount); final String filename = dir + bname +".png"; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index 73b76debb..2d3b0664e 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -47,6 +47,7 @@ import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.opengl.GLWindow; @@ -121,6 +122,17 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { @Override public void init(final GLAutoDrawable drawable) { + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + final Window window = (Window) upObj; + final float[] sDPI = window.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + System.err.println("DPI "+sDPI[0]+" x "+sDPI[1]); + + final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); + System.err.println("HiDPI PixelScale: "+hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + } autoDrawable = drawable; GL2ES2 gl = drawable.getGL().getGL2ES2(); if(debug) { @@ -302,9 +314,16 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { @Override public boolean run(final GLAutoDrawable drawable) { final GL gl = drawable.getGL(); - int i = gl.getSwapInterval(); - i = i==0 ? 1 : 0; + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = -1; break; + case -1: i = 1; break; + case 1: i = 0; break; + default: i = 1; break; + } gl.setSwapInterval(i); + final GLAnimatorControl a = drawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); @@ -312,7 +331,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { if(drawable instanceof FPSCounter) { ((FPSCounter)drawable).resetFPSCounter(); } - System.err.println("Swap Interval: "+i); + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); return true; } }); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java index f7e779cd3..bf0a907b0 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java @@ -34,7 +34,6 @@ import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RenderState; -import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.SVertex; import com.jogamp.newt.opengl.GLWindow; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java index c648708d4..945204052 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java @@ -165,9 +165,14 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB super.init(drawable); final Object upObj = drawable.getUpstreamWidget(); if( upObj instanceof Window ) { - final float[] pixelsPerMM = new float[2]; - ((Window)upObj).getPixelsPerMM(pixelsPerMM); - dpiH = pixelsPerMM[1]*25.4f; + final Window window = (Window) upObj; + final float[] sDPI = window.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + dpiH = sDPI[1]; + System.err.println("Using screen DPI of "+dpiH); + } else { + System.err.println("Using default DPI of "+dpiH); } fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH)); switchHeadBox(); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java index 4bb72bbd2..a55ed26c0 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java @@ -6,6 +6,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; @@ -16,6 +17,7 @@ import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLRunnable; import com.jogamp.common.net.Uri; +import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; @@ -354,7 +356,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { button.addMouseListener(new UIShape.MouseGestureAdapter() { @Override public void mouseClicked(final MouseEvent e) { - new Thread() { + new InterruptSource.Thread() { public void run() { if( null != cDrawable ) { final GLAnimatorControl actrl = cDrawable.getAnimator(); @@ -521,6 +523,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { mPlayer.setTextureUnit(texUnitMediaPlayer); final MediaPlayerButton mPlayerButton = new MediaPlayerButton(renderer.getRenderState().getVertexFactory(), renderModes, button2XSize, button2YSize, mPlayer); + mPlayerButton.setVerbose(true); mPlayerButton.addDefaultEventListener(); mPlayerButton.translate(xStartRight, yStartTop - diffY*1, 0f); mPlayerButton.setToggleable(true); @@ -665,14 +668,17 @@ public class GPUUISceneGLListener0A implements GLEventListener { if( upObj instanceof Window ) { final Window upWin = (Window)upObj; final MonitorDevice mm = upWin.getMainMonitor(); - final float[] monitorPixelsPerMM = mm.getPixelsPerMM(new float[2]); - final float monitorDpiH = monitorPixelsPerMM[1]*25.4f; - final float[] surfacePixelsPerMM = upWin.getPixelsPerMM(new float[2]); - dpiH = surfacePixelsPerMM[1]*25.4f; + final float[] monitorDPI = mm.getPixelsPerMM(new float[2]); + monitorDPI[0] *= 25.4f; + monitorDPI[1] *= 25.4f; + final float[] sDPI = upWin.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + dpiH = sDPI[1]; System.err.println("Monitor detected: "+mm); - System.err.println("Monitor dpi: "+monitorDpiH); + System.err.println("Monitor dpi: "+monitorDPI[0]+" x "+monitorDPI[1]); System.err.println("Surface scale: native "+Arrays.toString(upWin.getMaximumSurfaceScale(new float[2]))+", current "+Arrays.toString(upWin.getCurrentSurfaceScale(new float[2]))); - System.err.println("Surface dpi: "+dpiH); + System.err.println("Surface dpi "+sDPI[0]+" x "+sDPI[1]); } else { System.err.println("Using default DPI of "+dpiH); } @@ -785,7 +791,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { public void printScreen(final GL gl) { final String modeS = Region.getRenderModeString(jogampLabel.getRenderModes()); - final String filename = String.format("GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png", + final String filename = String.format((Locale)null, "GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png", shotCount++, renderer.getWidth(), renderer.getHeight(), modeS, sceneUIController.getSampleCount()); gl.glFinish(); // just make sure rendering finished .. @@ -943,7 +949,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { // final float dy = -(ny - dragLastY); shapeEvent.shape.translate(dx, dy, 0f); final float[] tx = shapeEvent.shape.getTranslate(); - actionText = String.format("Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]); + actionText = String.format((Locale)null, "Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]); } } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java index 8b5b70239..721fe9cb0 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java @@ -180,10 +180,6 @@ public class GPUUISceneNewtCanvasAWTDemo { frame.setVisible(true); } }); - final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); - System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ - valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ - hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); animator.start(); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java index aa6dd00cc..3053ed40a 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java @@ -145,10 +145,6 @@ public class GPUUISceneNewtDemo { }); window.setVisible(true); - final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); - System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ - valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ - hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); animator.start(); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java index bdde61ad9..44e2c6034 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java @@ -28,7 +28,7 @@ package com.jogamp.opengl.test.junit.graph.demos.ui; import com.jogamp.opengl.GL2ES2; - +import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Vertex.Factory; @@ -41,7 +41,7 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; * GPU based resolution independent {@link GLMediaPlayer} Button impl */ public class MediaPlayerButton extends TextureSeqButton { - public boolean verbose = false; + private boolean verbose = false; /** * @param factory @@ -62,6 +62,8 @@ public class MediaPlayerButton extends TextureSeqButton { setEnabled(false); // data and shader n/a yet } + public void setVerbose(final boolean v) { verbose = v; } + /** * Add the default {@link GLMediaEventListener} to {@link #getGLMediaPlayer() this class's GLMediaPlayer}. */ @@ -91,7 +93,7 @@ public class MediaPlayerButton extends TextureSeqButton { // FIXME: mPlayer.resetGLState(); } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { - new Thread() { + new InterruptSource.Thread() { public void run() { // loop for-ever .. mPlayer.seek(0); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java index 2e3d2fac3..ab5bfb926 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import com.jogamp.opengl.FPSCounter; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAnimatorControl; @@ -285,16 +286,27 @@ public abstract class UIListenerBase01 implements GLEventListener { else if(arg0.getKeyCode() == KeyEvent.VK_V) { if(null != autoDrawable) { autoDrawable.invoke(false, new GLRunnable() { + @Override public boolean run(final GLAutoDrawable drawable) { final GL gl = drawable.getGL(); - int i = gl.getSwapInterval(); - i = i==0 ? 1 : 0; + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = 1; break; + case 1: i = -1; break; + case -1: i = 0; break; + default: i = 1; break; + } gl.setSwapInterval(i); + final GLAnimatorControl a = drawable.getAnimator(); if( null != a ) { a.resetFPSCounter(); } - System.err.println("Swap Interval: "+i); + if(drawable instanceof FPSCounter) { + ((FPSCounter)drawable).resetFPSCounter(); + } + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); return true; } }); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLProfile0XBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLProfile0XBase.java index 7fd3488ba..add8113bc 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLProfile0XBase.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLProfile0XBase.java @@ -43,9 +43,10 @@ import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.PropertyAccess; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -871,8 +872,8 @@ public abstract class GLProfile0XBase extends UITestCase { glWindow.setSize(128, 128); glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, true, null)); glWindow.display(); Thread.sleep(100); @@ -884,8 +885,8 @@ public abstract class GLProfile0XBase extends UITestCase { glWindow.getContext().isCreatedWithARBMethod()); } glWindow.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, false, null)); } protected void validateOnlineOffscreen(final String requestedProfile, final GLCapabilitiesImmutable caps) @@ -915,7 +916,7 @@ public abstract class GLProfile0XBase extends UITestCase { Thread.sleep(100); // Same definition as in GLProfile for 'disableOpenGLARBContext' final boolean isOSX = Platform.OSType.MACOS == Platform.getOSType(); - final boolean disableOpenGLARBContext = null != System.getProperty("jogl.disable.openglarbcontext") && !isOSX; + final boolean disableOpenGLARBContext = PropertyAccess.isPropertyDefined("jogl.disable.openglarbcontext", true) && !isOSX; if( disableOpenGLARBContext ) { Assert.assertFalse("Property 'jogl.disable.openglarbcontext' set, but created w/ ARB", glad.getContext().isCreatedWithARBMethod()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java index 7b28c6896..cf0adab67 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java @@ -30,6 +30,7 @@ package com.jogamp.opengl.test.junit.jogl.acore; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.util.Locale; import javax.imageio.ImageIO; import com.jogamp.opengl.GL; @@ -85,7 +86,7 @@ public abstract class GLReadBuffer00BaseAWT extends GLReadBuffer00Base { } public void snapshot(final int sn, final GL gl, final String fileSuffix, final String destPath) { final GLDrawable drawable = gl.getContext().getGLReadDrawable(); - final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter); + final String postSNDetail = String.format((Locale)null, "awt-usr%03d", textRendererGLEL.userCounter); final String filenameAWT = getSnapshotFilename(sn, postSNDetail, drawable.getChosenGLCapabilities(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), glReadBufferUtil.hasAlpha(), fileSuffix, destPath); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java index 3379129dd..7a5b49168 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java @@ -28,6 +28,8 @@ package com.jogamp.opengl.test.junit.jogl.acore; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.nativewindow.Capabilities; import com.jogamp.nativewindow.util.InsetsImmutable; import com.jogamp.opengl.GLCapabilities; @@ -194,11 +196,11 @@ public abstract class InitConcurrentBaseNEWT extends UITestCase { final String currentThreadName = Thread.currentThread().getName(); final Object syncDone = new Object(); final JOGLTask[] tasks = new JOGLTask[num]; - final Thread[] threads = new Thread[num]; + final InterruptSource.Thread[] threads = new InterruptSource.Thread[num]; int i; for(i=0; i<num; i++) { tasks[i] = new JOGLTask(syncDone, i, reuse); - threads[i] = new Thread(tasks[i], currentThreadName+"-jt"+i); + threads[i] = new InterruptSource.Thread(null, tasks[i], currentThreadName+"-jt"+i); } final long t0 = System.currentTimeMillis(); @@ -211,7 +213,7 @@ public abstract class InitConcurrentBaseNEWT extends UITestCase { try { syncDone.wait(500); } catch (final InterruptedException e) { - throw new RuntimeException(e); + throw new InterruptedRuntimeException(e); } System.err.println(i+": "+doneDump(tasks)); i++; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug1146GLContextDialogToolTipAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug1146GLContextDialogToolTipAWT.java index 42646c07e..402358899 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug1146GLContextDialogToolTipAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug1146GLContextDialogToolTipAWT.java @@ -52,6 +52,7 @@ import org.junit.Test; import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLCapabilitiesImmutable; import com.jogamp.opengl.GLProfile; @@ -127,13 +128,13 @@ public class TestBug1146GLContextDialogToolTipAWT extends UITestCase { final String cancelButtonText = UIManager.getString("FileChooser.cancelButtonText",l); // launch robot action .. - new Thread() + new InterruptSource.Thread() { public void run() { try { - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(fileChooser, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(fileChooser, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas1, true, null)); final Point approveButtonPos; final AbstractButton approveButton = findButton(0, fileChooser, approveButtonText); @@ -161,7 +162,7 @@ public class TestBug1146GLContextDialogToolTipAWT extends UITestCase { // hover to 'approve' -> tool tip if( null != approveButtonPos ) { AWTRobotUtil.mouseMove(robot, approveButtonPos, MOVE_ITER, MOVE_DELAY); - Thread.sleep(TOOLTIP_WAIT); + java.lang.Thread.sleep(TOOLTIP_WAIT); try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -173,7 +174,7 @@ public class TestBug1146GLContextDialogToolTipAWT extends UITestCase { } catch (final InvocationTargetException e) { e.printStackTrace(); } - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas2, true, null)); } if( null != cancelButtonPos ) { AWTRobotUtil.mouseClick(robot, cancelButtonPos, MOVE_ITER, MOVE_DELAY, ACTION_DELAY); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java index fd012e86f..a034f9c8a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java @@ -44,6 +44,7 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.RunnableTask; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -83,7 +84,7 @@ public class TestFBOAutoDrawableDeadlockAWT extends UITestCase { System.err.println("BB.0: "+rTask.getSyncObject()); synchronized (rTask.getSyncObject()) { System.err.println("BB.1: "+rTask.getSyncObject()); - new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); + new InterruptSource.Thread(null, rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); try { System.err.println("BB.2"); rTask.getSyncObject().wait(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java index d122a0709..05aea5ac7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java @@ -47,7 +47,7 @@ import com.jogamp.opengl.FBObject; import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -339,7 +339,7 @@ public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { szStep = 1; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); // - SWAP_ODD glad.display(); // - SWAP_EVEN @@ -387,7 +387,7 @@ public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { szStep = 4; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); // - SWAP_EVEN glad.display(); // - SWAP_ODD @@ -446,7 +446,7 @@ public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { szStep = 3; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java index f2e8b86af..3f5540501 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java @@ -32,13 +32,14 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; @@ -114,7 +115,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { if( 3 == c ) { demo.setMSAA(4); } else if( 6 == c ) { - new Thread() { + new InterruptSource.Thread() { @Override public void run() { glWindow.setSize(dw+64, dh+64); @@ -124,14 +125,14 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { } else if( 12 == c ) { demo.setMSAA(0); } else if( 15 == c ) { - new Thread() { + new InterruptSource.Thread() { @Override public void run() { glWindow.setSize(dw+128, dh+128); } }.start(); } else if( 18 == c ) { c=0; - new Thread() { + new InterruptSource.Thread() { @Override public void run() { glWindow.setSize(dw+256, dh+256); @@ -167,7 +168,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { } System.err.println("*** "+e); if(e.getKeyChar()=='f') { - new Thread() { + new InterruptSource.Thread() { public void run() { System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setFullscreen(!glWindow.isFullscreen()); @@ -205,7 +206,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { Assert.assertFalse(animator.isAnimating()); Assert.assertFalse(animator.isStarted()); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java index 26d510a45..b0b9b53e4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java @@ -35,8 +35,8 @@ import java.io.InputStreamReader; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; @@ -48,7 +48,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.GLFinishOnDisplay; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; - +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.SurfaceUpdatedListener; import com.jogamp.opengl.GL; @@ -192,7 +192,7 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase { } if(9 == c) { c=0; - new Thread() { + new InterruptSource.Thread() { @Override public void run() { glWindow.setSize(dw+256, dh+256); @@ -258,7 +258,7 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase { fbod2.destroy(); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java index 0586eef8e..2bc512fa0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java @@ -35,8 +35,8 @@ import java.io.InputStreamReader; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; @@ -46,7 +46,7 @@ import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.test.junit.jogl.demos.GLFinishOnDisplay; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; - +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.SurfaceUpdatedListener; import com.jogamp.opengl.GL; @@ -178,7 +178,7 @@ public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase { } if(9 == c) { c=0; - new Thread() { + new InterruptSource.Thread() { @Override public void run() { glWindow.setSize(dw+256, dh+256); @@ -231,7 +231,7 @@ public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase { fbod1.destroy(); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java index ff05b63a1..4432fad3e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java @@ -50,8 +50,8 @@ import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowUpdateEvent; import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -83,8 +83,8 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase { Assert.assertNotNull(window); window.setSize(640, 400); window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null)); System.out.println("Window: "+window.getClass().getName()); final GLDrawable drawable = factory.createGLDrawable(window); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java index bf870b257..4f666920a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java @@ -55,7 +55,8 @@ import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -96,8 +97,8 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { Assert.assertNotNull(window); window.setSize(widthStep*szStep, heightStep*szStep); window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null)); System.out.println("Window: "+window.getClass().getName()); // Check caps of NativeWindow config w/o GL @@ -199,7 +200,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { // 1 - szStep = 2 final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep }); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -210,7 +211,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -221,7 +222,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java index daa784fbb..7cef9e448 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java @@ -48,7 +48,7 @@ import org.junit.runners.MethodSorters; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -128,7 +128,7 @@ public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase { // 1 - szStep = 2 Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -136,7 +136,7 @@ public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase { szStep = 1; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -144,7 +144,7 @@ public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase { szStep = 4; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java index dad7fb1ed..a23e81d69 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java @@ -48,7 +48,7 @@ import org.junit.runners.MethodSorters; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -128,7 +128,7 @@ public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase { // 1 - szStep = 2 Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -136,7 +136,7 @@ public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase { szStep = 1; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -144,7 +144,7 @@ public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase { szStep = 4; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java new file mode 100644 index 000000000..9934ae862 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java @@ -0,0 +1,247 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import com.jogamp.nativewindow.AbstractGraphicsDevice; +import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLContext; +import com.jogamp.opengl.GLDrawableFactory; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLOffscreenAutoDrawable; +import com.jogamp.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.GLTestUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Testing producing {@link GLContext} instances of different {@link GLProfile}s + * using different {@link AbstractGraphicsDevice}s. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableFactoryGLProfileDeviceNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLProfile getProfile(final AbstractGraphicsDevice device, final String profile) { + if( !GLProfile.isAvailable(device, profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } else { + return GLProfile.get(device, profile); + } + } + + void doTest(final boolean isEGL, final GLDrawableFactory factory, final AbstractGraphicsDevice device, + final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException { + System.err.println("Factory: "+factory.getClass().getName()); + System.err.println("Requested GL Caps: "+reqGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(device, reqGLCaps, null, widthStep*szStep, heightStep*szStep); + + Assert.assertNotNull(glad); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + Assert.assertNotNull(chosenCaps); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + Assert.assertNotNull(chosenGLCaps); + System.err.println("Choosen GL Caps: "+chosenGLCaps); + + glad.addGLEventListener(demo); + final GLEventListenerCounter glelc = new GLEventListenerCounter(); + glad.addGLEventListener(glelc); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); + glad.display(); + + Thread.sleep(50); + + final AbstractGraphicsDevice adevice = glad.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + glad.destroy(); + System.err.println("Fin isEGL "+isEGL+", "+adevice); + System.err.println("Fin "+glelc); + Assert.assertTrue("init count: "+glelc, glelc.initCount > 0); + Assert.assertTrue("reshape count: "+glelc, glelc.reshapeCount > 0); + Assert.assertTrue("display count: "+glelc, glelc.displayCount > 0); + Assert.assertTrue("dispose count: "+glelc, glelc.disposeCount > 0); + Assert.assertEquals("EGL/Desktop not matching: isEGL "+isEGL+", "+adevice, isEGL, adevice instanceof EGLGraphicsDevice); + } + + @Test + public void test00AvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void test01ES2OnEGL() throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getEGLFactory(); + if( null == factory ) { + System.err.println("EGL Factory n/a"); + return; + } + final AbstractGraphicsDevice prodDevice = factory.getDefaultDevice(); + final GLProfile glp = getProfile(prodDevice, GLProfile.GLES2); + if(null != glp) { + Assert.assertTrue("Not a GLES2 profile but "+glp, glp.isGLES2()); + Assert.assertTrue("Not a GL2ES2 profile but "+glp, glp.isGL2ES2()); + } + if(null == glp) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(glp); + reqGLCaps.setOnscreen(false); + final GearsES2 demo = new GearsES2(1); + demo.setVerbose(false); + doTest(true /* isEGL */, factory, prodDevice, reqGLCaps, demo); + } + + @Test + public void test02GLOnEGL() throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getEGLFactory(); + if( null == factory ) { + System.err.println("EGL Factory n/a"); + return; + } + final AbstractGraphicsDevice prodDevice = factory.getDefaultDevice(); + final GLProfile glp = getProfile(prodDevice, GLProfile.GL2GL3); + if(null != glp) { + Assert.assertTrue("Not a GL2GL3 profile but "+glp, glp.isGL2GL3()); + } + if(null == glp || !glp.isGL2ES2()) { + if( null != glp ) { + System.err.println("Not a GL2ES2 profile but "+glp); + } + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(glp); + reqGLCaps.setOnscreen(false); + final GearsES2 demo = new GearsES2(1); + demo.setVerbose(false); + doTest(true /* isEGL */, factory, prodDevice, reqGLCaps, demo); + } + + @Test + public void test11ES2OnDesktop() throws InterruptedException { + final GLDrawableFactory deskFactory = GLDrawableFactory.getDesktopFactory(); + if( null == deskFactory ) { + System.err.println("Desktop Factory n/a"); + return; + } + final AbstractGraphicsDevice prodDevice = deskFactory.getDefaultDevice(); + final GLProfile glp = getProfile(prodDevice, GLProfile.GLES2); + if(null != glp) { + Assert.assertTrue("Not a GLES2 profile but "+glp, glp.isGLES2()); + Assert.assertTrue("Not a GL2ES2 profile but "+glp, glp.isGL2ES2()); + } + if(null == glp) { + return; + } + final GLDrawableFactory prodFactory = GLDrawableFactory.getFactory(glp); + if( null == prodFactory ) { + System.err.println("Production Factory n/a"); + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(glp); + reqGLCaps.setOnscreen(false); + final GearsES2 demo = new GearsES2(1); + demo.setVerbose(false); + doTest(true /* isEGL */, prodFactory, prodDevice, reqGLCaps, demo); + } + + @Test + public void test12GLOnDesktop() throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); + if( null == factory ) { + System.err.println("Desktop Factory n/a"); + return; + } + final AbstractGraphicsDevice prodDevice = factory.getDefaultDevice(); + final GLProfile glp = getProfile(prodDevice, GLProfile.GL2GL3); + if(null != glp) { + Assert.assertTrue("Not a GL2GL3 profile but "+glp, glp.isGL2GL3()); + } + if(null == glp || !glp.isGL2ES2()) { + if( null != glp ) { + System.err.println("Not a GL2ES2 profile but "+glp); + } + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(glp); + reqGLCaps.setOnscreen(false); + final GearsES2 demo = new GearsES2(1); + demo.setVerbose(false); + doTest(false /* isEGL */, factory, prodDevice, reqGLCaps, demo); + } + + public static void main(final String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryGLProfileDeviceNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java index 7e53f9579..6a7b09be1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java @@ -48,7 +48,7 @@ import org.junit.runners.MethodSorters; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -120,7 +120,7 @@ public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT extends UITestCase { // 1 - szStep = 2 Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -128,7 +128,7 @@ public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT extends UITestCase { szStep = 1; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -136,7 +136,7 @@ public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT extends UITestCase { szStep = 4; glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + GLTestUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep, null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java index 347463eae..6138ce6ee 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java @@ -32,6 +32,7 @@ import java.awt.Dimension; import java.awt.Frame; import java.io.IOException; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; @@ -55,6 +56,7 @@ import org.junit.runners.MethodSorters; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -133,8 +135,8 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { Assume.assumeNoException( throwable ); } - Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true, null)); + Assert.assertTrue(GLTestUtil.waitForRealized(glad, true, null)); System.out.println("Window: "+glad.getClass().getName()); // Check caps of NativeWindow config w/o GL @@ -198,7 +200,7 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { // 1 - szStep = 2 final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep }); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -209,7 +211,7 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); glad.display(); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -221,7 +223,7 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); glad.display(); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -345,7 +347,7 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { } } if(waitForKey) { - UITestCase.waitForKey("Start"); + JunitTracer.waitForKey("Start"); } org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java index bb5861fdc..34148501d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java @@ -51,7 +51,8 @@ import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -90,8 +91,8 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { Assert.assertNotNull(glad); glad.setSize(widthStep*szStep, heightStep*szStep); glad.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glad, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glad, true, null)); System.out.println("Window: "+glad.getClass().getName()); // Check caps of NativeWindow config w/o GL @@ -154,7 +155,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { // 1 - szStep = 2 final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep }); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -165,7 +166,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -176,7 +177,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java index 57d3fcb3d..ce968751e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java @@ -57,7 +57,8 @@ import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -145,8 +146,8 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase Assume.assumeNoException( throwable ); } - Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glad, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glad, true, null)); System.out.println("Window: "+glad.getClass().getName()); // Check caps of NativeWindow config w/o GL @@ -210,7 +211,7 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase // 1 - szStep = 2 final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep }); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -221,7 +222,7 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); glad.display(); snapshotGLEventListener.setMakeSnapshot(); glad.display(); @@ -233,7 +234,7 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase expSurfaceSize[1] = heightStep*szStep; glad.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1], null)); glad.display(); snapshotGLEventListener.setMakeSnapshot(); glad.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java index 1e78691c4..8d26ebb82 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java @@ -31,6 +31,7 @@ package com.jogamp.opengl.test.junit.jogl.acore; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; @@ -194,8 +195,8 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { final Object sync = new Object(); final MyRunnable[] animTasks = new MyRunnable[animThreadCount]; final MyRunnable[] resizeTasks = new MyRunnable[animThreadCount]; - final Thread[] animThreads = new Thread[reszThreadCount]; - final Thread[] resizeThreads = new Thread[reszThreadCount]; + final InterruptSource.Thread[] animThreads = new InterruptSource.Thread[reszThreadCount]; + final InterruptSource.Thread[] resizeThreads = new InterruptSource.Thread[reszThreadCount]; System.err.println("animThreadCount "+animThreadCount+", frameCount "+frameCount); System.err.println("reszThreadCount "+reszThreadCount+", resizeCount "+resizeCount); @@ -204,12 +205,12 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { for(int i=0; i<animThreadCount; i++) { System.err.println("create anim task/thread "+i); animTasks[i] = new RudeAnimator(glWindow, frameCount, sync, i); - animThreads[i] = new Thread(animTasks[i], currentThreadName+"-anim"+i); + animThreads[i] = new InterruptSource.Thread(null, animTasks[i], currentThreadName+"-anim"+i); } for(int i=0; i<reszThreadCount; i++) { System.err.println("create resz task/thread "+i); resizeTasks[i] = new RudeResizer(glWindow, resizeCount, sync, i); - resizeThreads[i] = new Thread(resizeTasks[i], currentThreadName+"-resz"+i); + resizeThreads[i] = new InterruptSource.Thread(null, resizeTasks[i], currentThreadName+"-resz"+i); } myEventCounter.reset(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java index dcee114e5..8319a1c22 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java @@ -32,7 +32,6 @@ import java.io.IOException; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; -import com.jogamp.opengl.GL2GL3; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLDebugListener; @@ -58,6 +57,14 @@ public class TestGLDebug00NEWT extends UITestCase { static String dbgTstMsg0 = "Hello World"; static int dbgTstId0 = 42; + static GLProfile getGLProfile(final String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return GLProfile.get(profile); + } + public static class WindowContext { public final Window window; public final GLContext context; @@ -115,9 +122,7 @@ public class TestGLDebug00NEWT extends UITestCase { } - void test01GLDebug01EnableDisable(final boolean enable) throws InterruptedException { - final GLProfile glp = GLProfile.getDefault(); - + void testX1GLDebugEnableDisable(final GLProfile glp, final boolean enable) throws InterruptedException { final WindowContext winctx = createWindow(glp, enable); final String glDebugExt = winctx.context.getGLDebugMessageExtension(); System.err.println("glDebug extension: "+glDebugExt); @@ -131,19 +136,42 @@ public class TestGLDebug00NEWT extends UITestCase { } @Test - public void test01GLDebugDisabled() throws InterruptedException { - test01GLDebug01EnableDisable(false); + public void test01GL2GL3DebugDisabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, false); } @Test - public void test01GLDebugEnabled() throws InterruptedException { - test01GLDebug01EnableDisable(true); + public void test02GL2GL3DebugEnabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, true); } @Test - public void test02GLDebugError() throws InterruptedException { - final GLProfile glp = GLProfile.getDefault(); + public void test11GLES2DebugDisabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, false); + } + + @Test + public void test12GLES2DebugEnabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, true); + } + void testX2GLDebugError(final GLProfile glp) throws InterruptedException { final WindowContext winctx = createWindow(glp, true); final MyGLDebugListener myGLDebugListener = new MyGLDebugListener( @@ -164,8 +192,24 @@ public class TestGLDebug00NEWT extends UITestCase { } @Test - public void test03GLDebugInsert() throws InterruptedException { - final GLProfile glp = GLProfile.getDefault(); + public void test03GL2GL3DebugError() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX2GLDebugError(glp); + } + + @Test + public void test13GLES2DebugError() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX2GLDebugError(glp); + } + + void testX3GLDebugInsert(final GLProfile glp) throws InterruptedException { final WindowContext winctx = createWindow(glp, true); final MyGLDebugListener myGLDebugListener = new MyGLDebugListener(dbgTstMsg0, dbgTstId0); winctx.context.addGLDebugListener(myGLDebugListener); @@ -184,6 +228,23 @@ public class TestGLDebug00NEWT extends UITestCase { destroyWindow(winctx); } + @Test + public void test04GL2GL3DebugInsert() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX3GLDebugInsert(glp); + } + + @Test + public void test14GLES2DebugInsert() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX3GLDebugInsert(glp); + } public static void main(final String args[]) throws IOException { final String tstname = TestGLDebug00NEWT.class.getName(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java index 66733209c..43d207a0d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java @@ -31,7 +31,6 @@ package com.jogamp.opengl.test.junit.jogl.acore; import java.io.IOException; import com.jogamp.opengl.GL2ES2; -import com.jogamp.opengl.GL2GL3; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLContext; @@ -54,6 +53,14 @@ public class TestGLDebug01NEWT extends UITestCase { static String dbgTstMsg0 = "Hello World"; static int dbgTstId0 = 42; + static GLProfile getGLProfile(final String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return GLProfile.get(profile); + } + GLWindow createWindow(final GLProfile glp, final boolean debugGL) { final GLCapabilities caps = new GLCapabilities(glp); // @@ -76,9 +83,7 @@ public class TestGLDebug01NEWT extends UITestCase { } - void test01GLDebug01EnableDisable(final boolean enable, final String dbgTstMsg, final int dbgTstId) throws InterruptedException { - final GLProfile glp = GLProfile.getDefault(); - + void testX1GLDebugEnableDisable(final GLProfile glp, final boolean enable, final String dbgTstMsg, final int dbgTstId) throws InterruptedException { final GLWindow window = createWindow(glp, enable); final GLContext ctx = window.getContext(); final MyGLDebugListener myGLDebugListener = new MyGLDebugListener(dbgTstMsg, dbgTstId); @@ -109,19 +114,42 @@ public class TestGLDebug01NEWT extends UITestCase { } @Test - public void test01GLDebug01Disabled() throws InterruptedException { - test01GLDebug01EnableDisable(false, null, -1); + public void test01GL2GL3DebugDisabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, false, null, -1); } @Test - public void test01GLDebug01Enabled() throws InterruptedException { - test01GLDebug01EnableDisable(true, dbgTstMsg0, dbgTstId0); + public void test02GL2GL3DebugEnabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, true, dbgTstMsg0, dbgTstId0); } @Test - public void test02GLDebug01Error() throws InterruptedException { - final GLProfile glp = GLProfile.getDefault(); + public void test11GLES2DebugDisabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, false, null, -1); + } + @Test + public void test12GLES2DebugEnabled() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX1GLDebugEnableDisable(glp, true, dbgTstMsg0, dbgTstId0); + } + + void testX3GLDebugError(final GLProfile glp) throws InterruptedException { final GLWindow window = createWindow(glp, true); final MyGLDebugListener myGLDebugListener = new MyGLDebugListener( @@ -144,6 +172,23 @@ public class TestGLDebug01NEWT extends UITestCase { destroyWindow(window); } + @Test + public void test03GL2GL3DebugError() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GL2GL3); + if( null == glp ) { + return; + } + testX3GLDebugError(glp); + } + + @Test + public void test13GLES2DebugError() throws InterruptedException { + final GLProfile glp = getGLProfile(GLProfile.GLES2); + if( null == glp ) { + return; + } + testX3GLDebugError(glp); + } public static void main(final String args[]) throws IOException { final String tstname = TestGLDebug01NEWT.class.getName(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java index 3add9685d..f558f698f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.test.junit.jogl.acore; import java.io.File; +import java.util.Locale; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.DimensionImmutable; @@ -184,7 +185,7 @@ public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base { } public void snapshot(final int sn, final GLAutoDrawable drawable, final String fileSuffix, final String destPath) { final GL gl = drawable.getGL(); - final String postSNDetail = String.format("jgl-usr%03d", textRendererGLEL.userCounter); + final String postSNDetail = String.format((Locale)null, "jgl-usr%03d", textRendererGLEL.userCounter); final String filenameJGL = getSnapshotFilename(sn, postSNDetail, drawable.getChosenGLCapabilities(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), glReadBufferUtil.hasAlpha(), fileSuffix, destPath); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java index b11b16812..8d16ee356 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java @@ -171,8 +171,8 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase { frame1.setSize(frameSize0); setupFrameAndShow(frame1, glc); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true, null)); Assert.assertEquals(true, glc.isOffscreenLayerSurfaceEnabled()); final GLAnimatorControl animator1 = new Animator(glc); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java index 65925c6b5..a5abd9466 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java @@ -49,16 +49,27 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.Window; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; +/** + * <p> + * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}, and many more, see {@link #main(String[])} + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase { static boolean singleBuffer = false; @@ -162,12 +173,12 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase { } setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null)); + glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1)); frame1.setSize(frameSize0); setupFrameAndShow(frame1, newtCanvasAWT1); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow1, true, null)); Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent()); Assert.assertEquals(true, newtCanvasAWT1.isOffscreenLayerSurfaceEnabled()); @@ -189,7 +200,7 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase { end(animator1, frame1, glWindow1); if( waitForKey ) { - UITestCase.waitForKey("Continue"); + JunitTracer.waitForKey("Continue"); } } @@ -234,7 +245,7 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase { } } if(waitForKey) { - UITestCase.waitForKey("Start"); + JunitTracer.waitForKey("Start"); } final String tstname = TestOffscreenLayer02NewtCanvasAWT.class.getName(); /* diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java index aef64e4e9..ae9dac003 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java @@ -43,6 +43,7 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.RunnableTask; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -82,7 +83,7 @@ public class TestPBufferDeadlockAWT extends UITestCase { System.err.println("BB.0: "+rTask.getSyncObject()); synchronized (rTask.getSyncObject()) { System.err.println("BB.1: "+rTask.getSyncObject()); - new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); + new InterruptSource.Thread(null, rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); try { System.err.println("BB.2"); rTask.getSyncObject().wait(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java index 7e39b890c..fa4ff013a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java @@ -118,7 +118,7 @@ public class TestSharedContextListAWT extends UITestCase { public void run() { frame.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); return glCanvas; } @@ -161,11 +161,11 @@ public class TestSharedContextListAWT extends UITestCase { public void run() { try { f1.dispose(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc1, false)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc1, false, null)); f2.dispose(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc2, false)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc2, false, null)); f3.dispose(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc3, false)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc3, false, null)); } catch (final Throwable t) { throw new RuntimeException(t); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java index 37aaa33b4..263e78def 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java @@ -39,7 +39,7 @@ import com.jogamp.opengl.GLOffscreenAutoDrawable; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; @@ -106,8 +106,8 @@ public class TestSharedContextListNEWT extends UITestCase { animator.add(glWindow); glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, true, null)); glWindow.setPosition(x, y); return glWindow; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java index e84ae4997..095b03207 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java @@ -38,7 +38,7 @@ import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import org.junit.Assert; @@ -108,8 +108,8 @@ public class TestSharedContextListNEWT2 extends UITestCase { animator.start(); glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, true, null)); glWindow.setPosition(x, y); return glWindow; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java index 2a83912b9..7a1d48cf0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java @@ -77,8 +77,9 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.TestUtil; +import com.jogamp.opengl.test.junit.util.TestUtil.WindowClosingListener; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; import com.jogamp.opengl.util.Animator; @@ -553,7 +554,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { */ public void testContextSharingCreateVisibleDestroy(final boolean useNewt, final boolean shareContext) throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("Simple JOGL App for testing context sharing"); - final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); + final TestUtil.WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); // // GLDrawableFactory factory = GLDrawableFactory.getFactory(GLProfile.get(GLProfile.GL2)); @@ -751,7 +752,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { while(animator.isAnimating() && animator.getTotalFPSDuration() < durationPerTest) { Thread.sleep(100); } - AWTRobotUtil.closeWindow(frame, true, awtClosingListener); + AWTRobotUtil.closeWindow(frame, true, awtClosingListener, null); final boolean windowClosed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS); Assert.assertEquals(true, windowClosed); } catch (final InterruptedException e) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java index ba7176ad0..a6406d4a0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java @@ -40,8 +40,9 @@ import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; @@ -96,7 +97,8 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { dummyDrawable.setRealized(true); sharedDrawable = new GLAutoDrawableDelegate(dummyDrawable, null, null, true /*ownDevice*/, null) { }; Assert.assertNotNull(sharedDrawable); - Assert.assertTrue(AWTRobotUtil.waitForRealized(sharedDrawable, true)); + final GLAutoDrawable obj = sharedDrawable; + Assert.assertTrue(GLTestUtil.waitForRealized(obj, true, null)); sharedGears = new GearsES1(); Assert.assertNotNull(sharedGears); @@ -104,7 +106,7 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { // init and render one frame, which will setup the Gears display lists sharedDrawable.display(); final GLContext ctxM = sharedDrawable.getContext(); - Assert.assertTrue("Master ctx not created", AWTRobotUtil.waitForContextCreated(sharedDrawable, true)); + Assert.assertTrue("Master ctx not created", GLTestUtil.waitForContextCreated(sharedDrawable, true, null)); Assert.assertTrue("Master Ctx is shared before shared creation", !ctxM.isShared()); Assert.assertTrue("Master Gears is shared", !sharedGears.usesSharedGears()); } @@ -134,9 +136,9 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { animator.add(glWindow); glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(glWindow, true, null)); MiscUtils.dumpSharedGLContext("Master Context", sharedDrawable.getContext()); MiscUtils.dumpSharedGLContext("New Context", glWindow.getContext()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java index bee121126..16c53564c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java @@ -39,7 +39,9 @@ import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -135,19 +137,19 @@ public class TestSharedContextVBOES2AWT3 extends UITestCase { Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(GLTestUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(GLTestUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(GLTestUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = c1.getContext(); @@ -223,9 +225,9 @@ public class TestSharedContextVBOES2AWT3 extends UITestCase { } }}); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(GLTestUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(GLTestUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(GLTestUtil.waitForRealized(c3, false, null)); } @Test @@ -282,19 +284,19 @@ public class TestSharedContextVBOES2AWT3 extends UITestCase { Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(GLTestUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(GLTestUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(GLTestUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = c1.getContext(); @@ -374,9 +376,9 @@ public class TestSharedContextVBOES2AWT3 extends UITestCase { } }}); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(GLTestUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(GLTestUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(GLTestUtil.waitForRealized(c3, false, null)); } static long duration = 1000; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java index 94238503e..f6eb479fa 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java @@ -39,6 +39,7 @@ import com.jogamp.opengl.awt.GLJPanel; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -126,19 +127,19 @@ public class TestSharedContextVBOES2AWT3b extends UITestCase { Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = c1.getContext(); @@ -185,9 +186,9 @@ public class TestSharedContextVBOES2AWT3b extends UITestCase { } }}); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false, null)); } @Test @@ -235,19 +236,19 @@ public class TestSharedContextVBOES2AWT3b extends UITestCase { Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = c1.getContext(); @@ -298,9 +299,9 @@ public class TestSharedContextVBOES2AWT3b extends UITestCase { } }}); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false, null)); } static long duration = 1000; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java index fcca1884d..88099f578 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java @@ -39,7 +39,8 @@ import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -91,10 +92,10 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { animator.add(glWindow); glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, true, null)); glWindow.display(); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(glWindow, true, null)); Assert.assertTrue("Gears not initialized", gears.waitForInit(true)); return glWindow; @@ -184,9 +185,9 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { } f3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); { final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); @@ -205,9 +206,9 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); } f2.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); { final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); @@ -226,9 +227,9 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); } f1.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); { final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java index 962d10bf4..7b06fcc5d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java @@ -38,7 +38,8 @@ import com.jogamp.opengl.GLDrawableFactory; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -108,7 +109,8 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { sharedDrawable = GLDrawableFactory.getFactory(glp).createDummyAutoDrawable(null, true /* createNewDevice */, caps, null); } Assert.assertNotNull(sharedDrawable); - Assert.assertTrue(AWTRobotUtil.waitForRealized(sharedDrawable, true)); + final GLAutoDrawable obj = sharedDrawable; + Assert.assertTrue(GLTestUtil.waitForRealized(obj, true, null)); sharedGears = new GearsES2(); Assert.assertNotNull(sharedGears); @@ -116,7 +118,7 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { // init and render one frame, which will setup the Gears display lists sharedDrawable.display(); final GLContext ctxM = sharedDrawable.getContext(); - Assert.assertTrue("Master ctx not created", AWTRobotUtil.waitForContextCreated(sharedDrawable, true)); + Assert.assertTrue("Master ctx not created", GLTestUtil.waitForContextCreated(sharedDrawable, true, null)); Assert.assertTrue("Master Ctx is shared before shared creation", !ctxM.isShared()); Assert.assertTrue("Master Gears not initialized", sharedGears.waitForInit(true)); System.err.println("Master Gears Init done: "+sharedGears); @@ -149,9 +151,9 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { animator.add(glWindow); animator.start(); glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(glWindow, true, null)); final GLContext sharedMasterContext = sharedDrawable.getContext(); MiscUtils.dumpSharedGLContext("Master Context", sharedMasterContext); @@ -191,15 +193,15 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { f1.destroy(); f2.destroy(); f3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); releaseShared(); } @@ -229,15 +231,15 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { f1.destroy(); f2.destroy(); f3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); releaseShared(); } @@ -262,15 +264,15 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { f1.destroy(); f2.destroy(); f3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); releaseShared(); } @@ -300,15 +302,15 @@ public class TestSharedContextVBOES2NEWT1 extends UITestCase { f1.destroy(); f2.destroy(); f3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); releaseShared(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java index 83138c44b..05ee9bab4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java @@ -38,7 +38,8 @@ import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -128,33 +129,33 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { animator.add(f3); f3.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); f1.setVisible(true); // kick off f1 GLContext .. and hence allow f2 + f3 creation - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = f1.getContext(); @@ -202,12 +203,12 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { f2.destroy(); f3.destroy(); } - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); } @Test @@ -250,32 +251,32 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { a3.start(); f3.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); f1.setVisible(true); // kicks off f1 GLContext .. and hence gears of f2 + f3 completion - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = f1.getContext(); @@ -329,12 +330,12 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { f2.destroy(); f3.destroy(); } - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); } static long duration = 1000; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java index 6fd11c033..bac5784ac 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java @@ -38,8 +38,9 @@ import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -129,24 +130,24 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { animator.add(f2); f2.setVisible(true); // shall wait until f1 is ready - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); f1.setVisible(true); // kicks off f1 GLContext .. and hence gears of f2 + f3 completion - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); final GearsES2 g3 = new GearsES2(0); @@ -157,9 +158,9 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { animator.add(f3); f3.setVisible(true); // shall wait until f1 is ready - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = f1.getContext(); @@ -217,12 +218,12 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { f3.destroy(); try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); } } - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); animator.stop(); } @@ -267,24 +268,24 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { a2.start(); f2.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); f1.setVisible(true); // test pending creation of f2 - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); final Animator a3 = new Animator(); @@ -297,9 +298,9 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { a3.start(); f3.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = f1.getContext(); @@ -365,12 +366,12 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { f3.destroy(); try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); } } - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); } static long duration = 1000; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java index 61d109ba1..19d20b978 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java @@ -41,7 +41,8 @@ import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -132,33 +133,33 @@ public class TestSharedContextVBOES2NEWT4 extends UITestCase { }); f3.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, false, null)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, false, null)); f1.setVisible(true); // kick off f1 GLContext .. and hence allow f2 + f3 creation - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(f3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); Assert.assertFalse("Unexpected exception (animator) caught", gotAnimException.get()); @@ -203,12 +204,12 @@ public class TestSharedContextVBOES2NEWT4 extends UITestCase { f2.destroy(); f1.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(f3, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(f3, false, null)); } static long duration = 1000; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java index 84ccfa8b5..4e2457181 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java @@ -37,8 +37,9 @@ import com.jogamp.opengl.GLProfile; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.swt.GLCanvas; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -200,17 +201,27 @@ public class TestSharedContextVBOES2SWT3 extends UITestCase { shell2.open(); // shall wait until f1 is ready shell3.open(); // shall wait until f1 is ready } } ); + final long t0 = System.currentTimeMillis(); animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion - Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) - - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + final Runnable waitAction = new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + } }; + Assert.assertEquals(true, GLTestUtil.waitForRealized(c1, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForContextCreated(c1, true, waitAction)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(c2, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForContextCreated(c2, true, waitAction)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(c3, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForContextCreated(c3, true, waitAction)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); final GLContext ctx1 = c1.getContext(); @@ -236,11 +247,10 @@ public class TestSharedContextVBOES2SWT3 extends UITestCase { Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); - try { - Thread.sleep(duration); - } catch(final Exception e) { - e.printStackTrace(); + while(animator.isAnimating() && System.currentTimeMillis()-t0<duration) { + waitAction.run(); } + // Stopped animator allows native windowing system 'repaint' event // to trigger GLAD 'display' animator.stop(); @@ -266,10 +276,16 @@ public class TestSharedContextVBOES2SWT3 extends UITestCase { } } ); a1.start(); - - Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) - - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + final Runnable waitAction = new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + } }; + Assert.assertEquals(true, GLTestUtil.waitForRealized(c1, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForContextCreated(c1, true, waitAction)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); final Animator a2 = new Animator(); @@ -284,8 +300,6 @@ public class TestSharedContextVBOES2SWT3 extends UITestCase { } } ); a2.start(); - Thread.sleep(200); // wait a while .. - final Animator a3 = new Animator(); final GearsES2 g3 = new GearsES2(0); g3.setSharedGears(g1); @@ -298,12 +312,16 @@ public class TestSharedContextVBOES2SWT3 extends UITestCase { } } ); a3.start(); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(c2, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForContextCreated(c2, true, waitAction)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(c3, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForContextCreated(c3, true, waitAction)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + final long t0 = System.currentTimeMillis(); + final GLContext ctx1 = c1.getContext(); final GLContext ctx2 = c2.getContext(); final GLContext ctx3 = c3.getContext(); @@ -327,10 +345,8 @@ public class TestSharedContextVBOES2SWT3 extends UITestCase { Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); - try { - Thread.sleep(duration); - } catch(final Exception e) { - e.printStackTrace(); + while(System.currentTimeMillis()-t0<duration) { + waitAction.run(); } // Stopped animator allows native windowing system 'repaint' event // to trigger GLAD 'display' diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java index 81489df17..0987b2978 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java @@ -14,6 +14,7 @@ import javax.swing.Timer; import org.junit.Test; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.opengl.*; @@ -69,7 +70,7 @@ public class TestSharedExternalContextAWT { // which is suppose to lie outside of the JVM. // The thread is kept alive, since this detail // may be required for the OpenGL driver implementation. - final Thread thread = new Thread(runnable); + final Thread thread = new InterruptSource.Thread(null, runnable); thread.setDaemon(true); thread.start(); masterLatch.await(3, TimeUnit.SECONDS); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java index bbbd92e5e..933e79731 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java @@ -111,27 +111,17 @@ public class TestVersionSemanticsNOUI extends SingletonJunitCase { } @Test - public void testVersionV230V23x_00std() throws IllegalArgumentException, IOException, URISyntaxException { - final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.NON_BACKWARD_COMPATIBLE; - // final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER; - - final VersionNumberString preVersionNumber = new VersionNumberString("2.3.0"); - final File previousJar = new File("lib/v"+preVersionNumber.getVersionString()+"/"+jarFile); - - final ClassLoader currentCL = TestVersionSemanticsNOUI.class.getClassLoader(); - - VersionSemanticsUtil.testVersion(diffCriteria, expectedCompatibilityType, - previousJar, preVersionNumber, - curVersion.getClass(), currentCL, curVersionNumber, - excludesDefault); + public void testVersionV230V232() throws IllegalArgumentException, IOException, URISyntaxException { + testVersions(diffCriteria, Delta.CompatibilityType.BACKWARD_COMPATIBLE_BINARY, "2.3.0", "2.3.2", excludesStereoPackageAndAppletUtils); } + @Test - public void testVersionV230V23x_01patch() throws IllegalArgumentException, IOException, URISyntaxException { - // final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.NON_BACKWARD_COMPATIBLE; + public void testVersionV232V24x() throws IllegalArgumentException, IOException, URISyntaxException { + final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.NON_BACKWARD_COMPATIBLE; // final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER; - final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.BACKWARD_COMPATIBLE_BINARY; + // final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.BACKWARD_COMPATIBLE_BINARY; - final VersionNumberString preVersionNumber = new VersionNumberString("2.3.0"); + final VersionNumberString preVersionNumber = new VersionNumberString("2.3.2"); final File previousJar = new File("lib/v"+preVersionNumber.getVersionString()+"/"+jarFile); final ClassLoader currentCL = TestVersionSemanticsNOUI.class.getClassLoader(); @@ -139,7 +129,7 @@ public class TestVersionSemanticsNOUI extends SingletonJunitCase { VersionSemanticsUtil.testVersion(diffCriteria, expectedCompatibilityType, previousJar, preVersionNumber, curVersion.getClass(), currentCL, curVersionNumber, - excludesStereoPackageAndAppletUtils); + excludesDefault); } public static void main(final String args[]) throws IOException { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java index b30bb1192..4cdcbd10a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java @@ -30,6 +30,7 @@ package com.jogamp.opengl.test.junit.jogl.acore.anim; import java.awt.BorderLayout; import java.awt.Dimension; +import com.jogamp.common.util.InterruptSource; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; @@ -85,10 +86,10 @@ public class Bug898AnimatorFromEDTAWT extends javax.swing.JFrame { lastTime = time; animator.pause(); System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.pause(): paused "+animator); - new Thread() { + new InterruptSource.Thread() { public void run() { try { - Thread.sleep(1000); + java.lang.Thread.sleep(1000); } catch (final InterruptedException e) { e.printStackTrace(); } @@ -98,9 +99,9 @@ public class Bug898AnimatorFromEDTAWT extends javax.swing.JFrame { final long td = System.currentTimeMillis() - lastTime; if (animator.isPaused()) { animator.resume(); //Doesn't work on v2.0.2 or higher - System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): animating "+animator); + System.out.println(java.lang.Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): animating "+animator); } else { - System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): Ooops - not paused! - animating "+animator); + System.out.println(java.lang.Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): Ooops - not paused! - animating "+animator); } } } ); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java index 8e52ea329..bec3fe2ef 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java @@ -36,6 +36,7 @@ import com.jogamp.opengl.awt.GLJPanel; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -116,19 +117,19 @@ public class TestAnimatorGLJPanel01AWT extends UITestCase { f3.setVisible(true); } } ); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); try { @@ -168,9 +169,9 @@ public class TestAnimatorGLJPanel01AWT extends UITestCase { } }}); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false, null)); } @Test @@ -218,19 +219,19 @@ public class TestAnimatorGLJPanel01AWT extends UITestCase { f3.setVisible(true); } } ); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); try { @@ -276,9 +277,9 @@ public class TestAnimatorGLJPanel01AWT extends UITestCase { } }}); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false, null)); } static long duration = 3*500; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java index 58af4bf2d..3eeea1690 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java @@ -34,7 +34,8 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -108,19 +109,19 @@ public class TestAnimatorGLWindow01NEWT extends UITestCase { c2.setVisible(true); c3.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); try { @@ -153,9 +154,9 @@ public class TestAnimatorGLWindow01NEWT extends UITestCase { c2.destroy(); c3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c3, false, null)); } @Test @@ -191,19 +192,19 @@ public class TestAnimatorGLWindow01NEWT extends UITestCase { Assert.assertEquals(true, a3.isAnimating()); c3.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(c1, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null)); Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c2, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(c2, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null)); Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c3, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(c3, true, null)); + Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null)); Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); try { @@ -242,9 +243,9 @@ public class TestAnimatorGLWindow01NEWT extends UITestCase { c2.destroy(); c3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c1, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(c3, false, null)); } static long duration = 3*500; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java index b2608303a..1598a90fb 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java @@ -30,10 +30,9 @@ package com.jogamp.opengl.test.junit.jogl.acore.ect; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Window; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -361,7 +360,7 @@ public abstract class ExclusiveContextBase00 extends UITestCase { // Destroy GLWindows for(int i=0; i<drawableCount; i++) { destroyGLAutoDrawableVisible(drawables[i]); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawables[i], false)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(drawables[i], false, null)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java index 1908d1ec2..50f04ed17 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java @@ -30,10 +30,9 @@ package com.jogamp.opengl.test.junit.jogl.acore.ect; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Window; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -183,7 +182,7 @@ public abstract class ExclusiveContextBase10 extends UITestCase { // Destroy GLWindows for(int i=0; i<drawableCount; i++) { destroyGLAutoDrawableVisible(drawables[i]); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawables[i], false)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(drawables[i], false, null)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java index 712679982..632fd9e3d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java @@ -49,6 +49,8 @@ import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.GLTestUtil; +import com.jogamp.opengl.test.junit.util.TestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import org.junit.Assert; @@ -208,11 +210,11 @@ public abstract class GLContextDrawableSwitchBase1 extends UITestCase { if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) { setFrameVisible(frame); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); } else if( GLADType.GLWindow == gladType ) { ((GLWindow)glad).setVisible(true); } - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, true)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(glad, true, null)); Assert.assertNotNull(glad.getContext()); Assert.assertTrue(glad.isRealized()); @@ -235,10 +237,10 @@ public abstract class GLContextDrawableSwitchBase1 extends UITestCase { Assert.assertEquals(false, glelsIn.isOwner()); } - for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && + for (int wait=0; wait<TestUtil.POLL_DIVIDER && ( 1 > glelTracker.initCount || 1 > glelTracker.reshapeCount || 1 > glelTracker.displayCount ); wait++) { - Thread.sleep(AWTRobotUtil.TIME_SLICE); + Thread.sleep(TestUtil.TIME_SLICE); } final long t0 = System.currentTimeMillis(); @@ -270,13 +272,13 @@ public abstract class GLContextDrawableSwitchBase1 extends UITestCase { } if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) { destroyFrame(frame); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false, null)); } else if( GLADType.GLWindow == gladType ) { glad.destroy(); } else if( GLADType.GLOffscreen == gladType ) { glad.destroy(); } - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, false)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(glad, false, null)); Assert.assertEquals(1, glelTracker.initCount); Assert.assertTrue(1 <= glelTracker.reshapeCount); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java index a872d692d..393bff746 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java @@ -51,7 +51,7 @@ import com.jogamp.opengl.util.GLDrawableUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -89,8 +89,8 @@ public class TestGLContextDrawableSwitch01NEWT extends UITestCase { window.setPosition(x, y); window.setSize(width, height); window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null)); final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); final GLDrawable drawable = factory.createGLDrawable(window); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java index 2fe56dbfe..cd9defd83 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java @@ -50,8 +50,8 @@ import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -104,8 +104,8 @@ public class TestGLContextDrawableSwitch10NEWT extends UITestCase { window.setPosition(x, y); window.setSize(width, height); window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null)); final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); final GLDrawable drawable = factory.createGLDrawable(window); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug1225EventQueueInterruptedAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug1225EventQueueInterruptedAWT.java new file mode 100644 index 000000000..6469a26d8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug1225EventQueueInterruptedAWT.java @@ -0,0 +1,378 @@ +/** + * Copyright 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 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.test.junit.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Label; +import java.lang.Thread.UncaughtExceptionHandler; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import org.junit.Assert; + +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptedRuntimeException; +import com.jogamp.common.util.SourcedInterruptedException; +import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.awt.GLCanvas; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test to check if interrupt on AWT-EventQueue causes a malfunction in JOGL. + * <p> + * After tests are displaying an ever color rotating rectangle in an AWT component alone + * and with an additional GearsES2 within a GLCanvas. + * </p> + * <p> + * The AWT component is issuing an interrupt during paint on the AWT-EDT. + * </p> + * <p> + * The reporter claims that an interrupt on the AWT-EDT shall not disturb neither AWT nor JOGL's GLCanvas + * and rendering shall continue. + * <ul> + * <li>This seems to be true for JRE 1.8.0_60</li> + * <li>This seems to be false for JRE 1.7.0_45. This JRE's AWT-EDT even dies occasionally when interrupted.</li> + * </ul> + * </p> + * <p> + * The test passes on GNU/Linux and Windows using JRE 1.8.0_60. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug1225EventQueueInterruptedAWT extends UITestCase { + static long durationPerTest = 1000; // ms + + private void setVisible(final JFrame frame, final boolean v) throws InterruptedException, InvocationTargetException { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + // frame.setSize(new Dimension(800, 600)); + frame.setVisible(v); + }}); + } + private void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jFrame.dispose(); + } } ) ; + } + + + @Test(timeout=180000) // TO 3 min + public void test01_NoGL() throws InterruptedException, InvocationTargetException { + testImpl(false); + } + + @Test(timeout=180000) // TO 3 min + public void test02_WithGL() throws InterruptedException, InvocationTargetException { + testImpl(true); + } + + class OurUncaughtExceptionHandler implements UncaughtExceptionHandler { + public volatile Thread thread = null; + public volatile Throwable exception = null; + + @Override + public void uncaughtException(final Thread t, final Throwable e) { + thread = t; + exception = e; + System.err.println("*** UncaughtException (this Thread "+Thread.currentThread().getName()+") : Thread <"+t.getName()+">, "+e.getClass().getName()+": "+e.getMessage()); + ExceptionUtils.dumpThrowable("", e); + } + } + void testImpl(final boolean useGL) throws InterruptedException, InvocationTargetException { + if( !AWTRobotUtil.isAWTEDTAlive() ) { + System.err.println("Test aborted: AWT not alive"); + return; + } + // Assume.assumeTrue("AWT not alive", AWTRobotUtil.isAWTEDTAlive()); + // Assert.assertTrue("AWT not alive", AWTRobotUtil.isAWTEDTAlive()); + final OurUncaughtExceptionHandler uncaughtHandler = new OurUncaughtExceptionHandler(); + Thread.setDefaultUncaughtExceptionHandler( uncaughtHandler ); + + final Dimension csize = new Dimension(800, 400); + final JPanel panel = new JPanel(new GridLayout(2, 1)); + final GLCanvas glc; + final InterruptableGLEL iglel; + if( useGL ) { + glc = new GLCanvas(); + { + final GearsES2 gears = new GearsES2(); + gears.setVerbose(false); + glc.addGLEventListener(gears); + } + iglel = new InterruptableGLEL(); + glc.addGLEventListener(iglel); + glc.setSize(csize); + glc.setPreferredSize(csize); + panel.add(glc); + } else { + NativeWindowFactory.initSingleton(); + glc = null; + iglel = null; + final Label l = new Label("No GL Object"); + l.setSize(csize); + l.setPreferredSize(csize); + panel.add(l); + } + final InterruptingComponent icomp = new InterruptingComponent(); + panel.add(icomp); + icomp.setSize(csize); + icomp.setPreferredSize(csize); + + final JFrame frame = new JFrame(); + frame.setResizable(true); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.getContentPane().add(panel, BorderLayout.CENTER); + setVisible(frame, true); + if( useGL ) { + Assert.assertTrue(AWTRobotUtil.waitForRealized(glc, true, null)); + } + Assert.assertTrue(AWTRobotUtil.waitForRealized(icomp, true, null)); + + final InterruptableLoop loop = new InterruptableLoop(icomp, glc); + final Thread thread = new Thread(loop); + + synchronized(loop) { + thread.start(); + try { + loop.notifyAll(); // wake-up startup-block + while( !loop.isRunning && !loop.shallStop ) { + loop.wait(); // wait until started + } + loop.ack = true; + loop.notifyAll(); // wake-up startup-block + } catch (final InterruptedException e) { + Assert.assertNull("while starting loop", new InterruptedRuntimeException(e)); + } + } + + for(int i=0; thread.isAlive() && null == loop.exception && null == uncaughtHandler.exception && i<100; i++) { + icomp.interruptAWTEventQueue(); + Thread.sleep(durationPerTest/100); + } + + loop.shallStop = true; + synchronized(loop) { + try { + loop.notifyAll(); // wake-up pause-block (opt) + while( loop.isRunning ) { + loop.wait(); // wait until stopped + } + } catch (final InterruptedException e) { + Assert.assertNull("while stopping loop", new InterruptedRuntimeException(e)); + } + } + + // + // Notifications only! + // + // Note: + // On JRE 1.8.0_60: Interrupt is cleared on AWT-EDT + // On JRE 1.7.0_45: Interrupt is *NOT* cleared on AWT-EDT + // + if( null != iglel && null != iglel.exception ) { + ExceptionUtils.dumpThrowable("GLEventListener", iglel.exception); + } + if( null != icomp.exception ) { + ExceptionUtils.dumpThrowable("InterruptingComponent", icomp.exception); + } + if( null != loop.exception ) { + ExceptionUtils.dumpThrowable("loop", loop.exception); + } + if( null != uncaughtHandler.exception ) { + ExceptionUtils.dumpThrowable("uncaughtHandler", uncaughtHandler.exception); + } + if( !AWTRobotUtil.isAWTEDTAlive() ) { + System.err.println("AWT is not alive anymore!!! Ooops"); + // cannot do anything anymore on AWT-EDT .. frame.dispose(); + } else { + dispose(frame); + } + + // + // Fail if interrupt was propagated to loop or uncaught handler + // + Assert.assertNull("Caught Exception in loop", loop.exception); + Assert.assertNull("Caught Exception via uncaughtHandler", uncaughtHandler.exception); + } + + static class InterruptableLoop implements Runnable { + public volatile Exception exception = null; + public volatile boolean shallStop = false; + public volatile boolean isRunning = false; + public volatile boolean ack = false; + final InterruptingComponent icomp; + final GLCanvas glc; + boolean alt = false;; + + InterruptableLoop(final InterruptingComponent icomp, final GLCanvas glc) { + this.icomp = icomp; + this.glc = glc; + } + + public void stop() { + shallStop = true; + } + + @Override + public void run() + { + synchronized ( this ) { + isRunning = true; + this.notifyAll(); + try { + while( !ack ) { + this.wait(); // wait until ack + } + this.notifyAll(); + } catch (final InterruptedException e) { + throw new InterruptedRuntimeException(e); + } + ack = false; + } + synchronized ( this ) { + try { + while( !shallStop ) { + if( alt ) { + icomp.repaint(); // issues paint of GLCanvas on AWT-EDT + } else if( null != glc ) { + // Avoid invokeAndWait(..) in GLCanvas.display() if AWT-EDT dies! + glc.repaint(); // issues paint of GLCanvas on AWT-EDT, which then issues display()! + } + alt = !alt; + Thread.sleep(16); + if( Thread.interrupted() ) { + final InterruptedRuntimeException e = new InterruptedRuntimeException(new InterruptedException("Interrupt detected in loop, thread: "+Thread.currentThread().getName())); + throw e; + } + } + } catch (final InterruptedException e) { + exception = SourcedInterruptedException.wrap(e); + ExceptionUtils.dumpThrowable("", exception); + } catch (final Exception e) { + exception = e; + ExceptionUtils.dumpThrowable("", exception); + } finally { + isRunning = false; + this.notifyAll(); + } + } + } + } + + static class InterruptableGLEL implements GLEventListener { + public volatile InterruptedException exception = null; + @Override + public void init(final GLAutoDrawable drawable) { + } + @Override + public void dispose(final GLAutoDrawable drawable) { + } + @Override + public void display(final GLAutoDrawable drawable) { + final Thread c = Thread.currentThread(); + if( c.isInterrupted() && null == exception ) { + exception = new InterruptedException("Interrupt detected in GLEventListener, thread: "+c.getName()); + drawable.removeGLEventListener(this); + } + } + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + } + } + + static class InterruptingComponent extends Component { + private static final long serialVersionUID = 1L; + public volatile InterruptedException exception = null; + + private volatile boolean doInterrupt = false; + + private final Color[] colors = + new Color[] { Color.BLACK, Color.BLUE, Color.DARK_GRAY, Color.GRAY, Color.LIGHT_GRAY }; + private int colorIdx = 0; + + public InterruptingComponent() { + } + + public void interruptAWTEventQueue() { + doInterrupt = true; + } + + @Override + public void paint(final Graphics g) + { + final Thread c = Thread.currentThread(); + if( c.isInterrupted() && null == exception ) { + exception = new InterruptedException("Interrupt detected in AWT Component, thread: "+c.getName()); + } + + g.setColor(colors[colorIdx++]); + if( colorIdx >= colors.length ) { + colorIdx = 0; + } + g.fillRect(0, 0, getWidth(), getHeight()); + + if(doInterrupt) { + System.err.println("Thread "+c.getName()+": *Interrupting*"); + doInterrupt = false; + c.interrupt(); + } + } + } + + public static void main(final String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + org.junit.runner.JUnitCore.main(TestBug1225EventQueueInterruptedAWT.class.getName()); + } +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug1245JTabbedPanelCrashAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug1245JTabbedPanelCrashAWT.java new file mode 100644 index 000000000..f041d5d01 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug1245JTabbedPanelCrashAWT.java @@ -0,0 +1,228 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.awt.GLCanvas; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 1245 + * <p> + * https://jogamp.org/bugzilla/show_bug.cgi?id=1245 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug1245JTabbedPanelCrashAWT extends UITestCase { + + static long durationPerTest = 500*4; // ms + static boolean manual = false; + + @SuppressWarnings("serial") + static class View3D extends JPanel { + final GLCanvas canvas; + final Animator animator; + final int num; + + public View3D(final int num) { + this.num = num; + this.setLayout(new BorderLayout()); + canvas = new GLCanvas(); + canvas.setSize(new Dimension(100, 100)); + canvas.setMinimumSize(new Dimension(100, 100)); + add(canvas, BorderLayout.CENTER); + animator = new Animator(); + animator.add(canvas); + // could do animator.start() here as well, + // just to be nice - we start/stop at add/remove Notify + } + @Override + public void addNotify() { + System.err.println("View3D["+num+"].addNotify()"); + super.addNotify(); + if( null != animator ) { + animator.start(); + } + } + @Override + public void removeNotify() { + System.err.println("View3D["+num+"].removeNotify()"); + if( null != animator ) { + animator.stop(); + } + super.removeNotify(); + } + + public String getGLCanvasStats() { + return "GLCanvas: comp "+canvas.getBounds()+", visible "+canvas.isVisible()+", showing "+canvas.isShowing()+ + ", displayable "+canvas.isDisplayable()+", "+canvas.getSurfaceWidth()+"x"+canvas.getSurfaceHeight()+ + ", "+canvas.getChosenGLCapabilities()+", drawable 0x"+Long.toHexString(canvas.getHandle()); + } + } + + final GLEventListenerCounter glelCounter = new GLEventListenerCounter(); + + private JTabbedPane createAndShowGUI(final JFrame frame, final View3D[] views) { + final JPanel panel = new JPanel(new GridLayout(1, 1)); + final JTabbedPane tabbedPanel = new JTabbedPane(); + for(int i=0; i<views.length; i++) { + final GLEventListener demo; + if( i%2 == 0 ) { + final GearsES2 gears = new GearsES2(1); + gears.setVerbose(false); + demo = gears; + } else { + final RedSquareES2 red = new RedSquareES2(1); + red.setVerbose(false); + demo = red; + } + views[i] = new View3D(i); + views[i].canvas.addGLEventListener(glelCounter); + views[i].canvas.addGLEventListener(demo); + tabbedPanel.addTab("Tab "+i, null, views[i], "Does nothing"); + } + tabbedPanel.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + tabbedPanel.addChangeListener(new javax.swing.event.ChangeListener() { + @Override + public void stateChanged(final javax.swing.event.ChangeEvent evt) { + final int idx = tabbedPanel.getSelectedIndex(); + if( 0 <= idx && idx < views.length ) { + System.err.println("Pane["+idx+"]: State Changed: "+evt); + System.err.println("Pane["+idx+"]: "+views[idx].getGLCanvasStats()); + } + } + }); + + panel.add(tabbedPanel); + frame.add(panel, BorderLayout.CENTER); + frame.setSize(640,480); + + return tabbedPanel; + } + + private static String id(final Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); } + + @BeforeClass + public static void startup() { + GLProfile.initSingleton(); + } + + @Test + public void test01() throws InterruptedException, InvocationTargetException { + final JFrame frame = new JFrame("Java3DApplication"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + final View3D[] views = new View3D[4]; + final JTabbedPane[] tabbedPane = { null }; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + //Turn off metal's use of bold fonts + UIManager.put("swing.boldMetal", Boolean.FALSE); + tabbedPane[0] = createAndShowGUI(frame, views); + System.err.println("XXX SetVisible ON XXX"); + frame.setVisible(true); + } } ); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + for(int i=0; i<views.length; i++) { + System.err.printf("View "+i+": "+views[i]+",%n "+views[i].getGLCanvasStats()+"%n%n"); + } + + System.err.println("XXX POST.VISIBLE: "+glelCounter); + if(manual) { + Thread.sleep(durationPerTest); + System.err.println("XXX POST.ACTION: "+glelCounter); + } else { + final JTabbedPane tabbedPanel = tabbedPane[0]; + + for(int i=0; i<views.length; i++) { + Thread.sleep(durationPerTest/views.length); + switchTab(tabbedPanel, views, i, (i+1)%views.length); + } + Thread.sleep(durationPerTest/views.length); + switchTab(tabbedPanel, views, 0, 1); + + Thread.sleep(durationPerTest/views.length); + switchTab(tabbedPanel, views, 1, 0); + + System.err.println("XXX POST.ACTION: "+glelCounter); + Assert.assertTrue(glelCounter.initCount >= views.length); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + System.err.println("XXX SetVisible OFF XXX"); + frame.dispose(); + } }); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false, null)); + System.err.println("XXX POST.DISPOSE: "+glelCounter); + } + + void switchTab(final JTabbedPane tabbedPanel, final View3D[] views, final int thisId, final int nextId) throws InvocationTargetException, InterruptedException { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Panel("+id(views[thisId])+" -> Panel("+id(views[nextId])+") START"); + tabbedPanel.setSelectedIndex(nextId); + }}); + } + + public static void main(final String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } else if(args[i].equals("-manual")) { + manual = true; + } + } + org.junit.runner.JUnitCore.main(TestBug1245JTabbedPanelCrashAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java index 1250ab6f2..5d8713c86 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java @@ -110,8 +110,8 @@ public class TestBug572AWT extends UITestCase { realizeAction.run(); // Wait until it's displayable after issuing initial setVisible(true) on current thread (non AWT-EDT)! - Assert.assertTrue("GLCanvas didn't become visible", AWTRobotUtil.waitForVisible(glCanvas, true)); - Assert.assertTrue("GLCanvas didn't become realized", AWTRobotUtil.waitForRealized(glCanvas, true)); // implies displayable + Assert.assertTrue("GLCanvas didn't become visible", AWTRobotUtil.waitForVisible(glCanvas, true, null)); + Assert.assertTrue("GLCanvas didn't become realized", AWTRobotUtil.waitForRealized(glCanvas, true, null)); // implies displayable } System.err.println("XXXX-0 "+glCanvas.getDelegatedDrawable().isRealized()+", "+glCanvas); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java index 2b6d8233f..16e61246a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java @@ -187,8 +187,8 @@ public class TestBug664GLCanvasSetVisibleSwingAWT extends UITestCase { System.err.println("XXXX Visible Part 1/3"); frameCount = 0; setFrameVisible(top[0], true); - Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true)); - Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true)); + Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true, null)); + Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true, null)); anim.setUpdateFPSFrames(60, System.err); anim.start(); @@ -200,7 +200,7 @@ public class TestBug664GLCanvasSetVisibleSwingAWT extends UITestCase { System.err.println("XXXXX Invisible Part 2/3"); setComponentVisible(glc, false); - Assert.assertTrue("Component didn't become invisible", AWTRobotUtil.waitForVisible(glc, false)); + Assert.assertTrue("Component didn't become invisible", AWTRobotUtil.waitForVisible(glc, false, null)); final int frameCountT0 = frameCount; anim.resetFPSCounter(); @@ -215,7 +215,7 @@ public class TestBug664GLCanvasSetVisibleSwingAWT extends UITestCase { System.err.println("XXXX Visible Part 3/3"); setComponentVisible(glc, true); - Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true, null)); anim.resetFPSCounter(); while( anim.getTotalFPSDuration() < durationPerTest ) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java index 7758a525e..7f0233915 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java @@ -155,8 +155,8 @@ public class TestBug816GLCanvasFrameHoppingB849B889AWT extends UITestCase { frame2.setVisible(true); } }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); dumpGLCanvasStats(glCanvas); if(manual) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java index 1aeaccb81..541cceac0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java @@ -118,8 +118,8 @@ public class TestBug816JTabbedPanelVisibilityB849B878AWT extends UITestCase { System.err.println("XXX SetVisible ON XXX GLCanvas on Panel1("+id(panel1)+")"); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); dumpGLCanvasStats(glCanvas); if(manual) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java index c33b2e5ba..383bb3760 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java @@ -248,10 +248,10 @@ public class TestBug816OSXCALayerPos01AWT extends UITestCase { } frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); if( twoCanvas ) { - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true, null)); } animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java index 5e20bb3f7..15b4c6126 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java @@ -101,8 +101,8 @@ public class TestBug816OSXCALayerPos02AWT extends UITestCase { frame.setSize(width, height); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); animator.start(); Assert.assertTrue(animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java index ac3903ec6..d24cccdc6 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java @@ -115,8 +115,8 @@ public class TestBug816OSXCALayerPos03aB729AWT extends UITestCase { frame.setSize(width, height); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); animator.start(); Assert.assertTrue(animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java index 62526420f..1ec6dae2c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java @@ -121,8 +121,8 @@ public class TestBug816OSXCALayerPos03bB849AWT extends UITestCase { frame.setSize(width, height); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); animator.start(); Assert.assertTrue(animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java index 3d46b5315..03bff669e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java @@ -123,8 +123,8 @@ public class TestBug816OSXCALayerPos03cB849AWT extends UITestCase { frame.setSize(width, height); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); animator.start(); Assert.assertTrue(animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java index 74046e8a1..4d1e8157e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java @@ -88,7 +88,7 @@ public class TestBug816OSXCALayerPos04aAWT extends UITestCase { frame.setSize(width, height); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); final Dialog dialog = new Dialog(frame, "Bug 816 AWT Top-Level Dialog"); dialog.setLayout(new BorderLayout()); @@ -100,8 +100,8 @@ public class TestBug816OSXCALayerPos04aAWT extends UITestCase { dialog.setSize(width/2, height/2); dialog.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); animator.start(); Assert.assertTrue(animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java index 704b589f3..dddfcabf8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java @@ -88,7 +88,7 @@ public class TestBug816OSXCALayerPos04bAWT extends UITestCase { frame.setSize(width, height); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); final JDialog dialog = new JDialog(frame, "Bug 816 AWT Top-Level JDialog"); dialog.setLayout(new BorderLayout()); @@ -100,8 +100,8 @@ public class TestBug816OSXCALayerPos04bAWT extends UITestCase { dialog.setSize(width/2, height/2); dialog.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); animator.start(); Assert.assertTrue(animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java index 46ae20765..e37a29b4f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java @@ -263,8 +263,8 @@ public class TestGLJPanelTextureStateAWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true)); - Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true)); + Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true, null)); + Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true, null)); Thread.sleep(100); setFrameSize(frame, true, glc_sz2); System.err.println("window resize pos/siz: "+glc.getX()+"/"+glc.getY()+" "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java index f3c2734b5..dfd2489e2 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java @@ -28,6 +28,8 @@ package com.jogamp.opengl.test.junit.jogl.caps; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; @@ -92,12 +94,12 @@ public class TestTranslucencyNEWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setFullscreen(!f_glWindow.isFullscreen()); } }.start(); } else if(e.getKeyChar()=='d') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setUndecorated(!f_glWindow.isUndecorated()); } }.start(); @@ -157,7 +159,7 @@ public class TestTranslucencyNEWT extends UITestCase { } } if( waitForKey ) { - UITestCase.waitForKey("main"); + JunitTracer.waitForKey("main"); } org.junit.runner.JUnitCore.main(TestTranslucencyNEWT.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLClearOnInitReshape.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLClearOnInitReshape.java new file mode 100644 index 000000000..46be7ef0a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLClearOnInitReshape.java @@ -0,0 +1,64 @@ +/** + * Copyright 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 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.test.junit.jogl.demos; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; + +public class GLClearOnInitReshape implements GLEventListener { + int lastWidth, lastHeight; + boolean doClear; + + @Override + public void init(final GLAutoDrawable drawable) { + lastWidth = drawable.getSurfaceWidth(); + lastHeight = drawable.getSurfaceHeight(); + doClear = true; + } + + @Override + public void dispose(final GLAutoDrawable drawable) { } + + @Override + public void display(final GLAutoDrawable drawable) { + if( doClear ) { + drawable.getGL().glClear(GL.GL_COLOR_BUFFER_BIT); + doClear = false; + } + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + if( lastHeight != height || lastWidth != width ) { + doClear = true; + lastWidth = width; + lastHeight = height; + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java index 7189db1f3..e8acb0baf 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java @@ -181,9 +181,7 @@ public class PointsDemoES1 extends PointsDemo { // Thread.dumpStack(); final GL2ES1 gl = glad.getGL().getGL2ES1(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) - } + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) // Set location in front of camera gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java index 60ac6b233..7eebf4489 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java @@ -141,9 +141,7 @@ public class RedSquareES1 implements GLEventListener, TileRendererBase.TileRende @Override public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) { final GL2ES1 gl = glad.getGL().getGL2ES1(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); - } + gl.setSwapInterval(swapInterval); reshapeImpl(gl, x, y, width, height, width, height); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java index 771748a33..432652701 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es1.newt; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; @@ -92,12 +93,12 @@ public class TestGearsES1NEWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setFullscreen(!f_glWindow.isFullscreen()); } }.start(); } else if(e.getKeyChar()=='d') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setUndecorated(!f_glWindow.isUndecorated()); } }.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java index 9bf04a75f..769183e82 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es1.newt; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; @@ -90,12 +91,12 @@ public class TestRedSquareES1NEWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setFullscreen(!f_glWindow.isFullscreen()); } }.start(); } else if(e.getKeyChar()=='d') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setUndecorated(!f_glWindow.isUndecorated()); } }.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java index ff88af50a..de2d3458a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java @@ -267,9 +267,7 @@ public class FBOMix2DemosES2 implements GLEventListener { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) - } + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) System.err.println("**** Reshape: "+width+"x"+height); resetFBOs(gl, drawable); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index e1abcc752..c0a4756e7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -319,9 +319,7 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) { if( !isInit ) { return; } final GL2ES2 gl = glad.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); - } + gl.setSwapInterval(swapInterval); reshapeImpl(gl, x, y, width, height, width, height); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java index a504ec1ed..18c0ffd68 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java @@ -128,9 +128,7 @@ public class LandscapeES2 implements GLEventListener { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) - } + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) shaderState.useProgram(gl, true); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LineSquareXDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LineSquareXDemoES2.java new file mode 100644 index 000000000..2169b93d0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LineSquareXDemoES2.java @@ -0,0 +1,189 @@ +/** + * Copyright (C) 2015 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLUniformData; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class LineSquareXDemoES2 implements GLEventListener { + + private boolean multisample, clearBuffers; + private final ShaderState st; + private final PMVMatrix pmvMatrix; + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private ImmModeSink immModeSink; + + public LineSquareXDemoES2(final boolean multisample) { + this.multisample = multisample; + this.clearBuffers = true; + st = new ShaderState(); + st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + } + + public void setClearBuffers(final boolean v) { clearBuffers = v; } + + public void init(final GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + + System.err.println(); + System.err.println("req. msaa: "+multisample); + System.err.println("Requested: " + glad.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()); + multisample = multisample && glad.getChosenGLCapabilities().getNumSamples() > 0 ; + System.err.println("Chosen : " + glad.getChosenGLCapabilities()); + System.err.println("has msaa: "+multisample); + System.err.println(); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LineSquareXDemoES2.class, "shader", + "shader/bin", "mgl_default_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LineSquareXDemoES2.class, "shader", + "shader/bin", "mgl_default_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + final float c = 0f; + final float eX = 0.5f; + final float eH = 0.98f; + final float e2 = 1f; + + // Using predef array names, see + // GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex); + immModeSink = ImmModeSink.createGLSL(20*2, + 3, GL.GL_FLOAT, // vertex + 4, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW, st); + immModeSink.glBegin(GL.GL_LINES); + + // Rectangle + immModeSink.glVertex3f(-eX, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-eX, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-eX, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eX, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eX, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eX, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eX, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-eX, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + + // Square + immModeSink.glVertex3f(-eH, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-eH, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-eH, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eH, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eH, eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eH, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( eH, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-eH, -eH, 0f); immModeSink.glColor4f( c, c, c, c ); + + // X + immModeSink.glVertex3f(-e2, -e2, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( e2, e2, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f(-e2, e2, 0f); immModeSink.glColor4f( c, c, c, c ); + immModeSink.glVertex3f( e2, -e2, 0f); immModeSink.glColor4f( c, c, c, c ); + + immModeSink.glEnd(gl, false); + + st.useProgram(gl, false); + } + + public void dispose(final GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + immModeSink.destroy(gl); + immModeSink = null; + st.destroy(gl); + } + + public void display(final GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if (multisample) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + if( clearBuffers ) { + final float c = 0.9f; + gl.glClearColor(c, c, c, 0); + // gl.glEnable(GL.GL_DEPTH_TEST); + // gl.glDepthFunc(GL.GL_LESS); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + + st.useProgram(gl, true); + + immModeSink.draw(gl, true); + + st.useProgram(gl, false); + } + + // Unused routines + public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) { + System.err.println("reshape .."); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + final float left, right, bottom, top; + if( height > width ) { + final float a = (float)height / (float)width; + left = -1.0f; + right = 1.0f; + bottom = -a; + top = a; + } else { + final float a = (float)width / (float)height; + left = -a; + right = a; + bottom = -1.0f; + top = 1.0f; + } + // pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + // pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + pmvMatrix.glOrthof(left, right, top, bottom, 0.0f, 10.0f); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + + public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) { + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java index 6d202707e..3ec383ad8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java @@ -181,9 +181,7 @@ public class Mix2TexturesES2 implements GLEventListener { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) - } + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); pmvMatrix.glLoadIdentity(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java index 673552c5f..d59c1bb84 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java @@ -186,9 +186,7 @@ public class PointsDemoES2 extends PointsDemo { // Thread.dumpStack(); final GL2ES2 gl = glad.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) - } + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) st.useProgram(gl, true); // Set location in front of camera diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java index a0afef87a..eb96d1593 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java @@ -52,6 +52,7 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende private int swapInterval = 0; private float aspect = 1.0f; private boolean doRotate = true; + private boolean verbose = true; private boolean clearBuffers = true; private TileRendererBase tileRendererInUse = null; private boolean doRotateBeforePrinting; @@ -87,16 +88,21 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende public void setAspect(final float aspect) { this.aspect = aspect; } public void setDoRotation(final boolean rotate) { this.doRotate = rotate; } public void setClearBuffers(final boolean v) { clearBuffers = v; } + public void setVerbose(final boolean v) { verbose = v; } @Override public void init(final GLAutoDrawable glad) { - System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse); + if(verbose) { + System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse); + } final GL2ES2 gl = glad.getGL().getGL2ES2(); - System.err.println("RedSquareES2 init on "+Thread.currentThread()); - System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities()); - System.err.println("INIT GL IS: " + gl.getClass().getName()); - System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + if(verbose) { + System.err.println("RedSquareES2 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + } if( !gl.hasGLSL() ) { System.err.println("No GLSL available, no rendering."); return; @@ -149,7 +155,9 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende st.useProgram(gl, false); t0 = System.currentTimeMillis(); - System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); + if(verbose) { + System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); + } } @Override @@ -192,9 +200,7 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende @Override public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) { final GL2ES2 gl = glad.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); - } + gl.setSwapInterval(swapInterval); reshapeImpl(gl, x, y, width, height, width, height); } @@ -208,7 +214,9 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende } void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) { - System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse); + if(verbose) { + System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse); + } // Thread.dumpStack(); if( !gl.hasGLSL() ) { return; @@ -249,7 +257,9 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende @Override public void dispose(final GLAutoDrawable glad) { - System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse); + if(verbose) { + System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse); + } final GL2ES2 gl = glad.getGL().getGL2ES2(); if( !gl.hasGLSL() ) { return; @@ -257,6 +267,8 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende st.destroy(gl); st = null; pmvMatrix = null; - System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN"); + if(verbose) { + System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN"); + } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java index 9dab97d16..3b526401d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java @@ -211,9 +211,7 @@ public class RedSquareMappedES2 implements GLEventListener, TileRendererBase.Til @Override public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) { final GL2ES2 gl = glad.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); - } + gl.setSwapInterval(swapInterval); reshapeImpl(gl, x, y, width, height, width, height); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java index 2d6745594..e360b5987 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java @@ -230,9 +230,7 @@ public class TextureDraw02ES2ListenerFBO implements GLEventListener { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) - } + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) System.err.println("**** Reshape.Reset: "+width+"x"+height); if( keepTextureBound ) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java index b2ebc7068..cc4096672 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java @@ -29,6 +29,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.av;
import com.jogamp.common.net.Uri;
+import com.jogamp.common.util.InterruptSource;
import com.jogamp.opengl.util.av.AudioSink;
import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
@@ -73,7 +74,7 @@ public class CrossFadePlayer System.out.println("Duration: " + mp.getDuration() + "ms");
System.out.println("Volume: " + mp.getAudioVolume());
System.out.println("player.initGL()...");
- new Thread() {
+ new InterruptSource.Thread() {
public void run() {
try {
mp.initGL(null);
@@ -98,7 +99,7 @@ public class CrossFadePlayer stop = true;
} else {
System.err.println("Player State: EOS");
- new Thread() {
+ new InterruptSource.Thread() {
public void run() {
System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
mp.seek(0);
@@ -112,7 +113,7 @@ public class CrossFadePlayer if( null != se ) {
se.printStackTrace();
}
- new Thread() {
+ new InterruptSource.Thread() {
public void run() {
System.out.println("terminating...");
stop = true;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java index b938adb53..a8dede526 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java @@ -42,10 +42,12 @@ import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; import com.jogamp.common.net.Uri; +import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.font.Font; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -57,7 +59,6 @@ import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase; import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2; import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; @@ -75,7 +76,7 @@ public class MovieCube implements GLEventListener { private TextureSequenceCubeES2 cube=null; private GLMediaPlayer mPlayer=null; private int swapInterval = 1; - private int swapIntervalSet = -1; + private boolean swapIntervalSet = true; private long lastPerfPos = 0; private volatile boolean resetGLState = false; @@ -116,7 +117,7 @@ public class MovieCube implements GLEventListener { resetGLState(); } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { - new Thread() { + new InterruptSource.Thread() { public void run() { // loop for-ever .. mPlayer.seek(0); @@ -246,7 +247,7 @@ public class MovieCube implements GLEventListener { final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), - aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); + aspect, mPlayer.getFramerate(), lfps, tfps, swapInterval); final String text2 = String.format("audio: id %d, kbps %d, codec %s", mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec()); final String text3 = String.format("video: id %d, kbps %d, codec %s", @@ -278,10 +279,13 @@ public class MovieCube implements GLEventListener { int pts1 = 0; switch(e.getKeySymbol()) { case KeyEvent.VK_V: { - switch(swapIntervalSet) { - case 0: swapInterval = 1; break; - default: swapInterval = 0; break; + switch(swapInterval) { + case 0: swapInterval = -1; break; + case -1: swapInterval = 1; break; + case 1: swapInterval = 0; break; + default: swapInterval = 1; break; } + swapIntervalSet = true; break; } case KeyEvent.VK_O: displayOSD = !displayOSD; break; @@ -362,7 +366,7 @@ public class MovieCube implements GLEventListener { cube = new TextureSequenceCubeES2(mPlayer, false, zoom0, rotx, roty); if(waitForKey) { - UITestCase.waitForKey("Init>"); + JunitTracer.waitForKey("Init>"); } if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) { @@ -433,12 +437,14 @@ public class MovieCube implements GLEventListener { @Override public void display(final GLAutoDrawable drawable) { - if(-1 != swapInterval) { + if( swapIntervalSet ) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + final int _swapInterval = swapInterval; + gl.setSwapInterval(_swapInterval); // in case switching the drawable (impl. may bound attribute there) drawable.getAnimator().resetFPSCounter(); - swapIntervalSet = swapInterval; - swapInterval = -1; + swapInterval = gl.getSwapInterval(); + System.err.println("Swap Interval: "+_swapInterval+" -> "+swapInterval); + swapIntervalSet = false; } if(null == mPlayer) { return; } @@ -594,7 +600,7 @@ public class MovieCube implements GLEventListener { if( null != se ) { se.printStackTrace(); } - new Thread() { + new InterruptSource.Thread() { public void run() { window.destroy(); } }.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java index e936bf991..9b9073721 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java @@ -42,6 +42,7 @@ import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.common.net.Uri; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; @@ -800,7 +801,7 @@ public class MovieSBSStereo implements StereoGLEventListener { static class StereoGLMediaEventListener implements GLMediaEventListener { void destroyWindow(final Window window) { - new Thread() { + new InterruptSource.Thread() { public void run() { window.destroy(); } }.start(); @@ -846,7 +847,7 @@ public class MovieSBSStereo implements StereoGLEventListener { destroy = true; } else { System.err.println("MovieSimple State: EOS"); - new Thread() { + new InterruptSource.Thread() { public void run() { mp.setPlaySpeed(1f); mp.seek(0); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java index 22dfa923e..25ce93597 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java @@ -47,10 +47,12 @@ import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.common.net.Uri; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.font.Font; +import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -65,7 +67,6 @@ import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase; import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; @@ -105,7 +106,7 @@ public class MovieSimple implements GLEventListener { private int effects = EFFECT_NORMAL; private float alpha = 1.0f; private int swapInterval = 1; - private int swapIntervalSet = -1; + private boolean swapIntervalSet = true; private GLMediaPlayer mPlayer; private final boolean mPlayerShared; @@ -185,7 +186,7 @@ public class MovieSimple implements GLEventListener { final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); final String ptsPrec = null != regionFPS ? "3.1" : "3.0"; - final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %b", pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); @@ -265,10 +266,13 @@ public class MovieSimple implements GLEventListener { int pts1 = 0; switch(e.getKeySymbol()) { case KeyEvent.VK_V: { - switch(swapIntervalSet) { - case 0: swapInterval = 1; break; - default: swapInterval = 0; break; + switch(swapInterval) { + case 0: swapInterval = -1; break; + case -1: swapInterval = 1; break; + case 1: swapInterval = 0; break; + default: swapInterval = 1; break; } + swapIntervalSet = true; break; } case KeyEvent.VK_O: displayOSD = !displayOSD; break; @@ -352,7 +356,7 @@ public class MovieSimple implements GLEventListener { resetGLState(); } if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { - new Thread() { + new InterruptSource.Thread() { public void run() { // loop for-ever .. mPlayer.seek(0); @@ -483,7 +487,7 @@ public class MovieSimple implements GLEventListener { ", "+drawable.getClass().getName()+", "+drawable); if(waitForKey) { - UITestCase.waitForKey("Init>"); + JunitTracer.waitForKey("Init>"); } final Texture tex; try { @@ -736,11 +740,13 @@ public class MovieSimple implements GLEventListener { @Override public void display(final GLAutoDrawable drawable) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + if( swapIntervalSet ) { + final int _swapInterval = swapInterval; + gl.setSwapInterval(_swapInterval); // in case switching the drawable (impl. may bound attribute there) drawable.getAnimator().resetFPSCounter(); - swapIntervalSet = swapInterval; - swapInterval = -1; + swapInterval = gl.getSwapInterval(); + System.err.println("Swap Interval: "+_swapInterval+" -> "+swapInterval); + swapIntervalSet = false; } if(null == mPlayer) { return; } @@ -802,7 +808,7 @@ public class MovieSimple implements GLEventListener { static class MyGLMediaEventListener implements GLMediaEventListener { void destroyWindow(final Window window) { - new Thread() { + new InterruptSource.Thread() { public void run() { window.destroy(); } }.start(); @@ -836,7 +842,7 @@ public class MovieSimple implements GLEventListener { /** * Kick off player w/o GLEventListener, i.e. for audio only. * - new Thread() { + new InterruptSource.Thread() { public void run() { try { mp.initGL(null); @@ -868,7 +874,7 @@ public class MovieSimple implements GLEventListener { } else { System.err.println("MovieSimple State: EOS"); if( loopEOS ) { - new Thread() { + new InterruptSource.Thread() { public void run() { mp.setPlaySpeed(1f); mp.seek(0); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java index 2e805d8fd..83826bacc 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java @@ -158,7 +158,15 @@ public class TestGearsES2AWT extends UITestCase { private void setTitle(final Frame frame, final GLCanvas glc, final GLCapabilitiesImmutable caps) { final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; final java.awt.Rectangle b = glc.getBounds(); - frame.setTitle("GLCanvas["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight()); + final float[] minSurfacePixelScale = glc.getMinimumSurfaceScale(new float[2]); + final float[] maxSurfacePixelScale = glc.getMaximumSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale = glc.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale = glc.getCurrentSurfaceScale(new float[2]); + frame.setTitle("GLCanvas["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight()+ + ", scale[min "+minSurfacePixelScale[0]+"x"+minSurfacePixelScale[1]+", max "+ + maxSurfacePixelScale[0]+"x"+maxSurfacePixelScale[1]+", req "+ + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" -> has "+ + hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+"]"); } protected void runTestGL(final GLCapabilities caps, final ResizeBy resizeBy, final FrameLayout frameLayout) throws InterruptedException, InvocationTargetException { @@ -275,8 +283,8 @@ public class TestGearsES2AWT extends UITestCase { } frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); final float[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new float[2]); System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java index dfc2d1165..bbcb936f3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.awt; import java.awt.AWTException; import java.awt.BorderLayout; import java.awt.Dimension; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; import java.lang.reflect.InvocationTargetException; import com.jogamp.nativewindow.ScalableSurface; @@ -63,6 +65,7 @@ import com.jogamp.newt.event.TraceKeyAdapter; import com.jogamp.newt.event.TraceWindowAdapter; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.GLClearOnInitReshape; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; @@ -78,6 +81,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { static boolean forceES3 = false; static boolean forceGL3 = false; static boolean forceGLFFP = false; + static int demoType = 1; static boolean shallUsePBuffer = false; static boolean shallUseBitmap = false; static boolean useMSAA = false; @@ -118,17 +122,41 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { private void setTitle(final JFrame frame, final GLJPanel glc, final GLCapabilitiesImmutable caps) { final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; final java.awt.Rectangle b = glc.getBounds(); - frame.setTitle("GLJPanel["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight()); + + final float[] minSurfacePixelScale = glc.getMinimumSurfaceScale(new float[2]); + final float[] maxSurfacePixelScale = glc.getMaximumSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale = glc.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale = glc.getCurrentSurfaceScale(new float[2]); + frame.setTitle("GLJPanel["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight()+ + ", scale[min "+minSurfacePixelScale[0]+"x"+minSurfacePixelScale[1]+", max "+ + maxSurfacePixelScale[0]+"x"+maxSurfacePixelScale[1]+", req "+ + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" -> has "+ + hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+"]"); } - protected void runTestGL(final GLCapabilities caps) + protected GLEventListener createDemo(final GLCapabilities caps) { + final GLEventListener demo; + if( 1 == demoType ) { + if( caps.isBitmap() || caps.getGLProfile().isGL2() ) { + final Gears gears = new Gears(swapInterval); + gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + demo = gears; + } else { + final GearsES2 gears = new GearsES2(swapInterval); + gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + demo = gears; + } + } else if( 0 == demoType ) { + demo = new GLClearOnInitReshape(); + } else { + demo = null; + } + return demo; + } + + protected GLJPanel newGLJPanel(final JFrame frame, final GLCapabilities caps, final FPSAnimator animator, final SnapshotGLEventListener snap) throws AWTException, InterruptedException, InvocationTargetException { - System.err.println("Requesting: "+caps); - - final JFrame frame = new JFrame("Swing GLJPanel"); - Assert.assertNotNull(frame); - final GLJPanel glJPanel = new GLJPanel(caps); Assert.assertNotNull(glJPanel); glJPanel.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); @@ -136,18 +164,15 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { glJPanel.setPreferredSize(wsize); glJPanel.setSize(wsize); glJPanel.setSurfaceScale(reqSurfacePixelScale); - final float[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new float[2]); - if( caps.isBitmap() || caps.getGLProfile().isGL2() ) { - final Gears gears = new Gears(swapInterval); - gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); - glJPanel.addGLEventListener(gears); - } else { - final GearsES2 gears = new GearsES2(swapInterval); - gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); - glJPanel.addGLEventListener(gears); + { + final GLEventListener demo = createDemo(caps); + if( null != demo ) { + glJPanel.addGLEventListener(demo); + } + } + if( null != snap ) { + glJPanel.addGLEventListener(snap); } - final SnapshotGLEventListener snap = new SnapshotGLEventListener(); - glJPanel.addGLEventListener(snap); glJPanel.addGLEventListener(new GLEventListener() { @Override public void init(final GLAutoDrawable drawable) { } @@ -159,42 +184,128 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { setTitle(frame, glJPanel, caps); } + }); setTitle(frame, glJPanel, caps); - frame.setLocation(xpos, ypos); - final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null; + frame.addComponentListener(new ComponentListener() { + @Override + public void componentResized(final ComponentEvent e) { + setTitle(frame, glJPanel, caps); + } + + @Override + public void componentMoved(final ComponentEvent e) { + setTitle(frame, glJPanel, caps); + } - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame.getContentPane().add(glJPanel, BorderLayout.CENTER); - frame.getContentPane().validate(); - frame.pack(); - frame.setVisible(true); - } } ) ; - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel, true)); + @Override + public void componentShown(final ComponentEvent e) { } - final Screen screen = NewtFactoryAWT.createScreen(glJPanel, true); - screen.addReference(); // initial native creation - keep alive! - System.err.println("GetPixelScale: AWT -> Screen: "+screen); + @Override + public void componentHidden(final ComponentEvent e) { } + }); - final float[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new float[2]); - System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ - valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ - hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); - setTitle(frame, glJPanel, caps); + if( SwingUtilities.isEventDispatchThread() ) { + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.getContentPane().validate(); + frame.pack(); + frame.setVisible(true); + } else { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.getContentPane().validate(); + frame.pack(); + frame.setVisible(true); + } } ) ; + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel, true, null)); + + final float[] minSurfacePixelScale = glJPanel.getMinimumSurfaceScale(new float[2]); + final float[] maxSurfacePixelScale = glJPanel.getMaximumSurfaceScale(new float[2]); + final float[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale = glJPanel.getCurrentSurfaceScale(new float[2]); + System.err.println("HiDPI PixelScale: min "+ + minSurfacePixelScale[0]+"x"+minSurfacePixelScale[1]+", max "+ + maxSurfacePixelScale[0]+"x"+maxSurfacePixelScale[1]+", req "+ + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" -> val "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" -> has "+ + hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]); + setTitle(frame, glJPanel, caps); + } - if( useAnimator ) { + if( null != animator ) { + animator.add(glJPanel); animator.setUpdateFPSFrames(60, System.err); + } + return glJPanel; + } + + protected void destroy(final JFrame frame, final GLJPanel glJPanel) { + try { + if( SwingUtilities.isEventDispatchThread() ) { + if( null != frame ) { + frame.setVisible(false); + if( null != glJPanel ) { + frame.getContentPane().remove(glJPanel); + } + frame.remove(glJPanel); + } + if( null != glJPanel ) { + glJPanel.destroy(); + } + if( null != frame ) { + frame.dispose(); + } + } else { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if( null != frame ) { + frame.setVisible(false); + if( null != glJPanel ) { + frame.getContentPane().remove(glJPanel); + } + frame.remove(glJPanel); + } + if( null != glJPanel ) { + glJPanel.destroy(); + } + if( null != frame ) { + frame.dispose(); + } + } } ); + } + } catch (final Exception e) { + e.printStackTrace(); + } + } + + protected void runTestGL(final GLCapabilities caps) + throws AWTException, InterruptedException, InvocationTargetException + { + final JFrame frame = new JFrame("Swing GLJPanel"); + frame.setLocation(xpos, ypos); + Assert.assertNotNull(frame); + + final FPSAnimator animator = useAnimator ? new FPSAnimator(60) : null; + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + final GLJPanel glJPanel = newGLJPanel(frame, caps, animator, snap); + if( null != animator ) { animator.start(); Assert.assertEquals(true, animator.isAnimating()); } + final Screen screen = NewtFactoryAWT.createScreen(glJPanel, true); + screen.addReference(); // initial native creation - keep alive! + System.err.println("GetPixelScale: AWT -> Screen: "+screen); final QuitAdapter quitAdapter = new QuitAdapter(); new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel).addTo(glJPanel); new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel).addTo(frame); + final JFrame[] frame2 = { null }; + final GLJPanel[] glJPanel2 = { null }; + final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() { @Override public void keyPressed(final KeyEvent e) { @@ -262,6 +373,33 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { glJPanel.setRequestedGLCapabilities(capsNew); System.err.println("XXX-A2: "+animator.toString()); System.err.println("XXX: "+glJPanel.toString()); + } else if(e.getKeyChar()=='n') { + System.err.println("XXX: frame2: "+frame2[0]); + if( null != frame2[0] ) { + System.err.println("XXX: frame2.isShowing: "+frame2[0].isShowing()); + } + System.err.println("XXX: glJPanel2: "+glJPanel2[0]); + if( null != frame2[0] && frame2[0].isShowing() ) { + destroy(frame2[0], glJPanel2[0]); + frame2[0] = null; + glJPanel2[0] = null; + } else { + frame2[0] = new JFrame("GLJPanel2"); + frame2[0].setLocation(frame.getX()+frame.getWidth()+64, frame.getY()); + final FPSAnimator animator2 = useAnimator ? new FPSAnimator(60) : null; + if( null != animator2 ) { + animator2.start(); + } + final SnapshotGLEventListener snap2 = new SnapshotGLEventListener(); + try { + glJPanel2[0] = newGLJPanel(frame2[0], caps, animator2, snap2); + } catch (final Exception e2) { + e2.printStackTrace(); + destroy(frame2[0], glJPanel2[0]); + frame2[0] = null; + glJPanel2[0] = null; + } + } } } }; new AWTKeyAdapter(kl, glJPanel).addTo(glJPanel); @@ -300,15 +438,12 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { } else { Assert.assertNull(animator); } - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame.setVisible(false); - frame.getContentPane().remove(glJPanel); - frame.remove(glJPanel); - glJPanel.destroy(); - frame.dispose(); - } } ); + screen.removeReference(); // final native destroy + destroy(frame, glJPanel); + if( null != frame2[0] ) { + destroy(frame2[0], glJPanel2[0]); + } } @Test @@ -528,6 +663,9 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { shallUseBitmap = true; } else if(args[i].equals("-manual")) { manualTest = true; + } else if(args[i].equals("-demo")) { + i++; + demoType = MiscUtils.atoi(args[i], 0); } } wsize = new Dimension(w, h); @@ -547,6 +685,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { System.err.println("shallUsePBuffer "+shallUsePBuffer); System.err.println("shallUseBitmap "+shallUseBitmap); System.err.println("manualTest "+manualTest); + System.err.println("demoType "+demoType); org.junit.runner.JUnitCore.main(TestGearsES2GLJPanelAWT.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java index 5ecda9e20..b389c9ac9 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.TraceWindowAdapter; @@ -109,12 +110,12 @@ public class TestElektronenMultipliziererNEWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setFullscreen(!f_glWindow.isFullscreen()); } }.start(); } else if(e.getKeyChar()=='d') { - new Thread() { + new InterruptSource.Thread() { public void run() { f_glWindow.setUndecorated(!f_glWindow.isUndecorated()); } }.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index d5afdcfda..6733d7e57 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -33,34 +33,38 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.Display; -import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.TraceMouseAdapter; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.newt.util.EDTUtil; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.NEWTDemoListener; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.test.junit.jogl.demos.GLClearOnInitReshape; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; - +import com.jogamp.opengl.test.junit.jogl.demos.es2.LineSquareXDemoES2; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.Point; import com.jogamp.nativewindow.util.PointImmutable; import com.jogamp.nativewindow.util.DimensionImmutable; +import com.jogamp.opengl.GL; import com.jogamp.opengl.GLAnimatorControl; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLCapabilitiesImmutable; import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLProfile; import jogamp.newt.DefaultEDTUtil; @@ -72,6 +76,14 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +/** + * <p> + * The demo code uses {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000} and many more, see {@link #main(String[])} + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsES2NEWT extends UITestCase { static int screenIdx = 0; @@ -102,6 +114,10 @@ public class TestGearsES2NEWT extends UITestCase { static boolean forceES3 = false; static boolean forceGL3 = false; static boolean forceGL2 = false; + static boolean forceDebug = false; + static boolean forceTrace = false; + static int demoType = 1; + static boolean traceMouse = false; static boolean manualTest = false; static boolean exclusiveContext = false; static boolean useAnimator = true; @@ -142,10 +158,50 @@ public class TestGearsES2NEWT extends UITestCase { glWindow.setPointerVisible(mouseVisible); glWindow.confinePointer(mouseConfined); - final GearsES2 demo = new GearsES2(swapInterval); - demo.setUseMappedBuffers(useMappedBuffers); - demo.setValidateBuffers(true); - glWindow.addGLEventListener(demo); + final GLEventListener demo; + if( 2 == demoType ) { + final LineSquareXDemoES2 demo2 = new LineSquareXDemoES2(false); + demo = demo2; + } else if( 1 == demoType ) { + final GearsES2 gearsES2 = new GearsES2(swapInterval); + gearsES2.setUseMappedBuffers(useMappedBuffers); + gearsES2.setValidateBuffers(true); + demo = gearsES2; + } else if( 0 == demoType ) { + demo = new GLClearOnInitReshape(); + } else { + demo = null; + } + if( forceDebug || forceTrace ) { + glWindow.addGLEventListener(new GLEventListener() { + @Override + public void init(final GLAutoDrawable drawable) { + GL _gl = drawable.getGL(); + if(forceDebug) { + try { + _gl = _gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, _gl, null) ); + } catch (final Exception e) {e.printStackTrace();} + } + + if(forceTrace) { + try { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, _gl, new Object[] { System.err } ) ); + } catch (final Exception e) {e.printStackTrace();} + } + } + @Override + public void dispose(final GLAutoDrawable drawable) {} + @Override + public void display(final GLAutoDrawable drawable) {} + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {} + }); + } + + if( null != demo ) { + glWindow.addGLEventListener(demo); + } final SnapshotGLEventListener snap = new SnapshotGLEventListener(); glWindow.addGLEventListener(snap); @@ -172,32 +228,51 @@ public class TestGearsES2NEWT extends UITestCase { animator.setExclusiveContext(exclusiveContext); } - final QuitAdapter quitAdapter = new QuitAdapter(); - //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); - //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); - glWindow.addKeyListener(quitAdapter); - glWindow.addWindowListener(quitAdapter); - glWindow.addWindowListener(new WindowAdapter() { public void windowResized(final WindowEvent e) { - System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()); + System.err.println("window resized: "+glWindow.getBounds()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()); NEWTDemoListener.setTitle(glWindow); } public void windowMoved(final WindowEvent e) { - System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()); + System.err.println("window moved: "+glWindow.getBounds()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()); NEWTDemoListener.setTitle(glWindow); } }); - final PointerIcon[] pointerIcons = NEWTDemoListener.createPointerIcons(glWindow); - if( setPointerIcon ) { - glWindow.setPointerIcon(pointerIcons[0]); - System.err.println("Set PointerIcon: "+glWindow.getPointerIcon()); - } + final GLWindow[] glWindow2 = { null }; - final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow, pointerIcons); + final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow); + newtDemoListener.quitAdapterEnable(true); glWindow.addKeyListener(newtDemoListener); + if( traceMouse ) { + glWindow.addMouseListener(new TraceMouseAdapter()); + } glWindow.addMouseListener(newtDemoListener); + glWindow.addWindowListener(newtDemoListener); + glWindow.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='n') { + if( null != glWindow2[0] && glWindow2[0].isNativeValid() ) { + glWindow2[0].destroy(); + glWindow2[0] = null; + } else { + glWindow2[0] = GLWindow.create(screen, caps); + glWindow2[0].setTitle("GLWindow2"); + glWindow2[0].setPosition(glWindow.getX()+glWindow.getWidth()+64, glWindow.getY()); + glWindow2[0].setSize(glWindow.getWidth(), glWindow.getHeight()); + glWindow2[0].addGLEventListener(new LineSquareXDemoES2(false)); + final Animator animator2 = useAnimator ? new Animator(glWindow2[0]) : null; + if( null != animator2 ) { + animator2.start(); + } + glWindow2[0].setVisible(true); + } + } + } } ); if( useAnimator ) { animator.add(glWindow); @@ -231,7 +306,7 @@ public class TestGearsES2NEWT extends UITestCase { final EDTUtil edt = ((Window)upstream).getScreen().getDisplay().getEDTUtil(); System.err.println("EDT invokeAndWaitError: edt type "+edt.getClass().getName()); if( edt instanceof DefaultEDTUtil ) { - quitAdapter.doQuit(); + newtDemoListener.doQuit(); ((DefaultEDTUtil)edt).invokeAndWaitError(new Runnable() { public void run() { throw new RuntimeException("XXX Should never ever be seen! - "+Thread.currentThread()); @@ -255,6 +330,8 @@ public class TestGearsES2NEWT extends UITestCase { animator.setUpdateFPSFrames(60, showFPS ? System.err : null); } + System.err.println("Window Current State : "+glWindow.getStateMaskString()); + System.err.println("Window Supported States: "+glWindow.getSupportedStateMaskString()); System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets()); @@ -277,7 +354,7 @@ public class TestGearsES2NEWT extends UITestCase { final long t0 = System.currentTimeMillis(); long t1 = t0; - while(!quitAdapter.shouldQuit() && t1-t0<duration) { + while(!newtDemoListener.shouldQuit() && t1-t0<duration) { Thread.sleep(100); t1 = System.currentTimeMillis(); if( SysExit.testError == sysExit || SysExit.testExit == sysExit || SysExit.testEDTError == sysExit) { @@ -292,7 +369,7 @@ public class TestGearsES2NEWT extends UITestCase { final EDTUtil edt = glWindow.getScreen().getDisplay().getEDTUtil(); System.err.println("EDT invokeAndWaitError: edt type "+edt.getClass().getName()); if( edt instanceof DefaultEDTUtil ) { - quitAdapter.doQuit(); + newtDemoListener.doQuit(); ((DefaultEDTUtil)edt).invokeAndWaitError(new Runnable() { public void run() { throw new RuntimeException("XXX Should never ever be seen!"); @@ -312,8 +389,12 @@ public class TestGearsES2NEWT extends UITestCase { } Assert.assertEquals(null, glWindow.getExclusiveContextThread()); glWindow.destroy(); + if( null != glWindow2[0] && glWindow2[0].isNativeValid() ) { + glWindow2[0].destroy(); + glWindow2[0] = null; + } if( NativeWindowFactory.isAWTAvailable() ) { - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } } @@ -426,6 +507,10 @@ public class TestGearsES2NEWT extends UITestCase { forceGL3 = true; } else if(args[i].equals("-gl2")) { forceGL2 = true; + } else if(args[i].equals("-debug")) { + forceDebug = true; + } else if(args[i].equals("-trace")) { + forceTrace = true; } else if(args[i].equals("-mappedBuffers")) { useMappedBuffers = true; } else if(args[i].equals("-wait")) { @@ -476,6 +561,11 @@ public class TestGearsES2NEWT extends UITestCase { sysExit = SysExit.valueOf(args[i]); } else if(args[i].equals("-manual")) { manualTest = true; + } else if(args[i].equals("-demo")) { + i++; + demoType = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-traceMouse")) { + traceMouse = true; } } wsize = new Dimension(w, h); @@ -509,11 +599,15 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("forceES3 "+forceES3); System.err.println("forceGL3 "+forceGL3); System.err.println("forceGL2 "+forceGL2); + System.err.println("forceDebug "+forceDebug); + System.err.println("forceTrace "+forceTrace); System.err.println("swapInterval "+swapInterval); System.err.println("exclusiveContext "+exclusiveContext); System.err.println("useAnimator "+useAnimator); System.err.println("sysExitWithin "+sysExit); System.err.println("mappedBuffers "+useMappedBuffers); + System.err.println("demoType "+demoType); + System.err.println("traceMouse "+traceMouse); if(waitForKey) { JunitTracer.waitForKey("Start"); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java index 39d13f6a3..fb3d82f9a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java @@ -47,14 +47,16 @@ import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.nativewindow.util.Dimension; @@ -74,6 +76,14 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +/** + * <p> + * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}, and many more, see {@link #main(String[])} + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsES2NewtCanvasAWT extends UITestCase { public enum FrameLayout { None, TextOnBottom, BorderBottom, BorderBottom2, BorderCenter, BorderCenterSurrounded, DoubleBorderCenterSurrounded }; @@ -82,7 +92,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { static int screenIdx = 0; static PointImmutable wpos; static DimensionImmutable wsize, rwsize = null; - static FrameLayout frameLayout = FrameLayout.None; + static FrameLayout frameLayout = FrameLayout.BorderCenterSurrounded; static ResizeBy resizeBy = ResizeBy.Component; static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; @@ -248,17 +258,21 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { final GearsES2 demo = new GearsES2(swapInterval); glWindow.addGLEventListener(demo); + final NewtAWTReparentingKeyAdapter newtDemoListener = new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow); + newtDemoListener.quitAdapterEnable(true); + glWindow.addKeyListener(newtDemoListener); + glWindow.addMouseListener(newtDemoListener); + glWindow.addWindowListener(newtDemoListener); + frame.addComponentListener(new ComponentListener() { @Override public void componentResized(final ComponentEvent e) { - NewtAWTReparentingKeyAdapter.setTitle(frame, newtCanvasAWT, glWindow); + newtDemoListener.setTitle(); } - @Override public void componentMoved(final ComponentEvent e) { - NewtAWTReparentingKeyAdapter.setTitle(frame, newtCanvasAWT, glWindow); + newtDemoListener.setTitle(); } - @Override public void componentShown(final ComponentEvent e) { } @@ -272,12 +286,6 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { animator.setExclusiveContext(exclusiveContext); } - final QuitAdapter quitAdapter = new QuitAdapter(); - //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); - //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); - glWindow.addKeyListener(quitAdapter); - glWindow.addWindowListener(quitAdapter); - glWindow.addWindowListener(new WindowAdapter() { public void windowResized(final WindowEvent e) { System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()); @@ -287,10 +295,6 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { } }); - final NewtAWTReparentingKeyAdapter newtDemoListener = new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter); - glWindow.addKeyListener(newtDemoListener); - glWindow.addMouseListener(newtDemoListener); - if( useAnimator ) { animator.add(glWindow); animator.start(); @@ -309,8 +313,8 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); if( useAnimator ) { animator.setUpdateFPSFrames(60, showFPS ? System.err : null); @@ -324,7 +328,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); - NewtAWTReparentingKeyAdapter.setTitle(frame, newtCanvasAWT, glWindow); + newtDemoListener.setTitle(); if( null != rwsize ) { Thread.sleep(500); // 500ms delay @@ -334,7 +338,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { final long t0 = System.currentTimeMillis(); long t1 = t0; - while(!quitAdapter.shouldQuit() && t1-t0<duration) { + while(!newtDemoListener.shouldQuit() && t1-t0<duration) { Thread.sleep(100); t1 = System.currentTimeMillis(); } @@ -352,7 +356,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { } }); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java index 8dcffc662..00091e486 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java @@ -39,8 +39,9 @@ import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.swt.NewtCanvasSWT; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; @@ -184,14 +185,12 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setFullscreen(!glWindow.isFullscreen()); System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); - glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); } } }); @@ -218,16 +217,24 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + final Runnable waitAction = new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + } }; + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(glWindow, true, waitAction)); + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets()); if( null != rwsize ) { for(int i=0; i<50; i++) { // 500 ms dispatched delay - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - Thread.sleep(10); - } + waitAction.run(); } display.syncExec( new Runnable() { public void run() { @@ -238,10 +245,7 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { } while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - Thread.sleep(10); - } + waitAction.run(); } Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); @@ -252,7 +256,7 @@ public class TestGearsES2NewtCanvasSWT extends UITestCase { canvas1.dispose(); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java index d109c56cf..6aebeb91b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java @@ -40,14 +40,14 @@ import com.jogamp.newt.Window; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.NEWTDemoListener; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; - +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.DimensionImmutable; @@ -61,6 +61,14 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +/** + * <p> + * The demo code uses {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000} and using a translucent window {@code -translucent}. + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsES2SimpleNEWT extends UITestCase { static final DimensionImmutable wsize = new Dimension(800, 600); @@ -118,7 +126,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase { int idx = 0; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/cross-grey-alpha-16x16.png" }, glWindow.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 8, 8); System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); @@ -130,7 +138,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase { idx++; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/pointer-grey-alpha-16x24.png" }, glWindow.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); @@ -142,7 +150,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase { idx++; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-red-alpha-64x64.png" }, glWindow.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); @@ -154,7 +162,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase { idx++; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-blue-alpha-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-blue-alpha-64x64.png" }, glWindow.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); @@ -166,7 +174,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase { idx++; if( PNGIcon.isAvailable() ) { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "jogamp-pointer-64x64.png" }, glWindow.getClass().getClassLoader(), null); try { final URLConnection urlConn = res.resolve(0); final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java index 79c8cb39a..2c5b6028c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java @@ -87,15 +87,15 @@ public class TestLandscapeES2NEWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { glWindow.setFullscreen(!glWindow.isFullscreen()); - } }.start(); + } } ); } else if(e.getKeyChar()=='d') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { glWindow.setUndecorated(!glWindow.isUndecorated()); - } }.start(); + } } ); } } }); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java index 12ea6dbb3..c5bbecbc7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java @@ -39,13 +39,14 @@ import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.DimensionImmutable; @@ -58,6 +59,14 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +/** + * <p> + * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}, and many more, see {@link #main(String[])} + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestLandscapeES2NewtCanvasAWT extends UITestCase { static DimensionImmutable wsize = new Dimension(500, 290); @@ -104,12 +113,6 @@ public class TestLandscapeES2NewtCanvasAWT extends UITestCase { animator.setExclusiveContext(exclusiveContext); } - final QuitAdapter quitAdapter = new QuitAdapter(); - //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); - //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); - glWindow.addKeyListener(quitAdapter); - glWindow.addWindowListener(quitAdapter); - glWindow.addWindowListener(new WindowAdapter() { public void windowResized(final WindowEvent e) { System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()); @@ -119,7 +122,11 @@ public class TestLandscapeES2NewtCanvasAWT extends UITestCase { } }); - glWindow.addKeyListener(new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter)); + final NewtReparentingKeyAdapter newtDemoListener = new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow); + newtDemoListener.quitAdapterEnable(true); + glWindow.addKeyListener(newtDemoListener); + glWindow.addMouseListener(newtDemoListener); + glWindow.addWindowListener(newtDemoListener); if( useAnimator ) { animator.add(glWindow); @@ -143,7 +150,7 @@ public class TestLandscapeES2NewtCanvasAWT extends UITestCase { final long t0 = System.currentTimeMillis(); long t1 = t0; - while(!quitAdapter.shouldQuit() && t1-t0<duration) { + while(!newtDemoListener.shouldQuit() && t1-t0<duration) { Thread.sleep(100); t1 = System.currentTimeMillis(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java index e8e3741aa..786549fdc 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java @@ -31,8 +31,8 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; @@ -110,15 +110,15 @@ public class TestRedSquareES2NEWT extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { glWindow.setFullscreen(!glWindow.isFullscreen()); - } }.start(); + } } ); } else if(e.getKeyChar()=='d') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { glWindow.setUndecorated(!glWindow.isUndecorated()); - } }.start(); + } } ); } } }); @@ -143,7 +143,7 @@ public class TestRedSquareES2NEWT extends UITestCase { Assert.assertFalse(animator.isStarted()); glWindow.destroy(); if( NativeWindowFactory.isAWTAvailable() ) { - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java index c05444b02..f76081754 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java @@ -33,7 +33,9 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.swt.GLCanvas; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; @@ -171,11 +173,18 @@ public class TestGearsES2SWT extends UITestCase { animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + final Runnable waitAction = new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + } }; + Assert.assertEquals(true, GLTestUtil.waitForRealized(canvas, true, waitAction)); + while(animator.isAnimating() && !canvas.isRealized() && animator.getTotalFPSDuration()<duration) { - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - Thread.sleep(10); - } + waitAction.run(); } System.err.println("NW chosen: "+canvas.getDelegatedDrawable().getChosenGLCapabilities()); System.err.println("GL chosen: "+canvas.getChosenGLCapabilities()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java index c2761f694..a144ff1ff 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java @@ -230,9 +230,7 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) { if( !isInit ) { return; } final GL2 gl = glad.getGL().getGL2(); - if(-1 != swapInterval) { - gl.setSwapInterval(swapInterval); - } + gl.setSwapInterval(swapInterval); reshape(gl, x, y, width, height, width, height); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java index 22d24b67b..159fad9da 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java @@ -72,7 +72,7 @@ public class Teapot implements GLEventListener { gl.glClearColor(0.5f, 0.5f, 0.5f, 0.0f); try { - final URLConnection urlConn = IOUtil.getResource(PNGTstFiles.class, "test-ntscP_3-01-160x90.png"); + final URLConnection urlConn = IOUtil.getResource("test-ntscP_3-01-160x90.png", PNGTstFiles.class.getClassLoader(), PNGTstFiles.class); tex = TextureIO.newTexture(gl, TextureIO.newTextureData(gl.getGLProfile(), urlConn.getInputStream(), false, TextureIO.PNG)); } catch (final Exception e) { e.printStackTrace(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java index 0f3011c3d..0ab9308c2 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java @@ -28,16 +28,15 @@ package com.jogamp.opengl.test.junit.jogl.demos.gl2.newt; -import com.jogamp.newt.event.KeyAdapter; -import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; - +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLProfile; @@ -48,6 +47,14 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +/** + * <p> + * The demo code uses {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}. + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsNEWT extends UITestCase { static GLProfile glp; @@ -84,25 +91,9 @@ public class TestGearsNEWT extends UITestCase { glWindow.addKeyListener(quitAdapter); glWindow.addWindowListener(quitAdapter); - final GLWindow f_glWindow = glWindow; - glWindow.addKeyListener(new KeyAdapter() { - public void keyReleased(final KeyEvent e) { - if( !e.isPrintableKey() || e.isAutoRepeat() ) { - return; - } - if(e.getKeyChar()=='f') { - new Thread() { - public void run() { - f_glWindow.setFullscreen(!f_glWindow.isFullscreen()); - } }.start(); - } else if(e.getKeyChar()=='d') { - new Thread() { - public void run() { - f_glWindow.setUndecorated(!f_glWindow.isUndecorated()); - } }.start(); - } - } - }); + final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow); + glWindow.addKeyListener(newtDemoListener); + glWindow.addMouseListener(newtDemoListener); glWindow.setSize(width, height); glWindow.setVisible(true); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java index b769e312c..6b789a152 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java @@ -32,8 +32,7 @@ import com.jogamp.nativewindow.*; import com.jogamp.opengl.*; import com.jogamp.opengl.util.Animator; - -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; @@ -97,7 +96,7 @@ public class TestGearsNewtAWTWrapper extends UITestCase { glWindow.display(); final int[] expSurfaceSize = glWindow.getNativeSurface().convertToPixelUnits(new int[] { width/div, height/div }); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1], null)); Thread.sleep(600); div = 2; @@ -107,7 +106,7 @@ public class TestGearsNewtAWTWrapper extends UITestCase { expSurfaceSize[1] = height/div; glWindow.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1], null)); Thread.sleep(600); div = 1; @@ -117,7 +116,7 @@ public class TestGearsNewtAWTWrapper extends UITestCase { expSurfaceSize[1] = height/div; glWindow.getNativeSurface().convertToPixelUnits(expSurfaceSize); Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight(), - AWTRobotUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1])); + GLTestUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1], null)); Thread.sleep(600); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java index a4a665e5b..668d8877c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java @@ -193,7 +193,7 @@ public class GeomShader01TextureGL3 implements GLEventListener { } private Texture createTestTexture(final GL3 gl) throws IOException { - final URLConnection urlConn = IOUtil.getResource(this.getClass(), "../../util/texture/test-ntscN_3-01-160x90.png"); + final URLConnection urlConn = IOUtil.getResource("../../util/texture/test-ntscN_3-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); if(null == urlConn) { return null; } final InputStream istream = urlConn.getInputStream(); if(null == istream) { return null; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/javafx/PureJFXApp01.java b/src/test/com/jogamp/opengl/test/junit/jogl/javafx/PureJFXApp01.java new file mode 100644 index 000000000..d2a3b8073 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/javafx/PureJFXApp01.java @@ -0,0 +1,54 @@ +/** + * Copyright 2019 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.test.junit.jogl.javafx; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.stage.Stage; + +public class PureJFXApp01 extends Application { + + @Override public void start(Stage stage) { + Text text = new Text(10, 40, "Pure JFX App 01"); + text.setFont(new Font(40)); + Scene scene = new Scene(new Group(text)); + + stage.setTitle("JavaFX Stage"); + stage.setScene(scene); + stage.sizeToScene(); + stage.show(); + } + + public static void main(String[] args) { + Application.launch(args); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/javafx/TestNewtCanvasJFXGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/javafx/TestNewtCanvasJFXGLn.java new file mode 100644 index 000000000..179cd49f0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/javafx/TestNewtCanvasJFXGLn.java @@ -0,0 +1,517 @@ +/** + * Copyright 2019 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.test.junit.jogl.javafx; + +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.RunnableTask; +import com.jogamp.nativewindow.javafx.JFXAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.javafx.NewtCanvasJFX; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.newt.parenting.NewtJFXReparentingKeyAdapter; +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.stage.Stage; + +/** + * {@link NewtCanvasJFX} basic functional integration test + * of its native parented NEWT child {@link GLWindow} attached to JavaFX's {@link Canvas}. + * <p> + * {@link NewtCanvasJFX} allows utilizing custom {@link GLCapabilities} settings independent from the JavaFX's window + * as well as independent rendering from JavaFX's thread. + * </p> + * <p> + * This unit tests also tests {@link NewtCanvasJFX} native parenting operations before and after + * it's belonging Group's Scene has been attached to the JavaFX {@link javafx.stage.Window Window}'s actual native window, + * i.e. becoming fully realized and visible. + * </p> + * <p> + * Note that {@link JFXAccessor#runOnJFXThread(boolean, Runnable)} is still used to for certain + * mandatory JavaFX lifecycle operation on the JavaFX thread. + * </p> + * <p> + * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows running a single test, e.g. {@code -test 21}, and setting each tests's duration in milliseconds, e.g.{@code -time 10000}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtCanvasJFXGLn extends UITestCase { + + static int duration = 5000; // 250; + static int manualTestID = -1; + + com.jogamp.newt.Display jfxNewtDisplay = null; + + public static class JFXApp extends Application { + static Stage stage; + + final static Object sync = new Object(); + static volatile boolean isLaunched = false; + + public JFXApp() { + } + + @Override public void init() throws Exception { + // pre JFX thread + System.err.println("JFX init ...: "+Thread.currentThread()); + } + + @Override public void start(final Stage stage) { + System.err.println("JFX start.0 ...: "+Thread.currentThread()); + synchronized(sync) { + try { + // on JFX thread + final Scene scene = new Scene(new Group(), defWidth, defHeight); + stage.setTitle(TestNewtCanvasJFXGLn.class.getSimpleName()); + stage.setScene(scene); + stage.sizeToScene(); + { + final long h = JFXAccessor.getWindowHandle(stage); + System.err.println("t1 - Native window: 0x"+Long.toHexString(h)); + } + stage.show(); + { + final long h = JFXAccessor.getWindowHandle(stage); + System.err.println("t2 - Native window: 0x"+Long.toHexString(h)); + } + JFXApp.stage = stage; + } finally { + isLaunched = true; + sync.notifyAll(); + } + } + System.err.println("JFX start.X ...: "+Thread.currentThread()); + } + @Override public void stop() throws Exception { + System.err.println("JFX stop ...: "+Thread.currentThread()); + } + public static void startup() throws InterruptedException { + System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + System.err.println("JFX Available: "+JFXAccessor.isJFXAvailable()); + if( JFXAccessor.isJFXAvailable() ) { + Platform.setImplicitExit(false); // FIXME: Default for all NEWT cases? + synchronized(sync) { + final Thread ct = Thread.currentThread(); + RunnableTask.invokeOnNewThread(ct.getThreadGroup(), ct.getName()+"JFXLauncher", false, + new Runnable() { + public void run() { + Application.launch(JFXApp.class); + } + }); + while(!isLaunched) { + sync.wait(); + } + } + System.err.println("JFX launched ..."); + } + } + public static void shutdown() { + JFXAccessor.runOnJFXThread(true, new Runnable() { + public void run() { + if( null != stage ) { + stage.close(); + } + } }); + } + } + + @BeforeClass + public static void startup() throws InterruptedException { + JFXApp.startup(); + } + + @AfterClass + public static void shutdown() { + JFXApp.shutdown(); + Platform.exit(); + } + + @Before + public void init() { + jfxNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + jfxNewtDisplay = null; + } + + class WaitAction implements Runnable { + private final long sleepMS; + + WaitAction(final long sleepMS) { + this.sleepMS = sleepMS; + } + public void run() { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(sleepMS); + } catch (final InterruptedException e) { } + } + } + final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE); + final WaitAction generalWaitAction = new WaitAction(10); + + static final int defWidth = 800, defHeight = 600; + + static void populateScene(final Scene scene, final boolean postAttach, + final GLWindow glWindow, + final int width, final int height, final boolean useBorder, + final NewtCanvasJFX[] res) { + final javafx.stage.Window w = scene.getWindow(); + final boolean isShowing = null != w && w.isShowing(); + final Group g = new Group(); + + final int cx, cy, cw, ch, bw, bh; + if( useBorder ) { + bw = width/5; bh = height/5; + cx = bw; cy = bh; cw = width-bw-bw; ch = height-bh-bh; + } else { + bw = 0; bh = 0; + cx = 0; cy = 0; cw = width; ch = height; + } + System.err.println("Scene "+width+"x"+height+", isShowing "+isShowing+", postAttach "+postAttach); + System.err.println("Scene.canvas "+cx+"/"+cy+" "+cw+"x"+ch); + System.err.println("Scene.border "+bw+"x"+bh); + + if( !postAttach ) { + if(isShowing) { + JFXAccessor.runOnJFXThread(true, new Runnable() { + @Override + public void run() { + scene.setRoot(g); + }}); + } else { + scene.setRoot(g); + } + } + + final Canvas canvas0; + if( null == res ) { + canvas0 = new Canvas(); + } else { + res[0] = new NewtCanvasJFX( glWindow ); + canvas0 = res[0]; + } + canvas0.setWidth(cw); + canvas0.setHeight(ch); + if( null == res ) { + final GraphicsContext gc = canvas0.getGraphicsContext2D(); + gc.setFill(Color.BLUE); + gc.fillRect(0, 0, cw, ch); + } + canvas0.relocate(cx, cy); + + final Text text0 = new Text(0, 0, "left"); + { + text0.setFont(new Font(40)); + text0.relocate(0, height/2); + } + final Text text1 = new Text(0, 0, "above"); + { + text1.setFont(new Font(40)); + text1.relocate(width/2, bh-40); + } + final Text text2 = new Text(0, 0, "right"); + { + text2.setFont(new Font(40)); + text2.relocate(width-bw, height/2); + } + final Text text3 = new Text(0, 0, "below"); + { + text3.setFont(new Font(40)); + text3.relocate(width/2, height-bh); + } + final Runnable attach2Group = new Runnable() { + @Override + public void run() { + g.getChildren().add(text0); + g.getChildren().add(text1); + g.getChildren().add(canvas0); + g.getChildren().add(text2); + g.getChildren().add(text3); + } }; + if( !postAttach && isShowing ) { + JFXAccessor.runOnJFXThread(true, attach2Group); + } else { + attach2Group.run(); + } + if( postAttach ) { + if(isShowing) { + JFXAccessor.runOnJFXThread(true, new Runnable() { + @Override + public void run() { + scene.setRoot(g); + }}); + } else { + scene.setRoot(g); + } + } + } + + protected void runTestAGL( final GLCapabilitiesImmutable caps, final GLEventListener demo, + final boolean postAttachNewtCanvas, final boolean postAttachGLWindow, + final boolean useAnimator ) throws InterruptedException { + if( !JFXAccessor.isJFXAvailable() ) { + System.err.println("JFX not available"); + return; + } + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + final GLWindow glWindow1; + if( null == demo ) { + glWindow1 = null; + } else { + final Screen screen = NewtFactory.createScreen(jfxNewtDisplay, 0); + glWindow1 = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.addGLEventListener(demo); + glWindow1.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + public void display(final GLAutoDrawable drawable) { + if(displayCount < 3) { + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + public void dispose(final GLAutoDrawable drawable) { } + }); + } + + final NewtCanvasJFX[] glCanvas = null==demo? null : new NewtCanvasJFX[]{null}; + + final Scene scene = new Scene(new Group(), defWidth, defHeight); + if(!postAttachNewtCanvas) { + System.err.println("Stage set.A0"); + JFXAccessor.runOnJFXThread(true, new Runnable() { + public void run() { + System.err.println("Stage set.A1"); + JFXApp.stage.setScene(scene); + JFXApp.stage.sizeToScene(); + System.err.println("Stage set.AX"); + } }); + } + populateScene( scene, postAttachNewtCanvas, postAttachGLWindow?null:glWindow1, defWidth, defHeight, true, glCanvas); + if(postAttachNewtCanvas) { + System.err.println("Stage set.B0"); + JFXAccessor.runOnJFXThread(true, new Runnable() { + public void run() { + System.err.println("Stage set.B1"); + JFXApp.stage.setScene(scene); + JFXApp.stage.sizeToScene(); + System.err.println("Stage set.BX"); + } }); + } + + if(postAttachGLWindow && null != demo) { + glCanvas[0].setNEWTChild(glWindow1); + } + + if( null != glWindow1 ) { + Assert.assertTrue("GLWindow didn't become visible natively!", NewtTestUtil.waitForRealized(glWindow1, true, awtRobotWaitAction)); + System.err.println("GLWindow LOS.0: "+glWindow1.getLocationOnScreen(null)); + glWindow1.addWindowListener(new WindowAdapter() { + public void windowResized(final WindowEvent e) { + System.err.println("window resized: "+glWindow1.getX()+"/"+glWindow1.getY()+" "+glWindow1.getSurfaceWidth()+"x"+glWindow1.getSurfaceHeight()); + } + public void windowMoved(final WindowEvent e) { + System.err.println("window moved: "+glWindow1.getX()+"/"+glWindow1.getY()+" "+glWindow1.getSurfaceWidth()+"x"+glWindow1.getSurfaceHeight()); + } + }); + final NewtReparentingKeyAdapter newtDemoListener = new NewtJFXReparentingKeyAdapter(JFXApp.stage, glCanvas[0], glWindow1); + newtDemoListener.quitAdapterEnable(true); + glWindow1.addKeyListener(newtDemoListener); + glWindow1.addMouseListener(newtDemoListener); + glWindow1.addWindowListener(newtDemoListener); + + final ChangeListener<Number> sizeListener = new ChangeListener<Number>() { + @Override public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) { + newtDemoListener.setTitle(); + } }; + JFXApp.stage.widthProperty().addListener(sizeListener); + JFXApp.stage.heightProperty().addListener(sizeListener); + + } + if( null != demo ) { + System.err.println("NewtCanvasJFX LOS.0: "+glCanvas[0].getNativeWindow().getLocationOnScreen(null)); + } + + Animator anim; + if(useAnimator && null != demo) { + anim = new Animator(glWindow1); + anim.start(); + } else { + anim = null; + } + + final long lStartTime = System.currentTimeMillis(); + final long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) ) { + generalWaitAction.run(); + } + } catch( final Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + if(null != anim) { + anim.stop(); + } + + JFXAccessor.runOnJFXThread(true, new Runnable() { + public void run() { + populateScene( JFXApp.stage.getScene(), false, null, defWidth, defHeight, true, null); + JFXApp.stage.sizeToScene(); + } }); + } + + @Test + public void test00() throws InterruptedException { + if( 0 > manualTestID || 0 == manualTestID ) { + runTestAGL( null, null, + false /* postAttachNewtCanvas */, false /* postAttach */, false /* animator */); + } + } + + @Test + public void test11_preAttachNewtGL_NoAnim() throws InterruptedException { + if( 0 > manualTestID || 11 == manualTestID ) { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), + false /* postAttachNewtCanvas */, false /* postAttachGLWindow */, false /* animator */); + } + } + + @Test + public void test12_postAttachNewt_NoAnim() throws InterruptedException { + if( 0 > manualTestID || 12 == manualTestID ) { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), + true /* postAttachNewtCanvas */, false /* postAttachGLWindow */, false /* animator */); + } + } + + @Test + public void test13_postAttachGL_NoAnim() throws InterruptedException { + if( 0 > manualTestID || 13 == manualTestID ) { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), + false /* postAttachNewtCanvas */, true /* postAttachGLWindow */, false /* animator */); + } + } + + @Test + public void test14_postAttachNewtGL_NoAnim() throws InterruptedException { + if( 0 > manualTestID || 14 == manualTestID ) { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), + true /* postAttachNewtCanvas */, true /* postAttachGLWindow */, false /* animator */); + } + } + + @Test + public void test21_preAttachNewtGL_DoAnim() throws InterruptedException { + if( 0 > manualTestID || 21 == manualTestID ) { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), + false /* postAttachNewtCanvas */, false /* postAttachGLWindow */, true /* animator */); + } + } + + @Test + public void test22_postAttachNewt_DoAnim() throws InterruptedException { + if( 0 > manualTestID || 22 == manualTestID ) { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), + true /* postAttachNewtCanvas */, false /* postAttachGLWindow */, true /* animator */); + } + } + + @Test + public void test30_MultisampleAndAlpha() throws InterruptedException { + if( 0 > manualTestID || 30 == manualTestID ) { + final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setSampleBuffers(true); + caps.setNumSamples(2); + runTestAGL( caps, new MultisampleDemoES2(true), + false /* postAttachNewtCanvas */, false /* postAttachGLWindow */, false /* animator */); + } + } + + public static void main(final String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + if(args[i].equals("-test")) { + manualTestID = MiscUtils.atoi(args[++i], -1); + } + } + System.out.println("durationPerTest: "+duration+", test "+manualTestID); + org.junit.runner.JUnitCore.main(TestNewtCanvasJFXGLn.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java index 1e65b15bc..04413315a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java @@ -47,7 +47,6 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; -import com.jogamp.common.os.Platform; import com.jogamp.opengl.math.FloatUtil; import com.jogamp.opengl.math.geom.Frustum; import com.jogamp.opengl.test.junit.util.MiscUtils; @@ -102,6 +101,7 @@ public class TestPMVMatrix01NEWT extends UITestCase { 0.0f, 0.0f, 0.0f, 1.0f } ); @Test + @SuppressWarnings("deprecation") public void test00MatrixToString() { final String s4x4Cpmv = PMVMatrix.matrixToString(null, "%10.5f", translated123C).toString(); final String s4x4Cflu = FloatUtil.matrixToString(null, null, "%10.5f", translated123C, 0, 4, 4, false).toString(); @@ -328,7 +328,6 @@ public class TestPMVMatrix01NEWT extends UITestCase { // System.err.println("P2: "+pmv.toString()); } - @SuppressWarnings("unused") @Test public void test03MvTranslate() { final FloatBuffer pmvMv; @@ -367,7 +366,6 @@ public class TestPMVMatrix01NEWT extends UITestCase { // System.err.println("pmvMvit: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvit)); } - @SuppressWarnings("unused") @Test public void test04MvTranslateRotate() { final FloatBuffer pmvMv; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java index b899c426c..2840e4026 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java @@ -164,8 +164,8 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { robot.setAutoWaitForIdle(true); // NativeWindow/JOGL is not initialized yet .. - for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && !frame.isVisible(); wait++) { - Thread.sleep(AWTRobotUtil.TIME_SLICE); + for (int wait=0; wait<TestUtil.POLL_DIVIDER && !frame.isVisible(); wait++) { + Thread.sleep(TestUtil.TIME_SLICE); } Assert.assertEquals(true, frame.isVisible()); @@ -214,7 +214,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { AWTRobotUtil.toFrontAndRequestFocus(robot, frame); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawable, true)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(drawable, true, null)); drawable.addGLEventListener(new GearsES2()); @@ -268,7 +268,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { final GLWindow win0 = GLWindow.create(caps); win0.setSize(100,100); win0.setVisible(true); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(win0, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(win0, true, null)); final Screen screen = win0.getScreen(); final RectangleImmutable screenBoundsInWinU = screen.getViewportInWindowUnits(); @@ -283,7 +283,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { runTestGL(newtCanvasAWT, win1); win0.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(win0, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(win0, false, null)); Assert.assertEquals(false, win0.isNativeValid()); Assert.assertEquals(true, anim.isAnimating()); // due to newtCanvasAWT/win1 diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java index aec728cad..89df0b1fa 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java @@ -40,7 +40,9 @@ import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.swt.NewtCanvasSWT; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLTestUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; @@ -198,14 +200,14 @@ public class TestBug672NewtCanvasSWTSashForm extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setFullscreen(!glWindow.isFullscreen()); System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); } } }); @@ -228,7 +230,16 @@ public class TestBug672NewtCanvasSWTSashForm extends UITestCase { shell.open(); } }); - Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, awtRobotWaitAction, true)); + final Runnable waitAction = new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + } }; + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow, true, waitAction)); + Assert.assertEquals(true, GLTestUtil.waitForRealized(glWindow, true, waitAction)); Assert.assertNotNull( canvas1.getNativeWindow() ); System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); @@ -272,7 +283,7 @@ public class TestBug672NewtCanvasSWTSashForm extends UITestCase { canvas1.dispose(); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, waitAction)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java index 0578492e2..fd6a3691c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java @@ -41,6 +41,7 @@ import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.swt.NewtCanvasSWT; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; @@ -205,14 +206,14 @@ public class TestBug672NewtCanvasSWTSashFormComposite extends UITestCase { return; } if(e.getKeyChar()=='f') { - new Thread() { + glWindow.invokeOnNewThread(null, false, new Runnable() { public void run() { final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setFullscreen(!glWindow.isFullscreen()); System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); - } }.start(); + } } ); } } }); @@ -235,7 +236,7 @@ public class TestBug672NewtCanvasSWTSashFormComposite extends UITestCase { shell.open(); } }); - Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, awtRobotWaitAction, true)); + Assert.assertTrue("GLWindow didn't become visible natively!", NewtTestUtil.waitForRealized(glWindow, true, awtRobotWaitAction)); Assert.assertNotNull( canvas1.getNativeWindow() ); System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); @@ -279,7 +280,7 @@ public class TestBug672NewtCanvasSWTSashFormComposite extends UITestCase { canvas1.dispose(); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java index 9a422f411..329a08a48 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java @@ -50,7 +50,8 @@ import com.jogamp.opengl.GLCapabilities ; import com.jogamp.opengl.GLEventListener ; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; - +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.InterruptedRuntimeException; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.event.KeyAdapter; @@ -59,6 +60,7 @@ import com.jogamp.newt.opengl.GLWindow ; import com.jogamp.newt.swt.NewtCanvasSWT ; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; //////////////////////////////////////////////////////////////////////////////// @@ -143,14 +145,13 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { //////////////////////////////////////////////////////////////////////////////// - static class ResizeThread extends Thread { + static class ResizeThread extends InterruptSource.Thread { volatile boolean shallStop = false; private final Shell _shell ; private int _n ; public ResizeThread( final Shell shell ) { - super(); _shell = shell ; } @@ -196,9 +197,9 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { display.asyncExec( resizeAction ); display.wake(); - Thread.sleep( 50L ) ; + java.lang.Thread.sleep( 50L ) ; } catch( final InterruptedException e ) { - break ; + throw new InterruptedRuntimeException(e); } } System.err.println("*R-Exit* shallStop "+shallStop+", disposed "+_shell.isDisposed()); @@ -207,7 +208,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { //////////////////////////////////////////////////////////////////////////////// - static class KeyfireThread extends Thread + static class KeyfireThread extends InterruptSource.Thread { volatile boolean shallStop = false; Display _display; @@ -216,6 +217,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { public KeyfireThread(final Robot robot, final Display display) { + super(); _robot = robot; _display = display; } @@ -231,7 +233,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { AWTRobotUtil.waitForIdle(_robot); AWTRobotUtil.newtKeyPress(_n, _robot, true, KeyEvent.VK_0, 10); AWTRobotUtil.newtKeyPress(_n, _robot, false, KeyEvent.VK_0, 0); - Thread.sleep( 40L ) ; + java.lang.Thread.sleep( 40L ) ; _n++; if(!_display.isDisposed()) { _display.wake(); @@ -348,7 +350,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { dsc.shell.setSize( 400, 450 ) ; dsc.shell.open() ; } } ); - Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, dsc.awtRobotWaitAction, true)); + Assert.assertTrue("GLWindow didn't become visible natively!", NewtTestUtil.waitForRealized(glWindow, true, dsc.awtRobotWaitAction)); AWTRobotUtil.requestFocus(robot, glWindow, false); AWTRobotUtil.setMouseToClientLocation(robot, glWindow, 50, 50); @@ -368,7 +370,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { } { - final Thread t = new Thread(new Runnable() { + final Thread t = new InterruptSource.Thread(null, new Runnable() { @Override public void run() { try { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java index 0d9effb30..93b1af15a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java @@ -57,6 +57,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLReadBufferUtil; @@ -194,7 +195,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase { canvas1.setNEWTChild(glWindow1); } - Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow1, awtRobotWaitAction, true)); + Assert.assertTrue("GLWindow didn't become visible natively!", NewtTestUtil.waitForRealized(glWindow1, true, awtRobotWaitAction)); System.err.println("GLWindow LOS.0: "+glWindow1.getLocationOnScreen(null)); System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null)); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java new file mode 100644 index 000000000..bf98a8e95 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java @@ -0,0 +1,200 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.swt; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.junit.util.JunitTracer; +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests {@link SWTAccessor#getWindowHandle(org.eclipse.swt.widgets.Control)} on a basic simple SWT window. + * <p> + * Bug 1362 inspired this unit test, i.e. finding the issue of SWT >= 4.10 + GTK3. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSWTAccessor01 extends UITestCase { + + static int duration = 250; + + Display display = null; + Shell shell = null; + Composite composite = null; + + @BeforeClass + public static void startup() { + if( Platform.getOSType() == Platform.OSType.MACOS ) { + // NSLocking issues on OSX and AWT, able to freeze whole test suite! + // Since this test is merely a technical nature to validate the accessor w/ SWT + // we can drop it w/o bothering. + JunitTracer.setTestSupported(false); + return; + } + } + + protected void init() throws InterruptedException, InvocationTargetException { + System.err.println("SWT Platform: "+SWT.getPlatform()+", Version "+SWT.getVersion()); + System.err.println("GTK_VERSION: "+SWTAccessor.GTK_VERSION()); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new GridLayout(3, false) ); + shell.setBackground(new Color(display, 0, 0, 255)); + new Text(shell, SWT.NONE).setText("1"); + new Text(shell, SWT.NONE).setText("2"); + new Text(shell, SWT.NONE).setText("3"); + new Text(shell, SWT.NONE).setText("4"); + composite = new Composite( shell, SWT.NO_BACKGROUND /** | SWT.EMBEDDED */ ); + composite.setLayout( new FillLayout() ); + composite.setBackground(new Color(display, 0, 255, 0)); + final GridData gd = new GridData (GridData.FILL, GridData.FILL, true /* grabExcessHorizontalSpace */, true /* grabExcessVerticalSpace */); + composite.setLayoutData(gd); + new Text(shell, SWT.NONE).setText("6"); + new Text(shell, SWT.NONE).setText("7"); + new Text(shell, SWT.NONE).setText("8"); + new Text(shell, SWT.NONE).setText("9"); + Assert.assertNotNull( composite ); + }}); + } + + protected void release() throws InterruptedException, InvocationTargetException { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite.dispose(); + shell.close(); + shell.dispose(); + display.dispose(); + display = null; + shell = null; + composite = null; + }}); + } + + protected void runTest() throws InterruptedException, InvocationTargetException { + init(); + final Canvas canvas[] = { null }; + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas[0] = new Canvas (composite, SWT.NONE); + canvas[0].setBackground(new Color(display, 255, 255, 255)); + canvas[0].setForeground(new Color(display, 255, 0, 0)); + canvas[0].addPaintListener (new PaintListener() { + public void paintControl(final PaintEvent e) { + final Rectangle r = canvas[0].getClientArea(); + e.gc.fillRectangle(0, 0, r.width, r.height); + e.gc.drawRectangle(50, 50, r.width-100, r.height-100); + e.gc.drawString("I am a Canvas", r.width/2, r.height/2); + }}); + try { + System.err.println("Window handle.0 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0]))); + } catch (final Exception e) { + System.err.println(e.getMessage()); + } + shell.setText( getClass().getName() ); + shell.setBounds( 0, 0, 700, 700 ); + shell.open(); + canvas[0].redraw(); + }}); + + System.err.println("Window handle.1 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0]))); + + final long lStartTime = System.currentTimeMillis(); + final long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + }}); + } + SWTAccessor.invoke(true, new Runnable() { + public void run() { + System.err.println("Window handle.X 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0]))); + }}); + } + catch( final Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } finally { + release(); + } + } + + @Test + public void test() throws InterruptedException, InvocationTargetException { + runTest(); + } + + public static void main(final String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + org.junit.runner.JUnitCore.main( TestSWTAccessor01.class.getName() ); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02NewtGLWindow.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02NewtGLWindow.java new file mode 100644 index 000000000..6694df65a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02NewtGLWindow.java @@ -0,0 +1,256 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.swt; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.junit.util.JunitTracer; +import com.jogamp.nativewindow.AbstractGraphicsScreen; +import com.jogamp.nativewindow.NativeWindow; +import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos; +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests utilizing {@link SWTAccessor#getWindowHandle(org.eclipse.swt.widgets.Control)} + * for NEWT native window reparenting also using GL rendering {@link GLWindow#reparentWindow(NativeWindow, int, int, int)}. + * <p> + * This tests re-creates {@link NewtCanvasSWT}'s implementation ad-hock, allowing simplified debugging. + * </p> + * <p> + * Enhanced version of {@link TestSWTAccessor01}. + * </p> + * <p> + * Bug 1362 inspired this unit test, i.e. finding the issue of SWT >= 4.10 + GTK3. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSWTAccessor02NewtGLWindow extends UITestCase { + + static int duration = 250; + + Display display = null; + Shell shell = null; + Composite composite = null; + + @BeforeClass + public static void startup() { + if( Platform.getOSType() == Platform.OSType.MACOS ) { + // NSLocking issues on OSX and AWT, able to freeze whole test suite! + // Since this test is merely a technical nature to validate the accessor w/ SWT + // we can drop it w/o bothering. + JunitTracer.setTestSupported(false); + return; + } + } + + protected void init() throws InterruptedException, InvocationTargetException { + System.err.println("SWT Platform: "+SWT.getPlatform()+", Version "+SWT.getVersion()); + System.err.println("GTK_VERSION: "+SWTAccessor.GTK_VERSION()); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new GridLayout(3, false) ); + shell.setBackground(new Color(display, 0, 0, 255)); + new Text(shell, SWT.NONE).setText("1"); + new Text(shell, SWT.NONE).setText("2"); + new Text(shell, SWT.NONE).setText("3"); + new Text(shell, SWT.NONE).setText("4"); + composite = new Composite( shell, SWT.NO_BACKGROUND /** | SWT.EMBEDDED */ ); + composite.setLayout( new FillLayout() ); + composite.setBackground(new Color(display, 0, 255, 0)); + final GridData gd = new GridData (GridData.FILL, GridData.FILL, true /* grabExcessHorizontalSpace */, true /* grabExcessVerticalSpace */); + composite.setLayoutData(gd); + new Text(shell, SWT.NONE).setText("6"); + new Text(shell, SWT.NONE).setText("7"); + new Text(shell, SWT.NONE).setText("8"); + new Text(shell, SWT.NONE).setText("9"); + Assert.assertNotNull( composite ); + }}); + } + + protected void release(final GLWindow glwin) throws InterruptedException, InvocationTargetException { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + glwin.destroy(); + composite.dispose(); + shell.close(); + shell.dispose(); + display.dispose(); + display = null; + shell = null; + composite = null; + }}); + } + + protected void runTest() throws InterruptedException, InvocationTargetException { + init(); + + final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + final GLWindow glwin = GLWindow.create(caps); + final GearsES2 demo = new GearsES2(); + glwin.addGLEventListener(demo); + glwin.setSize(600, 600); + + final Canvas canvas[] = { null }; + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas[0] = new Canvas (composite, SWT.NO_BACKGROUND); + // Bug 1362 fix or workaround: Seems SWT/GTK3 at least performs lazy initialization + // Minimal action required: setBackground of the parent canvas before reparenting! + canvas[0].setBackground(new Color(display, 255, 255, 255)); + shell.setText( getClass().getName() ); + shell.setBounds( 0, 0, 700, 700 ); + shell.open(); + + // A full rolled-out native window reparenting example, very suitable to debug + final long parentWinHandle = SWTAccessor.getWindowHandle(canvas[0]); + final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(NativeWindowFactory.createDevice(null, true /* own */), -1); + final UpstreamWindowHookMutableSizePos upstreamSizePosHook = new UpstreamWindowHookMutableSizePos(0, 0, 600, 600, 600, 600); + final Listener listener = new Listener () { + @Override + public void handleEvent (final Event event) { + switch (event.type) { + case SWT.Paint: + glwin.display(); + break; + case SWT.Move: + case SWT.Resize: { + final Rectangle nClientArea = canvas[0].getClientArea(); + if( null != nClientArea ) { + upstreamSizePosHook.setSurfaceSize(nClientArea.width, nClientArea.height); + upstreamSizePosHook.setWinSize(nClientArea.width, nClientArea.height); + upstreamSizePosHook.setWinPos(nClientArea.x, nClientArea.y); + if( SWT.Resize == event.type ) { + glwin.setSize(nClientArea.width, nClientArea.height); + } + } + } + break; + case SWT.Dispose: + glwin.destroy(); + break; + } + } + }; + canvas[0].addListener (SWT.Move, listener); + canvas[0].addListener (SWT.Resize, listener); + canvas[0].addListener (SWT.Paint, listener); + canvas[0].addListener (SWT.Dispose, listener); + + final NativeWindow parentWindow = NativeWindowFactory.createWrappedWindow(aScreen, 0 /* surfaceHandle*/, parentWinHandle, upstreamSizePosHook); + glwin.reparentWindow(parentWindow, 0, 0, 0); + final Rectangle r = canvas[0].getClientArea(); + glwin.setSize(r.width, r.height); + glwin.setVisible(true); + canvas[0].redraw(); + }}); + + System.err.println("Window handle.1 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0]))); + + final long lStartTime = System.currentTimeMillis(); + final long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(10); + } catch (final InterruptedException e) { } + } + }}); + } + SWTAccessor.invoke(true, new Runnable() { + public void run() { + System.err.println("Window handle.X 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0]))); + }}); + } + catch( final Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } finally { + release(glwin); + } + } + + @Test + public void test() throws InterruptedException, InvocationTargetException { + runTest(); + } + + public static void main(final String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + org.junit.runner.JUnitCore.main( TestSWTAccessor02NewtGLWindow.class.getName() ); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java index 7072ed9ea..b8ba3b97e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java @@ -51,14 +51,15 @@ import com.jogamp.opengl.GLProfile; import jogamp.newt.swt.SWTEDTUtil; import jogamp.newt.swt.event.SWTNewtEventFactory; +import com.jogamp.common.util.InterruptSource; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.opengl.GLWindow ; import com.jogamp.newt.swt.NewtCanvasSWT ; import com.jogamp.opengl.swt.GLCanvas; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -110,7 +111,7 @@ public class TestSWTBug643AsyncExec extends UITestCase { //////////////////////////////////////////////////////////////////////////////// - static class AsyncExecEDTFeederThread extends Thread { + static class AsyncExecEDTFeederThread extends InterruptSource.Thread { volatile boolean shallStop = false; private final Display swtDisplay ; private final jogamp.newt.DisplayImpl newtDisplay; @@ -118,7 +119,6 @@ public class TestSWTBug643AsyncExec extends UITestCase { public AsyncExecEDTFeederThread( final Display swtDisplay, final com.jogamp.newt.Display newtDisplay ) { - super(); this.swtDisplay = swtDisplay ; this.newtDisplay = (jogamp.newt.DisplayImpl)newtDisplay; } @@ -152,7 +152,7 @@ public class TestSWTBug643AsyncExec extends UITestCase { // only perform async exec on valid and already running NEWT EDT! newtDisplay.runOnEDTIfAvail(false, newtAsyncAction); } - Thread.sleep( 50L ) ; + java.lang.Thread.sleep( 50L ) ; } catch( final InterruptedException e ) { break ; } @@ -241,7 +241,7 @@ public class TestSWTBug643AsyncExec extends UITestCase { if( glWindowPreVisible ) { newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, dsc.display)); // Especially Windows requires creation access via same thread! glWindow.setVisible(true); - AWTRobotUtil.waitForRealized(glWindow, true); + NewtTestUtil.waitForRealized(glWindow, true, null); Thread.sleep(120); // let it render a bit, before consumed by SWT } glad = glWindow; @@ -275,7 +275,7 @@ public class TestSWTBug643AsyncExec extends UITestCase { } { - final Thread t = new Thread(new Runnable() { + final Thread t = new InterruptSource.Thread(null, new Runnable() { @Override public void run() { try { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java index c880b1f13..3ce6113f9 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java @@ -165,9 +165,9 @@ public class TestTiledPrintingGearsAWT extends TiledPrintingAWTBase { frame.pack(); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true, null)); animator.setUpdateFPSFrames(60, System.err); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java index 48f1dbdb1..0c111328d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java @@ -170,9 +170,9 @@ public class TestTiledPrintingGearsNewtAWT extends TiledPrintingAWTBase { frame.pack(); frame.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas1, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas2, true, null)); animator.setUpdateFPSFrames(60, System.err); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java index 41d438f5d..5ad629fe0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java @@ -211,9 +211,9 @@ public class TestTiledPrintingGearsSwingAWT extends TiledPrintingAWTBase { frame.setVisible(true); } } ) ; - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true, null)); animator.setUpdateFPSFrames(60, System.err); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java index b069e8dba..2727e2792 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java @@ -206,8 +206,8 @@ public class TestTiledPrintingGearsSwingAWT2 extends TiledPrintingAWTBase { frame.setVisible(true); } } ) ; - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true, null)); if( null != animator ) { animator.setUpdateFPSFrames(60, System.err); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java index 3b48ccf6b..c8912f524 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java @@ -225,9 +225,9 @@ public class TestTiledPrintingNIOImageSwingAWT extends UITestCase { frame.setVisible(true); } } ) ; - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true, null)); // paint offscreen: array 72dpi ARGB { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java index be662fd1f..9c4943176 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java @@ -39,6 +39,7 @@ import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.util.Locale; import com.jogamp.opengl.GLAutoDrawable; import javax.print.StreamPrintService; @@ -139,7 +140,7 @@ public abstract class TiledPrintingAWTBase extends UITestCase { final String simpleTestName = getSimpleTestName("."); final String onoffscrn = 0 > offscrnImageType ? "on_screen" : "offscrn_"+offscrnImageType; final String aa = 0 <= numSamples ? "aa"+numSamples : "aaN"; - return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-%s-dpi%03d-%s-tSz%04dx%04d-resize%d.%s", + return String.format((Locale)null, "%-"+maxSimpleTestNameLen+"s-n%04d-%s-dpi%03d-%s-tSz%04dx%04d-resize%d.%s", simpleTestName, printCount, onoffscrn, dpi, aa, tileWidth, tileHeight, resizeWithinPrintTest?1:0, suffix).replace(' ', '_'); } private PrintableBase doPrintAutoImpl(final Container cont, final PrinterJob job, diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java index f90b32009..572871233 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java @@ -97,7 +97,7 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra } final GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); - final URLConnection testTextureUrlConn = IOUtil.getResource(PNGTstFiles.class, "test-ntscP_3-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscP_3-01-160x90.png", PNGTstFiles.class.getClassLoader(), PNGTstFiles.class); try { final InputStream testTextureStream = testTextureUrlConn.getInputStream(); textureData = TextureIO.newTextureData(gl.getGLProfile(), testTextureStream , false /* mipmap */, TextureIO.PNG); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/ImageTstFiles.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/ImageTstFiles.java new file mode 100644 index 000000000..25bb7e788 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/ImageTstFiles.java @@ -0,0 +1,128 @@ +/** + * 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.test.junit.jogl.util.texture; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; +import java.util.ArrayList; + +import com.jogamp.common.util.IOUtil; + +public class ImageTstFiles { + public static final String[] pngFileNames = new String[] { + "bug724-transparent-grey_gimpexp.png", + "bug724-transparent-grey_orig.png", + "cross-grey-alpha-16x16.png", + "grayscale_texture.png", + "pointer-grey-alpha-16x24.png", + "test-ntscI_3-01-160x90.png", + "test-ntscI_4-01-160x90.png", + "test-ntscIG3-01-160x90.png", + "test-ntscIG4-01-160x90.png", + "test-ntscN_3-01-160x90.png", + "test-ntscN_4-01-160x90.png", + "test-ntscNG4-01-160x90.png", + "test-ntscP_3-01-160x90.png", + "test-ntscP_4-01-160x90.png" + }; + + public static final String[] jpgFileNames = new String[] { + "bug745_qttdef_post_frame.jpg", + "darwin_03_N_4-YCCK-640x452.jpg", // local + "darwin_03_N_4-YCCK.jpg", // local + "j1-baseline.jpg", + "j2-progressive.jpg", + "j3-baseline_gray.jpg", + "test-cmyk-01.jpg", + "test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg", + "test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg", + "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg", + "test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg", + "test-ycck-01.jpg" }; + + public static final String[] tgaFileNames = new String[] { + "bug744-rle32.tga", + "bug982.rle32.256x256.tga", + "test-u32.tga" + }; + public static final String[] ddsFileNames = new String[] { + "test-64x32_DXT1.dds", + "test-64x32_DXT5.dds", + "test-64x32_uncompressed.dds" + }; + + public static class NamedInputStream { + final String fullPath; + final String basePath; + final InputStream stream; + public NamedInputStream(final String fullPath, final String basePath, final InputStream stream) { + this.fullPath = fullPath; + this.basePath = basePath; + this.stream = stream; + } + } + public ArrayList<NamedInputStream> pngStreams; + public ArrayList<NamedInputStream> jpgStreams; + public ArrayList<NamedInputStream> tgaStreams; + public ArrayList<NamedInputStream> ddsStreams; + public ArrayList<NamedInputStream> allStreams; + + private final ArrayList<NamedInputStream> init(final String[] source) throws IOException { + final ArrayList<NamedInputStream> sink = new ArrayList<NamedInputStream>(); + for(int i=0; i<source.length; i++) { + final URLConnection testTextureUrlConn = IOUtil.getResource(source[i], this.getClass().getClassLoader(), this.getClass()); + if( null != testTextureUrlConn ) { + final InputStream s = testTextureUrlConn.getInputStream(); + if( null != s ) { + sink.add(new NamedInputStream(testTextureUrlConn.getURL().toString(), source[i], s)); + } + } + } + return sink; + } + + public void init() throws IOException { + pngStreams = init(pngFileNames); + jpgStreams = init(jpgFileNames); + tgaStreams = init(tgaFileNames); + ddsStreams = init(ddsFileNames); + allStreams = new ArrayList<NamedInputStream>(); + allStreams.addAll(pngStreams); + allStreams.addAll(jpgStreams); + allStreams.addAll(tgaStreams); + allStreams.addAll(ddsStreams); + } + public void clear() { + pngStreams.clear(); + jpgStreams.clear(); + tgaStreams.clear(); + ddsStreams.clear(); + allStreams.clear(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java index a585e9eaf..71233d07c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java @@ -56,7 +56,7 @@ public class TestBug362DDSImageCreateFromData { } private File initFile(final String filename) throws URISyntaxException { - final URLConnection connection = IOUtil.getResource(getClass(), filename); + final URLConnection connection = IOUtil.getResource(filename, getClass().getClassLoader(), getClass()); Assert.assertNotNull(connection); final URL url = connection.getURL(); final File file = new File(url.toURI()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java index 201d60a78..d2ce4e19b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java @@ -119,8 +119,8 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true, null)); Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, glc.isOffscreenLayerSurfaceEnabled()); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java index a7196150c..3ac5f3618 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java @@ -144,8 +144,8 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true, null)); Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, glc.isOffscreenLayerSurfaceEnabled()); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java index 8339831a0..7fc14a609 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.test.junit.jogl.util.texture; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.GLAutoDrawable; @@ -99,7 +100,7 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase { c=0; snapshot(i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); dw_old = dw; - new Thread() { + new InterruptSource.Thread() { @Override public void run() { glWindow.setSize(2*dw, 2*dh); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestImageTypeNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestImageTypeNEWT.java new file mode 100644 index 000000000..952d54443 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestImageTypeNEWT.java @@ -0,0 +1,92 @@ +/** + * Copyright 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 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.test.junit.jogl.util.texture; + +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.texture.ImageType; + +import java.io.IOException; +import java.util.List; + +import org.junit.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestImageTypeNEWT extends UITestCase { + ImageTstFiles imageTstFiles; + + @Before + public void initTest() throws IOException { + imageTstFiles = new ImageTstFiles(); + imageTstFiles.init(); + } + + @After + public void cleanupTest() { + imageTstFiles.clear(); + } + + public void testImpl(final List<ImageTstFiles.NamedInputStream> streams, final ImageType expImageType) throws InterruptedException, IOException { + for(int i=0; i<streams.size(); i++) { + final ImageTstFiles.NamedInputStream s = streams.get(i); + final ImageType t = new ImageType(s.stream); + System.err.printf("Test %3d: path %s, exp-type %s, has-type %s%n", i, s.basePath, expImageType, t); + Assert.assertEquals(expImageType, t); + } + } + + @Test + public void test01AllPNG() throws InterruptedException, IOException { + testImpl(imageTstFiles.pngStreams, new ImageType(ImageType.T_PNG)); + } + + @Test + public void test02AllJPG() throws InterruptedException, IOException { + testImpl(imageTstFiles.jpgStreams, new ImageType(ImageType.T_JPG)); + } + + // TGA cannot be detected + // @Test + public void test03AllTGA() throws InterruptedException, IOException { + testImpl(imageTstFiles.tgaStreams, new ImageType(ImageType.T_TGA)); + } + + @Test + public void test04AllDDS() throws InterruptedException, IOException { + testImpl(imageTstFiles.ddsStreams, new ImageType(ImageType.T_DDS)); + } + + public static void main(final String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestImageTypeNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java index 925382901..8ccc73f34 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java @@ -146,7 +146,7 @@ public class TestJPEGImage01NEWT extends UITestCase { @Test public void testReadES2_RGBn() throws InterruptedException, IOException, MalformedURLException { final String fname = null == _fname ? "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg" : _fname; - final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final URLConnection urlConn = IOUtil.getResource(fname, this.getClass().getClassLoader(), this.getClass()); testImpl(urlConn.getInputStream()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java index 4fc774463..87a993de4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java @@ -64,7 +64,7 @@ public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase { { final long t0 = System.currentTimeMillis(); for(int i = 0; i< loops; i++ ) { - final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final URLConnection urlConn = IOUtil.getResource(fname, this.getClass().getClassLoader(), this.getClass()); final InputStream istream = urlConn.getInputStream(); final JPEGImage image = JPEGImage.read(istream); // parsing & completion done !!! final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; @@ -92,7 +92,7 @@ public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase { { final long t0 = System.currentTimeMillis(); for(int i = 0; i< loops; i++ ) { - final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final URLConnection urlConn = IOUtil.getResource(fname, this.getClass().getClassLoader(), this.getClass()); final InputStream istream = urlConn.getInputStream(); final JPEGImage image = JPEGImage.read(istream, TextureData.ColorSpace.YCbCr); // parsing & completion done !!! final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; @@ -120,7 +120,7 @@ public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase { { final long t0 = System.currentTimeMillis(); for(int i = 0; i< loops; i++ ) { - final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final URLConnection urlConn = IOUtil.getResource(fname, this.getClass().getClassLoader(), this.getClass()); final InputStream istream = urlConn.getInputStream(); Buffer data = null; try { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java index d5c80553d..b48000046 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java @@ -101,7 +101,7 @@ public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase { } GLWindow testJOGLJpeg(final String fname) throws InterruptedException, IOException { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), fname); + final URLConnection testTextureUrlConn = IOUtil.getResource(fname, this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); final InputStream istream = testTextureUrlConn.getInputStream(); Assert.assertNotNull(istream); @@ -160,7 +160,7 @@ public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase { } GLWindow testAWTJpeg(final String fname, final int xpos) throws InterruptedException, IOException { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), fname); + final URLConnection testTextureUrlConn = IOUtil.getResource(fname, this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); final InputStream istream = testTextureUrlConn.getInputStream(); Assert.assertNotNull(istream); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java index 114561666..b43fba479 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java @@ -82,63 +82,63 @@ public class TestJPEGTextureFromFileNEWT extends UITestCase { @Before public void initTest() throws IOException { { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_3-01-160x90-90pct-yuv444-base.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream01YUV444_Base = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream01YUV444_Base); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream01YUV444_Prog = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream01YUV444_Prog); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream01YUV422h_Base = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream01YUV422h_Base); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream01YUV422h_Prog = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream01YUV422h_Prog); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j1-baseline.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("j1-baseline.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream02YUV420_Base = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream02YUV420_Base); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j2-progressive.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("j2-progressive.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream02YUV420_Prog = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream02YUV420_Prog); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j3-baseline_gray.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("j3-baseline_gray.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream02YUV420_BaseGray = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream02YUV420_BaseGray); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-cmyk-01.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-cmyk-01.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream03CMYK_01 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream03CMYK_01); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ycck-01.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ycck-01.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream03YCCK_01 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream03YCCK_01); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug745_qttdef_post_frame.jpg"); + final URLConnection testTextureUrlConn = IOUtil.getResource("bug745_qttdef_post_frame.jpg", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream04QTTDefPostFrame = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream04QTTDefPostFrame); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java index 3918b6cb7..0506f840e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java @@ -128,7 +128,7 @@ public class TestPNGPixelRect00NEWT extends UITestCase { final File out2F_f=new File(getSimpleTestName(".")+"-02-"+basename+"-flipped.png"); final File out2R_f=new File(getSimpleTestName(".")+"-03-"+basename+"-reversed.png"); final File out2RF_f=new File(getSimpleTestName(".")+"-04-"+basename+"-reversed_flipped.png"); - final URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png"); + final URLConnection urlConn = IOUtil.getResource(pathname+basename+".png", this.getClass().getClassLoader(), this.getClass()); if( null == urlConn ) { throw new IOException("Cannot find "+pathname+basename+".png"); } @@ -205,7 +205,7 @@ public class TestPNGPixelRect00NEWT extends UITestCase { System.err.println("Test02: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); final File out1_f=new File(getSimpleTestName(".")+"-"+basename+"-orig.png"); - final URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png"); + final URLConnection urlConn = IOUtil.getResource(pathname+basename+".png", this.getClass().getClassLoader(), this.getClass()); final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented); System.err.println("PNGPixelRect - Orig: "+image1); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java index e299932b3..b6a047d03 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java @@ -156,7 +156,7 @@ public class TestPNGPixelRect01NEWT extends UITestCase { if( null == _fname ) { return; } - final URLConnection urlConn = IOUtil.getResource(this.getClass(), _fname); + final URLConnection urlConn = IOUtil.getResource(_fname, this.getClass().getClassLoader(), this.getClass()); if( null == urlConn ) { throw new IOException("Cannot find "+_fname+".png"); } @@ -170,7 +170,7 @@ public class TestPNGPixelRect01NEWT extends UITestCase { } for(int i=0; i<PNGTstFiles.allBasenames.length; i++) { final String basename = PNGTstFiles.allBasenames[i]; - final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png"); + final URLConnection urlConn = IOUtil.getResource(basename+".png", this.getClass().getClassLoader(), this.getClass()); if( null == urlConn ) { throw new IOException("Cannot find "+basename+".png"); } @@ -184,7 +184,7 @@ public class TestPNGPixelRect01NEWT extends UITestCase { } for(int i=0; i<PNGTstFiles.greyBasenames.length; i++) { final String basename = PNGTstFiles.greyBasenames[i]; - final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png"); + final URLConnection urlConn = IOUtil.getResource(basename+".png", this.getClass().getClassLoader(), this.getClass()); if( null == urlConn ) { throw new IOException("Cannot find "+basename+".png"); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java index 2d6b6da71..157fffb90 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java @@ -86,7 +86,7 @@ public class TestPNGTextureFromFileAWT extends UITestCase { grayTextureStream = TestPNGTextureFromFileAWT.class.getResourceAsStream( "grayscale_texture.png" ); Assert.assertNotNull(grayTextureStream); { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_3-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java index a82767f9a..d7017465e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java @@ -82,44 +82,44 @@ public class TestPNGTextureFromFileNEWT extends UITestCase { grayTextureStream = TestPNGTextureFromFileNEWT.class.getResourceAsStream( "grayscale_texture.png" ); Assert.assertNotNull(grayTextureStream); { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_3-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamN_3 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamN_3); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_4-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscN_4-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamN_4 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamN_4); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscNG4-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscNG4-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamNG4 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamNG4); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscI_3-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscI_3-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamI_3 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamI_3); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscIG3-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscIG3-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamIG3 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamIG3); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscI_4-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscI_4-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamI_4 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamI_4); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscIG4-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscIG4-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamIG4 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamIG4); @@ -127,13 +127,13 @@ public class TestPNGTextureFromFileNEWT extends UITestCase { { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscP_3-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscP_3-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamP_3 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamP_3); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscP_4-01-160x90.png"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-ntscP_4-01-160x90.png", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStreamP_4 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStreamP_4); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java index 618797e66..653ccadfd 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java @@ -83,7 +83,7 @@ public class TestPixelFormatUtil01NEWT extends UITestCase { { System.err.println("Test01: "+pathname+basename+".png, srcFmt "+srcFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); - final URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png"); + final URLConnection urlConn = IOUtil.getResource(pathname+basename+".png", this.getClass().getClassLoader(), this.getClass()); final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), srcFmt, false /* directBuffer */, destMinStrideInBytes, false /* isGLOriented */); System.err.println("PNGPixelRect - Orig: "+image1); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java index 6e0af17da..23f4593d8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java @@ -69,19 +69,19 @@ public class TestTGATextureFromFileNEWT extends UITestCase { @Before public void initTest() throws IOException { { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-u32.tga"); + final URLConnection testTextureUrlConn = IOUtil.getResource("test-u32.tga", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream01U32 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream01U32); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug744-rle32.tga"); + final URLConnection testTextureUrlConn = IOUtil.getResource("bug744-rle32.tga", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream02RLE32 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream02RLE32); } { - final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug982.rle32.256x256.tga"); + final URLConnection testTextureUrlConn = IOUtil.getResource("bug982.rle32.256x256.tga", this.getClass().getClassLoader(), this.getClass()); Assert.assertNotNull(testTextureUrlConn); testTextureStream03RLE32 = testTextureUrlConn.getInputStream(); Assert.assertNotNull(testTextureStream03RLE32); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureIONEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureIONEWT.java new file mode 100644 index 000000000..56d9d481e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureIONEWT.java @@ -0,0 +1,165 @@ +/** + * Copyright 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 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.test.junit.jogl.util.texture; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.ImageType; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import org.junit.Assert; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTextureIONEWT extends UITestCase { + static long duration = 100; // ms + + ImageTstFiles imageTstFiles; + + @Before + public void initTest() throws IOException { + imageTstFiles = new ImageTstFiles(); + imageTstFiles.init(); + } + + @After + public void cleanupTest() { + imageTstFiles.clear(); + } + + public void testImpl(final List<ImageTstFiles.NamedInputStream> streams, final ImageType expImageType) throws InterruptedException, IOException { + for(int i=0; i<streams.size(); i++) { + final ImageTstFiles.NamedInputStream s = streams.get(i); + System.err.printf("Test %3d: path %s, exp-type %s%n", i, s.basePath, expImageType); + testImpl(s.stream, expImageType); + } + } + public void testImpl(final InputStream istream, final ImageType expImageType) throws InterruptedException, IOException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLProfile glp = GLProfile.isAvailable(GLProfile.GL2ES2) ? GLProfile.getGL2ES2() : GLProfile.getDefault(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(1); + + final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, expImageType.type); + System.err.println("TextureData: "+texData); + Assert.assertEquals(expImageType, texData.getSourceImageType()); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle("TestTextureIONEWT."+expImageType.type); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = glp.isGL2ES2() ? new TextureDraw01ES2Listener( texData, 0 ) : new TextureDraw01GL2Listener( texData ) ; + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(final GLAutoDrawable drawable) {} + + public void display(final GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(final GLAutoDrawable drawable) { } + @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + }); + + final Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, null); + final QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glad.destroy(); + } + + @Test + public void test01AllPNG() throws InterruptedException, IOException { + testImpl(imageTstFiles.pngStreams, new ImageType(ImageType.T_PNG)); + } + + @Test + public void test02AllJPG() throws InterruptedException, IOException { + testImpl(imageTstFiles.jpgStreams, new ImageType(ImageType.T_JPG)); + } + + @Test + public void test03AllTGA() throws InterruptedException, IOException { + testImpl(imageTstFiles.tgaStreams, new ImageType(ImageType.T_TGA)); + } + + @Test + public void test04AllDDS() throws InterruptedException, IOException { + testImpl(imageTstFiles.ddsStreams, new ImageType(ImageType.T_DDS)); + } + + public static void main(final String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestTextureIONEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestBug1211IRQ00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestBug1211IRQ00NEWT.java new file mode 100644 index 000000000..186c3a79a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestBug1211IRQ00NEWT.java @@ -0,0 +1,324 @@ +/** + * Copyright 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 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.test.junit.newt; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.SourcedInterruptedException; +import com.jogamp.common.util.VersionUtil; +import com.jogamp.junit.util.SingletonJunitCase; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Unit test to identify Thread.interrupt() caller for DefaultEDTUtil.invokeImpl(..) wait interruption. + * <ul> + * <li>resize</li> + * <li>create/destroy</li> + * </ul> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug1211IRQ00NEWT extends SingletonJunitCase { + static long durationTest00 = 1000; // ms + static long durationTest01 = 1000; // ms + static int width = 800; + static int height = 600; + + static GLWindow createWindow(final GLCapabilitiesImmutable caps) { + Assert.assertNotNull(caps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setSize(width, height); + + glWindow.setUpdateFPSFrames(1, null); + + final GearsES2 demo = new GearsES2(); + demo.setVerbose(false); + glWindow.addGLEventListener(demo); + + return glWindow; + } + + static void destroyWindow(final GLWindow glWindow) throws InterruptedException { + if(null!=glWindow) { + glWindow.destroy(); + Assert.assertEquals(false,glWindow.isNativeValid()); + } + } + + static class MyThread extends InterruptSource.Thread implements Thread.UncaughtExceptionHandler { + volatile boolean myThreadStarted = false; + volatile boolean myThreadStopped = false; + + public MyThread(final Runnable target, final String name) { + super(null, target, name); + setUncaughtExceptionHandler(this); + } + + public static void testInterrupted1() throws InterruptedException { + if( java.lang.Thread.interrupted() ) { + throw SourcedInterruptedException.wrap( + new InterruptedException(java.lang.Thread.currentThread().getName()+".testInterrupted -> TRUE (silent interruption)")); + } + } + public synchronized void testInterrupted(final boolean ignore) throws InterruptedException { + if( isInterrupted() ) { + final boolean current; + if( this == java.lang.Thread.currentThread() ) { + java.lang.Thread.interrupted(); // clear! + current = true; + } else { + current = false; + } + final int counter = getInterruptCounter(false); + final Throwable source = getInterruptSource(true); + final InterruptedException e = new SourcedInterruptedException( + getName()+".testInterrupted -> TRUE (current "+current+", counter "+counter+")", + null, source); + if( !ignore ) { + throw e; + } else { + ExceptionUtils.dumpThrowable("Ignored", e); + } + } + } + + @Override + public void run() { + myThreadStarted = true; + try { + super.run(); + } finally { + myThreadStopped = true; + } + } + + @Override + public void uncaughtException(final java.lang.Thread t, final Throwable e) { + System.err.println("UncaughtException on Thread "+t.getName()+": "+e.getMessage()); + ExceptionUtils.dumpThrowable("UncaughtException", e); + } + } + + + volatile boolean interrupt1 = false; + volatile boolean interrupt2 = false; + volatile boolean interruptInit0 = false; + + public void initTest() { + interrupt1 = false; + interrupt2 = false; + } + + /** + * Test whether resize triggers DefaultEDTUtil.invokeImpl(..) wait interruption. + */ + public void subTest00() { + final MyThread t = (MyThread)Thread.currentThread(); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + Assert.assertNotNull(caps); + final GLWindow window1 = createWindow(caps); // local + final EDTUtil edt = window1.getScreen().getDisplay().getEDTUtil(); + final Animator anim = new Animator(window1); + try { + window1.setVisible(true); + Assert.assertEquals(true,window1.isVisible()); + Assert.assertEquals(true,window1.isNativeValid()); + anim.start(); + boolean ok = true; + for(int i=0; ok && i*100<durationTest00; i++) { + Thread.sleep(100); + final int ow = window1.getWidth(); + final int oh = window1.getHeight(); + final int nw, nh; + if( 0 == i % 2 ) { + nw = ow + 100; + nh = oh + 100; + } else { + nw = ow - 100; + nh = oh - 100; + } + System.err.println("test00.resize["+i+"]: "+ow+"x"+oh+" -> "+nw+"x"+nh); + window1.setSize(nw, nh); + ok = 0==t.getInterruptCounter(false) && !t.isInterrupted() && edt.isRunning() && anim.isAnimating(); + t.testInterrupted(false); + } + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("InterruptedException-1", e); + interrupt1 = true; + } + try { + anim.stop(); + destroyWindow(window1); + t.testInterrupted(false); + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("InterruptedException-2", e); + interrupt2 = true; + } + Assert.assertEquals("interruptCounter not zero", 0, t.getInterruptCounter(false)); + Assert.assertFalse("interrupt() occured!", t.isInterrupted()); + Assert.assertFalse("Interrupt-1 occured!", interrupt1); + Assert.assertFalse("Interrupt-2 occured!", interrupt2); + } + + /** + * Test whether create/destroy triggers DefaultEDTUtil.invokeImpl(..) wait interruption. + */ + public void subTest01() { + final MyThread t = (MyThread)Thread.currentThread(); + GLWindow lastWindow = null; + try { + final boolean ok = true; + for(int i=0; ok && i*100<durationTest01; i++) { + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + Assert.assertNotNull(caps); + final GLWindow window1 = createWindow(caps); // local + lastWindow = window1; + window1.setVisible(true); + Assert.assertEquals(true,window1.isVisible()); + Assert.assertEquals(true,window1.isNativeValid()); + System.err.println("test01.create["+i+"]: "+window1.getStateMaskString()+", "+window1.getWidth()+"x"+window1.getHeight()); + final Animator anim = new Animator(window1); + anim.start(); + Thread.sleep(100); + anim.stop(); + destroyWindow(window1); + t.testInterrupted(false); + } + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("InterruptedException-1", e); + interrupt1 = true; + } + try { + destroyWindow(lastWindow); + t.testInterrupted(false); + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("InterruptedException-2", e); + interrupt2 = true; + } + Assert.assertEquals("interruptCounter not zero", 0, t.getInterruptCounter(false)); + Assert.assertFalse("interrupt() occured!", t.isInterrupted()); + Assert.assertFalse("Interrupt-1 occured!", interrupt1); + Assert.assertFalse("Interrupt-2 occured!", interrupt2); + } + + @Test + public void testAll() { + interruptInit0 = false; + final MyThread t = new MyThread(new Runnable() { + public void run() { + final MyThread t = (MyThread)Thread.currentThread(); + TestBug1211IRQ00NEWT test = null; + try { + System.err.println(VersionUtil.getPlatformInfo()); + GLProfile.initSingleton(); + test = new TestBug1211IRQ00NEWT(); + t.testInterrupted(false); + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("InterruptedException-Init0", e); + interruptInit0 = true; + test = null; + } + t.clearInterruptSource(); + if( null != test ) { + test.initTest(); + test.subTest00(); + + test.initTest(); + test.subTest01(); + } + } + }, "MyMainThread"); + t.start(); + boolean interrupted = false; + try { + MyThread.testInterrupted1(); + while( !t.myThreadStarted ) { + Thread.yield(); + MyThread.testInterrupted1(); + } + while( !t.myThreadStopped ) { + Thread.yield(); + MyThread.testInterrupted1(); + } + MyThread.testInterrupted1(); + } catch (final InterruptedException e) { + ExceptionUtils.dumpThrowable("InterruptedException-All", e); + interrupted = true; + } + Assert.assertFalse("Thread Interrupt-All occured!", interrupted); + Assert.assertFalse("Interrupt-Init0 occured!", interruptInit0); + } + + static int atoi(final String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (final Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(final String args[]) throws IOException { + // We like to allow concurrent manual tests! + SingletonJunitCase.enableSingletonLock(false); + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time00")) { + durationTest00 = atoi(args[++i]); + } else if(args[i].equals("-time01")) { + durationTest01 = atoi(args[++i]); + } else if(args[i].equals("-width")) { + width = atoi(args[++i]); + } else if(args[i].equals("-height")) { + height = atoi(args[++i]); + } + } + System.out.println("durationTest00: "+durationTest00); + System.out.println("durationTest01: "+durationTest01); + System.out.println("defaultSize : "+width+"x"+height); + final String tstname = TestBug1211IRQ00NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java index a93aaca79..c6dc81342 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java @@ -47,8 +47,9 @@ import com.jogamp.newt.Window; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.TestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestCloseNewtAWT extends UITestCase { @@ -112,11 +113,12 @@ public class TestCloseNewtAWT extends UITestCase { frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(newtWindow, true)); - final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + final GLWindow obj = newtWindow; + Assert.assertEquals(true, NewtTestUtil.waitForRealized(obj, true, null)); + final TestUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener, null)); } public static void main(final String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java index 4426a087b..62e3df992 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java @@ -43,9 +43,9 @@ import com.jogamp.newt.opengl.*; import java.io.IOException; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -147,8 +147,8 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { // destruction.. ref count down, but keep all window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(screen,window.getScreen()); Assert.assertEquals(0,Display.getActiveDisplayNumber()); @@ -195,8 +195,8 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { System.err.println("duration: "+window.getTotalFPSDuration()); window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(screen,window.getScreen()); Assert.assertEquals(false,window.isNativeValid()); @@ -300,7 +300,7 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { // destruction ... window1.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window1, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window1, false, null)); Assert.assertNotNull(window1.getScreen()); Assert.assertEquals(false,window1.isNativeValid()); @@ -317,8 +317,8 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { // destruction window2.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window2, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window2, false, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertNotNull(window2.getScreen()); Assert.assertEquals(false,window2.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java index 9dd96acdd..38620ad92 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java @@ -49,6 +49,8 @@ import com.jogamp.nativewindow.AbstractGraphicsDevice; public class TestGLWindows00NEWT extends UITestCase { static GLProfile glp; static int width, height; + static boolean manual = false; + static int loopVisibleToggle = 10; static long durationPerTest = 100; // ms @BeforeClass @@ -58,7 +60,7 @@ public class TestGLWindows00NEWT extends UITestCase { glp = GLProfile.getDefault(); } - static GLWindow createWindow(final Screen screen, final GLCapabilitiesImmutable caps) + static GLWindow createWindow(final Screen screen, final GLCapabilitiesImmutable caps, final boolean undecor) throws InterruptedException { Assert.assertNotNull(caps); @@ -78,7 +80,9 @@ public class TestGLWindows00NEWT extends UITestCase { final GLEventListener demo = new GearsES2(); glWindow.addGLEventListener(demo); + glWindow.setUndecorated(undecor); glWindow.setSize(512, 512); + System.err.println("XXX VISIBLE.0 -> TRUE"); glWindow.setVisible(true); Assert.assertEquals(true,glWindow.isVisible()); Assert.assertEquals(true,glWindow.isNativeValid()); @@ -90,25 +94,103 @@ public class TestGLWindows00NEWT extends UITestCase { if(null!=glWindow) { glWindow.destroy(); Assert.assertEquals(false,glWindow.isNativeValid()); + Assert.assertEquals(false,glWindow.isVisible()); } } @Test - public void testWindow00() throws InterruptedException { + public void test01WindowCreateSimple() throws InterruptedException { + if( manual ) { + return; + } final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); - final GLWindow window1 = createWindow(null, caps); // local - Assert.assertEquals(true,window1.isNativeValid()); - Assert.assertEquals(true,window1.isVisible()); - final AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice(); + final GLWindow window = createWindow(null, caps, false /* undecor */); // local + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + final AbstractGraphicsDevice device1 = window.getScreen().getDisplay().getGraphicsDevice(); System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1)); for(int state=0; state*100<durationPerTest; state++) { Thread.sleep(100); } - destroyWindow(window1); + destroyWindow(window); + } + + @Test + public void test02WindowCreateUndecor() throws InterruptedException { + if( manual ) { + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final GLWindow window = createWindow(null, caps, true /* undecor */); // local + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + final AbstractGraphicsDevice device1 = window.getScreen().getDisplay().getGraphicsDevice(); + System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1)); + + for(int state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + + destroyWindow(window); + } + + @Test + public void test11WindowSimpleToggleVisibility() throws InterruptedException { + test1xWindowToggleVisibility(false /* undecor */, loopVisibleToggle); + } + @Test + public void test12WindowUndecorToggleVisibility() throws InterruptedException { + if( manual ) { + return; + } + test1xWindowToggleVisibility(true /* undecor */, loopVisibleToggle); + } + private void test1xWindowToggleVisibility(final boolean undecor, final int loopVisibleToggle) throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final GLWindow window = createWindow(null, caps, undecor); // local + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + window.display(); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + for(int state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + + for(int i=1; i<=loopVisibleToggle; i++) { + System.err.println("XXX VISIBLE."+i+" -> FALSE"); + window.setVisible(false); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + for(int state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + + window.display(); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + + System.err.println("XXX VISIBLE."+i+" -> TRUE"); + window.setVisible(true); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + for(int state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + window.display(); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + } + + destroyWindow(window); } static int atoi(final String a) { @@ -123,6 +205,10 @@ public class TestGLWindows00NEWT extends UITestCase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { durationPerTest = atoi(args[++i]); + } else if(args[i].equals("-loopvt")) { + loopVisibleToggle = atoi(args[++i]); + } else if(args[i].equals("-manual")) { + manual = true; } } System.out.println("durationPerTest: "+durationPerTest); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java index ab8304504..00b31f400 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java @@ -59,8 +59,7 @@ public class TestGLWindows01NEWT extends UITestCase { } static GLWindow createWindow(final Screen screen, final GLCapabilities caps, - final int width, final int height, final boolean onscreen, final boolean undecorated, - final boolean addGLEventListenerAfterVisible) + final int width, final int height, final boolean onscreen, final boolean addGLEventListenerAfterVisible) throws InterruptedException { Assert.assertNotNull(caps); @@ -79,7 +78,6 @@ public class TestGLWindows01NEWT extends UITestCase { Assert.assertNotNull(glWindow); } - glWindow.setUndecorated(onscreen && undecorated); Assert.assertEquals(false,glWindow.isVisible()); Assert.assertEquals(false,glWindow.isNativeValid()); @@ -122,16 +120,47 @@ public class TestGLWindows01NEWT extends UITestCase { if(null!=glWindow) { glWindow.destroy(); Assert.assertEquals(false,glWindow.isNativeValid()); + Assert.assertEquals(false,glWindow.isVisible()); } } + + @Test + public void test01WindowSimple() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final GLWindow window = createWindow(null, caps, width, height, + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); + System.out.println("Created: "+window); + int state; + for(state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + System.out.println("duration: "+window.getTotalFPSDuration()); + destroyWindow(window); + } + + @Test + public void test02WindowSimple() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final GLWindow window = createWindow(null, caps, width, height, + true /* onscreen */, true /*addGLEventListenerAfterVisible*/); + System.out.println("Created: "+window); + int state; + for(state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + System.out.println("duration: "+window.getTotalFPSDuration()); + destroyWindow(window); + } + @Test - public void testWindowNativeRecreate01aSimple() throws InterruptedException { + public void test10WindowNativeRecreateSimple() throws InterruptedException { final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); final GLWindow window = createWindow(null, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); @@ -155,12 +184,11 @@ public class TestGLWindows01NEWT extends UITestCase { } @Test - public void testWindowNativeRecreate01bSimple() throws InterruptedException { + public void test11WindowNativeRecreateSimple() throws InterruptedException { final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); final GLWindow window = createWindow(null, caps, width, height, - true /* onscreen */, false /* undecorated */, - true /*addGLEventListenerAfterVisible*/); + true /* onscreen */, true /*addGLEventListenerAfterVisible*/); Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); @@ -184,44 +212,11 @@ public class TestGLWindows01NEWT extends UITestCase { } @Test - public void testWindowDecor01aSimple() throws InterruptedException { - final GLCapabilities caps = new GLCapabilities(glp); - Assert.assertNotNull(caps); - final GLWindow window = createWindow(null, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); - System.out.println("Created: "+window); - int state; - for(state=0; state*100<durationPerTest; state++) { - Thread.sleep(100); - } - System.out.println("duration: "+window.getTotalFPSDuration()); - destroyWindow(window); - } - - @Test - public void testWindowDecor01bSimple() throws InterruptedException { - final GLCapabilities caps = new GLCapabilities(glp); - Assert.assertNotNull(caps); - final GLWindow window = createWindow(null, caps, width, height, - true /* onscreen */, false /* undecorated */, - true /*addGLEventListenerAfterVisible*/); - System.out.println("Created: "+window); - int state; - for(state=0; state*100<durationPerTest; state++) { - Thread.sleep(100); - } - System.out.println("duration: "+window.getTotalFPSDuration()); - destroyWindow(window); - } - - @Test - public void testWindowDecor02DestroyWinTwiceA() throws InterruptedException { + public void test21WindowDestroyWinTwiceA() throws InterruptedException { final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); final GLWindow window = createWindow(null, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); int state; for(state=0; state*100<durationPerTest; state++) { Thread.sleep(100); @@ -231,7 +226,7 @@ public class TestGLWindows01NEWT extends UITestCase { } @Test - public void testWindowDecor03TwoWinOneDisplay() throws InterruptedException { + public void test22WindowTwoWinOneDisplay() throws InterruptedException { final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); @@ -241,13 +236,11 @@ public class TestGLWindows01NEWT extends UITestCase { final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 Assert.assertNotNull(screen); final GLWindow window1 = createWindow(screen, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); Assert.assertNotNull(window1); final GLWindow window2 = createWindow(screen, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); Assert.assertNotNull(window2); Assert.assertEquals(1,Display.getActiveDisplayNumber()); @@ -281,7 +274,7 @@ public class TestGLWindows01NEWT extends UITestCase { } @Test - public void testWindowDecor03TwoWinTwoDisplays() throws InterruptedException { + public void test23WindowTwoWinTwoDisplays() throws InterruptedException { final GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); @@ -294,15 +287,13 @@ public class TestGLWindows01NEWT extends UITestCase { final Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0 Assert.assertNotNull(screen1); final GLWindow window1 = createWindow(screen1, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); Assert.assertNotNull(window1); final Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0 Assert.assertNotNull(screen2); final GLWindow window2 = createWindow(screen2, caps, width, height, - true /* onscreen */, false /* undecorated */, - false /*addGLEventListenerAfterVisible*/); + true /* onscreen */, false /*addGLEventListenerAfterVisible*/); Assert.assertNotNull(window2); Assert.assertEquals(2,Display.getActiveDisplayNumber()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java index 2220fbcd9..1817334e8 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java @@ -135,9 +135,9 @@ public class TestMultipleNewtCanvasAWT extends UITestCase { } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent2, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent1, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent2, true, null)); animator.start(); @@ -157,9 +157,9 @@ public class TestMultipleNewtCanvasAWT extends UITestCase { frame.dispose(); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent1, false)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent2, false)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent1, false, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent2, false, null)); } static int atoi(final String a) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java index 0ef554ec2..8e2d191b2 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java @@ -46,8 +46,8 @@ import com.jogamp.newt.Display; import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; @@ -94,7 +94,7 @@ public class TestWindowAndPointerIconNEWT extends SingletonJunitCase { final int idx = 0; { PointerIcon _pointerIcon = null; - final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } ); + final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-red-alpha-64x64.png" }, glWindow.getClass().getClassLoader(), null); try { _pointerIcon = disp.createPointerIcon(res, 0, 0); System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString()); @@ -126,7 +126,7 @@ public class TestWindowAndPointerIconNEWT extends SingletonJunitCase { glWindow.destroy(); if( NativeWindowFactory.isAWTAvailable() ) { - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java index 57f87ab97..8cf7c500e 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java @@ -46,8 +46,9 @@ import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.TestUtil; +import com.jogamp.opengl.test.junit.util.TestUtil.WindowClosingListener; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestWindowClosingProtocol01AWT extends UITestCase { @@ -55,7 +56,7 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { @Test public void testCloseFrameGLCanvas() throws InterruptedException, InvocationTargetException { final Frame frame = new Frame("testCloseFrameGLCanvas AWT"); - final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); + final TestUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); final GLProfile glp = GLProfile.getGL2ES2(); final GLCapabilities caps = new GLCapabilities(glp); final GLCanvas glCanvas = new GLCanvas(caps); @@ -68,8 +69,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { frame.validate(); frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); // // close with op: DO_NOTHING_ON_CLOSE -> NOP (default) @@ -77,7 +78,7 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { WindowClosingMode op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // nop + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener, null)); // nop Thread.sleep(100); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); @@ -95,7 +96,7 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // no frame close, but GLCanvas's GL resources will be destroyed + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener, null)); // no frame close, but GLCanvas's GL resources will be destroyed Thread.sleep(100); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); @@ -115,7 +116,7 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { @Test public void testCloseJFrameGLCanvas() throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("testCloseJFrameGLCanvas AWT"); - final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); + final TestUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); final GLProfile glp = GLProfile.getGL2ES2(); final GLCapabilities caps = new GLCapabilities(glp); @@ -129,8 +130,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { frame.validate(); frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); // // close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default) @@ -141,8 +142,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // hide - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener, null)); // hide + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false, null)); // hide -> invisible Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(true, glCanvas.isValid()); @@ -152,8 +153,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { public void run() { frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true, null)); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); @@ -165,8 +166,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener, null)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false, null)); Assert.assertEquals(false, frame.isDisplayable()); Assert.assertEquals(false, glCanvas.isValid()); Assert.assertEquals(false, glCanvas.isDisplayable()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java index 8b639d5da..232d333c3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java @@ -44,7 +44,8 @@ import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.TestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -55,7 +56,7 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { final GLProfile glp = GLProfile.getGL2ES2(); final GLCapabilities caps = new GLCapabilities(glp); final GLWindow glWindow = GLWindow.create(caps); - final AWTRobotUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(glWindow); + final TestUtil.WindowClosingListener closingListener = NewtTestUtil.addClosingListener(glWindow); glWindow.addGLEventListener(new GearsES2()); glWindow.setSize(512, 512); @@ -75,7 +76,7 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false, closingListener)); // nop + Assert.assertEquals(true, NewtTestUtil.closeWindow(glWindow, false, closingListener, null)); // nop Assert.assertEquals(true, glWindow.isNativeValid()); Assert.assertEquals(true, closingListener.isWindowClosing()); closingListener.reset(); @@ -87,7 +88,7 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { op = glWindow.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true, closingListener)); + Assert.assertEquals(true, NewtTestUtil.closeWindow(glWindow, true, closingListener, null)); Assert.assertEquals(false, glWindow.isNativeValid()); Assert.assertEquals(true, closingListener.isWindowClosing()); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java index 1859a8f87..24a6c58bf 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java @@ -47,8 +47,9 @@ import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.TestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestWindowClosingProtocol03NewtAWT extends UITestCase { @@ -56,12 +57,12 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { @Test public void testCloseJFrameNewtCanvasAWT() throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("testCloseJFrameNewtCanvasAWT"); - final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); + final TestUtil.WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); final GLProfile glp = GLProfile.getGL2ES2(); final GLCapabilities caps = new GLCapabilities(glp); final GLWindow glWindow = GLWindow.create(caps); - final AWTRobotUtil.WindowClosingListener newtClosingListener = AWTRobotUtil.addClosingListener(glWindow); + final TestUtil.WindowClosingListener newtClosingListener = NewtTestUtil.addClosingListener(glWindow); glWindow.addGLEventListener(new GearsES2()); @@ -75,8 +76,8 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { frame.validate(); frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); Assert.assertEquals(true, newtCanvas.isValid()); @@ -94,8 +95,8 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, awtClosingListener)); // hide - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, awtClosingListener, null)); // hide + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false, null)); // hide -> invisible Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(true, newtCanvas.isValid()); @@ -112,8 +113,8 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { public void run() { frame.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); @@ -129,8 +130,8 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, awtClosingListener)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, awtClosingListener, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); Assert.assertEquals(false, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(false, newtCanvas.isValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows02NEWT.java new file mode 100644 index 000000000..5cdb7e118 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows02NEWT.java @@ -0,0 +1,158 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.newt; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.nativewindow.*; + +import com.jogamp.newt.*; +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestWindows02NEWT extends UITestCase { + static int width, height; + static long durationPerTest = 100; // ms + + @BeforeClass + public static void initClass() { + NativeWindowFactory.initSingleton(); + width = 800; + height = 600; + } + + static Window createWindow(final Capabilities caps, final int x, final int y, final int width, final int height, final boolean onscreen, final boolean undecorated) throws InterruptedException { + final boolean userPos = x>=0 && y>=0 ; // user has specified a position + + Assert.assertNotNull(caps); + caps.setOnscreen(onscreen); + // System.out.println("Requested: "+caps); + + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(caps); + Assert.assertNotNull(window); + final Screen screen = window.getScreen(); + final Display display = screen.getDisplay(); + window.setUndecorated(onscreen && undecorated); + if(userPos) { + window.setPosition(x, y); + } + window.setSize(width, height); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + window.setVisible(true); + // System.err.println("************* Created: "+window); + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(width, window.getWidth()); + Assert.assertEquals(height, window.getHeight()); + + final CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities(); + Assert.assertNotNull(chosenCapabilities); + Assert.assertTrue(chosenCapabilities.getGreenBits()>=5); + Assert.assertTrue(chosenCapabilities.getBlueBits()>=5); + Assert.assertTrue(chosenCapabilities.getRedBits()>=5); + Assert.assertEquals(chosenCapabilities.isOnscreen(),onscreen); + + return window; + } + + static void destroyWindow(final Window window, final boolean last) { + if(null==window) { + return; + } + final Screen screen = window.getScreen(); + final Display display = screen.getDisplay(); + window.destroy(); + // System.err.println("************* Destroyed: "+window); + if(last) { + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,display.isNativeValid()); + } else { + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,display.isNativeValid()); + } + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + } + + + @Test + public void test01WindowDefault() throws InterruptedException { + final Capabilities caps = new Capabilities(); + Assert.assertNotNull(caps); + + final Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */); + final CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities(); + System.err.println("XXX: "+chosenCapabilities); + for(int state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + destroyWindow(window, true); + } + + @Test + public void test02WindowDefault() throws InterruptedException { + final Capabilities caps = new Capabilities(); + Assert.assertNotNull(caps); + caps.setBackgroundOpaque(false); + + final Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */); + final CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities(); + System.err.println("XXX: "+chosenCapabilities); + for(int state=0; state*100<durationPerTest; state++) { + Thread.sleep(100); + } + destroyWindow(window, true); + } + + public static void main(final String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + System.out.println("durationPerTest: "+durationPerTest); + final String tstname = TestWindows02NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java index 39c6c9f4d..5f88d1c6f 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java @@ -40,6 +40,7 @@ import org.junit.FixMethodOrder; import org.junit.Test ; import org.junit.runners.MethodSorters; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.event.MouseEvent; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; @@ -344,20 +345,17 @@ public abstract class BaseNewtEventModifiers extends UITestCase { } _testMouseListener.setModifierCheckEnabled( true ) ; - Throwable throwable = null; // final Object sync = new Object(); final RunnableTask rt = new RunnableTask( testAction, null, true, System.err ); try { // synchronized(sync) { - new Thread(rt, "Test-Thread").start(); + new InterruptSource.Thread(null, rt, "Test-Thread").start(); int i=0; - while( !rt.isExecuted() && null == throwable ) { + while( rt.isInQueue() ) { System.err.println("WAIT-till-done: eventDispatch() #"+i++); eventDispatch(); } - if(null==throwable) { - throwable = rt.getThrowable(); - } + final Throwable throwable = rt.getThrowable(); if(null!=throwable) { throw new RuntimeException(throwable); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java index 8cc266147..8f58ec7d9 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java @@ -73,9 +73,9 @@ public class TestNewtEventModifiersAWTCanvas extends BaseNewtEventModifiers { _testFrame.setVisible( true ) ; } }) ; - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(canvas, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(canvas, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(canvas, true, null)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(canvas, true, null)); AWTRobotUtil.assertRequestFocusAndWait(null, canvas, canvas, null, null); // programmatic Assert.assertNotNull(_robot); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java index 3db61b37b..7b45e590b 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java @@ -40,6 +40,7 @@ import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; /** * Test whether or not event modifiers are properly delivered by NEWT. @@ -61,8 +62,9 @@ public class TestNewtEventModifiersNEWTWindowAWT extends BaseNewtEventModifiers _glWindow.setPosition(TEST_FRAME_X, TEST_FRAME_Y); _glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(_glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(_glWindow, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(_glWindow, true, null)); + final GLWindow obj = _glWindow; + Assert.assertTrue(NewtTestUtil.waitForRealized(obj, true, null)); AWTRobotUtil.assertRequestFocusAndWait(null, _glWindow, _glWindow, null, null); // programmatic Assert.assertNotNull(_robot); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java index 1d19f527f..0fb34a062 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java @@ -47,6 +47,7 @@ import com.jogamp.newt.awt.NewtCanvasAWT ; import com.jogamp.newt.opengl.GLWindow ; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; /** * Test whether or not event modifiers are preserved by NEWT when @@ -83,9 +84,10 @@ public class TestNewtEventModifiersNewtCanvasAWT extends BaseNewtEventModifiers _testFrame.setVisible( true ) ; } } ) ; - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(_glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(_glWindow, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(_glWindow, true, null)); + final GLWindow obj = _glWindow; + Assert.assertTrue(NewtTestUtil.waitForRealized(obj, true, null)); AWTRobotUtil.assertRequestFocusAndWait(null, _glWindow, _glWindow, null, null); // programmatic Assert.assertNotNull(_robot); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java index 0b96f92b9..40ae3d29d 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java @@ -127,7 +127,7 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase { frame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); testImpl(glWindow); @@ -253,7 +253,7 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase { glWindow1KA.setVerbose(false); glWindow.addKeyListener(glWindow1KA); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); // Continuous animation .. final Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java index 60ea0e570..821063ee5 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java @@ -122,7 +122,7 @@ public class TestNewtKeyCodesAWT extends UITestCase { frame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); testImpl(glWindow); @@ -243,7 +243,7 @@ public class TestNewtKeyCodesAWT extends UITestCase { glWindow1KA.setVerbose(false); glWindow.addKeyListener(glWindow1KA); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); // Continuous animation .. final Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java index 112a7453d..e48193ed0 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java @@ -137,7 +137,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { frame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); testImpl(glWindow); @@ -261,7 +261,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { glWindow1KA.setVerbose(false); glWindow.addKeyListener(glWindow1KA); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); // Continuous animation .. final Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java index e3fa18ae4..c4fee01f0 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java @@ -126,7 +126,7 @@ public class TestNewtKeyEventOrderAWT extends UITestCase { frame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); testImpl(glWindow); @@ -210,7 +210,7 @@ public class TestNewtKeyEventOrderAWT extends UITestCase { glWindow1KA.setVerbose(false); glWindow.addKeyListener(glWindow1KA); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); // Continuous animation .. final Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java index e951ba2ee..87dc1576d 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java @@ -121,7 +121,7 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase { frame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); testImpl(glWindow); @@ -166,7 +166,7 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase { final SimpleKeyPressRelease simpleKeyPressRelease = new SimpleKeyPressRelease(); glWindow.addKeyListener(simpleKeyPressRelease); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); // Continuous animation .. final Animator animator = new Animator(glWindow); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java index d5ce78ce5..d3728e2be 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java @@ -147,8 +147,8 @@ public class TestParentingFocus01SwingAWTRobot extends UITestCase { public void run() { frame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null)); AWTRobotUtil.clearAWTFocus(robot); Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1)); @@ -188,7 +188,7 @@ public class TestParentingFocus01SwingAWTRobot extends UITestCase { // Should be OK to have the AWT component assume it also has the focus. // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); - if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) { + if( !TestUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA, null) ) { System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA); } System.err.println("FOCUS NEWT Canvas/GLWindow sync"); @@ -217,7 +217,7 @@ public class TestParentingFocus01SwingAWTRobot extends UITestCase { Assume.assumeNoException( throwable ); } glWindow1.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, false, null)); } static int atoi(final String a) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java index f9ae91fc8..b6a95caff 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java @@ -171,8 +171,8 @@ public class TestParentingFocus02SwingAWTRobot extends UITestCase { public void run() { jFrame1.setVisible(true); } } ); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(jFrame1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(jFrame1, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null)); AWTRobotUtil.clearAWTFocus(robot); Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, jFrame1)); @@ -212,7 +212,7 @@ public class TestParentingFocus02SwingAWTRobot extends UITestCase { // Should be OK to have the AWT component assume it also has the focus. // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); - if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) { + if( !TestUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA, null) ) { System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA); } Assert.assertEquals(false, buttonNorthInnerFA.focusGained()); @@ -252,7 +252,7 @@ public class TestParentingFocus02SwingAWTRobot extends UITestCase { // Should be OK to have the AWT component assume it also has the focus. // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); - if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) { + if( !TestUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA, null) ) { System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA); } @@ -280,7 +280,7 @@ public class TestParentingFocus02SwingAWTRobot extends UITestCase { } }); glWindow1.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, false)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, false, null)); } @Test diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java index cade05478..14cb9065e 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java @@ -53,6 +53,7 @@ import com.jogamp.opengl.*; import com.jogamp.opengl.util.Animator; import com.jogamp.newt.*; import com.jogamp.newt.opengl.*; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -64,12 +65,19 @@ import jogamp.newt.driver.DriverClearFocus; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; +import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter; /** * Testing focus <i>key</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached. * <p> * {@link Frame} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ] * </p> + * <p> + * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}, and many more, see {@link #main(String[])} + * </p> */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParentingFocus03KeyTraversalAWT extends UITestCase { @@ -154,7 +162,7 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { final GLEventListener demo1 = new GearsES2(1); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null)); + glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1)); glWindow1.addKeyListener(new KeyAdapter() { public void keyReleased(final KeyEvent e) { if( !e.isPrintableKey() || e.isAutoRepeat() ) { @@ -203,8 +211,8 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { frame1.validate(); frame1.setVisible(true); }}); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow1, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null)); Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent()); AWTRobotUtil.clearAWTFocus(robot); Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1)); @@ -228,14 +236,14 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { // bWest -> glWin AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, cWest, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); + Assert.assertTrue("Did not gain focus", NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA, null)); Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bWestFA.focusLost()); Thread.sleep(durationPerTest/numFocus); // glWin -> bEast AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, glWindow1, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA, null)); Assert.assertEquals(true, bEastFA.focusGained()); Assert.assertEquals(true, glWindow1FA.focusLost()); Thread.sleep(durationPerTest/numFocus); @@ -245,13 +253,13 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { // // bEast -> glWin AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, cEast, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA)); + Assert.assertTrue("Did not gain focus", NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA, null)); Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bEastFA.focusLost()); Thread.sleep(durationPerTest/numFocus); AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, glWindow1, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA, null)); Assert.assertEquals(true, bWestFA.focusGained()); Assert.assertEquals(true, glWindow1FA.focusLost()); Thread.sleep(durationPerTest/numFocus); @@ -264,7 +272,7 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { } }); } catch (final Exception ex) { ex.printStackTrace(); } - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); + Assert.assertTrue("Did not gain focus", NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA, null)); Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bWestFA.focusLost()); Thread.sleep(durationPerTest/numFocus); @@ -277,7 +285,7 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { } }); } catch (final Exception ex) { ex.printStackTrace(); } - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA, null)); Assert.assertEquals(true, bWestFA.focusGained()); Assert.assertEquals(true, glWindow1FA.focusLost()); Thread.sleep(durationPerTest/numFocus); @@ -287,7 +295,7 @@ public class TestParentingFocus03KeyTraversalAWT extends UITestCase { { // Short: Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); // More verbose: - final boolean ok = AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA); + final boolean ok = NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA, null); System.err.println("glWindow hasFocus "+glWindow1.hasFocus()); System.err.println("glWindow1FA "+glWindow1FA); System.err.println("bWestFA "+bWestFA); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java index ac8d28427..b4b640280 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java @@ -44,7 +44,7 @@ import com.jogamp.newt.Screen; import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -119,7 +119,7 @@ public class TestScreenMode00bNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java index deab32e03..31a16b8c6 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java @@ -49,8 +49,8 @@ import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; @@ -110,7 +110,7 @@ public class TestScreenMode00cNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java index 353856fe5..ab8ad8661 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java @@ -49,8 +49,8 @@ import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; @@ -111,7 +111,7 @@ public class TestScreenMode01aNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); } } @@ -219,7 +219,7 @@ public class TestScreenMode01aNEWT extends UITestCase { Assert.assertEquals(false,window0.isVisible()); Assert.assertEquals(false,window0.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java index 29068afca..60d61f905 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java @@ -49,8 +49,8 @@ import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -105,7 +105,7 @@ public class TestScreenMode01bNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); } } @@ -121,7 +121,7 @@ public class TestScreenMode01bNEWT extends UITestCase { testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY()); } finally { screen.removeReference(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); } } @@ -141,7 +141,7 @@ public class TestScreenMode01bNEWT extends UITestCase { testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY()); } finally { screen.removeReference(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java index 06173a9f1..61a8527a7 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java @@ -48,8 +48,8 @@ import com.jogamp.newt.Window; import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -105,7 +105,7 @@ public class TestScreenMode01cNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - AWTRobotUtil.waitForRealized(window, false); // don't override a previous assertion failure + NewtTestUtil.waitForRealized(window, false, null); // don't override a previous assertion failure } } @@ -121,7 +121,7 @@ public class TestScreenMode01cNEWT extends UITestCase { testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null); } finally { screen.removeReference(); - AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure + NewtTestUtil.waitForRealized(screen, false, null); // don't override a previous assertion failure } } @@ -141,7 +141,7 @@ public class TestScreenMode01cNEWT extends UITestCase { testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null); } finally { screen.removeReference(); - AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure + NewtTestUtil.waitForRealized(screen, false, null); // don't override a previous assertion failure } } @@ -164,7 +164,7 @@ public class TestScreenMode01cNEWT extends UITestCase { testScreenFullscreenImpl(screen, monitorVp.getX()+50, monitorVp.getY()+50, true, monitors); } finally { screen.removeReference(); - AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure + NewtTestUtil.waitForRealized(screen, false, null); // don't override a previous assertion failure } } @@ -184,7 +184,7 @@ public class TestScreenMode01cNEWT extends UITestCase { testScreenFullscreenImpl(screen, monitorVp.getX()-50, monitorVp.getY()+50, true, null); } finally { screen.removeReference(); - AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure + NewtTestUtil.waitForRealized(screen, false, null); // don't override a previous assertion failure } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java index 3247b87ac..7b22dea65 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java @@ -50,7 +50,7 @@ import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; @@ -142,7 +142,7 @@ public class TestScreenMode01dNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); } } @@ -189,7 +189,7 @@ public class TestScreenMode01dNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isRealized()); Assert.assertEquals(false,window.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); @@ -279,7 +279,7 @@ public class TestScreenMode01dNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isRealized()); Assert.assertEquals(false,window.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); @@ -386,7 +386,7 @@ public class TestScreenMode01dNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isRealized()); Assert.assertEquals(false,window.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java index 90952f502..d512df3d7 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java @@ -50,7 +50,7 @@ import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; import com.jogamp.nativewindow.util.Dimension; @@ -92,7 +92,7 @@ public class TestScreenMode02aNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); } } @@ -240,7 +240,7 @@ public class TestScreenMode02aNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java index 11e863217..8388a9ad0 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java @@ -49,7 +49,7 @@ import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -106,7 +106,7 @@ public class TestScreenMode02bNEWT extends UITestCase { static void destroyWindow(final Window window) throws InterruptedException { if(null!=window) { window.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, false, null)); } } @@ -249,7 +249,7 @@ public class TestScreenMode02bNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isNativeValid()); - Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertTrue(NewtTestUtil.waitForRealized(screen, false, null)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java index ae873eaf0..7e92c8438 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java @@ -1,5 +1,5 @@ /** - * Copyright 2011 JogAmp Community. All rights reserved. + * Copyright 2011, 2019 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: @@ -30,94 +30,37 @@ package com.jogamp.opengl.test.junit.newt.parenting; import java.awt.Frame; import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.NativeWindow; +import com.jogamp.nativewindow.NativeWindowHolder; import com.jogamp.nativewindow.util.InsetsImmutable; import com.jogamp.newt.Window; -import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.util.NEWTDemoListener; -import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.newt.opengl.util.NEWTDemoListener; -public class NewtAWTReparentingKeyAdapter extends NEWTDemoListener { +/** + * AWT specializing demo functionality of {@link NewtReparentingKeyAdapter}, includes {@link NEWTDemoListener}. + */ +public class NewtAWTReparentingKeyAdapter extends NewtReparentingKeyAdapter { final Frame frame; - final NewtCanvasAWT newtCanvasAWT; - public NewtAWTReparentingKeyAdapter(final Frame frame, final NewtCanvasAWT newtCanvasAWT, final GLWindow glWindow, final QuitAdapter quitAdapter) { - super(glWindow, quitAdapter, null); + public NewtAWTReparentingKeyAdapter(final Frame frame, final NativeWindowHolder winHolder, final GLWindow glWindow) { + super(winHolder, glWindow); this.frame = frame; - this.newtCanvasAWT = newtCanvasAWT; - } - - public void keyPressed(final KeyEvent e) { - if( e.isAutoRepeat() || e.isConsumed() ) { - return; - } - if( 0 == e.getModifiers() ) { // all modifiers go to super class .. - final int keySymbol = e.getKeySymbol(); - switch (keySymbol) { - case KeyEvent.VK_L: - e.setConsumed(true); - final com.jogamp.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null); - final com.jogamp.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null); - printlnState("[location]", "AWT "+p0+", NEWT "+p1); - break; - case KeyEvent.VK_R: - e.setConsumed(true); - quitAdapterOff(); - new Thread() { - public void run() { - final Thread t = glWindow.setExclusiveContextThread(null); - if(glWindow.getParent()==null) { - printlnState("[reparent pre - glWin to HOME]"); - glWindow.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */); - } else { - if( null != frame ) { - final InsetsImmutable nInsets = glWindow.getInsets(); - final java.awt.Insets aInsets = frame.getInsets(); - int dx, dy; - if( nInsets.getTotalHeight()==0 ) { - dx = aInsets.left; - dy = aInsets.top; - } else { - dx = nInsets.getLeftWidth(); - dy = nInsets.getTopHeight(); - } - final int topLevelX = frame.getX()+frame.getWidth()+dx; - final int topLevelY = frame.getY()+dy; - printlnState("[reparent pre - glWin to TOP.1]", topLevelX+"/"+topLevelY+" - insets " + nInsets + ", " + aInsets); - glWindow.reparentWindow(null, topLevelX, topLevelY, 0 /* hint */); - } else { - printlnState("[reparent pre - glWin to TOP.0]"); - glWindow.reparentWindow(null, -1, -1, 0 /* hints */); - } - } - printlnState("[reparent post]"); - glWindow.requestFocus(); - glWindow.setExclusiveContextThread(t); - quitAdapterOn(); - } }.start(); - break; - } - } - super.keyPressed(e); } @Override public void setTitle() { - setTitle(frame, newtCanvasAWT, glWindow); + setTitle(frame, winHolder.getNativeWindow(), glWindow); } - public static void setTitle(final Frame frame, final NewtCanvasAWT glc, final Window win) { + public void setTitle(final Frame frame, final NativeWindow nw, final Window win) { final CapabilitiesImmutable chosenCaps = win.getChosenCapabilities(); final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities(); final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps; final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; { - final java.awt.Rectangle b = glc.getBounds(); - frame.setTitle("NewtCanvasAWT["+capsA+"], win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getNativeWindow().getSurfaceWidth()+"x"+glc.getNativeWindow().getSurfaceHeight()); + frame.setTitle("Frame["+capsA+"], win: "+getNativeWinTitle(nw)); } - final float[] sDPI = win.getPixelsPerMM(new float[2]); - sDPI[0] *= 25.4f; - sDPI[1] *= 25.4f; - win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); + super.setTitle(nw, win); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtJFXReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtJFXReparentingKeyAdapter.java new file mode 100644 index 000000000..3ed847ae3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtJFXReparentingKeyAdapter.java @@ -0,0 +1,102 @@ +/** + * Copyright 2019 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.test.junit.newt.parenting; + +import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.NativeWindow; +import com.jogamp.nativewindow.NativeWindowHolder; +import com.jogamp.nativewindow.util.Insets; +import com.jogamp.nativewindow.util.InsetsImmutable; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; + +import javafx.geometry.Bounds; + +/** + * JavaFX specializing demo functionality of {@link NewtReparentingKeyAdapter}, includes {@link NEWTDemoListener}. + */ +public class NewtJFXReparentingKeyAdapter extends NewtReparentingKeyAdapter { + final javafx.stage.Stage frame; + + public NewtJFXReparentingKeyAdapter(final javafx.stage.Stage frame, final NativeWindowHolder winHolder, final GLWindow glWindow) { + super(winHolder, glWindow); + this.frame = frame; + } + + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() || e.isConsumed() ) { + return; + } + if( 0 == e.getModifiers() ) { // all modifiers go to super class .. + final int keySymbol = e.getKeySymbol(); + switch (keySymbol) { + case KeyEvent.VK_R: + e.setConsumed(true); + quitAdapterOff(); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + final java.lang.Thread t = glWindow.setExclusiveContextThread(null); + if(glWindow.getParent()==null) { + printlnState("[reparent pre - glWin to HOME: child pos "+winHolder.getNativeWindow().getX()+"/"+winHolder.getNativeWindow().getY()+"]"); + glWindow.reparentWindow(winHolder.getNativeWindow(), winHolder.getNativeWindow().getX(), winHolder.getNativeWindow().getY(), 0 /* hints */); + glWindow.setPosition(winHolder.getNativeWindow().getX(), winHolder.getNativeWindow().getY()); + } else { + final com.jogamp.nativewindow.util.Point p0 = winHolder.getNativeWindow().getLocationOnScreen(null); + final com.jogamp.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null); + printlnState("[reparent pre - glWin to TOP.1] frame ", p0+", glWindow "+p1); + glWindow.reparentWindow(null, p1.getX(), p1.getY(), 0 /* hint */); + } + printlnState("[reparent post]"); + glWindow.requestFocus(); + glWindow.setExclusiveContextThread(t); + quitAdapterOn(); + } } ); + break; + } + } + super.keyPressed(e); + } + + @Override + public void setTitle() { + setTitle(frame, winHolder.getNativeWindow(), glWindow); + } + public void setTitle(final javafx.stage.Stage frame, final NativeWindow nw, final Window win) { + final CapabilitiesImmutable chosenCaps = win.getChosenCapabilities(); + final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities(); + final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps; + final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; + { + frame.setTitle("Frame["+capsA+"], win: "+getNativeWinTitle(nw)); + } + super.setTitle(nw, win); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java new file mode 100644 index 000000000..339230d48 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java @@ -0,0 +1,111 @@ +/** + * Copyright 2011, 2019 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.test.junit.newt.parenting; + +import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.nativewindow.NativeWindow; +import com.jogamp.nativewindow.NativeWindowHolder; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.opengl.util.NEWTDemoListener; +import com.jogamp.opengl.GLAnimatorControl; + +/** + * Extending demo functionality of {@link NEWTDemoListener} + * <ul> + * <li>L: Print parent and (child) {@link GLWindow} location</li> + * <li>R: Toggel parenting (top-level/child)</li> + * </ul> + */ +public class NewtReparentingKeyAdapter extends NEWTDemoListener { + final NativeWindowHolder winHolder; + + public NewtReparentingKeyAdapter(final NativeWindowHolder winHolder, final GLWindow glWindow) { + super(glWindow, null); + this.winHolder = winHolder; + } + + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() || e.isConsumed() ) { + return; + } + if( 0 == e.getModifiers() ) { // all modifiers go to super class .. + final int keySymbol = e.getKeySymbol(); + switch (keySymbol) { + case KeyEvent.VK_L: + e.setConsumed(true); + final com.jogamp.nativewindow.util.Point p0 = winHolder.getNativeWindow().getLocationOnScreen(null); + final com.jogamp.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null); + printlnState("[location]", "Parent "+p0+", NEWT "+p1); + break; + case KeyEvent.VK_R: + e.setConsumed(true); + quitAdapterOff(); + glWindow.invokeOnNewThread(null, false, new Runnable() { + public void run() { + final java.lang.Thread t = glWindow.setExclusiveContextThread(null); + if(glWindow.getParent()==null) { + printlnState("[reparent pre - glWin to HOME: child pos "+winHolder.getNativeWindow().getX()+"/"+winHolder.getNativeWindow().getY()+"]"); + glWindow.reparentWindow(winHolder.getNativeWindow(), -1, -1, 0 /* hints */); + } else { + final com.jogamp.nativewindow.util.Point p0 = winHolder.getNativeWindow().getLocationOnScreen(null); + final com.jogamp.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null); + printlnState("[reparent pre - glWin to TOP.1] frame ", p0+", glWindow "+p1); + glWindow.reparentWindow(null, p1.getX(), p1.getY(), 0 /* hint */); + } + printlnState("[reparent post]"); + glWindow.requestFocus(); + glWindow.setExclusiveContextThread(t); + quitAdapterOn(); + } } ); + break; + } + } + super.keyPressed(e); + } + + @Override + public void setTitle() { + setTitle(winHolder.getNativeWindow(), glWindow); + } + String getNativeWinTitle(final NativeWindow nw) { + return "["+nw.getX()+"/"+nw.getY()+" "+nw.getWidth()+"x"+nw.getHeight()+"], pix: "+nw.getSurfaceWidth()+"x"+nw.getSurfaceHeight(); + } + public void setTitle(final NativeWindow nw, final Window win) { + final CapabilitiesImmutable chosenCaps = win.getChosenCapabilities(); + final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities(); + final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps; + final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; + final float[] sDPI = win.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java index 591ce5f4e..6e3c7c3e7 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java @@ -51,7 +51,8 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; public class TestParenting01NEWT extends UITestCase { static int width, height; static long durationPerTest = 600; - static long waitAbout10FramesAt30fps = 10*34; // 10 frames @ 30fps + static boolean manual = false; + static int loopVisibleToggle = 10; static GLCapabilities glCaps; @BeforeClass @@ -61,6 +62,37 @@ public class TestParenting01NEWT extends UITestCase { glCaps = new GLCapabilities(null); } + private static void waitForFrames(final String waitFor, final int prefixIdx, + final GLWindow glWindow1, final GLWindow glWindow2, + final long TO, final boolean doAssert) { + final long t0 = System.currentTimeMillis(); + int a, b; + long t1; + do { + try { Thread.sleep(16); } catch (final InterruptedException e) { } + if( null != glWindow1 ) { + a = glWindow1.getTotalFPSFrames(); + } else { + a = -1; + } + if( null != glWindow2 ) { + b = glWindow2.getTotalFPSFrames(); + } else { + b = -1; + } + t1 = System.currentTimeMillis(); + } while ( ( 0 == a || 0 == b ) && TO > ( t1 - t0 ) ); + System.err.println("Frames for "+waitFor+": A"+prefixIdx+": "+a+", B"+prefixIdx+": "+b); + if( doAssert ) { + if( null != glWindow1 ) { + Assert.assertTrue("No frames."+prefixIdx+" displayed on window1 during "+TO+"ms", 0 < a); + } + if( null != glWindow2 ) { + Assert.assertTrue("No frames."+prefixIdx+" displayed on window2 during "+TO+"ms", 0 < b); + } + } + } + @Test public void test01CreateVisibleDestroy() throws InterruptedException { Assert.assertEquals(0,Display.getActiveDisplayNumber()); @@ -109,44 +141,43 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(0,Display.getActiveDisplayNumber()); // visible test + for(int i=1; i<=loopVisibleToggle; i++) { + Assert.assertEquals(0, glWindow1.getTotalFPSFrames()); + Assert.assertEquals(0, glWindow2.getTotalFPSFrames()); + System.err.println("XXX VISIBLE."+i+" -> TRUE"); + glWindow1.setVisible(true); + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow1.isNativeValid()); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow2.isNativeValid()); + Assert.assertEquals(1,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(2,screen.getReferenceCount()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + waitForFrames("window1.setVisible(true)", 1, glWindow1, glWindow2, 2000, true); + + System.err.println("XXX VISIBLE."+i+" -> FALSE"); + glWindow1.setVisible(false); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow1.isNativeValid()); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow2.isNativeValid()); + + glWindow1.resetFPSCounter(); + glWindow2.resetFPSCounter(); + } Assert.assertEquals(0, glWindow1.getTotalFPSFrames()); Assert.assertEquals(0, glWindow2.getTotalFPSFrames()); + System.err.println("XXX VISIBLE.3 -> TRUE"); glWindow1.setVisible(true); - System.err.println("Frames for setVisible(true): A1: "+glWindow1.getTotalFPSFrames()+", B1: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); - - Assert.assertEquals(true, glWindow1.isVisible()); - Assert.assertEquals(true, glWindow1.isNativeValid()); - Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeValid()); - Assert.assertEquals(1,display.getReferenceCount()); - Assert.assertEquals(true,display.isNativeValid()); - Assert.assertNotNull(display.getEDTUtil()); - Assert.assertEquals(true,display.getEDTUtil().isRunning()); - Assert.assertEquals(2,screen.getReferenceCount()); - Assert.assertEquals(true,screen.isNativeValid()); - Assert.assertEquals(1,Display.getActiveDisplayNumber()); - - glWindow1.setVisible(false); - Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(true, glWindow1.isNativeValid()); - Assert.assertEquals(false, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeValid()); - - glWindow1.resetFPSCounter(); - glWindow2.resetFPSCounter(); - Assert.assertEquals(0, glWindow1.getTotalFPSFrames()); - Assert.assertEquals(0, glWindow2.getTotalFPSFrames()); - glWindow1.setVisible(true); - System.err.println("Frames for setVisible(true): A2: "+glWindow1.getTotalFPSFrames()+", B2: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); - Assert.assertEquals(true, glWindow1.isVisible()); Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); + waitForFrames("window1.setVisible(true)", 2, glWindow1, glWindow2, 2000, true); glWindow1.resetFPSCounter(); glWindow2.resetFPSCounter(); @@ -165,9 +196,7 @@ public class TestParenting01NEWT extends UITestCase { while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) { Thread.sleep(100); } - System.err.println("Frames for setVisible(true): A3: "+glWindow1.getTotalFPSFrames()+", B3: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("animator.start()", 3, glWindow1, glWindow2, 2000, true); Assert.assertEquals(true, animator1.pause()); Assert.assertEquals(false, animator1.isAnimating()); @@ -188,10 +217,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(true, animator2.isAnimating()); Assert.assertEquals(false, animator2.isPaused()); Assert.assertNotNull(animator2.getThread()); - Thread.sleep(waitAbout10FramesAt30fps); - System.err.println("Frames for setVisible(true): A4: "+glWindow1.getTotalFPSFrames()+", B4: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("animator.resume()", 4, glWindow1, glWindow2, 2000, true); animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); @@ -243,15 +269,13 @@ public class TestParenting01NEWT extends UITestCase { glWindow2.resetFPSCounter(); Assert.assertEquals(0, glWindow1.getTotalFPSFrames()); Assert.assertEquals(0, glWindow2.getTotalFPSFrames()); + System.err.println("XXX VISIBLE.4 -> TRUE"); glWindow1.setVisible(true); Assert.assertEquals(true, glWindow1.isVisible()); Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); - - System.err.println("Frames for setVisible(true): A3: "+glWindow1.getTotalFPSFrames()+", B3: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("window1.setVisible(true) recreate", 5, glWindow1, glWindow2, 2000, true); Assert.assertEquals(1,display.getReferenceCount()); Assert.assertEquals(true,display.isNativeValid()); @@ -287,11 +311,17 @@ public class TestParenting01NEWT extends UITestCase { @Test public void test02aReparentTop2WinReparentRecreate() throws InterruptedException { + if( manual ) { + return; + } test02ReparentTop2WinImpl(true); } @Test public void test02bReparentTop2WinReparentNative() throws InterruptedException { + if( manual ) { + return; + } test02ReparentTop2WinImpl(false); } @@ -348,12 +378,10 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(true,screen1.isNativeValid()); Assert.assertEquals(1,Display.getActiveDisplayNumber()); Assert.assertEquals(true, glWindow1.isVisible()); - System.err.println("Frames for setVisible(true) A1: "+glWindow1.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - + waitForFrames("window1.setVisible(true)", 1, glWindow1, null, 2000, true); Assert.assertEquals(0, glWindow2.getTotalFPSFrames()); - glWindow2.setVisible(true); + glWindow2.setVisible(true); Assert.assertEquals(1,display1.getReferenceCount()); Assert.assertEquals(true,display1.isNativeValid()); Assert.assertNotNull(display1.getEDTUtil()); @@ -362,8 +390,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(true,screen1.isNativeValid()); Assert.assertEquals(1,Display.getActiveDisplayNumber()); Assert.assertEquals(true, glWindow2.isVisible()); - System.err.println("Frames for setVisible(true) B1: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); + waitForFrames("window2.setVisible(true)", 2, glWindow1, glWindow2, 2000, true); final Animator animator1 = new Animator(glWindow1); animator1.setUpdateFPSFrames(1, null); @@ -405,9 +432,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertSame(glWindow1,glWindow2.getParent()); - Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz - System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B2: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("reparentWindow.child(parent, "+reparentRecreate+"), "+reparentAction, 10, glWindow1, glWindow2, 2000, true); Assert.assertEquals(1,display1.getReferenceCount()); Assert.assertEquals(true,display1.isNativeValid()); @@ -448,9 +473,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertNull(glWindow2.getParent()); - Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz - System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B3: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("reparentWindow.top(parent, "+reparentRecreate+"), "+reparentAction, 11, glWindow1, glWindow2, 2000, true); Assert.assertEquals(1,display1.getReferenceCount()); Assert.assertEquals(true,display1.isNativeValid()); @@ -523,11 +546,17 @@ public class TestParenting01NEWT extends UITestCase { @Test public void test03aReparentWin2TopReparentRecreate() throws InterruptedException { + if( manual ) { + return; + } test03ReparentWin2TopImpl(true); } @Test public void test03bReparentWin2TopReparentNative() throws InterruptedException { + if( manual ) { + return; + } test03ReparentWin2TopImpl(false); } @@ -579,10 +608,6 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(0, glWindow1.getTotalFPSFrames()); Assert.assertEquals(0, glWindow2.getTotalFPSFrames()); glWindow1.setVisible(true); - System.err.println("Frames for setVisible(): A1: "+glWindow1.getTotalFPSFrames()+", B1: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow1.getTotalFPSFrames()); - Assert.assertEquals(1,display1.getReferenceCount()); Assert.assertEquals(true,display1.isNativeValid()); Assert.assertNotNull(display1.getEDTUtil()); @@ -592,6 +617,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertSame(glWindow1,glWindow2.getParent()); Assert.assertSame(screen1,glWindow2.getScreen()); Assert.assertEquals(1,Display.getActiveDisplayNumber()); + waitForFrames("window1.setVisible(true)", 1, glWindow1, glWindow2, 2000, true); final Animator animator1 = new Animator(glWindow1); animator1.setUpdateFPSFrames(1, null); @@ -630,9 +656,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); - Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz - System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B2: "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("reparentWindow.top(parent, "+reparentRecreate+"), "+reparentAction, 10, glWindow1, glWindow2, 2000, true); Assert.assertNull(glWindow2.getParent()); Assert.assertSame(screen1,glWindow2.getScreen()); @@ -665,9 +689,7 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); - Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz - System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B3 "+glWindow2.getTotalFPSFrames()); - Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + waitForFrames("reparentWindow.child(parent, "+reparentRecreate+"), "+reparentAction, 11, glWindow1, glWindow2, 2000, true); Assert.assertSame(glWindow1,glWindow2.getParent()); Assert.assertSame(screen1,glWindow2.getScreen()); @@ -759,6 +781,10 @@ public class TestParenting01NEWT extends UITestCase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { durationPerTest = atoi(args[++i]); + } else if(args[i].equals("-loopvt")) { + loopVisibleToggle = atoi(args[++i]); + } else if(args[i].equals("-manual")) { + manual = true; } else if(args[i].equals("-asMain")) { asMain = true; } @@ -768,8 +794,8 @@ public class TestParenting01NEWT extends UITestCase { try { TestParenting01NEWT.initClass(); final TestParenting01NEWT m = new TestParenting01NEWT(); - m.test02aReparentTop2WinReparentRecreate(); m.test01CreateVisibleDestroy(); + m.test02aReparentTop2WinReparentRecreate(); } catch (final Throwable t ) { t.printStackTrace(); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java index 3878e8ba5..b030bc5e4 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java @@ -114,8 +114,8 @@ public class TestParenting01aAWT extends UITestCase { final Animator animator1 = new Animator(glWindow1); animator1.setUpdateFPSFrames(1, null); animator1.start(); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow1, true, null)); while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) { Thread.sleep(100); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java index b53da38d7..175b3c675 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java @@ -47,6 +47,7 @@ import javax.swing.WindowConstants; import com.jogamp.opengl.*; import com.jogamp.opengl.util.Animator; +import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.*; import com.jogamp.newt.opengl.*; import com.jogamp.newt.awt.NewtCanvasAWT; @@ -140,7 +141,7 @@ public class TestParenting01cSwingAWT extends UITestCase { animator1.start(); final GLDisturbanceAction disturbanceAction = new GLDisturbanceAction(glWindow1); - new Thread(disturbanceAction).start(); + new InterruptSource.Thread(null, disturbanceAction).start(); disturbanceAction.waitUntilRunning(); final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); @@ -177,8 +178,8 @@ public class TestParenting01cSwingAWT extends UITestCase { jFrame1.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null)); + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow1, true, null)); // visible test Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); @@ -195,14 +196,14 @@ public class TestParenting01cSwingAWT extends UITestCase { System.err.println("Demos: 3 - !Visible"); jFrame1.setVisible(false); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, false)); + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow1, false, null)); SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.err.println("Demos: 4 - Visible"); jFrame1.setVisible(true); } }); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow1, true, null)); final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen(); @@ -274,7 +275,7 @@ public class TestParenting01cSwingAWT extends UITestCase { animator1.start(); final GLDisturbanceAction disturbanceAction = new GLDisturbanceAction(glWindow1); - new Thread(disturbanceAction).start(); + new InterruptSource.Thread(null, disturbanceAction).start(); disturbanceAction.waitUntilRunning(); final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java index e23b36f07..f0cc0454c 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java @@ -145,8 +145,8 @@ public class TestParenting01dAWT extends UITestCase { }); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow1, true, null)); glWindow1.display(); Assert.assertEquals("Init Counter Invalid "+glelCounter, 1, glelCounter.initCount); Assert.assertEquals("Dispose Counter Invalid "+glelCounter, 0, glelCounter.disposeCount); @@ -172,14 +172,14 @@ public class TestParenting01dAWT extends UITestCase { // GL state shall be preserved! // glWindow1.setVisible(false); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, false)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow1, false, null)); System.err.println(getSimpleTestName(".")+": Start Reparent #2"); final Window.ReparentOperation rop2 = glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, reparentingHints); System.err.println(getSimpleTestName(".")+": Result Reparent #2: "+rop2); Assert.assertEquals(Window.ReparentOperation.ACTION_NATIVE_CREATION, rop2); glWindow1.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(glWindow1, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(glWindow1, true, null)); glWindow1.display(); if( triggerPreserveGLState ) { Assert.assertEquals("Init Counter Invalid (Preserve Failed 2) "+glelCounter, 1, glelCounter.initCount); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java index 6a7066820..b56010bc4 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java @@ -37,7 +37,8 @@ import org.junit.runners.MethodSorters; import com.jogamp.opengl.*; import com.jogamp.nativewindow.*; - +import com.jogamp.nativewindow.util.Point; +import com.jogamp.nativewindow.util.PointImmutable; import com.jogamp.newt.*; import com.jogamp.newt.event.*; import com.jogamp.newt.opengl.*; @@ -150,6 +151,7 @@ public class TestParenting02NEWT extends UITestCase { glWindow1.addGLEventListener(demo1); glWindow2.addGLEventListener(demo2); + glWindow2.addWindowListener(windowMoveDetection); boolean shouldQuit = false; long duration = durationPerTest; @@ -163,8 +165,19 @@ public class TestParenting02NEWT extends UITestCase { x += 1; y += 1; // glWindow1.setPosition(x,y); - glWindow2.setPosition(glWindow1.getWidth()/2,glWindow1.getHeight()/2-y); - Thread.sleep(step); + final PointImmutable expPos = new Point(glWindow1.getWidth()/2, glWindow1.getHeight()/2-y); + glWindow2.setPosition(expPos.getX(), expPos.getY()); + { + int waitCount=0; + do { + Thread.sleep(step); + waitCount++; + } while( !windowMoved && waitCount < 10); + final boolean didWindowMove = windowMoved; + windowMoved = false; + final PointImmutable hasPos = new Point(glWindow2.getX(), glWindow2.getY()); + System.err.println("Moved: exp "+expPos+", has "+hasPos+", equals "+expPos.equals(hasPos)+", didWindowMove "+didWindowMove+", waitCount "+waitCount); + } while( null != ( event = eventFifo.get() ) ) { final Window source = (Window) event.getSource(); @@ -186,6 +199,13 @@ public class TestParenting02NEWT extends UITestCase { destroyWindow(null, null, window2, glWindow2); destroyWindow(display, screen, window1, glWindow1); } + volatile boolean windowMoved = false; + final WindowListener windowMoveDetection = new WindowAdapter() { + @Override + public void windowMoved(final WindowEvent e) { + windowMoved = true; + } + }; public static void setDemoFields(final GLEventListener demo, final Window window, final GLWindow glWindow, final boolean debug) { Assert.assertNotNull(demo); @@ -214,17 +234,7 @@ public class TestParenting02NEWT extends UITestCase { } } final String tstname = TestParenting02NEWT.class.getName(); - org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { - tstname, - "filtertrace=true", - "haltOnError=false", - "haltOnFailure=false", - "showoutput=true", - "outputtoformatters=true", - "logfailedtests=true", - "logtestlistenerevents=true", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + org.junit.runner.JUnitCore.main(tstname); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java index 723b84081..005839cec 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java @@ -47,6 +47,7 @@ import com.jogamp.opengl.*; import com.jogamp.opengl.util.Animator; import com.jogamp.newt.*; import com.jogamp.newt.opengl.*; +import com.jogamp.newt.opengl.util.NEWTDemoListener; import com.jogamp.newt.awt.NewtCanvasAWT; import java.io.IOException; @@ -54,6 +55,14 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +/** + * <p> + * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality. + * </p> + * <p> + * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}, and many more, see {@link #main(String[])} + * </p> + */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting03AWT extends UITestCase { static Dimension glSize, fSize; @@ -88,7 +97,7 @@ public class TestParenting03AWT extends UITestCase { final GLEventListener demo1 = new GearsES2(1); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null)); + glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1)); final GLAnimatorControl animator1 = new Animator(glWindow1); animator1.start(); @@ -104,7 +113,7 @@ public class TestParenting03AWT extends UITestCase { final GLEventListener demo2 = new GearsES2(1); setDemoFields(demo2, glWindow2, false); glWindow2.addGLEventListener(demo2); - glWindow2.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT2, glWindow2, null)); + glWindow2.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT2, glWindow2)); animator2 = new Animator(glWindow2); animator2.start(); } diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java index 477b761bd..cbc969589 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java @@ -28,7 +28,6 @@ package com.jogamp.opengl.test.junit.util; -import jogamp.newt.WindowImplAccess; import jogamp.newt.awt.event.AWTNewtEventFactory; import java.lang.Thread.UncaughtExceptionHandler; @@ -43,24 +42,17 @@ import java.awt.Robot; import com.jogamp.nativewindow.NativeWindow; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.opengl.GLAutoDrawable; -import com.jogamp.opengl.GLContext; -import com.jogamp.opengl.GLDrawable; import org.junit.Assert; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.util.awt.AWTEDTExecutor; -import com.jogamp.newt.event.WindowEvent; -public class AWTRobotUtil { +public class AWTRobotUtil extends TestUtil { static final boolean DEBUG = false; - public static final int RETRY_NUMBER = 5; public static final int ROBOT_DELAY = 100; // ms - public static final int TIME_OUT = 2000; // 2s - public static final int POLL_DIVIDER = 20; // TO/20 - public static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ; public static Integer AWT_CLICK_TO = null; static class OurUncaughtExceptionHandler implements UncaughtExceptionHandler { @@ -125,6 +117,7 @@ public class AWTRobotUtil { System.err.println("******** clearAWTFocus.X"); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static int[] getCenterLocation(final Object obj, final boolean onTitleBarIfWindow) throws InterruptedException, InvocationTargetException { if(obj instanceof com.jogamp.newt.Window) { @@ -163,6 +156,7 @@ public class AWTRobotUtil { return new int[] { x0, y0 }; } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static int[] getClientLocation(final Object obj, final int x, final int y) throws InterruptedException, InvocationTargetException { if(obj instanceof com.jogamp.newt.Window) { @@ -239,6 +233,7 @@ public class AWTRobotUtil { /** * centerMouse + * FIXME: AWTRobotUtil Cleanup: Use specific type for argument object * @param onTitleBarIfWindow TODO */ public static void centerMouse(Robot robot, final Object obj, final boolean onTitleBarIfWindow) @@ -254,6 +249,7 @@ public class AWTRobotUtil { awtRobotMouseMove(robot, p0[0], p0[1] ); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static void setMouseToClientLocation(Robot robot, final Object obj, final int x, final int y) throws AWTException, InterruptedException, InvocationTargetException { @@ -266,6 +262,7 @@ public class AWTRobotUtil { awtRobotMouseMove(robot, p0[0], p0[1] ); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static int getClickTimeout(final Object obj) { if(obj instanceof com.jogamp.newt.Window) { return com.jogamp.newt.event.MouseEvent.getClickTimeout(); @@ -284,6 +281,8 @@ public class AWTRobotUtil { } /** + * FIXME: AWTRobotUtil Cleanup: Use specific type for argument object + * * requestFocus, if robot is valid, use mouse operation, * otherwise programmatic, ie call requestFocus */ @@ -293,6 +292,8 @@ public class AWTRobotUtil { } /** + * FIXME: AWTRobotUtil Cleanup: Use specific type for argument object + * * requestFocus, if robot is valid, use mouse operation, * otherwise programmatic, ie call requestFocus */ @@ -332,6 +333,7 @@ public class AWTRobotUtil { }}); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static void requestFocus(final Robot robot, final Object obj, final int x, final int y) throws AWTException, InterruptedException, InvocationTargetException { validateAWTEDTIsAlive(); @@ -350,6 +352,7 @@ public class AWTRobotUtil { robot.delay( d ); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static boolean hasFocus(final Object obj) { if(obj instanceof com.jogamp.newt.Window) { return ((com.jogamp.newt.Window) obj).hasFocus(); @@ -364,55 +367,36 @@ public class AWTRobotUtil { /** * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate * @return True if the Window became the global focused Window within TIME_OUT */ - public static boolean waitForFocus(final Object obj) throws InterruptedException { + public static boolean waitForFocus(final java.awt.Component comp, final Runnable waitAction) throws InterruptedException { int wait; - if(obj instanceof com.jogamp.newt.Window) { - final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; - for (wait=0; wait<POLL_DIVIDER && !win.hasFocus(); wait++) { - Thread.sleep(TIME_SLICE); - } - } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { - final java.awt.Component comp = (java.awt.Component) obj; - final java.awt.KeyboardFocusManager kfm = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager(); - for (wait=0; wait<POLL_DIVIDER && comp != kfm.getPermanentFocusOwner(); wait++) { + final java.awt.KeyboardFocusManager kfm = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager(); + for (wait=0; wait<POLL_DIVIDER && comp != kfm.getPermanentFocusOwner(); wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { Thread.sleep(TIME_SLICE); } - } else { - throw new RuntimeException("Neither AWT nor NEWT: "+obj); } return wait<POLL_DIVIDER; } /** * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate * @return True if the Window became the global focused Window within TIME_OUT */ - public static boolean waitForFocus(final FocusEventCountAdapter gain, - final FocusEventCountAdapter lost) throws InterruptedException { - int wait; - for (wait=0; wait<POLL_DIVIDER; wait++) { - if( ( null == lost || lost.focusLost() ) && ( null == gain || gain.focusGained() ) ) { - return true; - } - Thread.sleep(TIME_SLICE); - } - return false; - } - - /** - * - * @return True if the Window became the global focused Window within TIME_OUT - */ - public static boolean waitForFocus(final Object obj, final FocusEventCountAdapter gain, - final FocusEventCountAdapter lost) throws InterruptedException { - if(!waitForFocus(obj)) { + public static boolean waitForFocus(final java.awt.Component comp, final FocusEventCountAdapter gain, + final FocusEventCountAdapter lost, final Runnable waitAction) throws InterruptedException { + if(!waitForFocus(comp, waitAction)) { return false; } - return waitForFocus(gain, lost); + return TestUtil.waitForFocus(gain, lost, waitAction); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static void assertRequestFocusAndWait(final Robot robot, final Object requestFocus, final Object waitForFocus, final FocusEventCountAdapter gain, final FocusEventCountAdapter lost) throws AWTException, InterruptedException, InvocationTargetException { @@ -422,7 +406,13 @@ public class AWTRobotUtil { for(i=0; i < RETRY_NUMBER && !hasFocus; i++) { requestFocus(robot, requestFocus); - hasFocus = waitForFocus(waitForFocus, gain, lost); + if(waitForFocus instanceof com.jogamp.newt.Window) { + hasFocus = NewtTestUtil.waitForFocus((com.jogamp.newt.Window)waitForFocus, gain, lost, null); + } else if(NativeWindowFactory.isAWTAvailable() && waitForFocus instanceof java.awt.Component) { + hasFocus = waitForFocus((java.awt.Component)waitForFocus, gain, lost, null); + } else { + throw new RuntimeException("Neither AWT nor NEWT: "+waitForFocus); + } } if(!hasFocus) { System.err.print("*** AWTRobotUtil.assertRequestFocusAndWait() "); @@ -459,6 +449,7 @@ public class AWTRobotUtil { robot.delay(msDelay); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object public static int keyType(final int i, final Robot robot, final int keyCode, final Object obj, final KeyEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException { @@ -518,6 +509,8 @@ public class AWTRobotUtil { } /** + * FIXME: AWTRobotUtil Cleanup: Use specific type for argument object + * * @param keyCode TODO * @param counter shall return the number of keys typed (press + release) */ @@ -550,6 +543,8 @@ public class AWTRobotUtil { } /** + * FIXME: AWTRobotUtil Cleanup: Use specific type for argument object + * * @param keyCode TODO * @param counter shall return the number of keys typed (press + release) */ @@ -600,6 +595,7 @@ public class AWTRobotUtil { robot.delay(actionDelay); } + // FIXME: AWTRobotUtil Cleanup: Use specific type for argument object static int mouseClick(final int i, final Robot robot, final int mouseButton, final Object obj, final InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException { @@ -631,6 +627,8 @@ public class AWTRobotUtil { } /** + * FIXME: AWTRobotUtil Cleanup: Use specific type for argument object + * * @param mouseButton ie InputEvent.BUTTON1_MASK * @param clickCount ie 1, or 2 */ @@ -668,34 +666,17 @@ public class AWTRobotUtil { /** * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate * @return True if the Component becomes <code>visible</code> within TIME_OUT */ - public static boolean waitForVisible(final Object obj, final boolean visible) throws InterruptedException { + public static boolean waitForVisible(final java.awt.Component comp, final boolean visible, final Runnable waitAction) throws InterruptedException { int wait; - if(obj instanceof com.jogamp.newt.Window) { - final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; - for (wait=0; wait<POLL_DIVIDER && visible != win.isVisible(); wait++) { - Thread.sleep(TIME_SLICE); - } - } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { - final java.awt.Component comp = (java.awt.Component) obj; - for (wait=0; wait<POLL_DIVIDER && visible != comp.isShowing(); wait++) { + for (wait=0; wait<POLL_DIVIDER && visible != comp.isShowing(); wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { Thread.sleep(TIME_SLICE); } - } else { - throw new RuntimeException("Neither AWT nor NEWT: "+obj); - } - return wait<POLL_DIVIDER; - } - - /** - * - * @return True if the GLDrawable receives the expected size within TIME_OUT - */ - public static boolean waitForSize(final GLDrawable drawable, final int width, final int height) throws InterruptedException { - int wait; - for (wait=0; wait<POLL_DIVIDER && ( width != drawable.getSurfaceWidth() || height != drawable.getSurfaceHeight() ) ; wait++) { - Thread.sleep(TIME_SLICE); } return wait<POLL_DIVIDER; } @@ -703,46 +684,26 @@ public class AWTRobotUtil { /** * @param obj the component to wait for * @param realized true if waiting for component to become realized, otherwise false - * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT - * @throws InterruptedException - */ - public static boolean waitForRealized(final Object obj, final boolean realized) throws InterruptedException { - return waitForRealized(obj, null, realized); - } - - /** - * @param obj the component to wait for * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate - * @param realized true if waiting for component to become realized, otherwise false * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT * @throws InterruptedException */ - public static boolean waitForRealized(final Object obj, final Runnable waitAction, final boolean realized) throws InterruptedException { + public static boolean waitForRealized(final java.awt.Component comp, final boolean realized, final Runnable waitAction) throws InterruptedException { long t0 = System.currentTimeMillis(); long t1 = t0; - if(obj instanceof com.jogamp.newt.Screen) { - final com.jogamp.newt.Screen screen = (com.jogamp.newt.Screen) obj; - while( (t1-t0) < TIME_OUT && realized != screen.isNativeValid() ) { - if( null != waitAction ) { - waitAction.run(); - } else { - Thread.sleep(TIME_SLICE); - } - t1 = System.currentTimeMillis(); - } - } else if(obj instanceof com.jogamp.newt.Window) { - final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; - while( (t1-t0) < TIME_OUT && realized != win.isNativeValid() ) { - if( null != waitAction ) { - waitAction.run(); - } else { - Thread.sleep(TIME_SLICE); - } - t1 = System.currentTimeMillis(); + while( (t1-t0) < TIME_OUT && realized != comp.isShowing() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); } - } else if (NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { - final java.awt.Component comp = (java.awt.Component) obj; - while( (t1-t0) < TIME_OUT && realized != comp.isShowing() ) { + t1 = System.currentTimeMillis(); + } + // if GLCanvas, ensure it got also painted -> drawable.setRealized(true); + if( (t1-t0) < TIME_OUT && comp instanceof GLAutoDrawable) { + final GLAutoDrawable glad = (GLAutoDrawable) comp; + t0 = System.currentTimeMillis(); + while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { if( null != waitAction ) { waitAction.run(); } else { @@ -750,9 +711,10 @@ public class AWTRobotUtil { } t1 = System.currentTimeMillis(); } - // if GLCanvas, ensure it got also painted -> drawable.setRealized(true); - if( (t1-t0) < TIME_OUT && comp instanceof GLAutoDrawable) { - final GLAutoDrawable glad = (GLAutoDrawable) comp; + if( (t1-t0) >= TIME_OUT ) { + // for some reason GLCanvas hasn't been painted yet, force it! + System.err.println("XXX: FORCE REPAINT PRE - glad: "+glad); + comp.repaint(); t0 = System.currentTimeMillis(); while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { if( null != waitAction ) { @@ -762,130 +724,46 @@ public class AWTRobotUtil { } t1 = System.currentTimeMillis(); } - if( (t1-t0) >= TIME_OUT ) { - // for some reason GLCanvas hasn't been painted yet, force it! - System.err.println("XXX: FORCE REPAINT PRE - glad: "+glad); - comp.repaint(); - t0 = System.currentTimeMillis(); - while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { - if( null != waitAction ) { - waitAction.run(); - } else { - Thread.sleep(TIME_SLICE); - } - t1 = System.currentTimeMillis(); - } - System.err.println("XXX: FORCE REPAINT POST - glad: "+glad); - } - } - } else if(obj instanceof GLAutoDrawable) { - final GLAutoDrawable glad = (GLAutoDrawable) obj; - while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { - if( null != waitAction ) { - waitAction.run(); - } else { - Thread.sleep(TIME_SLICE); - } - t1 = System.currentTimeMillis(); + System.err.println("XXX: FORCE REPAINT POST - glad: "+glad); } - } else { - throw new RuntimeException("Neither AWT nor NEWT nor GLAutoDrawable: "+obj); } return (t1-t0) < TIME_OUT; } /** - * - * @return True if the GLContext becomes created or not within TIME_OUT - */ - public static boolean waitForContextCreated(final GLAutoDrawable autoDrawable, final boolean created) throws InterruptedException { - if( null == autoDrawable ) { - return !created; - } - int wait; - for (wait=0; wait<POLL_DIVIDER ; wait++) { - final GLContext ctx = autoDrawable.getContext(); - if( created ) { - if( null != ctx && ctx.isCreated() ) { - break; - } - } else { - if( null == ctx || !ctx.isCreated() ) { - break; - } - } - Thread.sleep(TIME_SLICE); - } - return wait<POLL_DIVIDER; - } - - /** * Programmatically issue windowClosing on AWT or NEWT. * Wait until the window is closing within TIME_OUT. * * @param obj either an AWT Window (Frame, JFrame) or NEWT Window * @param willClose indicating that the window will close, hence this method waits for the window to be closed + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate * @param wcl the WindowClosingListener to determine whether the AWT or NEWT widget has been closed. It should be attached * to the widget ASAP before any other listener, e.g. via {@link #addClosingListener(Object)}. * The WindowClosingListener will be reset before attempting to close the widget. * @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT * @throws InterruptedException */ - public static boolean closeWindow(final Object obj, final boolean willClose, final WindowClosingListener closingListener) throws InterruptedException { + public static boolean closeWindow(final java.awt.Window win, final boolean willClose, final TestUtil.WindowClosingListener closingListener, final Runnable waitAction) throws InterruptedException { closingListener.reset(); - if(obj instanceof java.awt.Window) { - final java.awt.Window win = (java.awt.Window) obj; - final java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit(); - final java.awt.EventQueue evtQ = tk.getSystemEventQueue(); - AWTEDTExecutor.singleton.invoke(true, new Runnable() { - public void run() { - evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING)); - } }); - } else if(obj instanceof com.jogamp.newt.Window) { - final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; - WindowImplAccess.windowDestroyNotify(win); - } - int wait; - for (wait=0; wait<POLL_DIVIDER && !closingListener.isWindowClosing(); wait++) { - Thread.sleep(TIME_SLICE); - } - if(wait<POLL_DIVIDER && willClose) { - for (wait=0; wait<POLL_DIVIDER && !closingListener.isWindowClosed(); wait++) { - Thread.sleep(TIME_SLICE); - } - } - return wait<POLL_DIVIDER; + final java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit(); + final java.awt.EventQueue evtQ = tk.getSystemEventQueue(); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING)); + } }); + return waitUntilClosed(willClose, closingListener, waitAction); } - public static WindowClosingListener addClosingListener(final Object obj) { - WindowClosingListener cl = null; - if(obj instanceof java.awt.Window) { - final java.awt.Window win = (java.awt.Window) obj; - final AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); - AWTEDTExecutor.singleton.invoke(true, new Runnable() { - public void run() { - win.addWindowListener(acl); - } } ); - cl = acl; - } else if(obj instanceof com.jogamp.newt.Window) { - final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; - final NEWTWindowClosingAdapter ncl = new NEWTWindowClosingAdapter(); - win.addWindowListener(ncl); - cl = ncl; - } else { - throw new RuntimeException("Neither AWT nor NEWT: "+obj); - } - return cl; - } - public static interface WindowClosingListener { - void reset(); - public int getWindowClosingCount(); - public int getWindowClosedCount(); - public boolean isWindowClosing(); - public boolean isWindowClosed(); + public static TestUtil.WindowClosingListener addClosingListener(final java.awt.Window win) { + final AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + win.addWindowListener(acl); + } } ); + return acl; } static class AWTWindowClosingAdapter - extends java.awt.event.WindowAdapter implements WindowClosingListener + extends java.awt.event.WindowAdapter implements TestUtil.WindowClosingListener { AtomicInteger closing = new AtomicInteger(0); AtomicInteger closed = new AtomicInteger(0); @@ -918,40 +796,6 @@ public class AWTRobotUtil { return "AWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; } } - static class NEWTWindowClosingAdapter - extends com.jogamp.newt.event.WindowAdapter implements WindowClosingListener - { - AtomicInteger closing = new AtomicInteger(0); - AtomicInteger closed = new AtomicInteger(0); - - public void reset() { - closing.set(0); - closed.set(0); - } - public int getWindowClosingCount() { - return closing.get(); - } - public int getWindowClosedCount() { - return closed.get(); - } - public boolean isWindowClosing() { - return 0 < closing.get(); - } - public boolean isWindowClosed() { - return 0 < closed.get(); - } - public void windowDestroyNotify(final WindowEvent e) { - closing.incrementAndGet(); - System.err.println("NEWTWindowClosingAdapter.windowDestroyNotify: "+this); - } - public void windowDestroyed(final WindowEvent e) { - closed.incrementAndGet(); - System.err.println("NEWTWindowClosingAdapter.windowDestroyed: "+this); - } - public String toString() { - return "NEWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; - } - } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/GLTestUtil.java b/src/test/com/jogamp/opengl/test/junit/util/GLTestUtil.java new file mode 100644 index 000000000..792dfa831 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/GLTestUtil.java @@ -0,0 +1,108 @@ +/** + * Copyright 2019 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.test.junit.util; + +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLContext; +import com.jogamp.opengl.GLDrawable; + +public class GLTestUtil extends TestUtil { + + /** + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the GLContext becomes created or not within TIME_OUT + */ + public static boolean waitForContextCreated(final GLAutoDrawable autoDrawable, final boolean created, final Runnable waitAction) throws InterruptedException { + if( null == autoDrawable ) { + return !created; + } + int wait; + for (wait=0; wait<POLL_DIVIDER ; wait++) { + final GLContext ctx = autoDrawable.getContext(); + if( created ) { + if( null != ctx && ctx.isCreated() ) { + break; + } + } else { + if( null == ctx || !ctx.isCreated() ) { + break; + } + } + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + return wait<POLL_DIVIDER; + } + + /** + * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the GLDrawable receives the expected surface size within TIME_OUT + */ + public static boolean waitForSize(final GLDrawable drawable, final int width, final int height, final Runnable waitAction) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && ( width != drawable.getSurfaceWidth() || height != drawable.getSurfaceHeight() ) ; wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + return wait<POLL_DIVIDER; + } + + /** + * @param glad the GLAutoDrawable to wait for + * @param realized true if waiting for component to become realized, otherwise false + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT + * @throws InterruptedException + */ + public static boolean waitForRealized(final GLAutoDrawable glad, final boolean realized, final Runnable waitAction) throws InterruptedException { + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + t1 = System.currentTimeMillis(); + } + return (t1-t0) < TIME_OUT; + } + +} + + + diff --git a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java index 60f2f962c..bf656bb4d 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java +++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java @@ -42,6 +42,7 @@ import java.util.List; import com.jogamp.opengl.GLContext; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; public class MiscUtils { public static boolean atob(final String str, final boolean def) { @@ -160,7 +161,7 @@ public class MiscUtils { return false; } - public static class StreamDump extends Thread { + public static class StreamDump extends InterruptSource.Thread { final InputStream is; final StringBuilder outString; final OutputStream outStream; diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java index 361a6c230..5dcfb2f98 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java @@ -67,8 +67,8 @@ public class NEWTGLContext { Assert.assertNotNull(window); window.setSize(width, height); window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null)); + Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null)); final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); final GLDrawable drawable = factory.createGLDrawable(window); diff --git a/src/test/com/jogamp/opengl/test/junit/util/NewtTestUtil.java b/src/test/com/jogamp/opengl/test/junit/util/NewtTestUtil.java new file mode 100644 index 000000000..295690f8a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/NewtTestUtil.java @@ -0,0 +1,206 @@ +/** + * Copyright 2019 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.test.junit.util; + +import java.util.concurrent.atomic.AtomicInteger; + +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowEvent; + +import jogamp.newt.WindowImplAccess; + +public class NewtTestUtil extends TestUtil { + public static class NEWTWindowClosingAdapter + extends com.jogamp.newt.event.WindowAdapter implements TestUtil.WindowClosingListener + { + AtomicInteger closing = new AtomicInteger(0); + AtomicInteger closed = new AtomicInteger(0); + + public void reset() { + closing.set(0); + closed.set(0); + } + public int getWindowClosingCount() { + return closing.get(); + } + public int getWindowClosedCount() { + return closed.get(); + } + public boolean isWindowClosing() { + return 0 < closing.get(); + } + public boolean isWindowClosed() { + return 0 < closed.get(); + } + public void windowDestroyNotify(final WindowEvent e) { + closing.incrementAndGet(); + System.err.println("NEWTWindowClosingAdapter.windowDestroyNotify: "+this); + } + public void windowDestroyed(final WindowEvent e) { + closed.incrementAndGet(); + System.err.println("NEWTWindowClosingAdapter.windowDestroyed: "+this); + } + public String toString() { + return "NEWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; + } + } + /** + * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Window became the global focused Window within TIME_OUT + */ + public static boolean waitForFocus(final Window win, final Runnable waitAction) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && !win.hasFocus(); wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + return wait<POLL_DIVIDER; + } + + /** + * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Window became the global focused Window within TIME_OUT + */ + public static boolean waitForFocus(final Window win, final FocusEventCountAdapter gain, + final FocusEventCountAdapter lost, final Runnable waitAction) throws InterruptedException { + if(!waitForFocus(win, waitAction)) { + return false; + } + return TestUtil.waitForFocus(gain, lost, waitAction); + } + + /** + * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Window receives the expected surface size within TIME_OUT + */ + public static boolean waitForSize(final Window window, final int width, final int height, final Runnable waitAction) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && ( width != window.getSurfaceWidth() || height != window.getSurfaceHeight() ) ; wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + return wait<POLL_DIVIDER; + } + + /** + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Component becomes <code>visible</code> within TIME_OUT + */ + public static boolean waitForVisible(final Window win, final boolean visible, final Runnable waitAction) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && visible != win.isVisible(); wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + return wait<POLL_DIVIDER; + } + + /** + * @param screen the Screen to wait for + * @param realized true if waiting for component to become realized, otherwise false + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT + * @throws InterruptedException + */ + public static boolean waitForRealized(final Screen screen, final boolean realized, final Runnable waitAction) throws InterruptedException { + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( (t1-t0) < TIME_OUT && realized != screen.isNativeValid() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + t1 = System.currentTimeMillis(); + } + return (t1-t0) < TIME_OUT; + } + /** + * @param win the Window to wait for + * @param realized true if waiting for component to become realized, otherwise false + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT + * @throws InterruptedException + */ + public static boolean waitForRealized(final Window win, final boolean realized, final Runnable waitAction) throws InterruptedException { + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( (t1-t0) < TIME_OUT && realized != win.isNativeValid() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + t1 = System.currentTimeMillis(); + } + return (t1-t0) < TIME_OUT; + } + + public static TestUtil.WindowClosingListener addClosingListener(final Window win) { + final NewtTestUtil.NEWTWindowClosingAdapter ncl = new NewtTestUtil.NEWTWindowClosingAdapter(); + win.addWindowListener(ncl); + return ncl; + } + + /** + * Programmatically issue windowClosing on AWT or NEWT. + * Wait until the window is closing within TIME_OUT. + * @param willClose indicating that the window will close, hence this method waits for the window to be closed + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @param obj either an AWT Window (Frame, JFrame) or NEWT Window + * @param wcl the WindowClosingListener to determine whether the AWT or NEWT widget has been closed. It should be attached + * to the widget ASAP before any other listener, e.g. via {@link #addClosingListener(Object)}. + * The WindowClosingListener will be reset before attempting to close the widget. + * + * @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT + * @throws InterruptedException + */ + public static boolean closeWindow(final Window win, final boolean willClose, final TestUtil.WindowClosingListener closingListener, final Runnable waitAction) throws InterruptedException { + closingListener.reset(); + WindowImplAccess.windowDestroyNotify(win); + return waitUntilClosed(willClose, closingListener, waitAction); + } +} + + + diff --git a/src/test/com/jogamp/opengl/test/junit/util/TestUtil.java b/src/test/com/jogamp/opengl/test/junit/util/TestUtil.java new file mode 100644 index 000000000..835fe81a4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/TestUtil.java @@ -0,0 +1,100 @@ +/** + * Copyright 2019 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.test.junit.util; + +public abstract class TestUtil { + public static interface WindowClosingListener { + void reset(); + public int getWindowClosingCount(); + public int getWindowClosedCount(); + public boolean isWindowClosing(); + public boolean isWindowClosed(); + } + public static final int RETRY_NUMBER = 5; + public static final int TIME_OUT = 2000; // 2s + public static final int POLL_DIVIDER = 20; // TO/20 + public static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ; + + /** + * + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @return True if the Window became the global focused Window within TIME_OUT + */ + public static boolean waitForFocus(final FocusEventCountAdapter gain, + final FocusEventCountAdapter lost, final Runnable waitAction) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER; wait++) { + if( ( null == lost || lost.focusLost() ) && ( null == gain || gain.focusGained() ) ) { + return true; + } + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + return false; + } + + /** + * Wait until the window is closing within TIME_OUT. + * + * @param willClose indicating that the window will close, hence this method waits for the window to be closed + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @param wcl the WindowClosingListener to determine whether the AWT or NEWT widget has been closed. It should be attached + * to the widget ASAP before any other listener, e.g. via {@link #addClosingListener(Object)}. + * The WindowClosingListener will be reset before attempting to close the widget. + * @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT + * @throws InterruptedException + */ + public static boolean waitUntilClosed(final boolean willClose, final TestUtil.WindowClosingListener closingListener, final Runnable waitAction) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && !closingListener.isWindowClosing(); wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + if(wait<POLL_DIVIDER && willClose) { + for (wait=0; wait<POLL_DIVIDER && !closingListener.isWindowClosed(); wait++) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + } + } + return wait<POLL_DIVIDER; + } +} + + + diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java index 2b1bb7062..7003b3980 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java +++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.StringTokenizer; import java.util.concurrent.atomic.AtomicInteger; @@ -241,7 +242,7 @@ public abstract class UITestCase extends SingletonJunitCase { final String aaext = caps.getSampleExtension(); postSNDetail = null != postSNDetail ? "-"+postSNDetail : ""; - filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s", + filenameBaseName = String.format((Locale)null, "%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s", simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel, scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext, width, height, fileSuffix).replace(' ', '_'); |