summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl/awt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-10-27 17:51:08 +0100
committerSven Gothel <[email protected]>2013-10-27 17:51:08 +0100
commit7f7a23dd0ddf106e6f0c69fc2a05ff92ac56200e (patch)
tree562e5835aecbdd5994d1e85657b3b948f23ff785 /src/jogl/classes/javax/media/opengl/awt
parentff3832bf24f02fc44a7494be49d210cacce43977 (diff)
Bug 776 GLContext Sharing: Refine API for relaxed and lazy GLContext sharing ; Fix GLContext memory contract (volatile)
(Unit test remarks see below) - Add shared GLContext queries - Refined GLContextShareSet: - Use IdentityHashMap since GLContext's can only be identical w/ same reference (footprint, performance) - Add API doc for clarification - Add methods: - ArrayList<GLContext> getCreatedShares(final GLContext context) - ArrayList<GLContext> getDestroyedShares(final GLContext context) - Use 'final' where possible - Add GLContext methods: - boolean isShared() - List<GLContext> getCreatedShares() - List<GLContext> getDestroyedShares() - Add GLSharedContextSetter interface defining setting a shared GLContext directly (GLContext) or via a GLAutoDrawable: - setSharedContext(GLContext) - setSharedAutoDrawable(GLAutoDrawable) Both cause initialization/creation of GLAutoDrawable's drawable/context to be postponed, if the shared GLContext is not yet created natively or the shared GLAutoDrawable's GLContext does not yet exist. Most of impl. resides in GLDrawableHelper Implemented in: - GLAutoDrawableBase, GLOffscreenAutoDrawable - GLWindow - AWT GLCanvas TODO: - GLJPanel - SWT GLCanvas - GLDrawableFactory: - Add 'GLOffscreenAutoDrawable createOffscreenAutoDrawable(..)' variant w/o passing the optional shared GLContext _and_ specifying lazy GLContext creation. This allows to benefit from GLSharedContextSetter contract. Lazy GLContext creation is performed at 2st display() call at the latest. All JOGL code and unit tests use this new method now. - Mark 'createOffscreenAutoDrawable(..)' w/ shared GLContext argument and immediate GLContext creation deprecated - shall be removed in 2.2.0 - Make reference to GLContext and it's native handle volatile Since we rely on the query 'GLContext.isCreated()' to properly allow GLAutoDrawable's to query whether a shared GLContext is natively created (already), the handle must be volatile since such query and the actual creation may operate on different threads. +++++ - Add/Refine shared GLContext unit tests demonstrating diff. sharing methods. All variants of using shared GLContext: com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBO* Most convenient way to share via setSharedAutoDrawable(GLAutoDrawable): com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2[NEWT|AWT]3 AWT use w/ JTabbedPane using setSharedAutoDrawable(GLAutoDrawable): com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextWithJTabbedPaneAWT
Diffstat (limited to 'src/jogl/classes/javax/media/opengl/awt')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java122
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java46
2 files changed, 111 insertions, 57 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 8757c7a26..b070ddd7d 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -81,6 +81,7 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
import javax.media.opengl.Threading;
import com.jogamp.common.GlueGenVersion;
@@ -114,7 +115,7 @@ import jogamp.opengl.awt.AWTTilePainter;
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>
+ * <h5><a name="offscreenlayer">Offscreen Layer Remarks</a></h5>
*
* {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
* maybe called to use an offscreen drawable (FBO or PBuffer) allowing
@@ -124,7 +125,7 @@ import jogamp.opengl.awt.AWTTilePainter;
* is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is <code>false</code>.
* </p>
*
- * <h5><A NAME="java2dgl">Java2D OpenGL Remarks</A></h5>
+ * <h5><a name="java2dgl">Java2D OpenGL Remarks</a></h5>
*
* To avoid any conflicts with a potential Java2D OpenGL context,<br>
* you shall consider setting the following JVM properties:<br>
@@ -141,7 +142,7 @@ import jogamp.opengl.awt.AWTTilePainter;
* <li><pre>sun.java2d.noddraw=true</pre></li>
* </ul>
*
- * <h5><A NAME="backgrounderase">Disable Background Erase</A></h5>
+ * <h5><a name="backgrounderase">Disable Background Erase</a></h5>
*
* GLCanvas tries to disable background erase for the AWT Canvas
* before native peer creation (X11) and after it (Windows), <br>
@@ -153,7 +154,7 @@ import jogamp.opengl.awt.AWTTilePainter;
*/
@SuppressWarnings("serial")
-public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle {
+public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle, GLSharedContextSetter {
private static final boolean DEBUG = Debug.debug("GLCanvas");
@@ -162,18 +163,20 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private AWTGraphicsConfiguration awtConfig;
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 GLContextImpl context;
private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
// copy of the cstr args, mainly for recreation
- private GLCapabilitiesImmutable capsReqUser;
- private GLCapabilitiesChooser chooser;
- private GLContext shareWith;
+ private final GLCapabilitiesImmutable capsReqUser;
+ private final GLCapabilitiesChooser chooser;
private int additionalCtxCreationFlags = 0;
- private GraphicsDevice device;
+ private final GraphicsDevice device;
private boolean shallUseOffscreenLayer = false;
- private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ protected GLContext sharedContext = null;
+ protected GLAutoDrawable sharedAutoDrawable = null;
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
@Override
public void run() {
@@ -207,6 +210,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
*
* @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
* @see GLCanvas#GLCanvas(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, javax.media.opengl.GLContext, java.awt.GraphicsDevice)
+ * @deprecated Use {@link #GLCanvas(GLCapabilitiesImmutable)}
+ * and set shared GLContext via {@link #setSharedContext(GLContext)} or {@link #setSharedAutoDrawable(GLAutoDrawable)}.
*/
public GLCanvas(GLCapabilitiesImmutable capsReqUser, GLContext shareWith)
throws GLException
@@ -219,17 +224,39 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
default set of capabilities is used. The GLCapabilitiesChooser
specifies the algorithm for selecting one of the available
GLCapabilities for the component; a DefaultGLCapabilitesChooser
+ is used if null is passed for this argument.
+ The passed GraphicsDevice indicates the screen on
+ which to create the GLCanvas; the GLDrawableFactory uses the
+ default screen device of the local GraphicsEnvironment if null
+ is passed for this argument.
+ * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
+ */
+ public GLCanvas(GLCapabilitiesImmutable capsReqUser,
+ GLCapabilitiesChooser chooser,
+ GraphicsDevice device)
+ throws GLException
+ {
+ this(capsReqUser, chooser, null, device);
+ }
+
+ /** Creates a new GLCanvas component. The passed GLCapabilities
+ specifies the OpenGL capabilities for the component; if null, a
+ default set of capabilities is used. The GLCapabilitiesChooser
+ specifies the algorithm for selecting one of the available
+ GLCapabilities for the component; a DefaultGLCapabilitesChooser
is used if null is passed for this argument. The passed
GLContext specifies an OpenGL context with which to share
textures, display lists and other OpenGL state, and may be null
if sharing is not desired. See the note in the overview
documentation on <a
- href="../../../overview-summary.html#SHARING">context
+ href="../../../spec-summary.html#SHARING">context
sharing</a>. The passed GraphicsDevice indicates the screen on
which to create the GLCanvas; the GLDrawableFactory uses the
default screen device of the local GraphicsEnvironment if null
is passed for this argument.
* @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
+ * @deprecated Use {@link #GLCanvas(GLCapabilitiesImmutable, GLCapabilitiesChooser, GraphicsDevice)}
+ * and set shared GLContext via {@link #setSharedContext(GLContext)} or {@link #setSharedAutoDrawable(GLAutoDrawable)}.
*/
public GLCanvas(GLCapabilitiesImmutable capsReqUser,
GLCapabilitiesChooser chooser,
@@ -266,11 +293,21 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// instantiation will be issued in addNotify()
this.capsReqUser = capsReqUser;
this.chooser = chooser;
- this.shareWith = shareWith;
+ this.sharedContext = shareWith;
this.device = device;
}
@Override
+ public final void setSharedContext(GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.context, sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
+ @Override
public final Object getUpstreamWidget() {
return this;
}
@@ -383,7 +420,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
destroyImpl( true );
// recreation!
awtConfig = config;
- createDrawableAndContext( true );
+ createJAWTDrawableAndContext();
validateGLDrawable();
} else {
awtConfig = config;
@@ -592,7 +629,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// after native peer is valid: Windows
disableBackgroundErase();
- createDrawableAndContext( true );
+ createJAWTDrawableAndContext();
// init drawable by paint/display makes the init sequence more equal
// for all launch flavors (applet/javaws/..)
@@ -608,22 +645,35 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
- private void createDrawableAndContext(boolean createJAWTWindow) {
+ private void createJAWTDrawableAndContext() {
if ( !Beans.isDesignTime() ) {
- if( createJAWTWindow ) {
- jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
- jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
- }
+ jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
jawtWindow.lockSurface();
try {
drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
- context = (GLContextImpl) drawable.createContext(shareWith);
- context.setContextCreationFlags(additionalCtxCreationFlags);
+ createContextImpl(drawable);
} finally {
jawtWindow.unlockSurface();
}
}
}
+ private boolean createContextImpl(final GLDrawable drawable) {
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ context = (GLContextImpl) drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Context created: has shared "+(null != shareWith[0]));
+ }
+ return true;
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Context !created: pending share");
+ }
+ return false;
+ }
+ }
private boolean validateGLDrawable() {
if( Beans.isDesignTime() || !isDisplayable() ) {
@@ -631,17 +681,22 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
final GLDrawable _drawable = drawable;
if ( null != _drawable ) {
- if( _drawable.isRealized() ) {
- return true;
- }
- if( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
- return false; // early out!
+ boolean res = _drawable.isRealized();
+ if( !res ) {
+ // re-try drawable creation
+ if( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
+ return false; // early out!
+ }
+ setRealized(true);
+ res = _drawable.isRealized();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
+ // Thread.dumpStack();
+ }
}
- setRealized(true);
- final boolean res = _drawable.isRealized();
- if(DEBUG) {
- System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
- // Thread.dumpStack();
+ if( res && null == context ) {
+ // re-try context creation
+ res = createContextImpl(_drawable); // pending creation.
}
return res;
}
@@ -791,8 +846,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
printGLAD = factory.createOffscreenAutoDrawable(null, caps, null,
printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
- printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE,
- null);
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
printDrawable = printGLAD.getDelegatedDrawable();
}
@@ -1251,7 +1305,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private class DisposeGLEventListenerAction implements Runnable {
GLEventListener listener;
- private boolean remove;
+ private final boolean remove;
private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
this.listener = listener;
this.remove = remove;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 84db62515..93e8b2c0b 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -108,22 +108,23 @@ import com.jogamp.opengl.util.texture.TextureState;
support. Provided for compatibility with Swing user interfaces
when adding a heavyweight doesn't work either because of
Z-ordering or LayoutManager problems.
- <P>
+ <p>
The GLJPanel can be made transparent by creating it with a
GLCapabilities object with alpha bits specified and calling {@link
#setOpaque}(false). Pixels with resulting OpenGL alpha values less
- than 1.0 will be overlaid on any underlying Swing rendering. </P>
- <P>
+ than 1.0 will be overlaid on any underlying Swing rendering.
+ </p>
+ <p>
This component attempts to use hardware-accelerated rendering via FBO or pbuffers and
falls back on to software rendering if none of the former are available
using {@link GLDrawableFactory#createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) GLDrawableFactory.createOffscreenDrawable(..)}.<br/>
- </P>
- <P>
+ </p>
+ <p>
In case FBO is used and GLSL is available, a fragment shader is utilized
to flip the FBO texture vertically. This hardware-accelerated step can be disabled via system property <code>jogl.gljpanel.noglsl</code>.
See <a href="#fboGLSLVerticalFlip">details here</a>.
- </P>
- <P>
+ </p>
+ <p>
The OpenGL path is concluded by copying the rendered pixels an {@link BufferedImage} via {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
for later Java2D composition.
</p>
@@ -210,7 +211,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return singleAWTGLPixelBufferProvider;
}
- private GLDrawableHelper helper = new GLDrawableHelper();
+ private final GLDrawableHelper helper = new GLDrawableHelper();
private volatile boolean isInitialized;
//
@@ -219,10 +220,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private AWTGLPixelBufferProvider customPixelBufferProvider = null;
/** Single buffered offscreen caps */
private GLCapabilitiesImmutable offscreenCaps;
- private GLProfile glProfile;
- private GLDrawableFactoryImpl factory;
- private GLCapabilitiesChooser chooser;
- private GLContext shareWith;
+ private final GLProfile glProfile;
+ private final GLDrawableFactoryImpl factory;
+ private final GLCapabilitiesChooser chooser;
+ private final GLContext shareWith;
private int additionalCtxCreationFlags = 0;
// Lazy reshape notification: reshapeWidth -> panelWidth -> backend.width
@@ -248,13 +249,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private volatile Backend backend;
// Used by all backends either directly or indirectly to hook up callbacks
- private Updater updater = new Updater();
+ private final Updater updater = new Updater();
private boolean oglPipelineUsable() {
return null == customPixelBufferProvider && useJava2DGLPipeline && java2DGLPipelineOK;
}
- private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
@Override
public void run() {
@@ -289,7 +290,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
GLContext specifies an OpenGL context with which to share
textures, display lists and other OpenGL state, and may be null
if sharing is not desired. See the note in the overview documentation on
- <a href="../../../overview-summary.html#SHARING">context sharing</a>.
+ <a href="../../../spec-summary.html#SHARING">context sharing</a>.
<P>
Note: Sharing cannot be enabled using J2D OpenGL FBO sharing,
since J2D GL Context must be shared and we can only share one context.
@@ -572,8 +573,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
printGLAD = factory.createOffscreenAutoDrawable(null, caps, null,
printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
- printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE,
- null);
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
printDrawable = printGLAD.getDelegatedDrawable();
}
@@ -1158,7 +1158,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private class DisposeGLEventListenerAction implements Runnable {
GLEventListener listener;
- private boolean remove;
+ private final boolean remove;
private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
this.listener = listener;
this.remove = remove;
@@ -1268,12 +1268,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
protected IntBuffer readBackIntsForCPUVFlip;
// Implementation using software rendering
- private GLDrawableImpl offscreenDrawable;
+ private volatile GLDrawableImpl offscreenDrawable;
private boolean offscreenIsFBO;
private FBObject fboFlipped;
private GLSLTextureRaster glslTextureRaster;
- private GLContextImpl offscreenContext;
+ private volatile GLContextImpl offscreenContext;
private boolean flipVertical;
// For saving/restoring of OpenGL state during ReadPixels
@@ -1694,11 +1694,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private GLContext joglContext;
// State captured from Java2D OpenGL context necessary in order to
// properly render into Java2D back buffer
- private int[] drawBuffer = new int[1];
- private int[] readBuffer = new int[1];
+ private final int[] drawBuffer = new int[1];
+ private final int[] readBuffer = new int[1];
// This is required when the FBO option of the Java2D / OpenGL
// pipeline is active
- private int[] frameBuffer = new int[1];
+ private final int[] frameBuffer = new int[1];
// Current (as of this writing) NVidia drivers have a couple of bugs
// relating to the sharing of framebuffer and renderbuffer objects
// between contexts. It appears we have to (a) reattach the color