diff options
Diffstat (limited to 'src/jogl/classes/javax')
14 files changed, 761 insertions, 398 deletions
diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java index 5fa8ce32d..b052769ca 100644 --- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -87,20 +87,20 @@ import jogamp.opengl.Debug; public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { private static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.CapabilitiesChooser", true); - final static int NO_SCORE = -9999999; - final static int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000; - final static int OPAQUE_MISMATCH_PENALTY = 750; - final static int STENCIL_MISMATCH_PENALTY = 500; - final static int MULTISAMPLE_MISMATCH_PENALTY = 500; - final static int MULTISAMPLE_EXTENSION_MISMATCH_PENALTY = 250; // just a little drop, no scale + private final static int NO_SCORE = -9999999; + private final static int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000; + private final static int OPAQUE_MISMATCH_PENALTY = 750; + private final static int STENCIL_MISMATCH_PENALTY = 500; + private final static int MULTISAMPLE_MISMATCH_PENALTY = 500; + private final static int MULTISAMPLE_EXTENSION_MISMATCH_PENALTY = 250; // just a little drop, no scale // Pseudo attempt to keep equal rank penalties scale-equivalent // (e.g., stencil mismatch is 3 * accum because there are 3 accum // components) - final static int COLOR_MISMATCH_PENALTY_SCALE = 36; - final static int DEPTH_MISMATCH_PENALTY_SCALE = 6; - final static int ACCUM_MISMATCH_PENALTY_SCALE = 1; - final static int STENCIL_MISMATCH_PENALTY_SCALE = 3; - final static int MULTISAMPLE_MISMATCH_PENALTY_SCALE = 3; + private final static int COLOR_MISMATCH_PENALTY_SCALE = 36; + private final static int DEPTH_MISMATCH_PENALTY_SCALE = 6; + private final static int ACCUM_MISMATCH_PENALTY_SCALE = 1; + private final static int STENCIL_MISMATCH_PENALTY_SCALE = 3; + private final static int MULTISAMPLE_MISMATCH_PENALTY_SCALE = 3; @Override public int chooseCapabilities(final CapabilitiesImmutable desired, @@ -150,11 +150,20 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { if (cur == null) { continue; } - if (gldes.isOnscreen() != cur.isOnscreen()) { - continue; + if (gldes.isOnscreen() && !cur.isOnscreen()) { + continue; // requested onscreen, but n/a } - if (!gldes.isOnscreen() && gldes.isPBuffer() && !cur.isPBuffer()) { - continue; // only skip if requested Offscreen && PBuffer, but no PBuffer available + if (!gldes.isOnscreen()) { + /** FBO is generic .. + if (gldes.isFBO() && !cur.isFBO()) { + continue; // requested FBO, but n/a + } */ + if (gldes.isPBuffer() && !cur.isPBuffer()) { + continue; // requested pBuffer, but n/a + } + if (gldes.isBitmap() && !cur.isBitmap()) { + continue; // requested pBuffer, but n/a + } } if (gldes.getStereo() != cur.getStereo()) { continue; diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index 0b2c664fe..38f1746f9 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -115,6 +115,12 @@ public interface GLAutoDrawable extends GLDrawable { public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true); /** + * If the implementation uses delegation, return the delegated {@link GLDrawable} instance, + * otherwise return <code>this</code> instance. + */ + public GLDrawable getDelegatedDrawable(); + + /** * Returns the context associated with this drawable. The returned * context will be synchronized. * Don't rely on it's identity, the context may change. @@ -124,23 +130,31 @@ public interface GLAutoDrawable extends GLDrawable { /** * Associate a new context to this drawable and also propagates the context/drawable switch by * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}. - * <code>drawable</code> might be an inner GLDrawable instance if using such a delegation pattern, - * or this GLAutoDrawable itself. - * <p> - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - * </p> + * <code>drawable</code> might be an inner GLDrawable instance if using a delegation pattern, + * or this GLAutoDrawable instance. * <p> * If the old or new context was current on this thread, it is being released before switching the drawable. * The new context will be made current afterwards, if it was current before. - * However the user shall take extra care that not other thread - * attempts to make this context current. Otherwise a race condition may happen. + * However the user shall take extra care that no other thread + * attempts to make this context current. + * </p> + * <p> + * Be aware that the old context is still bound to the drawable, + * and that one context can only be bound to one drawable at one time! * </p> * <p> - * <b>Disclaimer</b>: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! + * In case you do not intend to use the old context anymore, i.e. + * not assigning it to another drawable, it shall be + * destroyed before setting the new context, i.e.: + * <pre> + GLContext oldCtx = glad.getContext(); + if(null != oldCtx) { + oldCtx.destroy(); + } + glad.setContext(newCtx); + * </pre> + * This is required, since a context must have a valid drawable at all times + * and this API shall not restrict the user in any way. * </p> * * @param newCtx the new context diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java deleted file mode 100644 index 67e81270d..000000000 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright 2012 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 javax.media.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; - -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -import jogamp.opengl.Debug; -import jogamp.opengl.GLAutoDrawableBase; -import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLDrawableImpl; - - -/** - * Fully functional {@link GLAutoDrawable} implementation - * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. - * <p> - * Since no native windowing system events are being processed, it is recommended - * to handle at least: - * <ul> - * <li>{@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #defaultWindowRepaintOp()}</li> - * <li>{@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #defaultWindowResizedOp()}</li> - * <li>{@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #defaultWindowDestroyNotifyOp()}</li> - * </ul> - * </p> - * <p> - * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. - * </p> - */ -public class GLAutoDrawableDelegate extends GLAutoDrawableBase { - public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. - * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass <code>false</code>. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. - */ - public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) { - super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice); - this.upstreamWidget = null; - } - - // - // expose default methods - // - - public final void windowRepaintOp() { - super.defaultWindowRepaintOp(); - } - - public final void windowResizedOp() { - super.defaultWindowResizedOp(); - } - - public final void windowDestroyNotifyOp() { - super.defaultWindowDestroyNotifyOp(); - } - - // - // Complete GLAutoDrawable - // - - private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock - private final Object upstreamWidget; - - @Override - protected final RecursiveLock getLock() { return lock; } - - @Override - public final Object getUpstreamWidget() { - return upstreamWidget; - } - - /** - * {@inheritDoc} - * <p> - * This implementation calls {@link #defaultDestroy()}. - * </p> - * <p> - * User still needs to destroy the upstream window, which details are hidden from this aspect. - * This can be performed by overriding {@link #destroyImplInLock()}. - * </p> - */ - @Override - public final void destroy() { - defaultDestroy(); - } - - @Override - public void display() { - defaultDisplay(); - } - - // - // GLDrawable delegation - // - - @Override - public final GLDrawableFactory getFactory() { - return drawable.getFactory(); - } - - @Override - public final void setRealized(boolean realized) { - } - - @Override - public final void swapBuffers() throws GLException { - defaultSwapBuffers(); - } - -} diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index f5831a72d..9bcee819a 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -273,6 +273,42 @@ public interface GLBase { */ public boolean isExtensionAvailable(String glExtensionName); + /** + * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>. + * <p> + * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>. + * </p> + * <p> + * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + * </p> + * @see GLContext#hasBasicFBOSupport() + */ + public boolean hasBasicFBOSupport(); + + /** + * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>. + * <p> + * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * <code>ARB_framebuffer_object</code>, or all of + * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>, + * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>. + * </p> + * <p> + * Full FBO support includes multiple color attachments and multisampling. + * </p> + * @see GLContext#hasFullFBOSupport() + */ + public boolean hasFullFBOSupport(); + + /** + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. + * @see GLContext#getMaxRenderbufferSamples() + */ + public int getMaxRenderbufferSamples(); + /** * Returns true if the GL context supports non power of two (NPOT) textures, * otherwise false. @@ -284,6 +320,8 @@ public interface GLBase { */ public boolean isNPOTTextureAvailable(); + 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 diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java index 8845ec665..9b004a0af 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java @@ -102,23 +102,52 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil } } + /** + * Copies all {@link GLCapabilities} and {@link Capabilities} values + * from <code>source</code> into this instance. + * @return this instance + */ + public GLCapabilities copyFrom(GLCapabilitiesImmutable source) { + super.copyFrom(source); + glProfile = source.getGLProfile(); + isPBuffer = source.isPBuffer(); + isFBO = source.isFBO(); + doubleBuffered = source.getDoubleBuffered(); + stereo = source.getStereo(); + hardwareAccelerated = source.getHardwareAccelerated(); + depthBits = source.getDepthBits(); + stencilBits = source.getStencilBits(); + accumRedBits = source.getAccumRedBits(); + accumGreenBits = source.getAccumGreenBits(); + accumBlueBits = source.getAccumBlueBits(); + accumAlphaBits = source.getAccumAlphaBits(); + sampleBuffers = source.getSampleBuffers(); + pbufferFloatingPointBuffers = source.getPbufferFloatingPointBuffers(); + pbufferRenderToTexture = source.getPbufferRenderToTexture(); + pbufferRenderToTextureRectangle = source.getPbufferRenderToTextureRectangle(); + numSamples = source.getNumSamples(); + sampleExtension = source.getSampleExtension(); + return this; + } + @Override public int hashCode() { // 31 * x == (x << 5) - x - int hash = 31 + this.glProfile.hashCode() ; + int hash = super.hashCode(); + hash = ((hash << 5) - hash) + this.glProfile.hashCode() ; + hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 ); + hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 ); hash = ((hash << 5) - hash) + ( this.isFBO ? 1 : 0 ); hash = ((hash << 5) - hash) + ( this.isPBuffer ? 1 : 0 ); - hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 ); - hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 ); + hash = ((hash << 5) - hash) + ( this.sampleBuffers ? 1 : 0 ); + hash = ((hash << 5) - hash) + this.getNumSamples(); + hash = ((hash << 5) - hash) + this.sampleExtension.hashCode(); hash = ((hash << 5) - hash) + this.depthBits; hash = ((hash << 5) - hash) + this.stencilBits; hash = ((hash << 5) - hash) + this.accumRedBits; hash = ((hash << 5) - hash) + this.accumGreenBits; hash = ((hash << 5) - hash) + this.accumBlueBits; hash = ((hash << 5) - hash) + this.accumAlphaBits; - hash = ((hash << 5) - hash) + ( this.sampleBuffers ? 1 : 0 ); - hash = ((hash << 5) - hash) + this.numSamples; - hash = ((hash << 5) - hash) + this.sampleExtension.hashCode(); hash = ((hash << 5) - hash) + ( this.pbufferFloatingPointBuffers ? 1 : 0 ); hash = ((hash << 5) - hash) + ( this.pbufferRenderToTexture ? 1 : 0 ); hash = ((hash << 5) - hash) + ( this.pbufferRenderToTextureRectangle ? 1 : 0 ); @@ -136,6 +165,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil other.getGLProfile()==glProfile && other.isPBuffer()==isPBuffer && other.isFBO()==isFBO && + other.getDoubleBuffered() == doubleBuffered && other.getStereo()==stereo && other.getHardwareAccelerated()==hardwareAccelerated && other.getDepthBits()==depthBits && @@ -148,9 +178,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil other.getPbufferFloatingPointBuffers()==pbufferFloatingPointBuffers && other.getPbufferRenderToTexture()==pbufferRenderToTexture && other.getPbufferRenderToTextureRectangle()==pbufferRenderToTextureRectangle; - if(sampleBuffers) { - res = res && - other.getNumSamples()==numSamples && + if(res && sampleBuffers) { + res = other.getNumSamples()==getNumSamples() && other.getSampleExtension().equals(sampleExtension) ; } return res; @@ -222,19 +251,24 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil public void setGLProfile(GLProfile profile) { glProfile=profile; } - + @Override public final boolean isPBuffer() { return isPBuffer; } /** - * Enables or disables pbuffer usage. + * Requesting offscreen pbuffer mode. * <p> * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}. * </p> + * <p> * Defaults to false. - */ + * </p> + * <p> + * Requesting offscreen pbuffer mode disables the offscreen auto selection. + * </p> + */ public void setPBuffer(boolean enable) { if(enable) { setOnscreen(false); @@ -248,11 +282,16 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil } /** - * Enables or disables FBO usage. + * Requesting offscreen FBO mode. * <p> * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}. * </p> + * <p> * Defaults to false. + * </p> + * <p> + * Requesting offscreen FBO mode disables the offscreen auto selection. + * </p> */ public void setFBO(boolean enable) { if(enable) { @@ -261,21 +300,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil isFBO = enable; } - /** - * Sets whether the drawable surface supports onscreen.<br> - * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)} - * and {@link #setFBO(int) setFBO(false)}<br> - * Defaults to true. - */ - @Override - public void setOnscreen(boolean onscreen) { - if(onscreen) { - setPBuffer(false); - setFBO(false); - } - super.setOnscreen(onscreen); - } - @Override public final boolean getDoubleBuffered() { return doubleBuffered; @@ -465,9 +489,9 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil sink = new StringBuilder(); } - int samples = sampleBuffers ? numSamples : 0 ; + final int samples = sampleBuffers ? numSamples : 0 ; - super.toString(sink); + super.toString(sink, false); sink.append(", accum-rgba ").append(accumRedBits).append("/").append(accumGreenBits).append("/").append(accumBlueBits).append("/").append(accumAlphaBits); sink.append(", dp/st/ms: ").append(depthBits).append("/").append(stencilBits).append("/").append(samples); @@ -490,20 +514,37 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil sink.append(", sw, "); } sink.append(glProfile); - if(!isOnscreen()) { - if(isFBO) { - sink.append(", fbo"); - } - if(isPBuffer) { - sink.append(", pbuffer [r2t ").append(pbufferRenderToTexture?1:0) - .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0) - .append(", float ").append(pbufferFloatingPointBuffers?1:0) - .append("]"); - } - if(!isFBO && !isPBuffer) { - sink.append(", pixmap"); + if(isOnscreen()) { + sink.append(", on-scr["); + } else { + sink.append(", offscr["); + } + boolean ns=false; + if(isFBO()) { + sink.append("fbo"); + ns = true; + } + if(isPBuffer()) { + if(ns) { sink.append(", "); } + sink.append("pbuffer [r2t ").append(pbufferRenderToTexture?1:0) + .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0) + .append(", float ").append(pbufferFloatingPointBuffers?1:0) + .append("]"); + ns = true; + } + if(isBitmap()) { + if(ns) { sink.append(", "); } + sink.append("bitmap"); + ns = true; + } + if(!ns) { // !FBO !PBuffer !Bitmap + if(isOnscreen()) { + sink.append("."); // no additional off-screen modes besides on-screen + } else { + sink.append("auto-cfg"); // auto-config off-screen mode } } + sink.append("]"); return sink; } diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java index 7e0459b2d..ee261ca01 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java @@ -50,7 +50,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { GLProfile getGLProfile(); /** - * Returns the number of bits requested for the accumulation + * Returns the number of bits for the accumulation * buffer's alpha component. On some systems only the accumulation * buffer depth, which is the sum of the red, green, and blue bits, * is considered. @@ -58,7 +58,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { int getAccumAlphaBits(); /** - * Returns the number of bits requested for the accumulation + * Returns the number of bits for the accumulation * buffer's blue component. On some systems only the accumulation * buffer depth, which is the sum of the red, green, and blue bits, * is considered. @@ -66,7 +66,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { int getAccumBlueBits(); /** - * Returns the number of bits requested for the accumulation + * Returns the number of bits for the accumulation * buffer's green component. On some systems only the accumulation * buffer depth, which is the sum of the red, green, and blue bits, * is considered. @@ -74,7 +74,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { int getAccumGreenBits(); /** - * Returns the number of bits requested for the accumulation + * Returns the number of bits for the accumulation * buffer's red component. On some systems only the accumulation * buffer depth, which is the sum of the red, green, and blue bits, * is considered. @@ -82,74 +82,115 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { int getAccumRedBits(); /** - * Returns the number of bits requested for the depth buffer. + * Returns the number of depth buffer bits. */ int getDepthBits(); /** - * Indicates whether double-buffering is enabled. + * Returns whether double-buffering is requested, available or chosen. + * <p> + * Default is true. + * </p> */ boolean getDoubleBuffered(); /** - * Indicates whether hardware acceleration is enabled. + * Returns whether hardware acceleration is requested, available or chosen. + * <p> + * Default is true. + * </p> */ boolean getHardwareAccelerated(); /** - * Returns the used extension for full-scene antialiasing - * (FSAA), default is {@link #DEFAULT_SAMPLE_EXTENSION}. + * Returns the extension for full-scene antialiasing + * (FSAA). + * <p> + * Default is {@link #DEFAULT_SAMPLE_EXTENSION}. + * </p> */ String getSampleExtension(); /** * Returns whether sample buffers for full-scene antialiasing - * (FSAA) should be allocated for this drawable. Defaults to - * false. + * (FSAA) should be allocated for this drawable. + * <p> + * Default is false. + * </p> */ boolean getSampleBuffers(); /** * Returns the number of sample buffers to be allocated if sample - * buffers are enabled, otherwise returns 0. Defaults to 2. + * buffers are enabled, otherwise returns 0. + * <p> + * Default is 0 due to disable sample buffers per default. + * </p> */ int getNumSamples(); /** * For pbuffers only, returns whether floating-point buffers should - * be used if available. Defaults to false. + * be used if available. + * <p> + * Default is false. + * </p> */ boolean getPbufferFloatingPointBuffers(); /** * For pbuffers only, returns whether the render-to-texture - * extension should be used if available. Defaults to false. + * extension should be used if available. + * <p> + * Default is false. + * </p> */ boolean getPbufferRenderToTexture(); /** * For pbuffers only, returns whether the render-to-texture - * extension should be used. Defaults to false. + * extension should be used. + * <p> + * Default is false. + * </p> */ boolean getPbufferRenderToTextureRectangle(); /** - * Returns the number of bits requested for the stencil buffer. + * Returns the number of stencil buffer bits. + * <p> + * Default is 0. + * </p> */ int getStencilBits(); /** - * Indicates whether stereo is enabled. + * Returns whether stereo is requested, available or chosen. + * <p> + * Default is false. + * </p> */ boolean getStereo(); /** - * Indicates whether pbuffer offscreen is used/requested. + * Returns whether pbuffer offscreen mode is requested, available or chosen. + * <p> + * Default is false. + * </p> + * <p> + * For chosen capabilities, only the selected offscreen surface is set to <code>true</code>. + * </p> */ boolean isPBuffer(); /** - * Indicates whether FBO offscreen is used/requested. + * Returns whether FBO offscreen mode is requested, available or chosen. + * <p> + * Default is false. + * </p> + * <p> + * For chosen capabilities, only the selected offscreen surface is set to <code>true</code>. + * </p> */ boolean isFBO(); diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index a2ce619e7..a5e639c74 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -52,7 +52,6 @@ import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import com.jogamp.common.os.Platform; -import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.opengl.GLExtensions; @@ -97,6 +96,9 @@ public abstract class GLContext { */ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true); + protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true); + protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true); + public static final boolean DEBUG = Debug.debug("GLContext"); public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true); @@ -128,9 +130,9 @@ public abstract class GLContext { /** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8; - /** Context supports basic FBO, details see {@link #hasFBO()}. + /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}. * Not a cache key. - * @see #hasFBO() + * @see #hasBasicFBOSupport() * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile) */ protected static final int CTX_IMPL_FBO = 1 << 9; @@ -140,8 +142,7 @@ public abstract class GLContext { private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>(); - private final HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>(); - private final IntObjectHashMap attachedObjectsByInt = new IntObjectHashMap(); + private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>(); // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock. protected final RecursiveLock lock = LockFactory.createRecursiveLock(); @@ -168,8 +169,7 @@ public abstract class GLContext { ctxMinorVersion=-1; ctxOptions=0; ctxVersionString=null; - attachedObjectsByString.clear(); - attachedObjectsByInt.clear(); + attachedObjects.clear(); contextHandle=0; currentSwapInterval = -1; } @@ -181,11 +181,6 @@ public abstract class GLContext { * and made current afterwards. However the user shall take extra care that not other thread * attempts to make this context current. Otherwise a race condition may happen. * </p> - * <p> - * <b>Disclaimer</b>: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! - * </p> * @param readWrite the read/write drawable for framebuffer operations. * @param setWriteOnly if <code>true</code> and if the current read-drawable differs * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}), @@ -425,27 +420,8 @@ public abstract class GLContext { /** * Returns the attached user object for the given name to this GLContext. */ - public final Object getAttachedObject(int name) { - return attachedObjectsByInt.get(name); - } - - /** - * Returns the attached user object for the given name to this GLContext. - */ public final Object getAttachedObject(String name) { - return attachedObjectsByString.get(name); - } - - /** - * Sets the attached user object for the given name to this GLContext. - * Returns the previously set object or null. - */ - public final Object attachObject(int name, Object obj) { - return attachedObjectsByInt.put(name, obj); - } - - public final Object detachObject(int name) { - return attachedObjectsByInt.remove(name); + return attachedObjects.get(name); } /** @@ -453,11 +429,11 @@ public abstract class GLContext { * Returns the previously set object or null. */ public final Object attachObject(String name, Object obj) { - return attachedObjectsByString.put(name, obj); + return attachedObjects.put(name, obj); } public final Object detachObject(String name) { - return attachedObjectsByString.remove(name); + return attachedObjects.remove(name); } /** @@ -625,12 +601,23 @@ public abstract class GLContext { /** * @return true if impl. is a hardware rasterizer, otherwise false. + * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile) * @see GLProfile#isHardwareRasterizer() */ public final boolean isHardwareRasterizer() { return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ; } + /** + * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} <i>and</i> major-version > 1. + * @see GLProfile#hasGLSL() + */ + public final boolean hasGLSL() { + return isGLES2() || + isGL3() || + isGL2() && ctxMajorVersion>1 ; + } + /** * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>. * <p> @@ -642,21 +629,54 @@ public abstract class GLContext { * as well as limited internal formats for renderbuffer. * </p> * @see #CTX_IMPL_FBO - * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) - * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ - public final boolean hasFBO() { + public final boolean hasBasicFBOSupport() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; } + /** + * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>. + * <p> + * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * <code>ARB_framebuffer_object</code>, or all of + * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>, + * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>. + * </p> + * <p> + * Full FBO support includes multiple color attachments and multisampling. + * </p> + */ + public final boolean hasFullFBOSupport() { + return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() && + ( isGL3() || // GL >= 3.0 + isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) + ) + ) ; + } + /** - * @return true if context supports GLSL - * @see GLProfile#hasGLSL() + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. */ - public final boolean hasGLSL() { - return isGL2ES2() ; + public final int getMaxRenderbufferSamples() { + if( hasFullFBOSupport() ) { + final GL gl = getGL(); + final int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + final int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + return val[0]; + } else if(DEBUG) { + System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + return 0; } - + /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */ public boolean isNPOTTextureAvailable() { return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two); @@ -1036,6 +1056,9 @@ public abstract class GLContext { 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(); @@ -1219,18 +1242,36 @@ public abstract class GLContext { * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. * </p> * <p> - * FBO support is queried as described in {@link #hasFBO()}. + * FBO support is queried as described in {@link #hasBasicFBOSupport()}. * </p> * * @param device the device to request whether FBO is available for * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() + * @see GLContext#hasBasicFBOSupport() */ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); } /** + * @return <code>1</code> if using a hardware rasterizer, <code>0</code> if using a software rasterizer and <code>-1</code> if not determined yet. + * @see GLContext#isHardwareRasterizer() + * @see GLProfile#isHardwareRasterizer() + */ + public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) { + final int r; + final int ctp = getAvailableContextProperties(device, glp); + if(0 == ctp) { + r = -1; + } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) { + r = 1; + } else { + r = 0; + } + return r; + } + + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index acda45bff..b6e7b0576 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -48,14 +48,16 @@ import java.util.List; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.opengl.GLAutoDrawableDelegate; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; -import javax.media.opengl.GLProfile.ShutdownType; +import javax.media.nativewindow.UpstreamSurfaceHook; import jogamp.opengl.Debug; @@ -106,6 +108,7 @@ public abstract class GLDrawableFactory { // Shutdown hook mechanism for the factory private static boolean factoryShutdownHookRegistered = false; private static Thread factoryShutdownHook = null; + private static volatile boolean isJVMShuttingDown = false; /** * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones. @@ -176,21 +179,24 @@ public abstract class GLDrawableFactory { } } - protected static void shutdown(ShutdownType shutdownType) { + protected static void shutdown() { if (isInit) { // volatile: ok synchronized (GLDrawableFactory.class) { if (isInit) { isInit=false; - unregisterFactoryShutdownHook(); - shutdownImpl(shutdownType); + shutdownImpl(); } } } } - private static void shutdownImpl(ShutdownType shutdownType) { + + private static void shutdownImpl() { + // Following code will _always_ remain in shutdown hook + // due to special semantics of native utils, i.e. X11Utils. + // The latter requires shutdown at JVM-Shutdown only. synchronized(glDrawableFactories) { for(int i=0; i<glDrawableFactories.size(); i++) { - glDrawableFactories.get(i).destroy(shutdownType); + glDrawableFactories.get(i).destroy(); } glDrawableFactories.clear(); @@ -198,6 +204,8 @@ public abstract class GLDrawableFactory { nativeOSFactory = null; eglFactory = null; } + GLContext.shutdown(); + NativeWindowFactory.shutdown(isJVMShuttingDown); } private static synchronized void registerFactoryShutdownHook() { @@ -206,7 +214,8 @@ public abstract class GLDrawableFactory { } factoryShutdownHook = new Thread(new Runnable() { public void run() { - GLDrawableFactory.shutdownImpl(GLProfile.ShutdownType.COMPLETE); + isJVMShuttingDown = true; + GLDrawableFactory.shutdownImpl(); } }); AccessController.doPrivileged(new PrivilegedAction<Object>() { @@ -218,20 +227,6 @@ public abstract class GLDrawableFactory { factoryShutdownHookRegistered = true; } - private static synchronized void unregisterFactoryShutdownHook() { - if (!factoryShutdownHookRegistered) { - return; - } - AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - Runtime.getRuntime().removeShutdownHook(factoryShutdownHook); - return null; - } - }); - factoryShutdownHookRegistered = false; - } - - protected GLDrawableFactory() { synchronized(glDrawableFactories) { glDrawableFactories.add(this); @@ -244,7 +239,7 @@ public abstract class GLDrawableFactory { protected void enterThreadCriticalZone() {}; protected void leaveThreadCriticalZone() {}; - protected abstract void destroy(ShutdownType shutdownType); + protected abstract void destroy(); /** * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection}, @@ -381,44 +376,100 @@ public abstract class GLDrawableFactory { // Methods to create high-level objects /** - * Returns a GLDrawable according to it's chosen Capabilities,<br> + * Returns a GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br> * which determines pixel format, on- and offscreen incl. PBuffer type. * <p> - * The native platform's chosen Capabilties are referenced within the target - * NativeSurface's AbstractGraphicsConfiguration.<p> - * - * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is true,<br> - * an onscreen GLDrawable will be realized. + * The chosen {@link GLCapabilitiesImmutable} are referenced within the target + * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.<p> + * </p> * <p> - * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is false,<br> - * either a Pbuffer drawable is created if target's {@link javax.media.opengl.GLCapabilities#isPBuffer()} is true,<br> - * or a simple pixmap/bitmap drawable is created. The latter is unlikely to be hardware accelerated.<br> + * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true. + * </p> * <p> - * + * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + * </p> + * <p> + * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * </p> + * <p> + * If not onscreen and neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + * </p> + * * @throws IllegalArgumentException if the passed target is null * @throws GLException if any window system-specific errors caused * the creation of the GLDrawable to fail. * + * @see #canCreateGLPbuffer(AbstractGraphicsDevice) + * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) + * @see javax.media.opengl.GLCapabilities#isOnscreen() + * @see javax.media.opengl.GLCapabilities#isFBO() + * @see javax.media.opengl.GLCapabilities#isPBuffer() * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ public abstract GLDrawable createGLDrawable(NativeSurface target) throws IllegalArgumentException, GLException; - + + /** + * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + * <p> + * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current. + * </p> + * <p> + * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e. + * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>, + * it is auto-configured. The latter will set offscreen and also FBO <i>or</i> Pbuffer, whichever is available in that order. + * </p> + * <p> + * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + * </p> + * <p> + * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * </p> + * <p> + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated. + * </p> + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device. + * @param caps the requested GLCapabilties + * @param chooser the custom chooser, may be null for default + * @param width the requested offscreen width + * @param height the requested offscreen height + * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance + * + * @throws GLException if any window system-specific errors caused + * the creation of the Offscreen to fail. + * + * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) + */ + public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device, + GLCapabilitiesImmutable caps, + GLCapabilitiesChooser chooser, + int width, int height, + GLContext shareWith) throws GLException; /** - * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. * <p> - * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e. + * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>, + * it is auto-configured. The latter will set offscreen and also FBO <i>or</i> Pbuffer, whichever is available in that order. * </p> * <p> - * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. * </p> * <p> - * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. * </p> * <p> - * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated. * </p> * * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device. @@ -427,16 +478,17 @@ public abstract class GLDrawableFactory { * @param width the requested offscreen width * @param height the requested offscreen height * - * @return the created offscreen GLDrawable + * @return the created offscreen {@link GLDrawable} * * @throws GLException if any window system-specific errors caused * the creation of the Offscreen to fail. + * + * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) */ public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device, - GLCapabilitiesImmutable capabilities, + GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, - int width, int height) - throws GLException; + int width, int height) throws GLException; /** * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance. @@ -467,6 +519,21 @@ public abstract class GLDrawableFactory { GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); /** + * Returns true if it is possible to create an <i>framebuffer object</i> (FBO). + * <p> + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + * </p> + * <p> + * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}. + * </p> + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device. + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasBasicFBOSupport() + */ + public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp); + + /** * Returns true if it is possible to create a GLPbuffer. Some older * graphics cards do not have this capability. * @@ -475,7 +542,10 @@ public abstract class GLDrawableFactory { public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device); /** - * Creates a GLPbuffer with the given capabilites and dimensions. <P> + * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions. + * <p> + * The GLPbuffer drawable is realized and initialized eagerly. + * </p> * * See the note in the overview documentation on * <a href="../../../overview-summary.html#SHARING">context sharing</a>. @@ -487,10 +557,12 @@ public abstract class GLDrawableFactory { * @param initialHeight initial height of pbuffer * @param shareWith a shared GLContext this GLPbuffer shall use * - * @return the new {@link GLPbuffer} specific {@link GLAutoDrawable} + * @return the created and initialized {@link GLPbuffer} instance * * @throws GLException if any window system-specific errors caused * the creation of the GLPbuffer to fail. + * + * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)} */ public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device, GLCapabilitiesImmutable capabilities, diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java new file mode 100644 index 000000000..45fd3b686 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java @@ -0,0 +1,173 @@ +/** + * Copyright 2012 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 javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; + +/** + * Platform-independent {@link GLDrawable} specialization, + * exposing {@link FBObject} functionality. + * + * <p> + * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound + * and made current the first time. + * </p> + * + * <p> + * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}. + * </p> + * <p> + * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}. + * </p> + * <p> + * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}. + * Hence double buffering is always the case w/ MSAA. + * </p> + * <p> + * In non MSAA a second explicit {@link FBObject framebuffer} is being used. + * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection + * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}. + * This method also allows usage of both textures seperately. + * </p> + * <p> + * It would be possible to implement double buffering simply using + * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}. + * This would require mode selection and hence complicate the API. Besides, it would + * not support differentiation of read and write framebuffer and hence not be spec compliant. + * </p> + * <p> + * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer} + * is performed either in the {@link #contextMadeCurrent(boolean) context current hook} + * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.<br/> + * </p> + */ +public interface GLFBODrawable extends GLDrawable { + // public enum DoubleBufferMode { NONE, TEXTURE, FBO }; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * @return <code>true</code> if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise <code>false</code>. + */ + public boolean isInitialized(); + + /** + * Notify this instance about upstream size change + * to reconfigure the {@link FBObject}. + * @param gl GL context object bound to this drawable, will be made current during operation. + * A prev. current context will be make current after operation. + * @throws GLException if resize operation failed + */ + void resetSize(GL gl) throws GLException; + + /** + * @return the used texture unit + */ + int getTextureUnit(); + + /** + * + * @param unit the texture unit to be used + */ + void setTextureUnit(int unit); + + /** + * Set a new sample size + * @param gl GL context object bound to this drawable, will be made current during operation. + * A prev. current context will be make current after operation. + * @param newSamples new sample size + * @throws GLException if resetting the FBO failed + */ + void setNumSamples(GL gl, int newSamples) throws GLException; + + /** + * @return the number of sample buffers if using MSAA, otherwise 0 + */ + int getNumSamples(); + + /** + * @return the used {@link DoubleBufferMode} + */ + // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization}, + * otherwise an exception is thrown. + * <p> + * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}. + * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested} + * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored. + * </p> + * <p> + * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect. + * </p> + * @throws GLException if already initialized, see {@link #isInitialized()}. + */ + // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * If MSAA is being used and {@link GL#GL_FRONT} is requested, + * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned. + * + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link FBObject} + * @throws IllegalArgumentException if an illegal buffer name is being used + */ + FBObject getFBObject(int bufferName) throws IllegalArgumentException; + + /** + * Returns the named texture buffer. + * <p> + * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible + * and an exception is being thrown if {@link GL#GL_BACK} is being requested. + * </p> + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link TextureAttachment} + * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used + */ + FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException; + + /** Resizeable {@link GLFBODrawable} specialization */ + public interface Resizeable extends GLFBODrawable { + /** + * Resize this drawable. + * <p> + * This drawable is being locked during operation. + * </p> + * @param context the {@link GLContext} bound to this drawable, will be made current during operation + * A prev. current context will be make current after operation. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case an error during the resize operation occurred + */ + void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException; + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java new file mode 100644 index 000000000..6fe76a3f4 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java @@ -0,0 +1,63 @@ +/** + * Copyright 2012 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 javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; + +/** + * Platform-independent {@link GLAutoDrawable} specialization, + * exposing offscreen functionality. + * <p> + * This class distinguishes itself from {@link GLAutoDrawable} + * with it's {@link #setSize(int, int)} functionality. + * </p> + */ +public interface GLOffscreenAutoDrawable extends GLAutoDrawable { + + /** + * Resize this auto drawable. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case of an error during the resize operation + */ + void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException; + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + void setUpstreamWidget(Object newUpstreamWidget); + + /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */ + public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable { + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java index 273a992cf..de7731a3b 100644 --- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java +++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java @@ -45,7 +45,11 @@ package javax.media.opengl; contains experimental methods for accessing the pbuffer's contents as a texture map and enabling rendering to floating-point frame buffers. These methods are not guaranteed to be supported on all - platforms and may be deprecated in a future release. */ + platforms and may be deprecated in a future release. + + @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} + via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}. + */ public interface GLPbuffer extends GLAutoDrawable { /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */ diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 513ccd101..23d789afd 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -198,44 +198,25 @@ public class GLProfile { getProfileMap(device, true); } - /** - * Shutdown type for {@link GLProfile#shutdown(ShutdownType)}. - * <p> - * {@link #SHARED_ONLY} For thread based resources only, suitable for eg. {@link java.applet.Applet Applet} restart.<br> - * {@link #COMPLETE} Everything.<br> - * </p> - */ - public enum ShutdownType { - /* Shared thread based resources only, eg. for Applets */ - SHARED_ONLY, - /* Everything */ - COMPLETE; - } - /** * Manual shutdown method, may be called after your last JOGL use * within the running JVM.<br> * It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.<br> * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked.<br> * <p> - * This method shall not need to be called for other reasons than issuing a proper shutdown of resources. + * This method shall not need to be called for other reasons than issuing a proper shutdown of resources at a defined time. * </p> - * @param type the shutdown type, see {@link ShutdownType}. */ - public static void shutdown(ShutdownType type) { + public static void shutdown() { initLock.lock(); try { if(initialized) { // volatile: ok initialized = false; if(DEBUG) { - System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName()); + System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName()); Thread.dumpStack(); } - GLDrawableFactory.shutdown(type); - if(ShutdownType.COMPLETE == type) { - GLContext.shutdown(); - } - NativeWindowFactory.shutdown(); + GLDrawableFactory.shutdown(); } } finally { initLock.unlock(); @@ -1480,7 +1461,7 @@ public class GLProfile { if(DEBUG) { System.err.println("Info: GLProfile.init - EGL/ES2 ANGLE disabled"); } - eglFactory.destroy(ShutdownType.COMPLETE); + eglFactory.destroy(); eglFactory = null; hasEGLFactory = false; } else { diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 033591fe3..329cf9e3f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -98,6 +98,7 @@ import jogamp.common.awt.AWTEDTExecutor; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on our @@ -109,6 +110,16 @@ import jogamp.opengl.GLDrawableHelper; interfaces when adding a heavyweight doesn't work either because of Z-ordering or LayoutManager problems. * + * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5> + * + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * maybe called to use an offscreen drawable (FBO or PBuffer) allowing + * the underlying JAWT mechanism to composite the image, if supported. + * <p> + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is <code>false</code>. + * </p> + * * <h5><A NAME="java2dgl">Java2D OpenGL Remarks</A></h5> * * To avoid any conflicts with a potential Java2D OpenGL context,<br> @@ -145,7 +156,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); private AWTGraphicsConfiguration awtConfig; - private volatile GLDrawable drawable; // volatile: avoid locking for read-only access + private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle private GLContextImpl context; private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking @@ -237,6 +248,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // don't allow the user to change data capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable(); } + if(!capsReqUser.isOnscreen()) { + setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported + } if(null==device) { GraphicsConfiguration gc = super.getGraphicsConfiguration(); @@ -451,11 +465,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing /** Overridden to cause OpenGL rendering to be performed during repaint cycles. Subclasses which override this method must call super.paint() in their paint() method in order to function - properly. <P> - - <B>Overrides:</B> - <DL><DD><CODE>paint</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ - @Override + properly. + */ + @Override public void paint(Graphics g) { if (Beans.isDesignTime()) { // Make GLCanvas behave better in NetBeans GUI builder @@ -544,7 +556,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); jawtWindow.lockSurface(); try { - drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); + drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); context = (GLContextImpl) drawable.createContext(shareWith); context.setContextCreationFlags(additionalCtxCreationFlags); } finally { @@ -561,13 +573,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if (!Beans.isDesignTime() && 0 < _drawable.getWidth() * _drawable.getHeight() ) { // make sure drawable realization happens on AWT EDT, due to AWTTree lock - AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction); - sendReshape=true; // ensure a reshape is being send .. - if(DEBUG) { - System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString()); - Thread.dumpStack(); + AWTEDTExecutor.singleton.invoke(getTreeLock(), true, setRealizedOnEDTAction); + if( _drawable.isRealized() ) { + sendReshape=true; // ensure a reshape is being send .. + if(DEBUG) { + System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString()); + Thread.dumpStack(); + } + return true; } - return true; } } return false; @@ -575,7 +589,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private Runnable setRealizedOnEDTAction = new Runnable() { @Override public void run() { - drawable.setRealized(true); + final GLDrawable _drawable = drawable; + if ( null != _drawable && 0 < _drawable.getWidth() * _drawable.getHeight() ) { + _drawable.setRealized(true); + } } }; /** <p>Overridden to track when this component is removed from a @@ -620,22 +637,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { - super.reshape(x, y, width, height); - final GLDrawable _drawable = drawable; - if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) { - dispose(true); - } else { - sendReshape = true; + synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape + super.reshape(x, y, width, height); + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } } } - /** <B>Overrides:</B> - <DL><DD><CODE>update</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ /** * Overridden from Canvas to prevent the AWT's clearing of the * canvas from interfering with the OpenGL rendering. */ - @Override + @Override public void update(Graphics g) { paint(g); } @@ -681,7 +713,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing _lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -693,6 +725,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + + @Override public GLContext getContext() { return context; } @@ -866,7 +903,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(!disposeRegenerate) { if(null != awtConfig) { - disposeAbstractGraphicsDevice(); + AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT); } awtConfig=null; } @@ -881,7 +918,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } }; - private final Runnable disposeAbstractGraphicsDeviceAction = new Runnable() { + /** + * Disposes the AbstractGraphicsDevice within EDT, + * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. + * + * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) + */ + private final Runnable disposeAbstractGraphicsDeviceActionOnEDT = new Runnable() { @Override public void run() { if(null != awtConfig) { @@ -900,27 +943,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } }; - - /** - * Disposes the AbstractGraphicsDevice within EDT, - * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. - * - * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) - */ - private void disposeAbstractGraphicsDevice() { - if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { - disposeAbstractGraphicsDeviceAction.run(); - } else { - try { - EventQueue.invokeAndWait(disposeAbstractGraphicsDeviceAction); - } catch (InvocationTargetException e) { - throw new GLException(e.getTargetException()); - } catch (InterruptedException e) { - throw new GLException(e); - } - } - } - + private final Runnable initAction = new Runnable() { @Override public void run() { @@ -1046,7 +1069,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing * @param device * @return the chosen AWTGraphicsConfiguration * - * @see #disposeAbstractGraphicsDevice() + * @see #disposeAbstractGraphicsDeviceActionOnEDT */ private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index acb8f2183..6d4a5861f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -121,7 +121,7 @@ import com.jogamp.opengl.util.GLBuffers; * </P> */ -@SuppressWarnings("serial") +@SuppressWarnings({ "serial", "deprecation" }) public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); @@ -396,7 +396,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing their reshape() method in order to function properly. <P> <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ - @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); @@ -471,7 +470,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return null; } final GLContext oldCtx = backend.getContext(); - final boolean newCtxCurrent = helper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); backend.setContext(newCtx); if(newCtxCurrent) { newCtx.makeCurrent(); @@ -481,6 +480,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override + public final GLDrawable getDelegatedDrawable() { + if (backend == null) { + return null; + } + return backend.getDrawable(); + } + + @Override public GLContext getContext() { if (backend == null) { return null; |