diff options
Diffstat (limited to 'src/jogl/classes')
25 files changed, 192 insertions, 133 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index c5b3b3f44..ac2b24117 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -145,7 +145,7 @@ public class Animator extends AnimatorBase { public void run() { try { if(DEBUG) { - System.err.println("Animator start on " + Thread.currentThread().getName() + ": " + toString()); + System.err.println("Animator start on " + getThreadName() + ": " + toString()); } fpsCounter.resetFPSCounter(); animThread = Thread.currentThread(); @@ -265,7 +265,7 @@ public class Animator extends AnimatorBase { runnable = new MainLoop(); } fpsCounter.resetFPSCounter(); - String threadName = Thread.currentThread().getName()+"-"+baseName; + String threadName = getThreadName()+"-"+baseName; Thread thread; if(null==threadGroup) { thread = new Thread(runnable, threadName); diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java index aa0e70132..837fc84bd 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java @@ -138,7 +138,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { baseName = getBaseName(""); } if(DEBUG) { - System.err.println("Animator.initImpl: baseName "+baseName+", implClazz "+impl.getClass().getName()+" - "+toString()+" - "+Thread.currentThread().getName()); + System.err.println("Animator.initImpl: baseName "+baseName+", implClazz "+impl.getClass().getName()+" - "+toString()+" - "+getThreadName()); } } } @@ -173,7 +173,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { @Override public synchronized void add(final GLAutoDrawable drawable) { if(DEBUG) { - System.err.println("Animator add: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+Thread.currentThread().getName()); + System.err.println("Animator add: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName()); } if( drawables.contains(drawable) ) { throw new IllegalArgumentException("Drawable already added to animator: "+this+", "+drawable); @@ -204,7 +204,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { @Override public synchronized void remove(final GLAutoDrawable drawable) { if(DEBUG) { - System.err.println("Animator remove: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+Thread.currentThread().getName()); + System.err.println("Animator remove: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName()); } if( !drawables.contains(drawable) ) { throw new IllegalArgumentException("Drawable not added to animator: "+this+", "+drawable); @@ -539,14 +539,14 @@ public abstract class AnimatorBase implements GLAnimatorControl { } if(DEBUG || blocking && nok) { // Info only if DEBUG or ( blocking && not-ok ) ; !blocking possible if AWT if( remaining<=0 && nok ) { - System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): ++++++ timeout reached ++++++ " + Thread.currentThread().getName()); + System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): ++++++ timeout reached ++++++ " + getThreadName()); } stateSync.lock(); // avoid too many lock/unlock ops try { System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): OK "+(!nok)+ "- pollPeriod "+pollPeriod+", blocking "+blocking+ ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION + - " - " + Thread.currentThread().getName()); + " - " + getThreadName()); System.err.println(" - "+toString()); } finally { stateSync.unlock(); @@ -571,6 +571,8 @@ public abstract class AnimatorBase implements GLAnimatorControl { } } + protected static String getThreadName() { return Thread.currentThread().getName(); } + public String toString() { return getClass().getName()+"[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+ ", totals[dt "+getTotalFPSDuration()+", frames "+getTotalFPSFrames()+", fps "+getTotalFPS()+ diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java index bfcab23fd..7613efec6 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java @@ -235,7 +235,7 @@ public class FPSAnimator extends AnimatorBase { if ( null != timer || null != task || isStartedImpl() ) { return false; } - timer = new Timer( Thread.currentThread().getName()+"-"+baseName+"-Timer"+(timerNo++) ); + timer = new Timer( getThreadName()+"-"+baseName+"-Timer"+(timerNo++) ); task = new MainTask(); if(DEBUG) { System.err.println("FPSAnimator.start() START: "+task+", "+ Thread.currentThread() + ": " + toString()); diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java index eceeea6db..7d110659a 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java @@ -172,7 +172,10 @@ public class ShaderUtil { info.shaderBinaryFormats.add(new Integer(formats[i])); } } - } catch (GLException gle) { System.err.println("Catched Exception: "+gle.getMessage()); gle.printStackTrace(); } + } catch (GLException gle) { + System.err.println("Catched Exception on thread "+Thread.currentThread().getName()); + gle.printStackTrace(); + } } } return info.shaderBinaryFormats; @@ -199,7 +202,10 @@ public class ShaderUtil { } info.shaderCompilerAvailable = new Boolean(v); queryOK = true; - } catch (GLException gle) { System.err.println("Catched Exception: "+gle.getMessage()); gle.printStackTrace(); } + } catch (GLException gle) { + System.err.println("Catched Exception on thread "+Thread.currentThread().getName()); + gle.printStackTrace(); + } if(!queryOK) { info.shaderCompilerAvailable = new Boolean(true); } diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 05200324d..be947e5f5 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -1559,9 +1559,7 @@ public abstract class GLContext { return needColon; } - protected static String getThreadName() { - return Thread.currentThread().getName(); - } + protected static String getThreadName() { return Thread.currentThread().getName(); } } diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java index 95c314a48..65c8b2ea5 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java @@ -65,29 +65,31 @@ public interface GLDrawable { public GLContext createContext(GLContext shareWith); /** - * Indicates to on-screen GLDrawable implementations whether the - * underlying window has been created and can be drawn into. End - * users do not need to call this method; it is not necessary to - * call <code>setRealized</code> on a GLCanvas, a GLJPanel, or a - * GLPbuffer, as these perform the appropriate calls on their - * underlying GLDrawables internally. - * - * <P> - * + * Indicates to GLDrawable implementations whether the + * underlying {@link NativeSurface surface} has been created and can be drawn into. + * <p> + * If realized, the {@link #getHandle() drawable handle} may become + * valid while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}. + * </p> + * <p> + * End users do not need to call this method; it is not necessary to + * call <code>setRealized</code> on a {@link GLAutoDrawable} + * as these perform the appropriate calls on their underlying GLDrawables internally. + * </p> + * <p> * Developers implementing new OpenGL components for various window * toolkits need to call this method against GLDrawables obtained - * from the GLDrawableFactory via the {@link - * GLDrawableFactory#getGLDrawable - * GLDrawableFactory.getGLDrawable()} method. It must typically be + * from the GLDrawableFactory via the + * {@link GLDrawableFactory#createGLDrawable(NativeSurface)} method. + * It must typically be * called with an argument of <code>true</code> when the component * associated with the GLDrawable is realized and with an argument * of <code>false</code> just before the component is unrealized. * For the AWT, this means calling <code>setRealized(true)</code> in * the <code>addNotify</code> method and with an argument of * <code>false</code> in the <code>removeNotify</code> method. - * - * <P> - * + * </p> + * <p> * <code>GLDrawable</code> implementations should handle multiple * cycles of <code>setRealized(true)</code> / * <code>setRealized(false)</code> calls. Most, if not all, Java @@ -101,12 +103,11 @@ public interface GLDrawable { * <code>GLDrawable</code> to re-initialize and destroy any * associated resources as the component becomes realized and * unrealized, respectively. - * - * <P> - * + * </p> + * <p> * With an argument of <code>true</code>, * the minimum implementation shall call - * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successfull: + * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successful: * <ul> * <li> Update the {@link GLCapabilities}, which are associated with * the attached {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.</li> @@ -115,14 +116,17 @@ public interface GLDrawable { * This is important since {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} * ensures resolving the window/surface handles, and the drawable's {@link GLCapabilities} * might have changed. - * - * <P> - * + * </p> + * <p> * Calling this method has no other effects. For example, if * <code>removeNotify</code> is called on a Canvas implementation * for which a GLDrawable has been created, it is also necessary to * destroy all OpenGL contexts associated with that GLDrawable. This * is not done automatically by the implementation. + * </p> + * @see #isRealized() + * @see #getHandle() + * @see NativeSurface#lockSurface() */ public void setRealized(boolean realized); @@ -131,6 +135,7 @@ public interface GLDrawable { * <p> * A drawable can be realized and unrealized via {@link #setRealized(boolean)}. * </p> + * @see #setRealized(boolean) */ public boolean isRealized(); @@ -172,11 +177,22 @@ public interface GLDrawable { public NativeSurface getNativeSurface(); /** - * This is the GL/Windowing drawable handle.<br> - * It is usually the {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle()}, - * ie the native surface handle of the underlying windowing toolkit.<br> - * However, on X11/GLX this reflects a GLXDrawable, which represents a GLXWindow, GLXPixmap, or GLXPbuffer.<br> - * On EGL, this represents the EGLSurface.<br> + * Returns the GL drawable handle, + * guaranteed to be valid after {@link #setRealized(boolean) realization} + * <i>and</i> while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}. + * <p> + * It is usually identical to the underlying windowing toolkit {@link NativeSurface surface}'s + * {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle() handle} + * or an intermediate layer to suite GL, e.g. an EGL surface. + * </p> + * <p> + * On EGL it is represented by the EGLSurface.<br> + * On X11/GLX it is represented by either the Window XID, GLXPixmap, or GLXPbuffer.<br> + * On Windows it is represented by the HDC, which may change with each {@link #lockSurface()}.<br> + * </p> + * @see #setRealized(boolean) + * @see NativeSurface#lockSurface() + * @see NativeSurface#unlockSurface() */ public long getHandle(); diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 9d5bd0524..e775afbff 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -255,6 +255,8 @@ public abstract class GLDrawableFactory { } } + protected static String getThreadName() { return Thread.currentThread().getName(); } + /** Returns true if this factory is complete, i.e. ready to be used. Otherwise return false. */ protected abstract boolean isComplete(); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 2fdf18404..c1d5fb1d2 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -687,7 +687,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(DEBUG) { final NativeSurface ns = getNativeSurface(); final long nsH = null != ns ? ns.getSurfaceHandle() : 0; - System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(nsH)); + System.err.println("GLCanvas.sizeChanged: ("+getThreadName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(nsH)); // Thread.dumpStack(); } if( validateGLDrawable() ) { @@ -1209,9 +1209,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing return config; } - protected static String getThreadName() { - return Thread.currentThread().getName(); - } + protected static String getThreadName() { return Thread.currentThread().getName(); } /** * A most simple JOGL AWT test entry diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index f1a2ccc7e..dfb769eb4 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -832,9 +832,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return tmp[0]; } - protected static String getThreadName() { - return Thread.currentThread().getName(); - } + protected static String getThreadName() { return Thread.currentThread().getName(); } //---------------------------------------------------------------------- // Implementations of the various backends diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java index 610f08e21..1a862a3b7 100644 --- a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java +++ b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java @@ -247,8 +247,6 @@ final class ExtensionAvailabilityCache { private int glXExtensionCount = 0; private HashSet<String> availableExtensionCache = new HashSet<String>(50); - static String getThreadName() { - return Thread.currentThread().getName(); - } + static String getThreadName() { return Thread.currentThread().getName(); } } diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 1eb7c618c..705f8b94e 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -118,7 +118,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe final boolean res = isGLStatePreservationSupported() ? true : false; if( res ) { if( DEBUG ) { - System.err.println("GLAutoDrawableBase.setPreserveGLStateAtDestroy: ("+Thread.currentThread().getName()+"): "+preserveGLELSAtDestroy+" -> "+value+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + System.err.println("GLAutoDrawableBase.setPreserveGLStateAtDestroy: ("+getThreadName()+"): "+preserveGLELSAtDestroy+" -> "+value+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); } preserveGLELSAtDestroy = value; } @@ -200,7 +200,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe GLDrawableImpl _drawable = drawable; if( null!=_drawable ) { if(DEBUG) { - System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + System.err.println("GLAutoDrawableBase.sizeChanged: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); } if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { final RecursiveLock _lock = getLock(); @@ -678,6 +678,8 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe return null != _drawable ? _drawable.getHandle() : 0; } + protected static String getThreadName() { return Thread.currentThread().getName(); } + @Override public String toString() { return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 64ade3eff..0d8b193af 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -258,7 +258,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { String sgl1 = (null!=this.gl)?this.gl.getClass().getSimpleName()+", "+this.gl.toString():"<null>"; String sgl2 = (null!=gl)?gl.getClass().getSimpleName()+", "+gl.toString():"<null>"; - Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread().getName()+", "+sgl1+" -> "+sgl2); + Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+getThreadName()+", "+sgl1+" -> "+sgl2); e.printStackTrace(); } this.gl = gl; @@ -342,18 +342,24 @@ public abstract class GLContextImpl extends GLContext { @Override public final void destroy() { + if ( null == drawable ) { + throw new GLException("Drawable is null: "+toString()); + } if ( DEBUG_TRACE_SWITCH ) { System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock); } - if (contextHandle != 0) { + if ( 0 != contextHandle ) { final int lockRes = drawable.lockSurface(); - if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) { // this would be odd .. throw new GLException("Surface not ready to lock: "+drawable); } Throwable drawableContextRealizedException = null; try { + if ( !drawable.isRealized() ) { + throw new GLException("Drawable not realized: "+toString()); + } // Must hold the lock around the destroy operation to make sure we // don't destroy the context while another thread renders to it. lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering) @@ -365,17 +371,18 @@ public abstract class GLContextImpl extends GLContext { } } try { - // release current context - if(lock.getHoldCount() == 1) { - // needs current context to call associateDrawable(..) and to disable debug handler - makeCurrent(); + // if not current, makeCurrent(), to call associateDrawable(..) and to disable debug handler + if ( lock.getHoldCount() == 1 ) { + if ( GLContext.CONTEXT_NOT_CURRENT == makeCurrent() ) { + throw new GLException("GLContext.makeCurrent() failed: "+toString()); + } } try { associateDrawable(false); } catch (Throwable t) { drawableContextRealizedException = t; } - if(0 != defaultVAO) { + if ( 0 != defaultVAO ) { int[] tmp = new int[] { defaultVAO }; gl.getGL2GL3().glBindVertexArray(0); gl.getGL2GL3().glDeleteVertexArrays(1, tmp, 0); @@ -492,17 +499,13 @@ public abstract class GLContextImpl extends GLContext { return CONTEXT_NOT_CURRENT; } - boolean unlockContextAndSurface = true; // Must be cleared if successful, otherwise finally block will release context and surface! + boolean unlockResources = true; // Must be cleared if successful, otherwise finally block will release context and/or surface! int res = CONTEXT_NOT_CURRENT; try { - if (0 == drawable.getHandle()) { - throw new GLException("drawable has invalid handle: "+drawable); - } - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - drawable.updateHandle(); - } - if ( drawable.isRealized() ) { + if ( 0 == drawable.getHandle() ) { + throw new GLException("drawable has invalid handle: "+drawable); + } lock.lock(); try { // One context can only be current by one thread, @@ -513,7 +516,7 @@ public abstract class GLContextImpl extends GLContext { // Assume we don't need to make this context current again // For Mac OS X, however, we need to update the context to track resizes drawableUpdatedNotify(); - unlockContextAndSurface = false; // success + unlockResources = false; // success if( TRACE_SWITCH ) { System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X2]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep - CONTEXT_CURRENT - "+lock); } @@ -523,7 +526,7 @@ public abstract class GLContextImpl extends GLContext { } } res = makeCurrentWithinLock(lockRes); - unlockContextAndSurface = CONTEXT_NOT_CURRENT == res; // success ? + unlockResources = CONTEXT_NOT_CURRENT == res; // success ? /** * FIXME: refactor dependence on Java 2D / JOGL bridge @@ -533,10 +536,10 @@ public abstract class GLContextImpl extends GLContext { } */ } catch (RuntimeException e) { - unlockContextAndSurface = true; + unlockResources = true; throw e; } finally { - if (unlockContextAndSurface) { + if (unlockResources) { if( DEBUG_TRACE_SWITCH ) { System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.1]: Context lock.unlock() due to error, res "+makeCurrentResultToString(res)+", "+lock); } @@ -545,10 +548,10 @@ public abstract class GLContextImpl extends GLContext { } } /* if ( drawable.isRealized() ) */ } catch (RuntimeException e) { - unlockContextAndSurface = true; + unlockResources = true; throw e; } finally { - if (unlockContextAndSurface) { + if (unlockResources) { drawable.unlockSurface(); } } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 9c1cd478b..177c465da 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -887,7 +887,7 @@ public class GLDrawableHelper { final Runnable initAction) { if(null==context) { if (DEBUG) { - Exception e = new GLException(Thread.currentThread().getName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); + Exception e = new GLException(getThreadName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); e.printStackTrace(); } return; @@ -935,7 +935,7 @@ public class GLDrawableHelper { res = context.makeCurrent(); if (GLContext.CONTEXT_NOT_CURRENT != res) { if(GLContext.CONTEXT_CURRENT_NEW == res) { - throw new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); + throw new GLException(getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); } if( listeners.size() > 0 && null != autoDrawable ) { disposeAllGLEventListener(autoDrawable, false); @@ -950,7 +950,7 @@ public class GLDrawableHelper { } flushGLRunnables(); } catch (Exception e) { - System.err.println("Catched: "+e.getMessage()); + System.err.println("Catched Exception on thread "+getThreadName()); e.printStackTrace(); } if (lastContext != null) { @@ -1036,7 +1036,7 @@ public class GLDrawableHelper { try { context.release(); } catch (Exception e) { - System.err.println("Catched: "+e.getMessage()); + System.err.println("Catched Exception on thread "+getThreadName()); e.printStackTrace(); } } @@ -1142,7 +1142,7 @@ public class GLDrawableHelper { context.release(); ctxReleased = true; } catch (Exception e) { - System.err.println("Catched: "+e.getMessage()); + System.err.println("Catched Exception on thread "+getThreadName()); e.printStackTrace(); } } @@ -1160,5 +1160,7 @@ public class GLDrawableHelper { long td = System.currentTimeMillis() - t0; System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed); } + + protected static String getThreadName() { return Thread.currentThread().getName(); } } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index d0c1461a9..a2b99c7da 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -79,14 +79,11 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { // volatile OK (locked below) return; // destroyed already } - int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] + final int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { return; } try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - updateHandle(); - } if( realized ) { // volatile OK final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); if ( caps.getDoubleBuffered() ) { @@ -145,11 +142,21 @@ public abstract class GLDrawableImpl implements GLDrawable { return surface; } - /** called with locked surface @ setRealized(false) */ + /** + * called with locked surface @ setRealized(false) or @ lockSurface(..) when surface changed + * <p> + * Must be paired w/ {@link #createHandle()}. + * </p> + */ protected void destroyHandle() {} - /** called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed */ - protected void updateHandle() {} + /** + * called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed + * <p> + * Must be paired w/ {@link #destroyHandle()}. + * </p> + */ + protected void createHandle() {} @Override public long getHandle() { @@ -174,7 +181,7 @@ public abstract class GLDrawableImpl implements GLDrawable { if(isProxySurface) { ((ProxySurface)surface).createNotify(); } - if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { + if(NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface()) { throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)"); } } else { @@ -185,7 +192,7 @@ public abstract class GLDrawableImpl implements GLDrawable { realized = realizedArg; if(realizedArg) { setRealizedImpl(); - updateHandle(); + createHandle(); } else { destroyHandle(); setRealizedImpl(); @@ -193,7 +200,7 @@ public abstract class GLDrawableImpl implements GLDrawable { } } finally { if(realizedArg) { - unlockSurface(); + surface.unlockSurface(); } else { aDevice.unlock(); if(isProxySurface) { @@ -276,12 +283,47 @@ public abstract class GLDrawableImpl implements GLDrawable { return surface.getHeight(); } - /** @see NativeSurface#lockSurface() */ + /** + * {@link NativeSurface#lockSurface() Locks} the underlying windowing toolkit's {@link NativeSurface surface}. + * <p> + * <i>If</i> drawable is {@link #setRealized(boolean) realized}, + * the {@link #getHandle() drawable handle} is valid after successfully {@link NativeSurface#lockSurface() locking} + * it's {@link NativeSurface surface} until being {@link #unlockSurface() unlocked}. + * </p> + * <p> + * In case the {@link NativeSurface surface} has changed as indicated by it's + * {@link NativeSurface#lockSurface() lock} result {@link NativeSurface#LOCK_SURFACE_CHANGED}, + * the implementation is required to update this information as needed within it's implementation. + * </p> + * + * @see NativeSurface#lockSurface() + * @see #getHandle() + */ public final int lockSurface() throws GLException { - return surface.lockSurface(); + final int lockRes = surface.lockSurface(); + if ( NativeSurface.LOCK_SURFACE_CHANGED == lockRes && realized ) { + // Update the drawable handle, in case the surface handle has changed. + final long _handle1 = getHandle(); + destroyHandle(); + createHandle(); + final long _handle2 = getHandle(); + if(DEBUG) { + if( _handle1 != _handle2) { + System.err.println(getThreadName() + ": Drawable handle changed: "+toHexString(_handle1)+" -> "+toHexString(_handle2)); + } + } + } + return lockRes; + } - /** @see NativeSurface#unlockSurface() */ + /** + * {@link NativeSurface#unlockSurface() Unlocks} the underlying windowing toolkit {@link NativeSurface surface}, + * which may render the {@link #getHandle() drawable handle} invalid. + * + * @see NativeSurface#unlockSurface() + * @see #getHandle() + */ public final void unlockSurface() { surface.unlockSurface(); } @@ -294,9 +336,7 @@ public abstract class GLDrawableImpl implements GLDrawable { ",\n\tSurface "+getNativeSurface()+"]"; } - protected static String getThreadName() { - return Thread.currentThread().getName(); - } + protected static String getThreadName() { return Thread.currentThread().getName(); } protected GLDrawableFactory factory; protected NativeSurface surface; diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 51ec7dda6..ac10e2728 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -546,7 +546,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { @Override public final void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException { if(DEBUG) { - System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); } int lockRes = lockSurface(); if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { diff --git a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java index f7d59e127..112dfcb64 100644 --- a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java +++ b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java @@ -219,9 +219,7 @@ public class GLWorkerThread { return (Thread.currentThread() == thread); } - protected static String getThreadName() { - return Thread.currentThread().getName(); - } + protected static String getThreadName() { return Thread.currentThread().getName(); } static class WorkerRunnable implements Runnable { public void run() { diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java index 7e050c81e..91187cc26 100644 --- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java +++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java @@ -116,17 +116,17 @@ public class SharedResourceRunner implements Runnable { if(null != thread && !thread.isAlive()) { // thread was killed unrecognized .. if (DEBUG) { - System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+getThreadName()); } releaseSharedResources(); thread = null; } if(null == thread) { if (DEBUG) { - System.err.println("SharedResourceRunner.start() - start new Thread - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.start() - start new Thread - "+getThreadName()); } resetState(); - thread = new Thread(this, Thread.currentThread().getName()+"-SharedResourceRunner"); + thread = new Thread(this, getThreadName()+"-SharedResourceRunner"); thread.setDaemon(true); // Allow JVM to exit, even if this one is running thread.start(); } @@ -136,7 +136,7 @@ public class SharedResourceRunner implements Runnable { public void stop() { if(null != thread) { if (DEBUG) { - System.err.println("SharedResourceRunner.stop() - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.stop() - "+getThreadName()); } synchronized (this) { shouldRelease = true; @@ -161,14 +161,14 @@ public class SharedResourceRunner implements Runnable { if (null == sr && !getDeviceTried(connection)) { addDeviceTried(connection); if (DEBUG) { - System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+getThreadName()); } if ( impl.isDeviceSupported(connection) ) { doAndWait(connection, null); sr = impl.mapGet(connection); } if (DEBUG) { - System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+getThreadName()); } } } @@ -183,11 +183,11 @@ public class SharedResourceRunner implements Runnable { if (null != sr) { removeDeviceTried(connection); if (DEBUG) { - System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+getThreadName()); } doAndWait(null, connection); if (DEBUG) { - System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+getThreadName()); } } } @@ -197,7 +197,7 @@ public class SharedResourceRunner implements Runnable { private final void doAndWait(String initConnection, String releaseConnection) { // wait until thread becomes ready to init new device, // pass the device and release the sync - final String threadName = Thread.currentThread().getName(); + final String threadName = getThreadName(); if (DEBUG) { System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName); } @@ -230,7 +230,7 @@ public class SharedResourceRunner implements Runnable { } public final void run() { - final String threadName = Thread.currentThread().getName(); + final String threadName = getThreadName(); if (DEBUG) { System.err.println("SharedResourceRunner.run(): STARTED - " + threadName); @@ -249,7 +249,7 @@ public class SharedResourceRunner implements Runnable { } catch (InterruptedException ex) { shouldRelease = true; if(DEBUG) { - System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+Thread.currentThread().getName()); + System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+threadName); ex.printStackTrace(); } } @@ -319,10 +319,12 @@ public class SharedResourceRunner implements Runnable { try { impl.releaseSharedResource(iter.next()); } catch (Throwable t) { - System.err.println("Catched Exception: "+t.getStackTrace()+" - "+Thread.currentThread().getName()); + System.err.println("Catched Exception on thread "+getThreadName()); t.printStackTrace(); } } impl.clear(); } + + protected static String getThreadName() { return Thread.currentThread().getName(); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index 167eebf3a..2edf26145 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -100,10 +100,10 @@ public abstract class EGLDrawable extends GLDrawableImpl { } @Override - protected final void updateHandle() { + protected final void createHandle() { final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; if(DEBUG) { - System.err.println(getThreadName() + ": updateHandle of "+eglws); + System.err.println(getThreadName() + ": createHandle of "+eglws); } if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index b390621fa..be3729a7d 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -456,7 +456,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } catch (Throwable t) { if(DEBUG) { - System.err.println("Catched Exception:"); + System.err.println("Catched Exception on thread "+getThreadName()); t.printStackTrace(); } success = false; @@ -597,7 +597,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } catch (GLException gle) { if(DEBUG) { - System.err.println("Catched Exception while EGL Shared Resource initialization"); + System.err.println("Catched Exception on thread "+getThreadName()); gle.printStackTrace(); } } @@ -658,8 +658,6 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target)); } - static String getThreadName() { return Thread.currentThread().getName(); } - @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { if (target == null) { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index f99d89df7..a197bd51f 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -669,7 +669,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl setSwapIntervalImpl(nsOpenGLLayer, interval); // enabled per default in layered surface valid = true; if (DEBUG) { - System.err.println("NSOpenGLLayer.Attach: OK, layer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbuffer)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", drawableHandle "+toHexString(drawable.getHandle())+" - "+Thread.currentThread().getName()); + System.err.println("NSOpenGLLayer.Attach: OK, layer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbuffer)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", drawableHandle "+toHexString(drawable.getHandle())+" - "+getThreadName()); } } finally { MacOSXCGLContext.this.lock.unlock(); @@ -685,7 +685,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl if( !valid ) { // could not acquire lock, re-queue if (DEBUG) { - System.err.println("NSOpenGLLayer.Attach: Re-Queue, drawableHandle "+toHexString(drawable.getHandle())+" - "+Thread.currentThread().getName()); + System.err.println("NSOpenGLLayer.Attach: Re-Queue, drawableHandle "+toHexString(drawable.getHandle())+" - "+getThreadName()); } OSXUtil.RunLater(this, 1); } @@ -713,17 +713,17 @@ public abstract class MacOSXCGLContext extends GLContextImpl ols.detachSurfaceLayer(); } } catch(Throwable t) { - System.err.println("Catched exception @ "+Thread.currentThread().getName()+": "); + System.err.println("Catched Exception on thread "+getThreadName()); t.printStackTrace(); } CGL.releaseNSOpenGLLayer(cmd.nsOpenGLLayer); if(DEBUG) { - System.err.println("NSOpenGLLayer.Detach: OK, layer "+toHexString(cmd.nsOpenGLLayer)+" - "+Thread.currentThread().getName()); + System.err.println("NSOpenGLLayer.Detach: OK, layer "+toHexString(cmd.nsOpenGLLayer)+" - "+getThreadName()); } cmd.nsOpenGLLayer = 0; cmd.valid = false; } else if(DEBUG) { - System.err.println("NSOpenGLLayer.Detach: Skipped "+toHexString(cmd.nsOpenGLLayer)+" - "+Thread.currentThread().getName()); + System.err.println("NSOpenGLLayer.Detach: Skipped "+toHexString(cmd.nsOpenGLLayer)+" - "+getThreadName()); } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index 1daa892ba..910158d1f 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -152,10 +152,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { return getFactoryImpl().getGLDynamicLookupHelper(0); } - protected static String getThreadName() { - return Thread.currentThread().getName(); - } - // Support for "mode switching" as described in MacOSXCGLDrawable public void setOpenGLMode(GLBackendType mode) { if (mode == openGLMode) { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index aaca7c78a..6c647108f 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -291,7 +291,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } } catch (GLException gle) { if(DEBUG) { - System.err.println("Catched Exception while MaxOSXCGL Shared Resource initialization:"); + System.err.println("Catched Exception on thread "+getThreadName()); gle.printStackTrace(); } } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index aea0d7973..d7d6ceab4 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -174,7 +174,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { long pid = GDI.GetCurrentProcess(); if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) { if(DEBUG) { - System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName()); + System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName()); // Thread.dumpStack(); } processAffinityChanges = pid; @@ -194,7 +194,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { " this PID 0x" + Long.toHexString(pid) ); } if(DEBUG) { - System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName()); + System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName()); } GDI.SetProcessAffinityMask(pid, sysMask.get(0)); } @@ -432,7 +432,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } } catch (GLException gle) { if(DEBUG) { - System.err.println("Catched Exception while WindowsWGL Shared Resource initialization"); + System.err.println("Catched Exception on thread "+getThreadName()); gle.printStackTrace(); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index f22bbfc52..2f3940baa 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -360,7 +360,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } } catch (GLException gle) { if(DEBUG) { - System.err.println("Catched Exception while X11GLX Shared Resource initialization"); + System.err.println("Catched Exception on thread "+getThreadName()); gle.printStackTrace(); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java index c15065cfa..6b239a43d 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java @@ -56,7 +56,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable { glXWindow=0; useGLXWindow=false; if(realized) { - updateHandle(); + createHandle(); } } @@ -82,7 +82,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable { } @Override - protected final void updateHandle() { + protected final void createHandle() { if(USE_GLXWINDOW) { X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration(); if(config.getFBConfig()>=0) { |