jogl.debug.GLDrawable.PerfStats
is defined. */
private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
private Object listenersLock = new Object();
private ArrayList* Please consider using {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)} * for correctness! *
* @param drawable */ public final void dispose(GLAutoDrawable drawable) { synchronized(listenersLock) { for (int i=0; i < listeners.size(); i++) { listeners.get(i).dispose(drawable); } } } private boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { if(listenersToBeInit.remove(l)) { l.init(drawable); if(sendReshape) { reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false); } return true; } return false; } public final void init(GLAutoDrawable drawable) { synchronized(listenersLock) { for (int i=0; i < listeners.size(); i++) { final GLEventListener listener = listeners.get(i) ; // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), // hence the must always be initialized unconditional. listenersToBeInit.add(listener); if ( ! init( listener, drawable, false ) ) { throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); } } } } public final void display(GLAutoDrawable drawable) { displayImpl(drawable); if(!execGLRunnables(drawable)) { displayImpl(drawable); } } private void displayImpl(GLAutoDrawable drawable) { synchronized(listenersLock) { for (int i=0; i < listeners.size(); i++) { final GLEventListener listener = listeners.get(i) ; // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable init( listener, drawable, true ) ; listener.display(drawable); } } } private void reshape(GLEventListener listener, GLAutoDrawable drawable, int x, int y, int width, int height, boolean setViewport, boolean checkInit) { if(checkInit) { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable init( listener, drawable, false ) ; } if(setViewport) { drawable.getGL().glViewport(x, y, width, height); } listener.reshape(drawable, x, y, width, height); } public final void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { synchronized(listenersLock) { for (int i=0; i < listeners.size(); i++) { reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i, true); } } } private boolean execGLRunnables(GLAutoDrawable drawable) { boolean res = true; if(glRunnables.size()>0) { // swap one-shot list asap ArrayListjogl.debug.GLDrawable.PerfStats
.
*/
public final void setSkipContextReleaseThread(Thread t) {
skipContextReleaseThread = t;
}
/**
* @deprecated see {@link #setSkipContextReleaseThread(Thread)}
*/
public final Thread getSkipContextReleaseThread() {
return skipContextReleaseThread;
}
private static final ThreadLocalNote: Locking of the surface is implicit done by {@link GLContext#makeCurrent()}, where unlocking is performed by the latter {@link GLContext#release()}.
* * @param drawable * @param context * @param runnable * @param initAction */ public final void invokeGL(GLDrawable drawable, GLContext context, Runnable runnable, Runnable initAction) { if(null==context) { if (DEBUG) { Exception e = new GLException(Thread.currentThread().getName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); e.printStackTrace(); } return; } if(PERF_STATS) { invokeGLImplStats(drawable, context, runnable, initAction, null); } else { invokeGLImpl(drawable, context, runnable, initAction, null); } } /** * Principal helper method which runs {@link #dispose(GLAutoDrawable)} with the context * made current and destroys the context afterwards while holding the lock. * * @param autoDrawable * @param drawable * @param context * @param postAction */ public final void disposeGL(GLAutoDrawable autoDrawable, GLDrawable drawable, GLContext context, Runnable postAction) { if(PERF_STATS) { invokeGLImplStats(drawable, context, null, null, autoDrawable); } else { invokeGLImpl(drawable, context, null, null, autoDrawable); } if(null != postAction) { postAction.run(); } } private final void invokeGLImpl(GLDrawable drawable, GLContext context, Runnable runnable, Runnable initAction, GLAutoDrawable disposeAutoDrawable) { final Thread currentThread = Thread.currentThread(); final boolean isDisposeAction = null==initAction ; // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's GLContext lastContext = GLContext.getCurrent(); Runnable lastInitAction = null; if (lastContext != null) { if (lastContext == context) { lastContext = null; // utilize recursive locking } else { lastInitAction = perThreadInitAction.get(); lastContext.release(); } } int res = GLContext.CONTEXT_NOT_CURRENT; try { res = context.makeCurrent(); if (GLContext.CONTEXT_NOT_CURRENT != res) { if(!isDisposeAction) { perThreadInitAction.set(initAction); if (GLContext.CONTEXT_CURRENT_NEW == res) { if (DEBUG) { System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); } initAction.run(); } runnable.run(); if (autoSwapBufferMode) { drawable.swapBuffers(); } } else { if(GLContext.CONTEXT_CURRENT_NEW == res) { throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); } if(listeners.size()>0) { dispose(disposeAutoDrawable); } } } } finally { try { if(isDisposeAction) { context.destroy(); } else if( GLContext.CONTEXT_NOT_CURRENT != res ) { context.release(); } } catch (Exception e) { System.err.println("Catched: "+e.getMessage()); e.printStackTrace(); } if (lastContext != null) { final int res2 = lastContext.makeCurrent(); if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) { lastInitAction.run(); } } } } private final void invokeGLImplStats(GLDrawable drawable, GLContext context, Runnable runnable, Runnable initAction, GLAutoDrawable disposeAutoDrawable) { final Thread currentThread = Thread.currentThread(); final boolean isDisposeAction = null==initAction ; // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's int res = GLContext.CONTEXT_NOT_CURRENT; GLContext lastContext = GLContext.getCurrent(); Runnable lastInitAction = null; if (lastContext != null) { if (lastContext == context) { if( currentThread == skipContextReleaseThread ) { res = GLContext.CONTEXT_CURRENT; } // else: utilize recursive locking lastContext = null; } else { lastInitAction = perThreadInitAction.get(); lastContext.release(); } } long t0 = System.currentTimeMillis(); long tdA = 0; // makeCurrent long tdR = 0; // render time long tdS = 0; // swapBuffers long tdX = 0; // release boolean ctxClaimed = false; boolean ctxReleased = false; boolean ctxDestroyed = false; try { if (res == GLContext.CONTEXT_NOT_CURRENT) { res = context.makeCurrent(); ctxClaimed = true; } if (res != GLContext.CONTEXT_NOT_CURRENT) { if(!isDisposeAction) { perThreadInitAction.set(initAction); if (res == GLContext.CONTEXT_CURRENT_NEW) { if (DEBUG) { System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); } initAction.run(); } tdR = System.currentTimeMillis(); tdA = tdR - t0; // makeCurrent runnable.run(); tdS = System.currentTimeMillis(); tdR = tdS - tdR; // render time if (autoSwapBufferMode) { drawable.swapBuffers(); tdX = System.currentTimeMillis(); tdS = tdX - tdS; // swapBuffers } } else { if(res == GLContext.CONTEXT_CURRENT_NEW) { throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); } if(listeners.size()>0) { dispose(disposeAutoDrawable); } } } } finally { try { if(isDisposeAction) { context.destroy(); ctxDestroyed = true; } else if( res != GLContext.CONTEXT_NOT_CURRENT && (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) { context.release(); ctxReleased = true; } } catch (Exception e) { System.err.println("Catched: "+e.getMessage()); e.printStackTrace(); } tdX = System.currentTimeMillis() - tdX; // release / destroy if (lastContext != null) { final int res2 = lastContext.makeCurrent(); if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) { lastInitAction.run(); } } } 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); } }