aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/jogamp')
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java15
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java6
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java58
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java89
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java549
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextShareSet.java129
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java186
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java331
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableImpl.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java198
-rw-r--r--src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/GLRunnableTask.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/GLStateTracker.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/ThreadingImpl.java70
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java50
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java21
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java281
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java35
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java127
31 files changed, 1519 insertions, 784 deletions
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
index fa81e2a3f..fbd40ebdd 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
@@ -427,7 +427,7 @@ public class VBORegion2PMSAAES2 extends GLRegion {
gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
- fbo.use(gl, fbo.getSamplingSink());
+ fbo.use(gl, fbo.getSamplingSink().getTextureAttachment());
gca_FboVerticesAttr.enableBuffer(gl, true);
gca_FboTexCoordsAttr.enableBuffer(gl, true);
indicesFbo.bindBuffer(gl, true); // keeps VBO binding
@@ -454,19 +454,22 @@ public class VBORegion2PMSAAES2 extends GLRegion {
fboWidth = targetFboWidth;
fboHeight = targetFboHeight;
fbo = new FBObject();
- fbo.reset(gl, fboWidth, fboHeight, sampleCount[0], false);
+ fbo.init(gl, fboWidth, fboHeight, sampleCount[0]);
sampleCount[0] = fbo.getNumSamples();
fbo.attachColorbuffer(gl, 0, true);
- fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ if( !blendingEnabled ) {
+ // no depth-buffer w/ blending
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
+ }
final FBObject ssink = new FBObject();
{
- ssink.reset(gl, fboWidth, fboHeight);
+ ssink.init(gl, fboWidth, fboHeight, 0);
// FIXME: shall not use bilinear (GL_LINEAR), due to MSAA ???
// ssink.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
ssink.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
if( !blendingEnabled ) {
// no depth-buffer w/ blending
- ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
}
}
fbo.setSamplingSink(ssink);
@@ -475,7 +478,7 @@ public class VBORegion2PMSAAES2 extends GLRegion {
System.err.printf("XXX.createFBO: blending %b, %dx%d%n%s%n", blendingEnabled, fboWidth, fboHeight, fbo.toString());
}
} else if( targetFboWidth != fboWidth || targetFboHeight != fboHeight || fbo.getNumSamples() != sampleCount[0] ) {
- fbo.reset(gl, targetFboWidth, targetFboHeight, sampleCount[0], true /* resetSamplingSink */);
+ fbo.reset(gl, targetFboWidth, targetFboHeight, sampleCount[0]);
sampleCount[0] = fbo.getNumSamples();
if( DEBUG_FBO_1 ) {
System.err.printf("XXX.resetFBO: %dx%d -> %dx%d%n%s%n", fboWidth, fboHeight, targetFboWidth, targetFboHeight, fbo );
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
index 24fa09058..8f1de9157 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
@@ -573,20 +573,20 @@ public class VBORegion2PVBAAES2 extends GLRegion {
fboTexSize.put(1, fboHeight);
}
fbo = new FBObject();
- fbo.reset(gl, fboWidth, fboHeight);
+ fbo.init(gl, fboWidth, fboHeight, 0);
// Shall not use bilinear (GL_LINEAR), due to own VBAA. Result is smooth w/o it now!
// FIXME: FXAA requires bilinear filtering!
// texA = fbo.attachTexture2D(gl, 0, true, GL.GL_LINEAR, GL.GL_LINEAR, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
texA = fbo.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
if( !blendingEnabled ) {
// no depth-buffer w/ blending
- fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
}
if( DEBUG_FBO_1 ) {
System.err.printf("XXX.createFBO: %dx%d%n%s%n", fboWidth, fboHeight, fbo.toString());
}
} else if( newFboWidth != fboWidth || newFboHeight != fboHeight ) {
- fbo.reset(gl, newFboWidth, newFboHeight);
+ fbo.reset(gl, newFboWidth, newFboHeight, 0);
fbo.bind(gl);
if( DEBUG_FBO_1 ) {
System.err.printf("XXX.resetFBO: %dx%d -> %dx%d, target %dx%d%n", fboWidth, fboHeight, newFboWidth, newFboHeight, targetFboWidth, targetFboHeight);
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index 5bd49dce9..97570d605 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -32,8 +32,8 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.font.Font;
import com.jogamp.opengl.math.geom.AABBox;
-public class TypecastGlyph implements Font.Glyph {
- public static class Advance
+public final class TypecastGlyph implements Font.Glyph {
+ public static final class Advance
{
private final Font font;
private final float advance;
@@ -46,40 +46,42 @@ public class TypecastGlyph implements Font.Glyph {
size2advanceI.setKeyNotFoundValue(0);
}
- public void reset() {
+ public final void reset() {
size2advanceI.clear();
}
- public float getScale(final float pixelSize)
+ public final Font getFont() { return font; }
+
+ public final float getScale(final float pixelSize)
{
return this.font.getMetrics().getScale(pixelSize);
}
- public void add(final float advance, final float size)
+ public final void add(final float advance, final float size)
{
size2advanceI.put(Float.floatToIntBits(size), Float.floatToIntBits(advance));
}
- public float get(final float size, final boolean useFrationalMetrics)
+ public final float get(final float pixelSize, final boolean useFrationalMetrics)
{
- final int sI = Float.floatToIntBits(size);
+ final int sI = Float.floatToIntBits(pixelSize);
final int aI = size2advanceI.get(sI);
if( 0 != aI ) {
return Float.intBitsToFloat(aI);
}
final float a;
if ( useFrationalMetrics ) {
- a = this.advance * getScale(size);
+ a = this.advance * getScale(pixelSize);
} else {
- // a = Math.ceil(this.advance * getScale(size));
- a = Math.round(this.advance * getScale(size)); // TODO: check whether ceil should be used instead?
+ // a = Math.ceil(this.advance * getScale(pixelSize));
+ a = Math.round(this.advance * getScale(pixelSize)); // TODO: check whether ceil should be used instead?
}
size2advanceI.put(sI, Float.floatToIntBits(a));
return a;
}
@Override
- public String toString()
+ public final String toString()
{
return "\nAdvance:"+
"\n advance: "+this.advance+
@@ -87,7 +89,7 @@ public class TypecastGlyph implements Font.Glyph {
}
}
- public static class Metrics
+ public static final class Metrics
{
private final AABBox bbox;
private final Advance advance;
@@ -98,32 +100,34 @@ public class TypecastGlyph implements Font.Glyph {
this.advance = new Advance(font, advance);
}
- public void reset() {
+ public final void reset() {
advance.reset();
}
- public float getScale(final float pixelSize)
+ public final Font getFont() { return advance.getFont(); }
+
+ public final float getScale(final float pixelSize)
{
return this.advance.getScale(pixelSize);
}
- public AABBox getBBox()
+ public final AABBox getBBox()
{
return this.bbox;
}
- public void addAdvance(final float advance, final float size)
+ public final void addAdvance(final float advance, final float size)
{
this.advance.add(advance, size);
}
- public float getAdvance(final float size, final boolean useFrationalMetrics)
+ public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics)
{
- return this.advance.get(size, useFrationalMetrics);
+ return this.advance.get(pixelSize, useFrationalMetrics);
}
@Override
- public String toString()
+ public final String toString()
{
return "\nMetrics:"+
"\n bbox: "+this.bbox+
@@ -134,31 +138,21 @@ public class TypecastGlyph implements Font.Glyph {
public static final short INVALID_ID = (short)((1 << 16) - 1);
public static final short MAX_ID = (short)((1 << 16) - 2);
- private final Font font;
private final char symbol;
private final OutlineShape shape; // in EM units
private final short id;
- private final int advance;
private final Metrics metrics;
protected TypecastGlyph(final Font font, final char symbol, final short id, final AABBox bbox, final int advance, final OutlineShape shape) {
- this.font = font;
this.symbol = symbol;
this.shape = shape;
this.id = id;
- this.advance = advance;
- this.metrics = new Metrics(this.font, bbox, this.advance);
+ this.metrics = new Metrics(font, bbox, advance);
}
- /**
- public void reset(Path2D path) {
- this.path = path;
- this.metrics.reset();
- } */
-
@Override
public final Font getFont() {
- return this.font;
+ return this.metrics.getFont();
}
@Override
@@ -211,7 +205,7 @@ public class TypecastGlyph implements Font.Glyph {
@Override
public final int hashCode() {
// 31 * x == (x << 5) - x
- final int hash = 31 + font.getName(Font.NAME_UNIQUNAME).hashCode();
+ final int hash = 31 + getFont().getName(Font.NAME_UNIQUNAME).hashCode();
return ((hash << 5) - hash) + id;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
index 7bfffd58c..8ed450326 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
@@ -65,10 +65,10 @@ import com.jogamp.opengl.math.geom.AABBox;
* @version $Id: Glyph.java,v 1.3 2007-02-21 12:23:54 davidsch Exp $
* @author <a href="mailto:[email protected]">David Schweinsberg</a>, Sven Gothel
*/
-public class OTGlyph {
+public final class OTGlyph {
- protected short _leftSideBearing;
- protected int _advanceWidth;
+ private final short _leftSideBearing;
+ private final int _advanceWidth;
private Point[] _points;
AABBox _bbox;
@@ -102,33 +102,32 @@ public class OTGlyph {
}
}
- public void clearPointData() {
+ public final void clearPointData() {
_points = null;
}
- public AABBox getBBox() {
+ public final AABBox getBBox() {
return _bbox;
}
- public int getAdvanceWidth() {
+ public final int getAdvanceWidth() {
return _advanceWidth;
}
- public short getLeftSideBearing() {
+ public final short getLeftSideBearing() {
return _leftSideBearing;
}
- public Point getPoint(final int i) {
+ public final Point getPoint(final int i) {
return _points[i];
}
- public int getPointCount() {
+ public final int getPointCount() {
return null != _points ? _points.length : 0;
}
/**
* @param factor a 16.16 fixed value
- */
public void scale(final int factor) {
for (int i = 0; i < _points.length; i++) {
//points[i].x = ( points[i].x * factor ) >> 6;
@@ -139,11 +138,12 @@ public class OTGlyph {
_leftSideBearing = (short)(( _leftSideBearing * factor) >> 6);
_advanceWidth = (_advanceWidth * factor) >> 6;
}
+ */
/**
* Set the points of a glyph from the GlyphDescription
*/
- private void describe(final GlyphDescription gd) {
+ private final void describe(final GlyphDescription gd) {
int endPtIndex = 0;
_points = new Point[gd.getPointCount() /* + 2 */ ];
for (int i = 0; i < gd.getPointCount(); i++) {
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index fce5c1fcc..6e6aaf58d 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -57,9 +57,11 @@ import com.jogamp.opengl.GLStateKeeper;
/**
- * Abstract common code for GLAutoDrawable implementations.
+ * Abstract common code for GLAutoDrawable implementations
+ * utilizing multithreading, i.e. {@link #isThreadGLCapable()} always returns <code>true</code>.
*
* @see GLAutoDrawable
+ * @see GLAutoDrawable#getThreadingMode()
* @see GLAutoDrawableDelegate
* @see GLOffscreenAutoDrawable
* @see GLOffscreenAutoDrawableImpl
@@ -123,9 +125,6 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
helper.setSharedAutoDrawable(this, sharedAutoDrawable);
}
- /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access on top of {@link NativeSurface#lockSurface()}. */
- protected abstract RecursiveLock getLock();
-
@Override
public final GLStateKeeper.Listener setGLStateKeeperListener(final Listener l) {
final GLStateKeeper.Listener pre = glStateKeeperListener;
@@ -240,7 +239,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
System.err.println("GLAutoDrawableBase.sizeChanged: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(surfaceHandle));
}
if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight);
@@ -280,7 +279,13 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
shallClose = true;
}
if( shallClose ) {
- destroyAvoidAwareOfLocking();
+ try {
+ destroyAvoidAwareOfLocking();
+ } catch( final Throwable t ) {
+ // Intentionally catch and ignore exception,
+ // so the destroy mechanism of the native windowing system is not corrupted!
+ GLException.dumpThrowable("ignored", t);
+ }
}
}
@@ -332,7 +337,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
* Calls {@link #destroyImplInLock()} while claiming the lock.
*/
protected final void defaultDestroy() {
- final RecursiveLock lock = getLock();
+ final RecursiveLock lock = getUpstreamLock();
lock.lock();
try {
destroyImplInLock();
@@ -357,30 +362,52 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
preserveGLStateAtDestroy(false);
preserveGLEventListenerState();
}
+
+ GLException exceptionOnDisposeGL = null;
if( null != context ) {
if( context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
try {
helper.disposeGL(this, context, true);
} catch (final GLException gle) {
- gle.printStackTrace();
+ exceptionOnDisposeGL = gle;
}
}
context = null;
}
+
+ Throwable exceptionOnUnrealize = null;
+ Throwable exceptionOnDeviceClose = null;
if( null != drawable ) {
final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
- drawable.setRealized(false);
+ try {
+ drawable.setRealized(false);
+ } catch( final Throwable re ) {
+ exceptionOnUnrealize = re;
+ }
drawable = null;
- if( ownsDevice ) {
- device.close();
+ try {
+ if( ownsDevice ) {
+ device.close();
+ }
+ } catch (final Throwable re) {
+ exceptionOnDeviceClose = re;
}
}
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
+ }
+ if( null != exceptionOnUnrealize ) {
+ throw GLException.newGLException(exceptionOnUnrealize);
+ }
+ if( null != exceptionOnDeviceClose ) {
+ throw GLException.newGLException(exceptionOnDeviceClose);
+ }
}
public final void defaultSwapBuffers() throws GLException {
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
if(null != drawable) {
@@ -421,7 +448,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
destroy();
return;
}
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
if( null == context ) {
@@ -452,7 +479,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
}
protected final GLEventListener defaultDisposeGLEventListener(final GLEventListener listener, final boolean remove) {
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
return helper.disposeGLEventListener(GLAutoDrawableBase.this, drawable, context, listener, remove);
@@ -473,7 +500,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
@Override
public final GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
- final RecursiveLock lock = getLock();
+ final RecursiveLock lock = getUpstreamLock();
lock.lock();
try {
final GLContext oldCtx = context;
@@ -571,16 +598,21 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
}
@Override
- public final boolean invoke(final boolean wait, final GLRunnable glRunnable) {
+ public final boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
return helper.invoke(this, wait, glRunnable);
}
@Override
- public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) {
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
return helper.invoke(this, wait, glRunnables);
}
@Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
public final void setAutoSwapBufferMode(final boolean enable) {
helper.setAutoSwapBufferMode(enable);
}
@@ -604,6 +636,15 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
return additionalCtxCreationFlags;
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Implementation always supports multithreading, hence method always returns <code>true</code>.
+ * </p>
+ */
+ @Override
+ public final boolean isThreadGLCapable() { return true; }
+
//
// FPSCounter
//
@@ -664,7 +705,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
@Override
public final GLContext createContext(final GLContext shareWith) {
- final RecursiveLock lock = getLock();
+ final RecursiveLock lock = getUpstreamLock();
lock.lock();
try {
if(drawable != null) {
@@ -680,7 +721,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
@Override
public final void setRealized(final boolean realized) {
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
final GLDrawable _drawable = drawable;
@@ -727,6 +768,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
}
@Override
+ public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getRequestedGLCapabilities() : null;
+ }
+
+ @Override
public final GLProfile getGLProfile() {
final GLDrawable _drawable = drawable;
return null != _drawable ? _drawable.getGLProfile() : null;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index c175243ae..01478a422 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -108,10 +108,17 @@ public abstract class GLContextImpl extends GLContext {
private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
private int defaultVAO = 0;
+ /**
+ * <ul>
+ * <li>[GLAutoDrawable.upstreamLock].lock()</li>
+ * <li>drawable.surface.lock()</li>
+ * <li>contextLock.lock()</li>
+ * </ul>
+ */
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
- private volatile boolean pixelDataEvaluated;
+ private boolean pixelDataEvaluated;
private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
protected GL gl;
@@ -137,11 +144,16 @@ public abstract class GLContextImpl extends GLContext {
public GLContextImpl(final GLDrawableImpl drawable, final GLContext shareWith) {
super();
+ if( null == drawable ) {
+ throw new IllegalArgumentException("Null drawable");
+ }
bufferStateTracker = new GLBufferStateTracker();
if ( null != shareWith ) {
GLContextShareSet.registerSharing(this, shareWith);
bufferObjectTracker = ((GLContextImpl)shareWith).getBufferObjectTracker();
- assert (bufferObjectTracker != null) : "shared context hash null GLBufferObjectTracker: "+shareWith;
+ if( null == bufferObjectTracker ) {
+ throw new InternalError("shared-master context hash null GLBufferObjectTracker: "+toHexString(shareWith.hashCode()));
+ }
} else {
bufferObjectTracker = new GLBufferObjectTracker();
}
@@ -189,21 +201,28 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final GLDrawable setGLReadDrawable(final GLDrawable read) {
- if(!isGLReadDrawableAvailable()) {
- throw new GLException("Setting read drawable feature not available");
- }
- final boolean lockHeld = lock.isOwner(Thread.currentThread());
- if(lockHeld) {
- release();
- } else if(lock.isLockedByOtherThread()) { // still could glitch ..
- throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
- }
- final GLDrawable old = drawableRead;
- drawableRead = ( null != read ) ? (GLDrawableImpl) read : drawable;
- if(lockHeld) {
- makeCurrent();
- }
- return old;
+ // Validate constraints first!
+ if(!isGLReadDrawableAvailable()) {
+ throw new GLException("Setting read drawable feature not available");
+ }
+ final Thread currentThread = Thread.currentThread();
+ if( lock.isLockedByOtherThread() ) {
+ throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
+ }
+ final boolean lockHeld = lock.isOwner(currentThread);
+ if( lockHeld && lock.getHoldCount() > 1 ) {
+ // would need to makeCurrent * holdCount
+ throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
+ }
+ if(lockHeld) {
+ release(false);
+ }
+ final GLDrawable old = drawableRead;
+ drawableRead = ( null != read ) ? (GLDrawableImpl) read : drawable;
+ if(lockHeld) {
+ makeCurrent();
+ }
+ return old;
}
@Override
@@ -213,43 +232,46 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final GLDrawable setGLDrawable(final GLDrawable readWrite, final boolean setWriteOnly) {
- if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
- return drawable; // no change.
- }
- final Thread currentThread = Thread.currentThread();
- if( lock.isLockedByOtherThread() ) {
- throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
- }
- final boolean lockHeld = lock.isOwner(currentThread);
- if( lockHeld && lock.getHoldCount() > 1 ) {
- // would need to makeCurrent * holdCount
- throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
- }
- final GLDrawableImpl old = drawable;
- if( isCreated() && null != old && old.isRealized() ) {
- if(!lockHeld) {
- makeCurrent();
- }
- associateDrawable(false);
- if(!lockHeld) {
- release();
- }
- }
- if(lockHeld) {
- release();
- }
- if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
- drawableRead = (GLDrawableImpl) readWrite;
- }
- drawableRetargeted |= null != drawable && readWrite != drawable;
- drawable = (GLDrawableImpl) readWrite ;
- if( isCreated() && null != drawable && drawable.isRealized() ) {
- makeCurrent(true); // implicit: associateDrawable(true)
- if( !lockHeld ) {
- release();
- }
- }
- return old;
+ // Validate constraints first!
+ final Thread currentThread = Thread.currentThread();
+ if( lock.isLockedByOtherThread() ) {
+ throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
+ }
+ final boolean lockHeld = lock.isOwner(currentThread);
+ if( lockHeld && lock.getHoldCount() > 1 ) {
+ // would need to makeCurrent * holdCount
+ throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
+ }
+ if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+ return drawable; // no change.
+ }
+ final GLDrawableImpl old = drawable;
+ if( isCreated() && null != old && old.isRealized() ) {
+ if(!lockHeld) {
+ makeCurrent();
+ }
+ // sync GL ctx w/ drawable's framebuffer before de-association
+ gl.glFinish();
+ associateDrawable(false);
+ if(!lockHeld) {
+ release(false);
+ }
+ }
+ if(lockHeld) {
+ release(false);
+ }
+ if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
+ drawableRead = (GLDrawableImpl) readWrite;
+ }
+ drawableRetargeted |= null != drawable && readWrite != drawable;
+ drawable = (GLDrawableImpl) readWrite ;
+ if( isCreated() && null != drawable && drawable.isRealized() ) {
+ makeCurrent(true); // implicit: associateDrawable(true)
+ if( !lockHeld ) {
+ release(false);
+ }
+ }
+ return old;
}
@Override
@@ -258,7 +280,7 @@ public abstract class GLContextImpl extends GLContext {
}
public final GLDrawableImpl getDrawableImpl() {
- return (GLDrawableImpl) getGLDrawable();
+ return drawable;
}
@Override
@@ -315,56 +337,57 @@ public abstract class GLContextImpl extends GLContext {
release(false);
}
private void release(final boolean inDestruction) throws GLException {
- if( TRACE_SWITCH ) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch[release.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock);
- }
- if ( !lock.isOwner(Thread.currentThread()) ) {
- final String msg = getThreadName() +": Context not current on thread, obj " + toHexString(hashCode())+", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock;
- if( DEBUG_TRACE_SWITCH ) {
- System.err.println(msg);
- if( null != lastCtxReleaseStack ) {
- System.err.print("Last release call: ");
- lastCtxReleaseStack.printStackTrace();
- } else {
- System.err.println("Last release call: NONE");
- }
- }
- throw new GLException(msg);
- }
-
- Throwable drawableContextMadeCurrentException = null;
- final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
- try {
- if( actualRelease ) {
- if( !inDestruction ) {
- try {
- contextMadeCurrent(false);
- } catch (final Throwable t) {
- drawableContextMadeCurrentException = t;
- }
- }
- releaseImpl();
- }
- } finally {
- // exception prone ..
- if( actualRelease ) {
- setCurrent(null);
+ if( TRACE_SWITCH ) {
+ final long drawH = null != drawable ? drawable.getHandle() : 0;
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[release.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+(null!=drawable)+" "+toHexString(drawH)+", inDestruction: "+inDestruction+", "+lock);
}
- drawable.unlockSurface();
- lock.unlock();
- if( DEBUG_TRACE_SWITCH ) {
- final String msg = getThreadName() +": GLContext.ContextSwitch[release.X]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+(actualRelease?"switch":"keep ")+" - "+lock;
- lastCtxReleaseStack = new Throwable(msg);
- if( TRACE_SWITCH ) {
+ if ( !lock.isOwner(Thread.currentThread()) ) {
+ final long drawH = null != drawable ? drawable.getHandle() : 0;
+ final String msg = getThreadName() +": Context not current on thread, obj " + toHexString(hashCode())+", ctx "+toHexString(contextHandle)+", surf "+(null!=drawable)+" "+toHexString(drawH)+", inDestruction: "+inDestruction+", "+lock;
+ if( DEBUG_TRACE_SWITCH ) {
System.err.println(msg);
- // Thread.dumpStack();
+ if( null != lastCtxReleaseStack ) {
+ System.err.print("Last release call: ");
+ lastCtxReleaseStack.printStackTrace();
+ } else {
+ System.err.println("Last release call: NONE");
+ }
}
+ throw new GLException(msg);
}
- }
- if(null != drawableContextMadeCurrentException) {
- throw new GLException("GLContext.release(false) during GLDrawableImpl.contextMadeCurrent(this, false)", drawableContextMadeCurrentException);
- }
+ Throwable drawableContextMadeCurrentException = null;
+ final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
+ try {
+ if( actualRelease ) {
+ if( !inDestruction ) {
+ try {
+ contextMadeCurrent(false);
+ } catch (final Throwable t) {
+ drawableContextMadeCurrentException = t;
+ }
+ }
+ releaseImpl();
+ }
+ } finally {
+ // exception prone ..
+ if( actualRelease ) {
+ setCurrent(null);
+ }
+ lock.unlock();
+ drawable.unlockSurface();
+ if( DEBUG_TRACE_SWITCH ) {
+ final String msg = getThreadName() +": GLContext.ContextSwitch[release.X]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+(actualRelease?"switch":"keep ")+" - "+lock;
+ lastCtxReleaseStack = new Throwable(msg);
+ if( TRACE_SWITCH ) {
+ System.err.println(msg);
+ // Thread.dumpStack();
+ }
+ }
+ }
+ if(null != drawableContextMadeCurrentException) {
+ throw new GLException("GLContext.release(false) during GLDrawableImpl.contextMadeCurrent(this, false)", drawableContextMadeCurrentException);
+ }
}
private Throwable lastCtxReleaseStack = null;
protected abstract void releaseImpl() throws GLException;
@@ -374,7 +397,7 @@ public abstract class GLContextImpl extends GLContext {
if ( DEBUG_TRACE_SWITCH ) {
final long drawH = null != drawable ? drawable.getHandle() : 0;
System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
- ", surf "+toHexString(drawH)+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ ", surf "+(null!=drawable)+" "+toHexString(drawH)+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
if ( 0 != contextHandle ) { // isCreated() ?
if ( null == drawable ) {
@@ -393,9 +416,9 @@ public abstract class GLContextImpl extends GLContext {
// Must hold the lock around the destroy operation to make sure we
// don't destroy the context while another thread renders to it.
lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering)
- if ( lock.getHoldCount() > 2 ) {
- final String msg = getThreadName() + ": GLContextImpl.destroy: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle);
- if ( DEBUG_TRACE_SWITCH ) {
+ if ( DEBUG_TRACE_SWITCH ) {
+ if ( lock.getHoldCount() > 2 ) {
+ final String msg = getThreadName() + ": GLContextImpl.destroy: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle);
System.err.println(msg+" - Lock was hold more than once - makeCurrent/release imbalance: "+lock);
Thread.dumpStack();
}
@@ -519,8 +542,16 @@ public abstract class GLContextImpl extends GLContext {
}
protected final int makeCurrent(boolean forceDrawableAssociation) throws GLException {
+ final boolean hasDrawable = null != drawable;
if( TRACE_SWITCH ) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+lock);
+ final long drawH = null != drawable ? drawable.getHandle() : 0;
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+hasDrawable+" "+toHexString(drawH)+" - "+lock);
+ }
+ if( !hasDrawable ) {
+ if( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - NULL Drawable - CONTEXT_NOT_CURRENT - "+lock);
+ }
+ return CONTEXT_NOT_CURRENT;
}
// Note: the surface is locked within [makeCurrent .. swap .. release]
@@ -589,12 +620,12 @@ public abstract class GLContextImpl extends GLContext {
}
}
- if (res != CONTEXT_NOT_CURRENT) {
+ if (res != CONTEXT_NOT_CURRENT) { // still locked!
setCurrent(this);
if(res == CONTEXT_CURRENT_NEW) {
// check if the drawable's and the GL's GLProfile are equal
// throws an GLException if not
- getGLDrawable().getGLProfile().verifyEquality(gl.getGLProfile());
+ drawable.getGLProfile().verifyEquality(gl.getGLProfile());
glDebugHandler.init( isGL2GL3() && isGLDebugEnabled() );
@@ -632,6 +663,10 @@ public abstract class GLContextImpl extends GLContext {
return res;
}
+ private final GLContextImpl getOtherSharedMaster() {
+ final GLContextImpl sharedMaster = (GLContextImpl) GLContextShareSet.getSharedMaster(this);
+ return this != sharedMaster ? sharedMaster : null;
+ }
private final int makeCurrentWithinLock(final int surfaceLockRes) throws GLException {
if (!isCreated()) {
if( 0 >= drawable.getSurfaceWidth() || 0 >= drawable.getSurfaceHeight() ) {
@@ -646,20 +681,23 @@ public abstract class GLContextImpl extends GLContext {
additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ;
}
- final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getCreatedShare(this);
- final long shareWithHandle;
- if (null != shareWith) {
- shareWith.getDrawableImpl().lockSurface();
- shareWithHandle = shareWith.getHandle();
- if (0 == shareWithHandle) {
- throw new GLException("GLContextShareSet returned an invalid OpenGL context: "+this);
+ final boolean created;
+ final GLContextImpl sharedMaster = getOtherSharedMaster();
+ if ( null != sharedMaster ) {
+ if ( NativeSurface.LOCK_SURFACE_NOT_READY >= sharedMaster.drawable.lockSurface() ) {
+ throw new GLException("GLContextShareSet could not lock sharedMaster surface: "+sharedMaster.drawable);
}
- } else {
- shareWithHandle = 0;
}
- final boolean created;
try {
- created = createImpl(shareWithHandle); // may throws exception if fails
+ if ( null != sharedMaster ) {
+ final long sharedMasterHandle = sharedMaster.getHandle();
+ if ( 0 == sharedMasterHandle ) {
+ throw new GLException("GLContextShareSet returned an invalid sharedMaster context: "+sharedMaster);
+ }
+ created = createImpl(sharedMasterHandle); // may throws exception if fails
+ } else {
+ created = createImpl(0); // may throws exception if fails
+ }
if( created && hasNoDefaultVAO() ) {
final int[] tmp = new int[1];
final GL rootGL = gl.getRootGL();
@@ -671,8 +709,8 @@ public abstract class GLContextImpl extends GLContext {
}
}
} finally {
- if (null != shareWith) {
- shareWith.getDrawableImpl().unlockSurface();
+ if ( null != sharedMaster ) {
+ sharedMaster.drawable.unlockSurface();
}
}
if ( DEBUG_TRACE_SWITCH ) {
@@ -702,13 +740,32 @@ public abstract class GLContextImpl extends GLContext {
} else {
reqMajor = ctxVersion.getMajor();
}
+ final boolean isCompat;
if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_CORE) ) {
reqProfile = GLContext.CTX_PROFILE_CORE;
+ isCompat = false;
} else {
reqProfile = GLContext.CTX_PROFILE_COMPAT;
+ isCompat = true;
+ }
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ // Perform all required profile mappings
+ if( isCompat ) {
+ // COMPAT via non ARB
+ GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ if( reqMajor >= 4 ) {
+ GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ GLContext.mapAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
+ if( reqMajor >= 3 ) {
+ GLContext.mapAvailableGLVersion(device, 2, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
+ } else {
+ // CORE via non ARB, unlikely, however ..
+ if( reqMajor >= 4 ) {
+ GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
}
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
- ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
GLContext.setAvailableGLVersionsSet(device);
if (DEBUG) {
@@ -749,8 +806,8 @@ public abstract class GLContextImpl extends GLContext {
*
* The implementation <b>must</b> leave the context current.<br>
*
- * @param share the shared context or null
- * @return the valid and current context if successful, or null
+ * @param sharedWithHandle the shared context handle or 0
+ * @return true if successful, or false
* @throws GLException
*/
protected abstract boolean createImpl(long sharedWithHandle) throws GLException ;
@@ -818,6 +875,9 @@ public abstract class GLContextImpl extends GLContext {
*/
protected final long createContextARB(final long share, final boolean direct)
{
+ if( GLProfile.disableOpenGLARBContext ) {
+ return 0;
+ }
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
@@ -879,7 +939,7 @@ public abstract class GLContextImpl extends GLContext {
/**
* OSX 10.9 GLRendererQuirks.GL4NeedsGL3Request, quirk is added as usual @ setRendererQuirks(..)
*/
- if( !hasGL4 && !hasGL3 ) {
+ if( !GLProfile.disableOpenGLCore && !hasGL4 && !hasGL3 ) {
hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3
success |= hasGL3;
if( hasGL3 ) {
@@ -896,25 +956,27 @@ public abstract class GLContextImpl extends GLContext {
}
}
}
- if( !hasGL4 ) {
- hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4
- success |= hasGL4;
- if( hasGL4 ) {
- if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) {
- // Map hw-accel GL4 to all lower core profiles: GL3
- GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
- if( PROFILE_ALIASING ) {
- hasGL3 = true;
+ if( !GLProfile.disableOpenGLCore ) {
+ if( !hasGL4 ) {
+ hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4
+ success |= hasGL4;
+ if( hasGL4 ) {
+ if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) {
+ // Map hw-accel GL4 to all lower core profiles: GL3
+ GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ if( PROFILE_ALIASING ) {
+ hasGL3 = true;
+ }
}
+ resetStates(false); // clean context states, since creation was temporary
}
- resetStates(false); // clean context states, since creation was temporary
}
- }
- if( !hasGL3 ) {
- hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3
- success |= hasGL3;
- if( hasGL3 ) {
- resetStates(false); // clean this context states, since creation was temporary
+ if( !hasGL3 ) {
+ hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3
+ success |= hasGL3;
+ if( hasGL3 ) {
+ resetStates(false); // clean this context states, since creation was temporary
+ }
}
}
if( !hasGL4bc ) {
@@ -1372,7 +1434,7 @@ public abstract class GLContextImpl extends GLContext {
}
if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) {
- setGL( createGL( getGLDrawable().getGLProfile() ) );
+ setGL( createGL( drawable.getGLProfile() ) );
}
updateGLXProcAddressTable();
@@ -1545,6 +1607,10 @@ public abstract class GLContextImpl extends GLContext {
ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT ) ;
}
+ if(!isCurrentContextHardwareRasterizer()) {
+ ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
+ }
+
final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
setRendererQuirks(adevice, getDrawableImpl().getFactoryImpl(),
@@ -1558,10 +1624,6 @@ public abstract class GLContextImpl extends GLContext {
return false;
}
- if(!isCurrentContextHardwareRasterizer()) {
- ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
- }
-
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
@@ -1669,9 +1731,6 @@ public abstract class GLContextImpl extends GLContext {
final int reqMajor, final int reqMinor, final int reqCTP,
final int major, final int minor, final int ctp, final VersionNumberString vendorVersion,
final boolean withinGLVersionsMapping) {
- final int[] quirks = new int[GLRendererQuirks.COUNT + 1]; // + 1 ( NoFullFBOSupport )
- int i = 0;
-
final String MesaSP = "Mesa ";
// final String MesaRendererAMDsp = " AMD ";
final String MesaRendererIntelsp = "Intel(R)";
@@ -1684,6 +1743,8 @@ public abstract class GLContextImpl extends GLContext {
final boolean isDriverATICatalyst = !isDriverMesa && ( glVendor.contains("ATI Technologies") || glRenderer.startsWith("ATI ") );
final boolean isDriverNVIDIAGeForce = !isDriverMesa && ( glVendor.contains("NVIDIA Corporation") || glRenderer.contains("NVIDIA ") );
+ final GLRendererQuirks quirks = new GLRendererQuirks();
+
//
// General Quirks
//
@@ -1693,14 +1754,14 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
if( withinGLVersionsMapping ) {
// Thread safe due to single threaded initialization!
- GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
} else {
// FIXME: Remove when moving EGL/ES to ARB ctx creation
synchronized(GLContextImpl.class) {
- GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
}
}
}
@@ -1718,17 +1779,17 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Mavericks) >= 0 && 3==reqMajor && 4==major ) {
final int quirk = GLRendererQuirks.GL4NeedsGL3Request;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", req "+reqMajor+"."+reqMinor);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
if( withinGLVersionsMapping ) {
// Thread safe due to single threaded initialization!
- GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
}
}
if( isDriverNVIDIAGeForce ) {
@@ -1738,14 +1799,14 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Lion) < 0 ) { // < OSX 10.7.0 w/ NV has unstable GLSL
final int quirk = GLRendererQuirks.GLSLNonCompliant;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
}
} else if( isWindows ) {
@@ -1757,7 +1818,7 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
if( isDriverATICatalyst ) {
@@ -1769,7 +1830,7 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"], driverVersion "+vendorVersion);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
if( Platform.getOSVersionNumber().compareTo(winXPVersionNumber) <= 0 ) {
@@ -1777,7 +1838,7 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS-Version "+Platform.getOSType()+" "+Platform.getOSVersionNumber()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"]");
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
}
} else if( Platform.OSType.ANDROID == Platform.getOSType() ) {
@@ -1790,14 +1851,14 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
if( glRenderer.contains("Immersion.16") ) {
- final int quirk = GLRendererQuirks.GLSharedContextBuggy;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
- }
- quirks[i++] = quirk;
+ final int quirk = GLRendererQuirks.GLSharedContextBuggy;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
}
}
@@ -1818,21 +1879,21 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
} else if( isDriverATICatalyst ) {
{
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
} else if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
{
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11Util Downstream");
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
}
}
@@ -1843,6 +1904,7 @@ public abstract class GLContextImpl extends GLContext {
// RENDERER related quirks
//
if( isDriverMesa ) {
+ final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0);
final VersionNumber mesaIntelBuggySharedCtx921 = new VersionNumber(9, 2, 1);
{
@@ -1850,88 +1912,103 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
}
- if( hwAccel /* glRenderer.contains( MesaRendererIntelsp ) || glRenderer.contains( MesaRendererAMDsp ) */ )
- {
+ if( hwAccel ) {
+ // hardware-acceleration
final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
+ } else {
+ // software
+ if( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // FIXME: Is it fixed in >= 8.0.0 ?
+ final int quirk = GLRendererQuirks.BuggyColorRenderbuffer;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks.addQuirk( quirk );
+ }
}
if (compatCtx && (major > 3 || (major == 3 && minor >= 1))) {
- // FIXME: Apply vendor version constraints!
- final int quirk = GLRendererQuirks.GLNonCompliant;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
- }
- quirks[i++] = quirk;
+ // FIXME: Apply vendor version constraints!
+ final int quirk = GLRendererQuirks.GLNonCompliant;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
}
if( glRenderer.contains( MesaRendererIntelsp ) &&
vendorVersion.compareTo(mesaIntelBuggySharedCtx921) >= 0 && isX11 ) { // FIXME: When is it fixed ?
- final int quirk = GLRendererQuirks.GLSharedContextBuggy;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
- }
- quirks[i++] = quirk;
+ final int quirk = GLRendererQuirks.GLSharedContextBuggy;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks.addQuirk( quirk );
}
if( glVendor.contains( "nouveau" )
// FIXME: && vendorVersion.compareTo(nouveauBuggyMSAAFixed) < 0
) {
- final int quirk = GLRendererQuirks.NoMultiSamplingBuffers;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Vendor "+glVendor);
- }
- quirks[i++] = quirk;
- if( withinGLVersionsMapping ) {
- // Thread safe due to single threaded initialization!
- GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
- }
+ final int quirk = GLRendererQuirks.NoMultiSamplingBuffers;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Vendor "+glVendor);
+ }
+ quirks.addQuirk( quirk );
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
+ }
}
- if( isWindows && glRenderer.contains("SVGA3D") ) {
- final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0);
- if ( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // includes: vendorVersion.isZero()
- final int quirk = GLRendererQuirks.NoFullFBOSupport;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
- }
- quirks[i++] = quirk;
+ if( isWindows && glRenderer.contains("SVGA3D") && vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) {
+ final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
}
+ quirks.addQuirk( quirk );
}
}
//
// Property related quirks
//
- if( FORCE_MIN_FBO_SUPPORT ) {
- final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if( FORCE_NO_COLOR_RENDERBUFFER ) {
+ final int quirk = GLRendererQuirks.BuggyColorRenderbuffer;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: property");
}
- quirks[i++] = quirk;
+ quirks.addQuirk( quirk );
+ }
+ if( FORCE_MIN_FBO_SUPPORT || quirks.exist(GLRendererQuirks.BuggyColorRenderbuffer) ) {
+ final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if(DEBUG) {
+ final String causeProps = FORCE_MIN_FBO_SUPPORT ? "property, " : "";
+ final String causeQuirk = quirks.exist(GLRendererQuirks.BuggyColorRenderbuffer) ? "BuggyColorRenderbuffer" : "";
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: "+causeProps+causeQuirk);
+ }
+ quirks.addQuirk( quirk );
}
- glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
if(DEBUG) {
- System.err.println("Quirks local.0: "+glRendererQuirks);
+ System.err.println("Quirks local.0: "+quirks);
}
{
// Merge sticky quirks, thread safe due to single threaded initialization!
- GLRendererQuirks.pushStickyDeviceQuirks(adevice, glRendererQuirks);
+ GLRendererQuirks.pushStickyDeviceQuirks(adevice, quirks);
final AbstractGraphicsDevice factoryDefaultDevice = factory.getDefaultDevice();
if( !GLRendererQuirks.areSameStickyDevice(factoryDefaultDevice, adevice) ) {
- GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, glRendererQuirks);
+ GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, quirks);
}
if( esCtx ) {
final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice();
if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) &&
!GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) {
- GLRendererQuirks.pushStickyDeviceQuirks(eglFactoryDefaultDevice, glRendererQuirks);
+ GLRendererQuirks.pushStickyDeviceQuirks(eglFactoryDefaultDevice, quirks);
}
}
}
+ glRendererQuirks = quirks;
if(DEBUG) {
System.err.println("Quirks local.X: "+glRendererQuirks);
System.err.println("Quirks sticky on "+adevice+": "+GLRendererQuirks.getStickyDeviceQuirks(adevice));
@@ -2106,35 +2183,31 @@ public abstract class GLContextImpl extends GLContext {
}
private final void evalPixelDataType() {
- if(!pixelDataEvaluated) {
- synchronized(this) {
- if(!pixelDataEvaluated) {
- boolean ok = false;
- /* if(isGL2GL3() && 3 == components) {
- pixelDataInternalFormat=GL.GL_RGB;
- pixelDataFormat=GL.GL_RGB;
- pixelDataType = GL.GL_UNSIGNED_BYTE;
- ok = true;
- } else */ if( isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format) ) {
- final int[] glImplColorReadVals = new int[] { 0, 0 };
- gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
- gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
- // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
- pixelDataFormat = glImplColorReadVals[0];
- pixelDataType = glImplColorReadVals[1];
- ok = 0 != pixelDataFormat && 0 != pixelDataType;
- }
- if( !ok ) {
- // RGBA read is safe for all GL profiles
- // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
- pixelDataFormat=GL.GL_RGBA;
- pixelDataType = GL.GL_UNSIGNED_BYTE;
- }
- // TODO: Consider:
- // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
- pixelDataEvaluated = true;
- }
- }
+ if(!pixelDataEvaluated) { // only valid while context is made current
+ boolean ok = false;
+ /* if(isGL2GL3() && 3 == components) {
+ pixelDataInternalFormat=GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGB;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ ok = true;
+ } else */ if( isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format) ) {
+ final int[] glImplColorReadVals = new int[] { 0, 0 };
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat = glImplColorReadVals[0];
+ pixelDataType = glImplColorReadVals[1];
+ ok = 0 != pixelDataFormat && 0 != pixelDataType;
+ }
+ if( !ok ) {
+ // RGBA read is safe for all GL profiles
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGBA;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ }
+ // TODO: Consider:
+ // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
+ pixelDataEvaluated = true;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java
index 209707f33..aed611edd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java
@@ -61,21 +61,33 @@ public class GLContextShareSet {
// to a share set, containing all shared contexts itself.
private static final Map<GLContext, ShareSet> shareMap = new IdentityHashMap<GLContext, ShareSet>();
- private static final Object dummyValue = new Object();
private static class ShareSet {
- private final Map<GLContext, Object> allShares = new IdentityHashMap<GLContext, Object>();
- private final Map<GLContext, Object> createdShares = new IdentityHashMap<GLContext, Object>();
- private final Map<GLContext, Object> destroyedShares = new IdentityHashMap<GLContext, Object>();
+ private final Map<GLContext, GLContext> createdShares = new IdentityHashMap<GLContext, GLContext>();
+ private final Map<GLContext, GLContext> destroyedShares = new IdentityHashMap<GLContext, GLContext>();
- public void add(final GLContext ctx) {
- if (allShares.put(ctx, dummyValue) == null) {
- if (ctx.isCreated()) {
- createdShares.put(ctx, dummyValue);
+ public final void addNew(final GLContext slave, final GLContext master) {
+ final GLContext preMaster;
+ if ( slave.isCreated() ) {
+ preMaster = createdShares.put(slave, master);
} else {
- destroyedShares.put(ctx, dummyValue);
+ preMaster= destroyedShares.put(slave, master);
+ }
+ if( null != preMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Slave "+toHexString(slave.hashCode())+
+ " is not new w/ master "+toHexString(preMaster.hashCode()));
+ }
+ }
+ public final void addIfNew(final GLContext slave, final GLContext master) {
+ final GLContext preMaster = getMaster(master);
+ if( null == preMaster ) {
+ addNew(slave, master);
}
- }
+ }
+
+ public final GLContext getMaster(final GLContext ctx) {
+ final GLContext c = createdShares.get(ctx);
+ return null != c ? c : destroyedShares.get(ctx);
}
public Set<GLContext> getCreatedShares() {
@@ -86,57 +98,55 @@ public class GLContextShareSet {
return destroyedShares.keySet();
}
- public GLContext getCreatedShare(final GLContext ignore) {
- for (final Iterator<GLContext> iter = createdShares.keySet().iterator(); iter.hasNext(); ) {
- final GLContext ctx = iter.next();
- if (ctx != ignore) {
- return ctx;
- }
- }
- return null;
- }
-
public void contextCreated(final GLContext ctx) {
- final Object res = destroyedShares.remove(ctx);
- assert res != null : "State of ShareSet corrupted; thought context " +
- ctx + " should have been in destroyed set but wasn't";
- final Object res2 = createdShares.put(ctx, dummyValue);
- assert res2 == null : "State of ShareSet corrupted; thought context " +
- ctx + " shouldn't have been in created set but was";
+ final GLContext ctxMaster = destroyedShares.remove(ctx);
+ if( null == ctxMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " should have been in destroyed-set");
+ }
+ final GLContext delMaster = createdShares.put(ctx, ctxMaster);
+ if( null != delMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " shouldn't have been in created-set");
+ }
}
public void contextDestroyed(final GLContext ctx) {
- final Object res = createdShares.remove(ctx);
- assert res != null : "State of ShareSet corrupted; thought context " +
- ctx + " should have been in created set but wasn't";
- final Object res2 = destroyedShares.put(ctx, dummyValue);
- assert res2 == null : "State of ShareSet corrupted; thought context " +
- ctx + " shouldn't have been in destroyed set but was";
+ final GLContext ctxMaster = createdShares.remove(ctx);
+ if( null == ctxMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " should have been in created-set");
+ }
+ final GLContext delMaster = destroyedShares.put(ctx, ctxMaster);
+ if( null != delMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " shouldn't have been in destroyed-set");
+ }
}
}
- /** Indicate that contexts <code>share1</code> and
- <code>share2</code> will share textures and display lists. Both
+ /** Indicate that contexts <code>slave</code> and
+ <code>master</code> will share textures and display lists. Both
must be non-null. */
- public static synchronized void registerSharing(final GLContext share1, final GLContext share2) {
- if (share1 == null || share2 == null) {
- throw new IllegalArgumentException("Both share1 and share2 must be non-null");
- }
- ShareSet share = entryFor(share1);
- if (share == null) {
- share = entryFor(share2);
- }
- if (share == null) {
- share = new ShareSet();
- }
- share.add(share1);
- share.add(share2);
- addEntry(share1, share);
- addEntry(share2, share);
- if (DEBUG) {
- System.err.println("GLContextShareSet: registereSharing: 1: " +
- toHexString(share1.getHandle()) + ", 2: " + toHexString(share2.getHandle()));
- }
+ public static synchronized void registerSharing(final GLContext slave, final GLContext master) {
+ if (slave == null || master == null) {
+ throw new IllegalArgumentException("Both slave and master must be non-null");
+ }
+ ShareSet share = entryFor(slave);
+ if ( null == share ) {
+ share = entryFor(master);
+ }
+ if ( null == share ) {
+ share = new ShareSet();
+ }
+ share.addNew(slave, master);
+ share.addIfNew(master, master); // this master could have a different master shared registered earlier!
+ addEntry(slave, share);
+ addEntry(master, share);
+ if (DEBUG) {
+ System.err.println("GLContextShareSet: registereSharing: 1: " +
+ toHexString(slave.hashCode()) + ", 2: " + toHexString(master.hashCode()));
+ }
}
public static synchronized void unregisterSharing(final GLContext lastContext) {
@@ -157,7 +167,7 @@ public class GLContextShareSet {
}
if (DEBUG) {
System.err.println("GLContextShareSet: unregisterSharing: " +
- toHexString(lastContext.getHandle())+", entries: "+s.size());
+ toHexString(lastContext.hashCode())+", entries: "+s.size());
}
for(final Iterator<GLContext> iter = s.iterator() ; iter.hasNext() ; ) {
final GLContext ctx = iter.next();
@@ -176,13 +186,18 @@ public class GLContextShareSet {
return share != null;
}
- /** Returns one created GLContext shared with the given <code>context</code>, otherwise return <code>null</code>. */
- public static synchronized GLContext getCreatedShare(final GLContext context) {
+ /**
+ * Returns the shared master GLContext of the given <code>context</code> if shared, otherwise return <code>null</code>.
+ * <p>
+ * Returns the given <code>context</code>, if it is a shared master.
+ * </p>
+ */
+ public static synchronized GLContext getSharedMaster(final GLContext context) {
final ShareSet share = entryFor(context);
if (share == null) {
return null;
}
- return share.getCreatedShare(context);
+ return share.getMaster(context);
}
private static synchronized Set<GLContext> getCreatedSharesImpl(final GLContext context) {
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 0b119b50d..8d65f16d3 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -41,8 +41,14 @@
package jogamp.opengl;
import java.nio.Buffer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
@@ -516,64 +522,98 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
- /**
- * Sets the gamma, brightness, and contrast of the current main
- * display. Returns true if the settings were changed, false if
- * not. If this method returns true, the display settings will
- * automatically be reset upon JVM exit (assuming the JVM does not
- * crash); if the user wishes to change the display settings back to
- * normal ahead of time, use resetDisplayGamma(). Throws
- * IllegalArgumentException if any of the parameters were
- * out-of-bounds.
- *
- * @param gamma The gamma value, typically > 1.0 (default value is
- * 1.0)
- * @param brightness The brightness value between -1.0 and 1.0,
- * inclusive (default value is 0)
- * @param contrast The contrast, greater than 0.0 (default value is 1)
- * @throws IllegalArgumentException if any of the parameters were
- * out-of-bounds
- */
- public boolean setDisplayGamma(final float gamma, final float brightness, final float contrast) throws IllegalArgumentException {
+ @Override
+ public synchronized final boolean setDisplayGamma(final NativeSurface surface, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException {
if ((brightness < -1.0f) || (brightness > 1.0f)) {
throw new IllegalArgumentException("Brightness must be between -1.0 and 1.0");
}
if (contrast < 0) {
throw new IllegalArgumentException("Contrast must be greater than 0.0");
}
- // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal?
- final int rampLength = getGammaRampLength();
- if (rampLength == 0) {
- return false;
+ if( NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface() ) {
+ return false;
+ }
+ try {
+ // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal?
+ final int rampLength = getGammaRampLength(surface);
+ if (rampLength == 0) {
+ return false;
+ }
+ final float[] gammaRamp = new float[rampLength];
+ for (int i = 0; i < rampLength; i++) {
+ final float intensity = (float) i / (float) (rampLength - 1);
+ // apply gamma
+ float rampEntry = (float) java.lang.Math.pow(intensity, gamma);
+ // apply brightness
+ rampEntry += brightness;
+ // apply contrast
+ rampEntry = (rampEntry - 0.5f) * contrast + 0.5f;
+ // Clamp entry to [0, 1]
+ if (rampEntry > 1.0f)
+ rampEntry = 1.0f;
+ else if (rampEntry < 0.0f)
+ rampEntry = 0.0f;
+ gammaRamp[i] = rampEntry;
+ }
+ final AbstractGraphicsScreen screen = surface.getGraphicsConfiguration().getScreen();
+ final DeviceScreenID deviceScreenID = new DeviceScreenID(screen.getDevice().getConnection(), screen.getIndex());
+ if( null == screen2OrigGammaRamp.get(deviceScreenID) ) {
+ screen2OrigGammaRamp.put(deviceScreenID, getGammaRamp(surface)); // cache original gamma ramp once
+ if( DEBUG ) {
+ System.err.println("DisplayGamma: Stored: "+deviceScreenID);
+ dumpGammaStore();
+ }
+ }
+ return setGammaRamp(surface, gammaRamp);
+ } finally {
+ surface.unlockSurface();
}
- final float[] gammaRamp = new float[rampLength];
- for (int i = 0; i < rampLength; i++) {
- final float intensity = (float) i / (float) (rampLength - 1);
- // apply gamma
- float rampEntry = (float) java.lang.Math.pow(intensity, gamma);
- // apply brightness
- rampEntry += brightness;
- // apply contrast
- rampEntry = (rampEntry - 0.5f) * contrast + 0.5f;
- // Clamp entry to [0, 1]
- if (rampEntry > 1.0f)
- rampEntry = 1.0f;
- else if (rampEntry < 0.0f)
- rampEntry = 0.0f;
- gammaRamp[i] = rampEntry;
+ }
+
+ @Override
+ public synchronized final void resetDisplayGamma(final NativeSurface surface) {
+ if( NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface() ) {
+ return;
}
- if( !needsGammaRampReset ) {
- originalGammaRamp = getGammaRamp();
- needsGammaRampReset = true;
+ try {
+ final AbstractGraphicsScreen screen = surface.getGraphicsConfiguration().getScreen();
+ final DeviceScreenID deviceScreenID = new DeviceScreenID(screen.getDevice().getConnection(), screen.getIndex());
+ final Buffer originalGammaRamp = screen2OrigGammaRamp.remove(deviceScreenID);
+ if( null != originalGammaRamp ) {
+ resetGammaRamp(surface, originalGammaRamp);
+ }
+ } finally {
+ surface.unlockSurface();
}
- return setGammaRamp(gammaRamp);
}
@Override
- public synchronized void resetDisplayGamma() {
- if( needsGammaRampReset ) {
- resetGammaRamp(originalGammaRamp);
- needsGammaRampReset = false;
+ public synchronized final void resetAllDisplayGamma() {
+ resetAllDisplayGammaNoSync();
+ }
+
+ @Override
+ protected final void resetAllDisplayGammaNoSync() {
+ if( DEBUG ) {
+ System.err.println("DisplayGamma: Reset");
+ dumpGammaStore();
+ }
+ final Set<DeviceScreenID> deviceScreenIDs = screen2OrigGammaRamp.keySet();
+ for( final Iterator<DeviceScreenID> i = deviceScreenIDs.iterator(); i.hasNext(); ) {
+ final DeviceScreenID deviceScreenID = i.next();
+ final Buffer originalGammaRamp = screen2OrigGammaRamp.remove(deviceScreenID);
+ if( null != originalGammaRamp ) {
+ resetGammaRamp(deviceScreenID, originalGammaRamp);
+ }
+ }
+ }
+ private void dumpGammaStore() {
+ final Set<DeviceScreenID> deviceScreenIDs = screen2OrigGammaRamp.keySet();
+ int count = 0;
+ for( final Iterator<DeviceScreenID> i = deviceScreenIDs.iterator(); i.hasNext(); count++) {
+ final DeviceScreenID deviceScreenID = i.next();
+ final Buffer originalGammaRamp = screen2OrigGammaRamp.get(deviceScreenID);
+ System.err.printf("%4d/%4d: %s -> %s%n", count, deviceScreenIDs.size(), deviceScreenID, originalGammaRamp);
}
}
@@ -582,30 +622,64 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
/** Returns the length of the computed gamma ramp for this OS and
- hardware. Returns 0 if gamma changes are not supported. */
- protected int getGammaRampLength() {
+ hardware. Returns 0 if gamma changes are not supported.
+ * @param surface TODO*/
+ protected int getGammaRampLength(final NativeSurface surface) {
return 0;
}
/** Sets the gamma ramp for the main screen. Returns false if gamma
- ramp changes were not supported. */
- protected boolean setGammaRamp(final float[] ramp) {
+ ramp changes were not supported.
+ * @param surface TODO*/
+ protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
return false;
}
/** Gets the current gamma ramp. This is basically an opaque value
used only on some platforms to reset the gamma ramp to its
- original settings. */
- protected Buffer getGammaRamp() {
+ original settings.
+ * @param surface TODO*/
+ protected Buffer getGammaRamp(final NativeSurface surface) {
return null;
}
/** Resets the gamma ramp, potentially using the specified Buffer as
- data to restore the original values. */
- protected void resetGammaRamp(final Buffer originalGammaRamp) {
+ data to restore the original values.
+ * @param surface TODO*/
+ protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
+ }
+ protected void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
}
// Shutdown hook mechanism for resetting gamma
- private volatile Buffer originalGammaRamp;
- private volatile boolean needsGammaRampReset = false;
+ public final class DeviceScreenID {
+ public final String deviceConnection;
+ public final int screenIdx;
+ DeviceScreenID(final String deviceConnection, final int screenIdx) {
+ this.deviceConnection = deviceConnection;
+ this.screenIdx = screenIdx;
+ }
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + deviceConnection.hashCode();
+ hash = ((hash << 5) - hash) + screenIdx;
+ return hash;
+ }
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof DeviceScreenID) {
+ final DeviceScreenID other = (DeviceScreenID)obj;
+ return this.deviceConnection.equals(other.deviceConnection) &&
+ this.screenIdx == other.screenIdx;
+ }
+ return false;
+ }
+ @Override
+ public String toString() {
+ return "DeviceScreenID[devCon "+deviceConnection+", screenIdx "+screenIdx+", hash 0x"+Integer.toHexString(hashCode())+"]";
+ }
+ }
+ private final Map<DeviceScreenID, Buffer> screen2OrigGammaRamp = new HashMap<DeviceScreenID, Buffer>();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index eac14fdff..3deeafd27 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -40,6 +40,7 @@
package jogamp.opengl;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
@@ -77,7 +78,8 @@ public class GLDrawableHelper {
private final ArrayList<GLEventListener> listeners = new ArrayList<GLEventListener>();
private final HashSet<GLEventListener> listenersToBeInit = new HashSet<GLEventListener>();
private final Object glRunnablesLock = new Object();
- private volatile ArrayList<GLRunnableTask> glRunnables = new ArrayList<GLRunnableTask>();
+ private ArrayList<GLRunnableTask> glRunnables = new ArrayList<GLRunnableTask>();
+ private volatile int glRunnableCount = 0;
private boolean autoSwapBufferMode;
private volatile Thread exclusiveContextThread;
/** -1 release, 0 nop, 1 claim */
@@ -102,6 +104,7 @@ public class GLDrawableHelper {
exclusiveContextThread = null;
exclusiveContextSwitch = 0;
synchronized(glRunnablesLock) {
+ glRunnableCount = 0;
glRunnables.clear();
}
animatorCtrl = null;
@@ -208,19 +211,23 @@ public class GLDrawableHelper {
/**
* Switch {@link GLContext} / {@link GLDrawable} association.
* <p>
- * The <code>oldCtx</code> will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
- * otherwise dis-associate <code>oldCtx</code> from <code>drawable</code>
- * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
- * </p>
- * <p>
- * Re-associate <code>newCtx</code> with <code>drawable</code>
- * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * </p>
- * <p>
- * If the old or new context was current on this thread, it is being released before switching the drawable.
- * </p>
- * <p>
- * No locking is being performed on the drawable, caller is required to take care of it.
+ * Remarks:
+ * <ul>
+ * <li>The <code>oldCtx</code> will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+ * otherwise disassociate <code>oldCtx</code> from <code>drawable</code>
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);} including {@link GL#glFinish() glFinish()}.</li>
+ * <li>Reassociate <code>newCtx</code> with <code>drawable</code>
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.</li>
+ * <li>If the old context was current on this thread, it is being released after disassociating the drawable.</li>
+ * <li>If the new context was current on this thread, it is being released before associating the drawable
+ * and made current afterwards.</li>
+ * <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
+ * <li>The user shall take extra care of thread synchronization,
+ * i.e. lock the involved {@link GLDrawable#getNativeSurface() drawable's} {@link NativeSurface}s
+ * to avoid a race condition. In case {@link GLAutoDrawable auto-drawable's} are used,
+ * their {@link GLAutoDrawable#getUpstreamLock() upstream-lock} must be locked beforehand
+ * see <a href="../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </ul>
* </p>
*
* @param drawable the drawable which context is changed
@@ -277,7 +284,6 @@ public class GLDrawableHelper {
if( currentContext != context ) {
context.makeCurrent();
}
- context.getGL().glFinish();
context.setGLDrawable(null, true); // dis-associate
}
@@ -295,7 +301,7 @@ public class GLDrawableHelper {
}
if(null != context) {
- context.setGLDrawable(drawable, true); // re-association
+ context.setGLDrawable(drawable, true); // re-association, implicit glFinish() ctx/drawable sync
}
if( null != currentContext ) {
@@ -506,15 +512,25 @@ public class GLDrawableHelper {
* </p>
* @param autoDrawable
* @return the disposal count
+ * @throws GLException caused by {@link GLEventListener#dispose(GLAutoDrawable)}
*/
- public final int disposeAllGLEventListener(final GLAutoDrawable autoDrawable, final boolean remove) {
+ public final int disposeAllGLEventListener(final GLAutoDrawable autoDrawable, final boolean remove) throws GLException {
+ Throwable firstCaught = null;
int disposeCount = 0;
synchronized(listenersLock) {
if( remove ) {
for (int count = listeners.size(); 0 < count && 0 < listeners.size(); count--) {
final GLEventListener listener = listeners.remove(0);
if( !listenersToBeInit.remove(listener) ) {
- listener.dispose(autoDrawable);
+ try {
+ listener.dispose(autoDrawable);
+ } catch (final Throwable t) {
+ if( null == firstCaught ) {
+ firstCaught = t;
+ } else {
+ GLException.dumpThrowable("subsequent", t);
+ }
+ }
disposeCount++;
}
}
@@ -522,13 +538,25 @@ public class GLDrawableHelper {
for (int i = 0; i < listeners.size(); i++) {
final GLEventListener listener = listeners.get(i);
if( !listenersToBeInit.contains(listener) ) {
- listener.dispose(autoDrawable);
+ try {
+ listener.dispose(autoDrawable);
+ } catch (final Throwable t) {
+ if( null == firstCaught ) {
+ firstCaught = t;
+ } else {
+ GLException.dumpThrowable("subsequent", t);
+ }
+ }
listenersToBeInit.add(listener);
disposeCount++;
}
}
}
}
+ if( null != firstCaught ) {
+ flushGLRunnables();
+ throw GLException.newGLException(firstCaught);
+ }
return disposeCount;
}
@@ -634,7 +662,7 @@ public class GLDrawableHelper {
init( listener, drawable, sendReshape, 0==i /* setViewport */);
}
} else {
- // Expose same GL initialization if not using GLEventListener
+ // Expose same GL initialization if not using any GLEventListener
drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
}
}
@@ -643,7 +671,7 @@ public class GLDrawableHelper {
public final void display(final GLAutoDrawable drawable) {
displayImpl(drawable);
// runForAllGLEventListener(drawable, displayAction);
- if( glRunnables.size()>0 && !execGLRunnables(drawable) ) { // glRunnables volatile OK; execGL.. only executed if size > 0
+ if( glRunnableCount > 0 && !execGLRunnables(drawable) ) { // glRunnableCount volatile OK; execGL.. only executed if size > 0
displayImpl(drawable);
// runForAllGLEventListener(drawable, displayAction);
}
@@ -701,11 +729,10 @@ public class GLDrawableHelper {
}
}
if(setViewport) {
- final GL gl = drawable.getGL();
- final int glerr0 = gl.glGetError();
- if( GL.GL_NO_ERROR != glerr0 ) {
- System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
- if(DEBUG) {
+ if( GLContext.DEBUG_GL || DEBUG ) {
+ final int glerr0 = drawable.getGL().glGetError();
+ if( GL.GL_NO_ERROR != glerr0 ) {
+ System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
Thread.dumpStack();
}
}
@@ -723,43 +750,29 @@ public class GLDrawableHelper {
}
private final boolean execGLRunnables(final GLAutoDrawable drawable) { // glRunnables.size()>0
- boolean res = true;
// swap one-shot list asap
final ArrayList<GLRunnableTask> _glRunnables;
synchronized(glRunnablesLock) {
- if(glRunnables.size()>0) {
+ if( glRunnables.size() > 0 ) {
+ glRunnableCount = 0;
_glRunnables = glRunnables;
glRunnables = new ArrayList<GLRunnableTask>();
} else {
- _glRunnables = null;
+ return true;
}
}
-
- if(null!=_glRunnables) {
- for (int i=0; i < _glRunnables.size(); i++) {
- res = _glRunnables.get(i).run(drawable) && res;
- }
+ boolean res = true;
+ for (int i=0; i < _glRunnables.size(); i++) {
+ res = _glRunnables.get(i).run(drawable) && res;
}
return res;
}
public final void flushGLRunnables() {
- if(glRunnables.size()>0) { // volatile OK
- // swap one-shot list asap
- final ArrayList<GLRunnableTask> _glRunnables;
- synchronized(glRunnablesLock) {
- if(glRunnables.size()>0) {
- _glRunnables = glRunnables;
- glRunnables = new ArrayList<GLRunnableTask>();
- } else {
- _glRunnables = null;
- }
- }
-
- if(null!=_glRunnables) {
- for (int i=0; i < _glRunnables.size(); i++) {
- _glRunnables.get(i).flush();
- }
+ synchronized(glRunnablesLock) {
+ glRunnableCount = 0;
+ while( glRunnables.size() > 0 ) {
+ glRunnables.remove(0).flush();
}
}
}
@@ -795,6 +808,30 @@ public class GLDrawableHelper {
return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() : false ;
}
+ public static final boolean isLockedByOtherThread(final GLAutoDrawable d) {
+ final Thread currentThread = Thread.currentThread();
+ final Thread upstreamLockOwner = d.getUpstreamLock().getOwner();
+ if( null != upstreamLockOwner && currentThread != upstreamLockOwner ) {
+ return true;
+ } else {
+ final NativeSurface s = d.getNativeSurface();
+ final Thread surfaceLockOwner = null != s ? s.getSurfaceLockOwner() : null;
+ return null != surfaceLockOwner && currentThread != surfaceLockOwner;
+ }
+ }
+
+ public static final boolean isLockedByThisThread(final GLAutoDrawable d) {
+ final Thread currentThread = Thread.currentThread();
+ final Thread upstreamLockOwner = d.getUpstreamLock().getOwner();
+ if( currentThread == upstreamLockOwner ) {
+ return true;
+ } else {
+ final NativeSurface s = d.getNativeSurface();
+ final Thread surfaceLockOwner = null != s ? s.getSurfaceLockOwner() : null;
+ return currentThread == surfaceLockOwner;
+ }
+ }
+
/**
* <p>
* If <code>wait</code> is <code>true</code> the call blocks until the <code>glRunnable</code>
@@ -805,13 +842,32 @@ public class GLDrawableHelper {
* the call is ignored and returns <code>false</code>.<br>
* This helps avoiding deadlocking the caller.
* </p>
+ * <p>
+ * <pre>
+ * 0 == deferredHere && 0 == isGLThread -> display() will issue on GL thread, blocking!
+ *
+ * deferredHere wait isGLThread lockedByThisThread Note
+ * OK 0 x 1 x
+ * OK 0 x 0 0
+ * ERROR 0 x 0 1 Will be deferred on GL thread by display() (blocking),
+ * but locked by this thread -> ERROR
+ *
+ * 1 0 x x All good, due to no wait, non blocking
+ *
+ * 1 1 1 0
+ * 1 1 0 0
+ * SWITCH 1 1 1 1 Run immediately, don't defer since locked by this thread, but isGLThread
+ * ERROR 1 1 0 1 Locked by this thread, but _not_ isGLThread -> ERROR
+ * </pre>
+ * </p>
*
* @param drawable the {@link GLAutoDrawable} to be used
* @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediatly w/o waiting
* @param glRunnable the {@link GLRunnable} to execute within {@link #display()}
* @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>.
+ * @throws IllegalStateException in case the drawable is locked by this thread, no animator is running on another thread and <code>wait</code> is <code>true</code>.
*/
- public final boolean invoke(final GLAutoDrawable drawable, boolean wait, final GLRunnable glRunnable) {
+ public final boolean invoke(final GLAutoDrawable drawable, boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
if( null == glRunnable || null == drawable ||
wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
return false;
@@ -821,18 +877,35 @@ public class GLDrawableHelper {
final Object rTaskLock = new Object();
Throwable throwable = null;
synchronized(rTaskLock) {
- final boolean deferred;
+ boolean deferredHere;
synchronized(glRunnablesLock) {
- deferred = isAnimatorAnimatingOnOtherThread();
- if(!deferred) {
- wait = false; // don't wait if exec immediatly
+ final boolean isGLThread = drawable.isThreadGLCapable();
+ deferredHere = isAnimatorAnimatingOnOtherThread();
+ if( deferredHere ) {
+ if( wait && isLockedByThisThread(drawable) ) {
+ if( isGLThread ) {
+ // Run immediately, don't defer since locked by this thread, but isGLThread
+ deferredHere = false;
+ wait = false;
+ } else {
+ // Locked by this thread, but _not_ isGLThread -> ERROR
+ throw new IllegalStateException("Deferred, wait, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ }
+ } else {
+ if( !isGLThread && isLockedByThisThread(drawable) ) {
+ // Will be deferred on GL thread by display() (blocking), but locked by this thread -> ERROR
+ throw new IllegalStateException("Not deferred, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ wait = false; // don't wait if exec immediately
}
rTask = new GLRunnableTask(glRunnable,
wait ? rTaskLock : null,
wait /* catch Exceptions if waiting for result */);
+ glRunnableCount++;
glRunnables.add(rTask);
}
- if( !deferred ) {
+ if( !deferredHere ) {
drawable.display();
} else if( wait ) {
try {
@@ -851,7 +924,16 @@ public class GLDrawableHelper {
return true;
}
- public final boolean invoke(final GLAutoDrawable drawable, boolean wait, final List<GLRunnable> newGLRunnables) {
+ /**
+ * @see #invoke(GLAutoDrawable, boolean, GLRunnable)
+ *
+ * @param drawable
+ * @param wait
+ * @param newGLRunnables
+ * @return
+ * @throws IllegalStateException
+ */
+ public final boolean invoke(final GLAutoDrawable drawable, boolean wait, final List<GLRunnable> newGLRunnables) throws IllegalStateException {
if( null == newGLRunnables || newGLRunnables.size() == 0 || null == drawable ||
wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
return false;
@@ -862,21 +944,39 @@ public class GLDrawableHelper {
final Object rTaskLock = new Object();
Throwable throwable = null;
synchronized(rTaskLock) {
- final boolean deferred;
+ boolean deferredHere;
synchronized(glRunnablesLock) {
- deferred = isAnimatorAnimatingOnOtherThread() || !drawable.isRealized();
- if(!deferred) {
+ final boolean isGLThread = drawable.isThreadGLCapable();
+ deferredHere = isAnimatorAnimatingOnOtherThread();
+ if( deferredHere ) {
+ if( wait && isLockedByThisThread(drawable) ) {
+ if( isGLThread ) {
+ // Run immediately, don't defer since locked by this thread, but isGLThread
+ deferredHere = false;
+ wait = false;
+ } else {
+ // Locked by this thread, but _not_ isGLThread -> ERROR
+ throw new IllegalStateException("Deferred, wait, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ }
+ } else {
+ if( !isGLThread && isLockedByThisThread(drawable) ) {
+ // Will be deferred on GL thread by display() (blocking), but locked by this thread -> ERROR
+ throw new IllegalStateException("Not deferred, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
wait = false; // don't wait if exec immediately
}
for(int i=0; i<count-1; i++) {
+ glRunnableCount++;
glRunnables.add( new GLRunnableTask(newGLRunnables.get(i), null, false) );
}
rTask = new GLRunnableTask(newGLRunnables.get(count-1),
wait ? rTaskLock : null,
wait /* catch Exceptions if waiting for result */);
+ glRunnableCount++;
glRunnables.add(rTask);
}
- if( !deferred ) {
+ if( !deferredHere ) {
drawable.display();
} else if( wait ) {
try {
@@ -900,6 +1000,7 @@ public class GLDrawableHelper {
return;
}
synchronized(glRunnablesLock) {
+ glRunnableCount++;
glRunnables.add( new GLRunnableTask(glRunnable, null, false) );
}
}
@@ -961,8 +1062,8 @@ public class GLDrawableHelper {
try {
forceNativeRelease(context);
} catch (final Throwable ex) {
- ex.printStackTrace();
- throw new GLException(ex);
+ flushGLRunnables();
+ throw GLException.newGLException(ex);
}
}
exclusiveContextThread = t;
@@ -980,7 +1081,21 @@ public class GLDrawableHelper {
return exclusiveContextThread;
}
- private static final ThreadLocal<Runnable> perThreadInitAction = new ThreadLocal<Runnable>();
+ private static final ThreadLocal<WeakReference<Runnable>> perThreadInitAction = new ThreadLocal<WeakReference<Runnable>>();
+ private static final Runnable getLastInitAction() {
+ final WeakReference<Runnable> lastInitActionWR = perThreadInitAction.get();
+ if( null != lastInitActionWR ) {
+ final Runnable lastInitAction = lastInitActionWR.get();
+ if( null == lastInitAction ) {
+ perThreadInitAction.set(null);
+ }
+ return lastInitAction;
+ }
+ return null;
+ }
+ private static final void setLastInitAction(final Runnable initAction) {
+ perThreadInitAction.set(new WeakReference<Runnable>(initAction));
+ }
/** Principal helper method which runs a Runnable with the context
made current. This could have been made part of GLContext, but a
@@ -1004,8 +1119,7 @@ public class GLDrawableHelper {
final Runnable initAction) {
if(null==context) {
if (DEBUG) {
- final Exception e = new GLException(getThreadName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext");
- e.printStackTrace();
+ GLException.dumpThrowable("informal", new GLException("Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"));
}
return;
}
@@ -1030,9 +1144,11 @@ public class GLDrawableHelper {
* @param autoDrawable
* @param context
* @param destroyContext destroy context in the end while holding the lock
+ * @throws GLException caused by {@link GLEventListener#dispose(GLAutoDrawable)} or context closing
+ *
*/
public final void disposeGL(final GLAutoDrawable autoDrawable,
- final GLContext context, final boolean destroyContext) {
+ final GLContext context, final boolean destroyContext) throws GLException {
// Support for recursive makeCurrent() calls as well as calling
// other drawables' display() methods from within another one's
GLContext lastContext = GLContext.getCurrent();
@@ -1042,20 +1158,27 @@ public class GLDrawableHelper {
lastContext = null;
} else {
// utilize recursive locking
- lastInitAction = perThreadInitAction.get();
+ lastInitAction = getLastInitAction();
lastContext.release();
}
}
+ GLException disposeCaught = null;
+ Throwable contextCloseCaught = null;
+
int res;
try {
res = context.makeCurrent();
if (GLContext.CONTEXT_NOT_CURRENT != res) {
if(GLContext.CONTEXT_CURRENT_NEW == res) {
- throw new GLException(getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+ throw new GLException(GLDrawableHelper.getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
}
if( listeners.size() > 0 && null != autoDrawable ) {
- disposeAllGLEventListener(autoDrawable, false);
+ try {
+ disposeAllGLEventListener(autoDrawable, false);
+ } catch(final GLException t) {
+ disposeCaught = t;
+ }
}
}
} finally {
@@ -1065,17 +1188,26 @@ public class GLDrawableHelper {
} else {
forceNativeRelease(context);
}
- flushGLRunnables();
- } catch (final Exception e) {
- System.err.println("Caught exception on thread "+getThreadName());
- e.printStackTrace();
+ } catch (final Throwable t) {
+ contextCloseCaught = t;
}
+ flushGLRunnables(); // always flush GLRunnables at dispose
+
if (lastContext != null) {
final int res2 = lastContext.makeCurrent();
if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
lastInitAction.run();
}
}
+ if( null != disposeCaught ) {
+ if( null != contextCloseCaught ) {
+ GLException.dumpThrowable("subsequent", contextCloseCaught);
+ }
+ throw disposeCaught;
+ }
+ if( null != contextCloseCaught ) {
+ throw GLException.newGLException(contextCloseCaught);
+ }
}
}
@@ -1085,6 +1217,9 @@ public class GLDrawableHelper {
final Runnable initAction) {
final Thread currentThread = Thread.currentThread();
+ Throwable glEventListenerCaught = null;
+ Throwable contextReleaseCaught = null;
+
// Exclusive Cases:
// 1: lock - unlock : default
// 2: lock - - : exclusive, not locked yet
@@ -1116,7 +1251,7 @@ public class GLDrawableHelper {
lastContext = null;
} else {
// utilize recursive locking
- lastInitAction = perThreadInitAction.get();
+ lastInitAction = getLastInitAction();
lastContext.release();
}
}
@@ -1131,7 +1266,7 @@ public class GLDrawableHelper {
}
if (GLContext.CONTEXT_NOT_CURRENT != res) {
try {
- perThreadInitAction.set(initAction);
+ setLastInitAction(initAction);
if (GLContext.CONTEXT_CURRENT_NEW == res) {
if (DEBUG) {
System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
@@ -1142,6 +1277,8 @@ public class GLDrawableHelper {
if ( autoSwapBufferMode ) {
drawable.swapBuffers();
}
+ } catch (final Throwable t) {
+ glEventListenerCaught = t;
} finally {
if( _releaseExclusiveThread ) {
exclusiveContextThread = null;
@@ -1152,9 +1289,8 @@ public class GLDrawableHelper {
if( releaseContext ) {
try {
context.release();
- } catch (final Exception e) {
- System.err.println("Caught exception on thread "+getThreadName());
- e.printStackTrace();
+ } catch (final Throwable t) {
+ contextReleaseCaught = t;
}
}
}
@@ -1166,6 +1302,17 @@ public class GLDrawableHelper {
lastInitAction.run();
}
}
+ if( null != glEventListenerCaught ) {
+ flushGLRunnables();
+ if( null != contextReleaseCaught ) {
+ GLException.dumpThrowable("subsequent", contextReleaseCaught);
+ }
+ throw GLException.newGLException(glEventListenerCaught);
+ }
+ if( null != contextReleaseCaught ) {
+ flushGLRunnables();
+ throw GLException.newGLException(contextReleaseCaught);
+ }
}
}
@@ -1175,6 +1322,9 @@ public class GLDrawableHelper {
final Runnable initAction) {
final Thread currentThread = Thread.currentThread();
+ Throwable glEventListenerCaught = null;
+ Throwable contextReleaseCaught = null;
+
// Exclusive Cases:
// 1: lock - unlock : default
// 2: lock - - : exclusive, not locked yet
@@ -1205,7 +1355,7 @@ public class GLDrawableHelper {
lastContext = null;
} else {
// utilize recursive locking
- lastInitAction = perThreadInitAction.get();
+ lastInitAction = getLastInitAction();
lastContext.release();
}
}
@@ -1229,7 +1379,7 @@ public class GLDrawableHelper {
}
if (GLContext.CONTEXT_NOT_CURRENT != res) {
try {
- perThreadInitAction.set(initAction);
+ setLastInitAction(initAction);
if (GLContext.CONTEXT_CURRENT_NEW == res) {
if (DEBUG) {
System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
@@ -1246,6 +1396,8 @@ public class GLDrawableHelper {
tdX = System.currentTimeMillis();
tdS = tdX - tdS; // swapBuffers
}
+ } catch (final Throwable t) {
+ glEventListenerCaught = t;
} finally {
if( _releaseExclusiveThread ) {
exclusiveContextSwitch = 0;
@@ -1258,9 +1410,8 @@ public class GLDrawableHelper {
try {
context.release();
ctxReleased = true;
- } catch (final Exception e) {
- System.err.println("Caught exception on thread "+getThreadName());
- e.printStackTrace();
+ } catch (final Throwable t) {
+ contextReleaseCaught = t;
}
}
}
@@ -1273,11 +1424,21 @@ public class GLDrawableHelper {
lastInitAction.run();
}
}
+ if( null != glEventListenerCaught ) {
+ flushGLRunnables();
+ if( null != contextReleaseCaught ) {
+ GLException.dumpThrowable("subsequent", contextReleaseCaught);
+ }
+ throw GLException.newGLException(glEventListenerCaught);
+ }
+ if( null != contextReleaseCaught ) {
+ flushGLRunnables();
+ throw GLException.newGLException(contextReleaseCaught);
+ }
}
final long td = System.currentTimeMillis() - t0;
System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed);
}
protected static String getThreadName() { return Thread.currentThread().getName(); }
-
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 3bb22612f..544aaf064 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -130,10 +130,11 @@ public abstract class GLDrawableImpl implements GLDrawable {
}
@Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
return (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
}
+ @Override
public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
return requestedCapabilities;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 6046527d1..991a351e6 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -15,6 +15,7 @@ import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.GLRendererQuirks;
import com.jogamp.opengl.FBObject.Attachment;
import com.jogamp.opengl.FBObject.Colorbuffer;
import com.jogamp.opengl.FBObject.TextureAttachment;
@@ -44,13 +45,15 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
static {
Debug.initSingleton();
DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
- DEBUG_SWAP = DEBUG || PropertyAccess.isPropertyDefined("jogl.debug.FBObject.Swap", true);
+ DEBUG_SWAP = PropertyAccess.isPropertyDefined("jogl.debug.FBObject.Swap", true);
}
private final GLDrawableImpl parent;
private GLCapabilitiesImmutable origParentChosenCaps;
private boolean initialized;
+ private int maxSamples;
+ private int fboModeBits;
private int texUnit;
private int samples;
private boolean fboResetQuirk;
@@ -59,9 +62,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
private int fboIBack; // points to GL_BACK buffer
private int fboIFront; // points to GL_FRONT buffer
private int pendingFBOReset = -1;
- /** Indicated whether the FBO is bound. */
+ /** Indicates whether the FBO is bound. */
private boolean fboBound;
- /** Indicated whether the FBO is swapped, resets to false after makeCurrent -> contextMadeCurrent. */
+ /** Indicates whether the FBO is swapped, resets to false after makeCurrent -> contextMadeCurrent. */
private boolean fboSwapped;
/** dump fboResetQuirk info only once pre ClassLoader and only in DEBUG mode */
@@ -89,17 +92,79 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
final GLCapabilitiesImmutable fboCaps, final int textureUnit) {
super(factory, surface, fboCaps, false);
this.initialized = false;
+ this.fboModeBits = FBOMODE_USE_TEXTURE;
this.parent = parent;
this.origParentChosenCaps = getChosenGLCapabilities(); // just to avoid null, will be reset at initialize(..)
this.texUnit = textureUnit;
this.samples = fboCaps.getNumSamples();
- fboResetQuirk = false;
+ this.fboResetQuirk = false;
+ this.swapBufferContext = null;
+ }
- // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
- // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ;
+ private final void setupFBO(final GL gl, final int idx, final int width, final int height, final int samples,
+ final boolean useAlpha, final int depthBits, final int stencilBits,
+ final boolean useTexture, final boolean realUnbind) {
+ final FBObject fbo = new FBObject();
+ fbos[idx] = fbo;
- this.swapBufferContext = null;
+ final boolean useDepth = depthBits > 0;
+ final boolean useStencil = stencilBits > 0;
+
+ fbo.init(gl, width, height, samples);
+ if(fbo.getNumSamples() != samples) {
+ throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbo);
+ }
+ if(samples > 0 || !useTexture) {
+ fbo.attachColorbuffer(gl, 0, useAlpha);
+ } else {
+ fbo.attachTexture2D(gl, 0, useAlpha);
+ }
+ if( useStencil ) {
+ if( useDepth ) {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, depthBits);
+ } else {
+ fbo.attachRenderbuffer(gl, Attachment.Type.STENCIL, stencilBits);
+ }
+ } else if( useDepth ) {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, depthBits);
+ }
+ if(samples > 0) {
+ final FBObject ssink = new FBObject();
+ {
+ ssink.init(gl, width, height, 0);
+ if( !useTexture ) {
+ ssink.attachColorbuffer(gl, 0, useAlpha);
+ } else {
+ ssink.attachTexture2D(gl, 0, useAlpha);
+ }
+ if( useStencil ) {
+ if( useDepth ) {
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, depthBits);
+ } else {
+ ssink.attachRenderbuffer(gl, Attachment.Type.STENCIL, stencilBits);
+ }
+ } else if( useDepth ) {
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, depthBits);
+ }
+ }
+ fbo.setSamplingSink(ssink);
+ fbo.resetSamplingSink(gl); // validate
+ }
+ // Clear the framebuffer allowing defined state not exposing previous content.
+ // Also remedy for Bug 1020, i.e. OSX/Nvidia's FBO needs to be cleared before blitting,
+ // otherwise first MSAA frame lacks antialiasing.
+ fbo.bind(gl);
+ if( useDepth ) {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ } else {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ }
+ if( realUnbind ) {
+ fbo.unbind(gl);
+ } else {
+ fbo.markUnbound();
+ }
}
private final void initialize(final boolean realize, final GL gl) {
@@ -116,7 +181,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
if(realize) {
final GLCapabilities chosenFBOCaps = (GLCapabilities) getChosenGLCapabilities(); // cloned at setRealized(true)
- final int maxSamples = gl.getMaxRenderbufferSamples();
+ maxSamples = gl.getMaxRenderbufferSamples(); // if > 0 implies fullFBOSupport
{
final int newSamples = samples <= maxSamples ? samples : maxSamples;
if(DEBUG) {
@@ -138,25 +203,21 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
fboIBack = 0; // head
fboIFront = fbos.length - 1; // tail
- for(int i=0; i<fbosN; i++) {
- fbos[i] = new FBObject();
- fbos[i].reset(gl, getSurfaceWidth(), getSurfaceHeight(), samples, false);
- if(fbos[i].getNumSamples() != samples) {
- throw new InternalError("Sample number mismatch: "+samples+", fbos["+i+"] "+fbos[i]);
- }
- if(samples > 0) {
- fbos[i].attachColorbuffer(gl, 0, chosenFBOCaps.getAlphaBits()>0);
- } else {
- fbos[i].attachTexture2D(gl, 0, chosenFBOCaps.getAlphaBits()>0);
- }
- if( chosenFBOCaps.getStencilBits() > 0 ) {
- fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
- } else {
- fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
- }
+ if( 0 == ( FBOMODE_USE_TEXTURE & fboModeBits ) &&
+ gl.getContext().hasRendererQuirk(GLRendererQuirks.BuggyColorRenderbuffer) ) {
+ // GLRendererQuirks.BuggyColorRenderbuffer also disables MSAA, i.e. full FBO support
+ fboModeBits |= FBOMODE_USE_TEXTURE;
}
- fbos[fboIFront].resetSamplingSink(gl);
+ final boolean useTexture = 0 != ( FBOMODE_USE_TEXTURE & fboModeBits );
+ final boolean useAlpha = chosenFBOCaps.getAlphaBits() > 0;
+ final int width = getSurfaceWidth();
+ final int height = getSurfaceHeight();
+
+ for(int i=0; i<fbosN; i++) {
+ setupFBO(gl, i, width, height, samples, useAlpha,
+ chosenFBOCaps.getDepthBits(), chosenFBOCaps.getStencilBits(), useTexture, fbosN-1==i);
+ }
fbos[0].formatToGLCapabilities(chosenFBOCaps);
chosenFBOCaps.setDoubleBuffered( chosenFBOCaps.getDoubleBuffered() || samples > 0 );
} else {
@@ -180,29 +241,26 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
swapBufferContext = sbc;
}
- private final void reset(final GL gl, final int idx, final int width, final int height, final int samples, final int alphaBits, final int stencilBits) {
+ private final void reset(final GL gl, final int idx, final int width, final int height, final int samples,
+ final boolean useAlpha, final int depthBits, final int stencilBits) {
if( !fboResetQuirk ) {
try {
- fbos[idx].reset(gl, width, height, samples, false);
+ fbos[idx].reset(gl, width, height, samples);
if(fbos[idx].getNumSamples() != samples) {
throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbos[idx]);
}
return;
} catch (final GLException e) {
fboResetQuirk = true;
- if(DEBUG) {
+ if( DEBUG ) {
if(!resetQuirkInfoDumped) {
resetQuirkInfoDumped = true;
System.err.println("GLFBODrawable: FBO Reset failed: "+e.getMessage());
System.err.println("GLFBODrawable: Enabling FBOResetQuirk, due to GL driver bug.");
final JoglVersion joglVersion = JoglVersion.getInstance();
- if(DEBUG) {
- System.err.println(VersionUtil.getPlatformInfo());
- System.err.println(joglVersion.toString());
- System.err.println(JoglVersion.getGLInfo(gl, null));
- } else {
- System.err.println(joglVersion.getBriefOSGLBuildInfo(gl, null));
- }
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(joglVersion.toString());
+ System.err.println(JoglVersion.getGLInfo(gl, null));
e.printStackTrace();
}
}
@@ -211,21 +269,8 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
// resetQuirk fallback
fbos[idx].destroy(gl);
- fbos[idx] = new FBObject();
- fbos[idx].reset(gl, getSurfaceWidth(), getSurfaceHeight(), samples, false);
- if(fbos[idx].getNumSamples() != samples) {
- throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbos[idx]);
- }
- if(samples > 0) {
- fbos[idx].attachColorbuffer(gl, 0, alphaBits>0);
- } else {
- fbos[idx].attachTexture2D(gl, 0, alphaBits>0);
- }
- if( stencilBits > 0 ) {
- fbos[idx].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
- } else {
- fbos[idx].attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
- }
+ final boolean useTexture = 0 != ( FBOMODE_USE_TEXTURE & fboModeBits );
+ setupFBO(gl, idx, width, height, samples, useAlpha, depthBits, stencilBits, useTexture, true);
}
private final void reset(final GL gl, int newSamples) throws GLException {
@@ -248,7 +293,6 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
fboBound = false; // clear bound-flag immediatly, caused by contextMadeCurrent(..) - otherwise we would swap @ release
fboSwapped = false;
try {
- final int maxSamples = gl.getMaxRenderbufferSamples();
newSamples = newSamples <= maxSamples ? newSamples : maxSamples;
if(0==samples && 0<newSamples || 0<samples && 0==newSamples) {
@@ -270,7 +314,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
for(int i=0; i<fbos.length; i++) {
if( pendingFBOReset != i ) {
- reset(gl, i, nWidth, nHeight, samples, caps.getAlphaBits(), caps.getStencilBits());
+ reset(gl, i, nWidth, nHeight, samples, caps.getAlphaBits()>0, caps.getDepthBits(), caps.getStencilBits());
}
}
final GLCapabilities fboCapsNative = (GLCapabilities) surface.getGraphicsConfiguration().getChosenCapabilities();
@@ -289,10 +333,10 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
}
if(null != tFBO) {
- throw new GLException("GLFBODrawableImpl.reset(..) FBObject.reset(..) exception", tFBO);
+ throw GLException.newGLException(tFBO);
}
if(null != tGL) {
- throw new GLException("GLFBODrawableImpl.reset(..) GLContext.release() exception", tGL);
+ throw GLException.newGLException(tGL);
}
if(DEBUG) {
System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): END "+this);
@@ -397,7 +441,8 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
// Safely reset the previous front FBO - after completing propagating swap
if(0 <= pendingFBOReset) {
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
- reset(glc.getGL(), pendingFBOReset, getSurfaceWidth(), getSurfaceHeight(), samples, caps.getAlphaBits(), caps.getStencilBits());
+ reset(glc.getGL(), pendingFBOReset, getSurfaceWidth(), getSurfaceHeight(), samples,
+ caps.getAlphaBits()>0, caps.getDepthBits(), caps.getStencilBits());
pendingFBOReset = -1;
}
}
@@ -414,17 +459,16 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
fboIBack = ( fboIBack + 1 ) % fbos.length;
final Colorbuffer colorbuffer = samples > 0 ? fbos[fboIFront].getSamplingSink() : fbos[fboIFront].getColorbuffer(0);
+ if(null == colorbuffer) {
+ throw new GLException("Front colorbuffer is null: samples "+samples+", "+this);
+ }
final TextureAttachment texAttachment;
- if(colorbuffer instanceof TextureAttachment) {
- texAttachment = (TextureAttachment) colorbuffer;
+ if( colorbuffer.isTextureAttachment() ) {
+ texAttachment = colorbuffer.getTextureAttachment();
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
} else {
- if(null == colorbuffer) {
- throw new GLException("Front colorbuffer is null: samples "+samples+", "+this);
- } else {
- throw new GLException("Front colorbuffer is not a texture: "+colorbuffer.getClass().getName()+": samples "+samples+", "+colorbuffer+", "+this);
- }
+ texAttachment = null;
}
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
fbos[fboIFront].use(gl, texAttachment);
/* Included in above use command:
@@ -447,6 +491,19 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
@Override
+ public final void setFBOMode(final int modeBits) throws IllegalStateException {
+ if( isInitialized() ) {
+ throw new IllegalStateException("Already initialized: "+this);
+ }
+ this.fboModeBits = modeBits;
+ }
+
+ @Override
+ public final int getFBOMode() {
+ return fboModeBits;
+ }
+
+ @Override
public final void resetSize(final GL gl) throws GLException {
reset(gl, samples);
}
@@ -468,9 +525,12 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
@Override
- public final int setNumBuffers(final int bufferCount) throws GLException {
+ public final int setNumBuffers(final int bufferCount) throws IllegalStateException, GLException {
+ if( isInitialized() ) {
+ throw new IllegalStateException("Already initialized: "+this);
+ }
// FIXME: Implement
- return bufferCount;
+ return GLFBODrawableImpl.bufferCount;
}
@Override
@@ -519,24 +579,24 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
@Override
- public final TextureAttachment getTextureBuffer(final int bufferName) throws IllegalArgumentException {
+ public final Colorbuffer getColorbuffer(final int bufferName) throws IllegalArgumentException {
if(!initialized) {
return null;
}
- final TextureAttachment res;
+ final Colorbuffer res;
switch(bufferName) {
case GL.GL_FRONT:
if( samples > 0 ) {
res = fbos[0].getSamplingSink();
} else {
- res = (TextureAttachment) fbos[fboIFront].getColorbuffer(0);
+ res = fbos[fboIFront].getColorbuffer(0);
}
break;
case GL.GL_BACK:
if( samples > 0 ) {
throw new IllegalArgumentException("Cannot access GL_BACK buffer of MSAA FBO: "+this);
} else {
- res = (TextureAttachment) fbos[fboIBack].getColorbuffer(0);
+ res = fbos[fboIBack].getColorbuffer(0);
}
break;
default:
diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
index 95c4ceb98..721dc7384 100644
--- a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
@@ -102,7 +102,7 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
}
@Override
- public final int setNumBuffers(final int bufferCount) throws GLException {
+ public final int setNumBuffers(final int bufferCount) throws /* IllegalStateException, */ GLException {
return ((GLFBODrawableImpl)drawable).setNumBuffers(bufferCount);
}
@@ -128,13 +128,24 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
}
@Override
- public final FBObject.TextureAttachment getTextureBuffer(final int bufferName) {
- return ((GLFBODrawableImpl)drawable).getTextureBuffer(bufferName);
+ public final FBObject.Colorbuffer getColorbuffer(final int bufferName) {
+ return ((GLFBODrawableImpl)drawable).getColorbuffer(bufferName);
}
@Override
public void resetSize(final GL gl) throws GLException {
((GLFBODrawableImpl)drawable).resetSize(gl);
}
+
+ @Override
+ public final void setFBOMode(final int modeBits) throws IllegalStateException {
+ ((GLFBODrawableImpl)drawable).setFBOMode(modeBits);
+
+ }
+
+ @Override
+ public final int getFBOMode() {
+ return ((GLFBODrawableImpl)drawable).getFBOMode();
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
index 0ceef6bf7..ca1c1869e 100644
--- a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
+++ b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
@@ -90,8 +90,10 @@ public class GLRunnableTask implements GLRunnable {
/**
* Simply flush this task and notify a waiting executor.
+ * <p>
* The executor which might have been blocked until notified
* will be unblocked and the task removed from the queue.
+ * </p>
*
* @see #isFlushed()
* @see #isInQueue()
diff --git a/src/jogl/classes/jogamp/opengl/GLStateTracker.java b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
index d532a2567..dc49b35f4 100644
--- a/src/jogl/classes/jogamp/opengl/GLStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
@@ -68,7 +68,7 @@ public class GLStateTracker {
private IntIntHashMap pixelStateMap;
private final ArrayList<SavedState> stack;
- private static class SavedState {
+ static class SavedState {
/**
* Empty pixel-store state
@@ -78,15 +78,14 @@ public class GLStateTracker {
/**
* set (client) pixel-store state, deep copy
*/
- private final void setPixelStateMap(final IntIntHashMap pixelStateMap) {
+ final void setPixelStateMap(final IntIntHashMap pixelStateMap) {
this.pixelStateMap = (IntIntHashMap) pixelStateMap.clone();
}
/**
* get (client) pixel-store state, return reference
*/
- private final IntIntHashMap getPixelStateMap() { return pixelStateMap; }
-
+ final IntIntHashMap getPixelStateMap() { return pixelStateMap; }
}
@@ -163,10 +162,11 @@ public class GLStateTracker {
if(null==state) {
throw new GLException("null stack element (remaining stack size "+stack.size()+")");
}
+ final IntIntHashMap statePixelStateMap = state.getPixelStateMap();
- if ( null != state.getPixelStateMap() ) {
+ if ( null != statePixelStateMap ) {
// use pulled client pixel-store state from stack
- pixelStateMap = state.getPixelStateMap();
+ pixelStateMap = statePixelStateMap;
} // else: empty-slot, not pushed by GL_CLIENT_PIXEL_STORE_BIT
}
}
diff --git a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
index 2b017e8e9..7b405e524 100644
--- a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
+++ b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
@@ -41,6 +41,7 @@ import java.security.PrivilegedAction;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.Threading.Mode;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.PropertyAccess;
@@ -49,16 +50,6 @@ import com.jogamp.common.util.ReflectionUtil;
/** Implementation of the {@link javax.media.opengl.Threading} class. */
public class ThreadingImpl {
- public enum Mode {
- MT(0), ST_AWT(1), ST_WORKER(2);
-
- public final int id;
-
- Mode(final int id){
- this.id = id;
- }
- }
-
protected static final boolean DEBUG = Debug.debug("Threading");
private static boolean singleThreaded;
@@ -93,28 +84,23 @@ public class ThreadingImpl {
_isX11 = NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false);
- // default setting
- singleThreaded = true;
- mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER );
-
if (singleThreadProp != null) {
if (singleThreadProp.equals("true") ||
singleThreadProp.equals("auto")) {
- singleThreaded = true;
- mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER );
+ mode = ( hasAWT ? Mode.ST_AWT : Mode.MT );
} else if (singleThreadProp.equals("worker")) {
- singleThreaded = true;
mode = Mode.ST_WORKER;
} else if (hasAWT && singleThreadProp.equals("awt")) {
- singleThreaded = true;
mode = Mode.ST_AWT;
} else if (singleThreadProp.equals("false")) {
- singleThreaded = false;
mode = Mode.MT;
} else {
throw new RuntimeException("Unsupported value for property jogl.1thread: "+singleThreadProp+", should be [true/auto, worker, awt or false]");
}
+ } else {
+ mode = ( hasAWT ? Mode.ST_AWT : Mode.MT );
}
+ singleThreaded = Mode.MT != mode;
ToolkitThreadingPlugin threadingPlugin=null;
if(hasAWT) {
@@ -155,9 +141,11 @@ public class ThreadingImpl {
method. This method should be called as early as possible in an
application. */
public static final void disableSingleThreading() {
- singleThreaded = false;
- if (Debug.verbose()) {
- System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation");
+ if( Mode.MT != mode ) {
+ singleThreaded = false;
+ if (Debug.verbose()) {
+ System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation");
+ }
}
}
@@ -167,22 +155,28 @@ public class ThreadingImpl {
return singleThreaded;
}
- /** Indicates whether the current thread is the single thread on
- which this implementation of the javax.media.opengl APIs
- performs all of its OpenGL-related work. This method should only
- be called if the single-thread model is in effect. */
+ /**
+ * Indicates whether the current thread is capable of
+ * performing OpenGL-related work.
+ * <p>
+ * Method always returns <code>true</code>
+ * if {@link #getMode()} == {@link Mode#MT} or {@link #isSingleThreaded()} == <code>false</code>.
+ * </p>
+ */
public static final boolean isOpenGLThread() throws GLException {
- if(null!=threadingPlugin) {
+ if( Mode.MT == mode || !singleThreaded ) {
+ return true;
+ } else if( null != threadingPlugin ) {
return threadingPlugin.isOpenGLThread();
- }
-
- switch (mode) {
- case ST_AWT:
- throw new InternalError();
- case ST_WORKER:
- return GLWorkerThread.isWorkerThread();
- default:
- throw new InternalError("Illegal single-threading mode " + mode);
+ } else {
+ switch (mode) {
+ case ST_AWT:
+ throw new InternalError();
+ case ST_WORKER:
+ return GLWorkerThread.isWorkerThread();
+ default:
+ throw new InternalError("Illegal single-threading mode " + mode);
+ }
}
}
@@ -213,6 +207,10 @@ public class ThreadingImpl {
invokeOnWorkerThread(wait, r);
break;
+ case MT:
+ r.run();
+ break;
+
default:
throw new InternalError("Illegal single-threading mode " + mode);
}
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
index 24b89cd02..495887e0f 100644
--- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -254,7 +254,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
@Override
protected final void initStreamImpl(final int vid, final int aid) throws IOException {
- if( null == getURI() ) {
+ if( null == getUri() ) {
return;
}
if( null == mp && null == cam ) {
@@ -263,7 +263,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
} else {
int cameraId = 0;
try {
- cameraId = Integer.parseInt(cameraPath);
+ cameraId = Integer.parseInt(cameraPath.decode());
} catch (final NumberFormatException nfe) {}
if( 0 <= cameraId && cameraId < Camera.getNumberOfCameras() ) {
cam = Camera.open(cameraId);
@@ -280,7 +280,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
} // else FIXME: Select aid !
// Note: Both FIXMEs seem to be n/a via Android's MediaPlayer -> Switch to API level 16 MediaCodec/MediaExtractor ..
try {
- final Uri _uri = Uri.parse(getURI().toString());
+ final Uri _uri = Uri.parse(getUri().toString());
mp.setDataSource(StaticContext.getContext(), _uri);
} catch (final IllegalArgumentException e) {
throw new RuntimeException(e);
@@ -293,7 +293,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
try {
mp.prepare();
} catch (final IOException ioe) {
- throw new IOException("MediaPlayer failed to process stream <"+getURI().toString()+">: "+ioe.getMessage(), ioe);
+ throw new IOException("MediaPlayer failed to process stream <"+getUri().toString()+">: "+ioe.getMessage(), ioe);
}
final int r_aid = GLMediaPlayer.STREAM_ID_NONE == aid ? GLMediaPlayer.STREAM_ID_NONE : 1 /* fake */;
final String icodec = "android";
@@ -381,7 +381,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
cam.setPreviewTexture(sTexFrame.surfaceTex);
cam.startPreview();
} catch (final IOException ioe) {
- throw new RuntimeException("MediaPlayer failed to process stream <"+getURI().toString()+">: "+ioe.getMessage(), ioe);
+ throw new RuntimeException("MediaPlayer failed to process stream <"+getUri().toString()+">: "+ioe.getMessage(), ioe);
}
}
if( null != surface ) {
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
index 26ec62785..3f8910fb5 100644
--- a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
@@ -108,6 +108,10 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
ThreadingImpl.invokeOnWorkerThread(wait, r);
break;
+ case MT:
+ r.run();
+ break;
+
default:
throw new InternalError("Illegal single-threading mode " + ThreadingImpl.getMode());
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index 5a9a30313..2edb22314 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -184,7 +184,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
if( null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper ) {
- if(isANGLE && !enableANGLE) {
+ if(isANGLE && !GLProfile.enableANGLE) {
if(DEBUG || GLProfile.DEBUG) {
System.err.println("Info: EGLDrawableFactory.init - EGL/ES2 ANGLE disabled");
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
index 9ff6bd637..51d8ca6fe 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
@@ -49,6 +49,7 @@ import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.GLException;
@@ -255,8 +256,8 @@ public class Mipmap {
*/
public static void closestFit( final GL gl, final int target, final int width, final int height, final int internalFormat,
final int format, final int type, final int[] newWidth, final int[] newHeight ) {
- // Use proxy textures if OpenGL version >= 1.1
- if( Double.parseDouble( gl.glGetString( GL.GL_VERSION ).trim().substring( 0, 3 ) ) >= 1.1 ) {
+ // Use proxy textures if OpenGL GL2/GL3 version >= 1.1
+ if( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version110) >= 0 ) {
int widthPowerOf2 = nearestPower( width );
int heightPowerOf2 = nearestPower( height );
final int[] proxyWidth = new int[1];
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index dbca7c2e8..7066a6db5 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -828,7 +828,7 @@ public class MacOSXCGLContext extends GLContextImpl
final long drawableHandle = drawable.getHandle();
if(drawable instanceof GLFBODrawableImpl) {
final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable;
- texID = fbod.getTextureBuffer(GL.GL_FRONT).getName();
+ texID = fbod.getColorbuffer(GL.GL_FRONT).getName();
pbufferHandle = 0;
fbod.setSwapBufferContext(new GLFBODrawableImpl.SwapBufferContext() {
@Override
@@ -1043,7 +1043,7 @@ public class MacOSXCGLContext extends GLContextImpl
final boolean valid;
final boolean isFBO = drawable instanceof GLFBODrawableImpl;
if( isFBO ){
- texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName();
+ texID = ((GLFBODrawableImpl)drawable).getColorbuffer(GL.GL_FRONT).getName();
valid = 0 != texID;
} else {
texID = 0;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 7c05b8eab..045abca4c 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -42,6 +42,7 @@ package jogamp.opengl.macosx.cgl;
import java.nio.Buffer;
import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -404,24 +405,29 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
/** Returns the length of the computed gamma ramp for this OS and
hardware. Returns 0 if gamma changes are not supported. */
@Override
- protected int getGammaRampLength() {
+ protected int getGammaRampLength(final NativeSurface surface) {
return GAMMA_RAMP_LENGTH;
}
@Override
- protected boolean setGammaRamp(final float[] ramp) {
+ protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
final FloatBuffer rampNIO = Buffers.newDirectFloatBuffer(ramp);
-
return CGL.setGammaRamp(ramp.length, rampNIO, rampNIO, rampNIO);
}
@Override
- protected Buffer getGammaRamp() {
- return null;
+ protected Buffer getGammaRamp(final NativeSurface surface) {
+ return ShortBuffer.allocate(0); // return a dummy gamma ramp default for reset
}
@Override
- protected void resetGammaRamp(final Buffer originalGammaRamp) {
+ protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
CGL.resetGammaRamp();
}
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
+ CGL.resetGammaRamp();
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 05e192bbc..0969199c6 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -28,7 +28,6 @@
package jogamp.opengl.util.av;
import java.io.IOException;
-import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -46,7 +45,8 @@ import javax.media.opengl.GLProfile;
import jogamp.opengl.Debug;
-import com.jogamp.common.net.URIQueryProps;
+import com.jogamp.common.net.UriQueryProps;
+import com.jogamp.common.net.Uri;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.LFRingbuffer;
import com.jogamp.common.util.Ringbuffer;
@@ -92,15 +92,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
private final int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE };
/** User requested URI stream location. */
- private URI streamLoc = null;
+ private Uri streamLoc = null;
/**
* In case {@link #streamLoc} is a {@link GLMediaPlayer#CameraInputScheme},
* {@link #cameraPath} holds the URI's path portion
- * as parsed in {@link #initStream(URI, int, int, int)}.
+ * as parsed in {@link #initStream(Uri, int, int, int)}.
* @see #cameraProps
*/
- protected String cameraPath = null;
+ protected Uri.Encoded cameraPath = null;
/** Optional camera properties, see {@link #cameraPath}. */
protected Map<String, String> cameraProps = null;
@@ -530,7 +530,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
@Override
- public final void initStream(final URI streamLoc, final int vid, final int aid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException {
+ public final void initStream(final Uri streamLoc, final int vid, final int aid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException {
synchronized( stateLock ) {
if(State.Uninitialized != state) {
throw new IllegalStateException("Instance not in state unintialized: "+this);
@@ -556,13 +556,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
// Pre-parse for camera-input scheme
cameraPath = null;
cameraProps = null;
- final String streamLocScheme = streamLoc.getScheme();
+ final Uri.Encoded streamLocScheme = streamLoc.scheme;
if( null != streamLocScheme && streamLocScheme.equals(CameraInputScheme) ) {
- final String rawPath = streamLoc.getRawPath();
+ final Uri.Encoded rawPath = streamLoc.path;
if( null != rawPath && rawPath.length() > 0 ) {
// cut-off root fwd-slash
cameraPath = rawPath.substring(1);
- final URIQueryProps props = URIQueryProps.create(streamLoc, ';');
+ final UriQueryProps props = UriQueryProps.create(streamLoc, ';');
cameraProps = props.getProperties();
} else {
throw new IllegalArgumentException("Camera path is empty: "+streamLoc.toString());
@@ -1472,7 +1472,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
@Override
- public final URI getURI() { return streamLoc; }
+ public final Uri getUri() { return streamLoc; }
@Override
public final int getVID() { return vid; }
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index 8ac1232b5..4601df67d 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -37,7 +37,6 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLException;
-import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.ProcAddressTable;
@@ -292,7 +291,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
System.err.println("initStream: p1 "+this);
}
- final String streamLocS = IOUtil.decodeURIIfFilePath(getURI());
+ final String streamLocS = IOUtil.getUriFilePathOrASCII(getUri());
destroyAudioSink();
if( GLMediaPlayer.STREAM_ID_NONE == aid ) {
audioSink = AudioSinkFactory.createNull();
@@ -317,10 +316,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
case HPUX:
case LINUX:
case SUNOS:
- resStreamLocS = dev_video_linux + cameraPath;
+ resStreamLocS = dev_video_linux + cameraPath.decode();
break;
case WINDOWS:
- resStreamLocS = cameraPath;
+ resStreamLocS = cameraPath.decode();
break;
case MACOS:
case OPENKODE:
@@ -345,7 +344,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
// setStream(..) issues updateAttributes*(..), and defines avChosenAudioFormat, vid, aid, .. etc
if(DEBUG) {
System.err.println("initStream: p3 cameraPath "+cameraPath+", isCameraInput "+isCameraInput);
- System.err.println("initStream: p3 stream "+getURI()+" -> "+streamLocS+" -> "+resStreamLocS);
+ System.err.println("initStream: p3 stream "+getUri()+" -> "+streamLocS+" -> "+resStreamLocS);
System.err.println("initStream: p3 vid "+vid+", sizes "+sizes+", reqVideo "+rw+"x"+rh+"@"+rr+", aid "+aid+", aMaxChannelCount "+aMaxChannelCount+", aPrefSampleRate "+aPrefSampleRate);
}
natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, sizes, rw, rh, rr, aid, aMaxChannelCount, aPrefSampleRate);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
index 0eeb54bf6..5baf9e543 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
@@ -100,10 +100,10 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}
- if(!getURI().getScheme().equals("file")) {
- throw new IOException("Only file schemes are allowed: "+getURI());
+ if( !getUri().isFileScheme() ) {
+ throw new IOException("Only file schemes are allowed: "+getUri());
}
- final String path=getURI().getPath();
+ final String path=getUri().path.decode();
if(DEBUG) {
System.out.println("initGLStream: clean path "+path);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
index a9848f899..2dde27b1d 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
@@ -36,6 +36,7 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLArrayData;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
import javax.media.opengl.fixedfunc.GLLightingFunc;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.fixedfunc.GLPointerFunc;
@@ -50,6 +51,7 @@ import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFunc {
public static final int MAX_TEXTURE_UNITS = 8;
+ protected final GLProfile gl2es1GLProfile;
protected FixedFuncPipeline fixedFunction;
protected PMVMatrix pmvMatrix;
protected boolean ownsPMVMatrix;
@@ -61,6 +63,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
* @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline}
*/
public FixedFuncHook (final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix) {
+ this.gl2es1GLProfile = GLProfile.createCustomGLProfile(GLProfile.GL2ES1, gl.getGLProfile().getImpl());
this.gl = gl;
if(null != pmvMatrix) {
this.ownsPMVMatrix = false;
@@ -81,6 +84,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
final Class<?> shaderRootClass, final String shaderSrcRoot, final String shaderBinRoot,
final String vertexColorFile, final String vertexColorLightFile,
final String fragmentColorFile, final String fragmentColorTextureFile) {
+ this.gl2es1GLProfile = GLProfile.createCustomGLProfile(GLProfile.GL2ES1, gl.getGLProfile().getImpl());
this.gl = gl;
if(null != pmvMatrix) {
this.ownsPMVMatrix = false;
@@ -110,6 +114,24 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
//
// FixedFuncHookIf - hooks
//
+ public final boolean isGL4core() {
+ return false;
+ }
+ public final boolean isGL3core() {
+ return false;
+ }
+ public final boolean isGLcore() {
+ return false;
+ }
+ public final boolean isGLES2Compatible() {
+ return false;
+ }
+ public final boolean isGLES3Compatible() {
+ return false;
+ }
+ public final GLProfile getGLProfile() {
+ return gl2es1GLProfile;
+ }
public void glDrawArrays(final int mode, final int first, final int count) {
fixedFunction.glDrawArrays(gl, mode, first, count);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java
index 30559924d..36e8bc5a5 100644
--- a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java
@@ -41,6 +41,7 @@ import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.FovHVHalves;
import com.jogamp.opengl.util.stereo.EyeParameter;
import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
import com.jogamp.opengl.util.stereo.StereoUtil;
@@ -207,16 +208,20 @@ public class GenericStereoDevice implements StereoDevice {
final float[] DEFAULT_EYE_POSITION_OFFSET_STEREO = { 0.0f, 0.3f, 3.0f }; // 0.3 up, 3 back
final float[] DEFAULT_EYE_POSITION_OFFSET_MONO = { 0.0f, 0.0f, 3.0f }; // 3 back
+ final DimensionImmutable surfaceSizeInPixel = new Dimension(1280, 800);
+ final float[] screenSizeInMeters = new float[] { 0.1498f, 0.0936f };
+ final float interpupillaryDistanceInMeters = 0.0635f;
+ final float pupilCenterFromScreenTopInMeters = screenSizeInMeters[1] / 2f;
final float d2r = FloatUtil.PI / 180.0f;
{
config01Mono01 = new Config(
"Def01Mono01",
ShutterType.RollingTopToBottom,
- new Dimension(1280, 800), // resolution
- new float[] { 0.1498f, 0.0936f }, // screenSize [m]
- new Dimension(1280, 800), // eye textureSize
- 0.0936f/2f, // pupilCenterFromScreenTop [m]
- 0.0635f, // IPD [m]
+ surfaceSizeInPixel, // resolution
+ screenSizeInMeters, // screenSize [m]
+ surfaceSizeInPixel, // eye textureSize
+ pupilCenterFromScreenTopInMeters, // pupilCenterFromScreenTop [m]
+ interpupillaryDistanceInMeters, // IPD [m]
new int[] { 0 }, // eye order
new EyeParameter[] {
new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_MONO,
@@ -231,11 +236,7 @@ public class GenericStereoDevice implements StereoDevice {
}
{
- final DimensionImmutable surfaceSizeInPixel = new Dimension(1280, 800);
- final float[] screenSizeInMeters = new float[] { 0.1498f, 0.0936f };
final DimensionImmutable eyeTextureSize = new Dimension(surfaceSizeInPixel.getWidth()/2, surfaceSizeInPixel.getHeight());
- final float interpupillaryDistanceInMeters = 0.0635f;
- final float pupilCenterFromScreenTopInMeters = screenSizeInMeters[1] / 2f;
final float[] horizPupilCenterFromLeft = Config.getHorizPupilCenterFromLeft(screenSizeInMeters[0], interpupillaryDistanceInMeters);
final float vertPupilCenterFromTop = Config.getVertPupilCenterFromTop(screenSizeInMeters[1], pupilCenterFromScreenTopInMeters);
final float fovy = 45f;
@@ -249,7 +250,7 @@ public class GenericStereoDevice implements StereoDevice {
surfaceSizeInPixel, // resolution
screenSizeInMeters, // screenSize [m]
eyeTextureSize, // eye textureSize
- 0.0936f/2f, // pupilCenterFromScreenTop [m]
+ pupilCenterFromScreenTopInMeters, // pupilCenterFromScreenTop [m]
interpupillaryDistanceInMeters, // IPD [m]
new int[] { 0, 1 }, // eye order
new EyeParameter[] {
@@ -274,11 +275,7 @@ public class GenericStereoDevice implements StereoDevice {
if(StereoDevice.DEBUG) { System.err.println("Caught: "+t.getMessage()); t.printStackTrace(); }
}
- final DimensionImmutable surfaceSizeInPixel = new Dimension(1280, 800);
- final float[] screenSizeInMeters = new float[] { 0.1498f, 0.0936f };
final DimensionImmutable eyeTextureSize = new Dimension(1122, 1553);
- final float interpupillaryDistanceInMeters = 0.0635f;
- final float pupilCenterFromScreenTopInMeters = screenSizeInMeters[1] / 2f;
final float[] horizPupilCenterFromLeft = Config.getHorizPupilCenterFromLeft(screenSizeInMeters[0], interpupillaryDistanceInMeters);
final float vertPupilCenterFromTop = Config.getVertPupilCenterFromTop(screenSizeInMeters[1], pupilCenterFromScreenTopInMeters);
final float fovy = 129f;
@@ -313,6 +310,7 @@ public class GenericStereoDevice implements StereoDevice {
configs = new Config[] { config01Mono01, config02StereoSBS01, config03StereoSBSLense01 };
}
+ private final StereoDeviceFactory factory;
public final int deviceIndex;
public final Config config;
@@ -321,7 +319,8 @@ public class GenericStereoDevice implements StereoDevice {
private boolean sensorsStarted = false;
- public GenericStereoDevice(final int deviceIndex, final StereoDevice.Config customConfig) {
+ public GenericStereoDevice(final StereoDeviceFactory factory, final int deviceIndex, final StereoDevice.Config customConfig) {
+ this.factory = factory;
this.deviceIndex = deviceIndex;
if( customConfig instanceof GenericStereoDevice.Config) {
@@ -341,6 +340,9 @@ public class GenericStereoDevice implements StereoDevice {
}
@Override
+ public final StereoDeviceFactory getFactory() { return factory; }
+
+ @Override
public String toString() {
return "GenericStereoDevice["+config+", surfacePos "+surfacePos+"]";
}
@@ -431,26 +433,34 @@ public class GenericStereoDevice implements StereoDevice {
defaultEyeParam.distNoseToPupilX, defaultEyeParam.distMiddleToPupilY, defaultEyeParam.eyeReliefZ);
}
+ final boolean usePP = null != config.distortionMeshProducer && 0 != distortionBits; // use post-processing
+
final RectangleImmutable[] eyeViewports = new RectangleImmutable[eyeParam.length];
final DimensionImmutable eyeTextureSize = config.eyeTextureSize;
final DimensionImmutable totalTextureSize;
if( 1 < eyeParam.length ) {
// Stereo SBS
totalTextureSize = new Dimension(eyeTextureSize.getWidth()*2, eyeTextureSize.getHeight());
+
if( 1 == textureCount ) { // validated in ctor below!
eyeViewports[0] = new Rectangle(0, 0,
- totalTextureSize.getWidth() / 2, totalTextureSize.getHeight());
+ eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
- eyeViewports[1] = new Rectangle((totalTextureSize.getWidth() + 1) / 2, 0,
- totalTextureSize.getWidth() / 2, totalTextureSize.getHeight());
+ eyeViewports[1] = new Rectangle(eyeTextureSize.getWidth(), 0,
+ eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
} else {
eyeViewports[0] = new Rectangle(0, 0, eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
- eyeViewports[1] = eyeViewports[0];
+ if( usePP ) {
+ eyeViewports[1] = eyeViewports[0];
+ } else {
+ eyeViewports[1] = new Rectangle(eyeTextureSize.getWidth(), 0,
+ eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
+ }
}
} else {
// Mono
totalTextureSize = eyeTextureSize;
- eyeViewports[0] = new Rectangle(0, 0, totalTextureSize.getWidth(), totalTextureSize.getHeight());
+ eyeViewports[0] = new Rectangle(0, 0, eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
}
return new GenericStereoDeviceRenderer(this, distortionBits, textureCount, eyePositionOffset, eyeParam, pixelsPerDisplayPixel, textureUnit,
eyeTextureSize, totalTextureSize, eyeViewports);
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java
index a59e8d833..f2fa74743 100644
--- a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java
@@ -38,6 +38,6 @@ public class GenericStereoDeviceFactory extends StereoDeviceFactory {
@Override
public final StereoDevice createDevice(final int deviceIndex, final StereoDevice.Config config, final boolean verbose) {
- return new GenericStereoDevice(deviceIndex, config);
+ return new GenericStereoDevice(this, deviceIndex, config);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 9c5a5b272..33980d663 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -51,6 +51,7 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.runtime.ProcAddressTable;
@@ -330,7 +331,7 @@ public class WindowsWGLContext extends GLContextImpl {
isProcCreateContextAttribsARBAvailable = false;
isExtARBCreateContextAvailable = false;
}
- if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) {
+ if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable && !GLProfile.disableOpenGLARBContext ) {
// initial ARB context creation
contextHandle = createContextARB(shareWithHandle, true);
createContextARBTried=true;
@@ -343,7 +344,9 @@ public class WindowsWGLContext extends GLContextImpl {
}
} else if (DEBUG) {
System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+
- ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
+ ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+
+ ", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable+
+ ", disableOpenGLARBContext "+GLProfile.disableOpenGLARBContext);
}
}
} else {
@@ -360,16 +363,18 @@ public class WindowsWGLContext extends GLContextImpl {
}
}
} else {
- if( glCaps.getGLProfile().isGL3() ) {
- WGL.wglMakeCurrent(0, 0);
- WGL.wglDeleteContext(temp_ctx);
- throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glCaps.getGLProfile()+", current: "+getGLVersion());
+ if( glCaps.getGLProfile().isGL3() && createContextARBTried ) {
+ // We shall not allow context creation >= GL3 w/ non ARB methods if ARB is used,
+ // otherwise context of similar profile but different creation method may not be share-able.
+ WGL.wglMakeCurrent(0, 0);
+ WGL.wglDeleteContext(temp_ctx);
+ throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glCaps.getGLProfile()+", current: "+getGLVersion());
}
if(DEBUG) {
- System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion());
+ System.err.println("WindowsWGLContext.createContext ARB not used, fall back to !ARB context "+getGLVersion());
}
- // continue with temp context for GL < 3.0
+ // continue with temp context
contextHandle = temp_ctx;
if ( !wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
WGL.wglMakeCurrent(0, 0);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 4d8c85137..fa052d784 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -68,6 +68,7 @@ import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIDummyUpstreamSurfaceHook;
import jogamp.nativewindow.windows.GDISurface;
import jogamp.nativewindow.windows.RegisteredClassFactory;
+import jogamp.opengl.Debug;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
@@ -77,17 +78,80 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.nio.PointerBuffer;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.GLRendererQuirks;
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
+ /**
+ * Bug 1036: NVidia Windows Driver 'Threaded optimization' workaround.
+ * <p>
+ * https://jogamp.org/bugzilla/show_bug.cgi?id=1036
+ * </p>
+ * <p>
+ * Since NV driver 260.99 from 2010-12-11 a 'Threaded optimization' feature has been introduced.
+ * The driver spawns off a dedicated thread to off-load certain OpenGL tasks from the calling thread
+ * to perform them async and off-thread.
+ * </p>
+ * <p>
+ * If 'Threaded optimization' is manually enabled 'on', the driver may crash with JOGL's consistent
+ * multi-threaded usage - this is a driver bug.
+ * </p>
+ * <p>
+ * If 'Threaded optimization' is manually disabled 'off', the driver always works correctly.
+ * </p>
+ * <p>
+ * 'Threaded optimization' default setting is 'auto' and the driver may crash without this workaround.
+ * </p>
+ * <p>
+ * If setting the process affinity to '1' (1st CPU) while initialization and launching
+ * the {@link SharedResourceRunner}, the driver does not crash anymore in 'auto' mode.
+ * This might be either because the driver does not enable 'Threaded optimization'
+ * or because the driver's worker thread is bound to the same CPU.
+ * </p>
+ * <p>
+ * Property integer value <code>jogl.windows.cpu_affinity_mode</code>:
+ * <ul>
+ * <li>0 - none (no affinity, may cause driver crash with 'Threaded optimization' = ['auto', 'on'])</li>
+ * <li>1 - process affinity (default, workaround for driver crash for 'Threaded optimization' = 'auto', still crashes if set to 'on')</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Test case reproducing the crash reliable is: com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT<br>
+ * (don't ask why ..)
+ * </p>
+ */
+ private static final int CPU_AFFINITY_MODE;
+
+ static {
+ Debug.initSingleton();
+ CPU_AFFINITY_MODE = PropertyAccess.getIntProperty("jogl.windows.cpu_affinity_mode", true, 1);
+ }
+
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
+ private final CPUAffinity cpuAffinity;
+
public WindowsWGLDrawableFactory() {
super();
+ switch( CPU_AFFINITY_MODE ) {
+ case 0:
+ cpuAffinity = new NopCPUAffinity();
+ break;
+ /**
+ * Doesn't work !
+ case 2:
+ cpuAffinity = new WindowsThreadAffinity();
+ break;
+ */
+ default:
+ cpuAffinity = new WindowsProcessAffinity();
+ break;
+ }
+
synchronized(WindowsWGLDrawableFactory.class) {
if( null == windowsWGLDynamicLookupHelper ) {
windowsWGLDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
@@ -168,45 +232,23 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return windowsWGLDynamicLookupHelper;
}
+ /* pp */ static String toHexString(final long l) { return "0x"+Long.toHexString(l); }
+
private WindowsGraphicsDevice defaultDevice;
private SharedResourceRunner sharedResourceRunner;
private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap;
- private long processAffinityChanges = 0;
- private final PointerBuffer procMask = PointerBuffer.allocateDirect(1);
- private final PointerBuffer sysMask = PointerBuffer.allocateDirect(1);
-
@Override
protected void enterThreadCriticalZone() {
- synchronized (sysMask) {
- if( 0 == processAffinityChanges) {
- final long pid = GDI.GetCurrentProcess();
- if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
- if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
- // Thread.dumpStack();
- }
- processAffinityChanges = pid;
- GDI.SetProcessAffinityMask(pid, 1);
- }
- }
+ synchronized (cpuAffinity) {
+ cpuAffinity.set(1);
}
}
@Override
protected void leaveThreadCriticalZone() {
- synchronized (sysMask) {
- if( 0 != processAffinityChanges) {
- final long pid = GDI.GetCurrentProcess();
- if( pid != processAffinityChanges) {
- throw new GLException("PID doesn't match: set PID 0x" + Long.toHexString(processAffinityChanges) +
- " this PID 0x" + Long.toHexString(pid) );
- }
- if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
- }
- GDI.SetProcessAffinityMask(pid, sysMask.get(0));
- }
+ synchronized (cpuAffinity) {
+ cpuAffinity.reset();
}
}
@@ -344,6 +386,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
if (null != sr.context) {
// may cause JVM SIGSEGV: sharedContext.destroy();
+ sr.context.destroy(); // will also pull the dummy MutableSurface
sr.context = null;
}
@@ -556,12 +599,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private static final int GAMMA_RAMP_LENGTH = 256;
@Override
- protected final int getGammaRampLength() {
+ protected final int getGammaRampLength(final NativeSurface surface) {
return GAMMA_RAMP_LENGTH;
}
@Override
- protected final boolean setGammaRamp(final float[] ramp) {
+ protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
final short[] rampData = new short[3 * GAMMA_RAMP_LENGTH];
for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) {
final short scaledValue = (short) (ramp[i] * 65535);
@@ -570,18 +613,26 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue;
}
- final long screenDC = GDI.GetDC(0);
- final boolean res = GDI.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData));
- GDI.ReleaseDC(0, screenDC);
+ final long hDC = surface.getSurfaceHandle();
+ if( 0 == hDC ) {
+ return false;
+ }
+ // final long screenDC = GDI.GetDC(0);
+ final boolean res = GDI.SetDeviceGammaRamp(hDC, ShortBuffer.wrap(rampData));
+ // GDI.ReleaseDC(0, screenDC);
return res;
}
@Override
- protected final Buffer getGammaRamp() {
+ protected final Buffer getGammaRamp(final NativeSurface surface) {
final ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]);
- final long screenDC = GDI.GetDC(0);
- final boolean res = GDI.GetDeviceGammaRamp(screenDC, rampData);
- GDI.ReleaseDC(0, screenDC);
+ final long hDC = surface.getSurfaceHandle();
+ if( 0 == hDC ) {
+ return null;
+ }
+ // final long screenDC = GDI.GetDC(0);
+ final boolean res = GDI.GetDeviceGammaRamp(hDC, rampData);
+ // GDI.ReleaseDC(0, screenDC);
if (!res) {
return null;
}
@@ -589,7 +640,22 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final void resetGammaRamp(final Buffer originalGammaRamp) {
+ protected final void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
+ if (originalGammaRamp == null) {
+ // getGammaRamp failed earlier
+ return;
+ }
+ final long hDC = surface.getSurfaceHandle();
+ if( 0 == hDC ) {
+ return;
+ }
+ // final long screenDC = GDI.GetDC(0);
+ GDI.SetDeviceGammaRamp(hDC, originalGammaRamp);
+ // GDI.ReleaseDC(0, hDC);
+ }
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
if (originalGammaRamp == null) {
// getGammaRamp failed earlier
return;
@@ -598,4 +664,143 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
GDI.SetDeviceGammaRamp(screenDC, originalGammaRamp);
GDI.ReleaseDC(0, screenDC);
}
+
+
+ static interface CPUAffinity {
+ boolean set(final int newAffinity);
+ boolean reset();
+ }
+ static final class WindowsThreadAffinity implements CPUAffinity {
+ private long threadHandle;
+ private long threadOrigAffinity;
+ private long threadNewAffinity;
+ public WindowsThreadAffinity() {
+ threadHandle = 0;
+ threadOrigAffinity = 0;
+ threadNewAffinity = 0;
+ }
+ @Override
+ public boolean set(final int newAffinity) {
+ final long tid = GDI.GetCurrentThread();
+ if( 0 != threadHandle ) {
+ throw new IllegalStateException("Affinity already set");
+ }
+ final long threadLastAffinity = GDI.SetThreadAffinityMask(tid, newAffinity);
+ final int werr = GDI.GetLastError();
+ final boolean res;
+ if( 0 != threadLastAffinity ) {
+ res = true;
+ this.threadHandle = tid;
+ this.threadNewAffinity = newAffinity;
+ this.threadOrigAffinity = threadLastAffinity;
+ } else {
+ res = false;
+ }
+ if(DEBUG) {
+ System.err.println("WindowsThreadAffinity.set() - tid " + toHexString(tid) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+werr+"), Affinity: "+toHexString(threadOrigAffinity) + " -> " + toHexString(newAffinity));
+ }
+ return res;
+ }
+ @Override
+ public boolean reset() {
+ if( 0 == threadHandle ) {
+ return true;
+ }
+ final long tid = GDI.GetCurrentThread();
+ if( tid != threadHandle) {
+ throw new IllegalStateException("TID doesn't match: set TID " + toHexString(threadHandle) +
+ " this TID " + toHexString(tid) );
+ }
+ final long preThreadAffinity = GDI.SetThreadAffinityMask(threadHandle, threadOrigAffinity);
+ final boolean res = 0 != preThreadAffinity;
+ if(DEBUG) {
+ System.err.println("WindowsThreadAffinity.reset() - tid " + toHexString(threadHandle) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+GDI.GetLastError()+"), Affinity: "+toHexString(threadNewAffinity)+" -> orig "+ toHexString(threadOrigAffinity));
+ }
+ this.threadHandle = 0;
+ this.threadNewAffinity = this.threadOrigAffinity;
+ return res;
+ }
+ }
+ static final class WindowsProcessAffinity implements CPUAffinity {
+ private long processHandle;
+ private long newAffinity;
+ private final PointerBuffer procMask;
+ private final PointerBuffer sysMask;
+
+ public WindowsProcessAffinity() {
+ processHandle = 0;
+ newAffinity = 0;
+ procMask = PointerBuffer.allocateDirect(1);
+ sysMask = PointerBuffer.allocateDirect(1);
+ }
+ @Override
+ public boolean set(final int newAffinity) {
+ if( 0 != processHandle ) {
+ throw new IllegalStateException("Affinity already set");
+ }
+ final long pid = GDI.GetCurrentProcess();
+ final boolean res;
+ if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
+ if( GDI.SetProcessAffinityMask(pid, newAffinity) ) {
+ this.processHandle = pid;
+ this.newAffinity = newAffinity;
+ res = true;
+ } else {
+ res = false;
+ }
+ if(DEBUG) {
+ System.err.println("WindowsProcessAffinity.set() - pid " + toHexString(pid) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+GDI.GetLastError()+"), Affinity: procMask "+ toHexString(procMask.get(0)) + ", sysMask "+ toHexString(sysMask.get(0)) +
+ " -> "+toHexString(newAffinity));
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println("WindowsProcessAffinity.set() - pid " + toHexString(pid) + " - " + getThreadName() +
+ ": Error, could not GetProcessAffinityMask, werr "+GDI.GetLastError());
+ }
+ res = false;
+ }
+ return res;
+ }
+ @Override
+ public boolean reset() {
+ if( 0 == processHandle ) {
+ return true;
+ }
+ final long pid = GDI.GetCurrentProcess();
+ if( pid != processHandle) {
+ throw new IllegalStateException("PID doesn't match: set PID " + toHexString(processHandle) +
+ " this PID " + toHexString(pid) );
+ }
+ final long origProcAffinity = procMask.get(0);
+ final boolean res = GDI.SetProcessAffinityMask(processHandle, origProcAffinity);
+ if(DEBUG) {
+ final int werr = GDI.GetLastError();
+ System.err.println("WindowsProcessAffinity.reset() - pid " + toHexString(processHandle) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+werr+"), Affinity: "+toHexString(newAffinity)+" -> procMask "+ toHexString(origProcAffinity));
+ }
+ this.processHandle = 0;
+ this.newAffinity = origProcAffinity;
+ return res;
+ }
+ }
+ static final class NopCPUAffinity implements CPUAffinity {
+ public NopCPUAffinity() { }
+ @Override
+ public boolean set(final int newAffinity) {
+ if(DEBUG) {
+ System.err.println("NopCPUAffinity.set() - " + getThreadName());
+ }
+ return false;
+ }
+ @Override
+ public boolean reset() {
+ if(DEBUG) {
+ System.err.println("NopCPUAffinity.reset() - " + getThreadName());
+ }
+ return false;
+ }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index d4c3abc49..9631dbb5b 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -303,8 +303,8 @@ public class X11GLXContext extends GLContextImpl {
if( !config.hasFBConfig() ) {
// not able to use FBConfig -> GLX 1.1
forceGLXVersionOneOne();
- if(glp.isGL3()) {
- throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context");
+ if( glp.isGL3() ) {
+ throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context w/o FBConfig");
}
contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), shareWithHandle, direct);
if ( 0 == contextHandle ) {
@@ -343,7 +343,7 @@ public class X11GLXContext extends GLContextImpl {
throw new GLException(getThreadName()+": Unable to create temp OpenGL context(1)");
}
if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx) ) {
- throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
+ throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
}
setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */); // use GL_VERSION
glXMakeContextCurrent(display, 0, 0, 0); // release temp context
@@ -351,7 +351,7 @@ public class X11GLXContext extends GLContextImpl {
// is*Available calls are valid since setGLFunctionAvailability(..) was called
final boolean isProcCreateContextAttribsARBAvailable = isFunctionAvailable("glXCreateContextAttribsARB");
final boolean isExtARBCreateContextAvailable = isExtensionAvailable("GLX_ARB_create_context");
- if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) {
+ if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable && !GLProfile.disableOpenGLARBContext ) {
// initial ARB context creation
contextHandle = createContextARB(shareWithHandle, direct);
createContextARBTried=true;
@@ -362,9 +362,11 @@ public class X11GLXContext extends GLContextImpl {
System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+toHexString(shareWithHandle));
}
}
- } else if (DEBUG) {
+ } else if( DEBUG ) {
System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+
- ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
+ ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+
+ ", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable+
+ ", disableOpenGLARBContext "+GLProfile.disableOpenGLARBContext);
}
}
} else {
@@ -380,21 +382,24 @@ public class X11GLXContext extends GLContextImpl {
}
}
} else {
- if( glp.isGL3() ) {
- glXMakeContextCurrent(display, 0, 0, 0);
- GLX.glXDestroyContext(display, temp_ctx);
- throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glp+", current: "+getGLVersion());
+ if( glp.isGL3() && createContextARBTried ) {
+ // We shall not allow context creation >= GL3 w/ non ARB methods if ARB is used,
+ // otherwise context of similar profile but different creation method may not be share-able.
+ glXMakeContextCurrent(display, 0, 0, 0);
+ GLX.glXDestroyContext(display, temp_ctx);
+ throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glp+", current: "+getGLVersion());
}
+
if(DEBUG) {
- System.err.println(getThreadName()+": X11GLXContext.createContextImpl failed, fall back to !ARB context "+getGLVersion());
+ System.err.println(getThreadName()+": X11GLXContext.createContextImpl ARB not used, fall back to !ARB context "+getGLVersion());
}
- // continue with temp context for GL <= 3.0
+ // continue with temp context
contextHandle = temp_ctx;
if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
- glXMakeContextCurrent(display, 0, 0, 0);
- GLX.glXDestroyContext(display, temp_ctx);
- throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
+ glXMakeContextCurrent(display, 0, 0, 0);
+ GLX.glXDestroyContext(display, temp_ctx);
+ throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
}
if (DEBUG) {
System.err.println(getThreadName() + ": createContextImpl: OK (old-2) share "+toHexString(shareWithHandle));
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index fbab32963..60e4438d0 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -72,6 +72,7 @@ import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
@@ -562,34 +563,34 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
private boolean gotGammaRampLength;
private int gammaRampLength;
@Override
- protected final synchronized int getGammaRampLength() {
+ protected final synchronized int getGammaRampLength(final NativeSurface surface) {
if (gotGammaRampLength) {
return gammaRampLength;
}
-
- final long display = getOrCreateSharedDpy(defaultDevice);
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return 0;
}
+ final int screenIdx = surface.getScreenIndex();
final int[] size = new int[1];
- final boolean res = X11Lib.XF86VidModeGetGammaRampSize(display,
- X11Lib.DefaultScreen(display),
- size, 0);
+ final boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, screenIdx, size, 0);
if (!res) {
return 0;
}
gotGammaRampLength = true;
gammaRampLength = size[0];
+ System.err.println("XXX: Gamma ramp size: "+gammaRampLength);
return gammaRampLength;
}
@Override
- protected final boolean setGammaRamp(final float[] ramp) {
- final long display = getOrCreateSharedDpy(defaultDevice);
+ protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return false;
}
+ final int screenIdx = surface.getScreenIndex();
final int len = ramp.length;
final short[] rampData = new short[len];
@@ -597,36 +598,52 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
rampData[i] = (short) (ramp[i] * 65535);
}
- final boolean res = X11Lib.XF86VidModeSetGammaRamp(display,
- X11Lib.DefaultScreen(display),
+ final boolean res = X11Lib.XF86VidModeSetGammaRamp(display, screenIdx,
rampData.length,
rampData, 0,
rampData, 0,
rampData, 0);
+ if( DEBUG ) {
+ dumpRamp("SET__", rampData.length, rampData, rampData, rampData);
+ }
return res;
}
+ private static void dumpRamp(final String prefix, final int size, final ShortBuffer r, final ShortBuffer g, final ShortBuffer b) {
+ for(int i=0; i<size; i++) {
+ if( 0 == i % 4 ) {
+ System.err.printf("%n%4d/%4d %s: ", i, size, prefix);
+ }
+ System.err.printf(" [%04X %04X %04X], ", r.get(i), g.get(i), b.get(i));
+ }
+ System.err.println();
+ }
+ private static void dumpRamp(final String prefix, final int size, final short[] r, final short[] g, final short[] b) {
+ for(int i=0; i<size; i++) {
+ if( 0 == i % 4 ) {
+ System.err.printf("%n%4d/%4d %s: ", i, size, prefix);
+ }
+ System.err.printf(" [%04X %04X %04X], ", r[i], g[i], b[i]);
+ }
+ System.err.println();
+ }
+
@Override
- protected final Buffer getGammaRamp() {
- final long display = getOrCreateSharedDpy(defaultDevice);
+ protected final Buffer getGammaRamp(final NativeSurface surface) {
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return null;
}
+ final int screenIdx = surface.getScreenIndex();
+
+ final int size = getGammaRampLength(surface);
- final int size = getGammaRampLength();
- final ShortBuffer rampData = ShortBuffer.wrap(new short[3 * size]);
- rampData.position(0);
- rampData.limit(size);
- final ShortBuffer redRampData = rampData.slice();
- rampData.position(size);
- rampData.limit(2 * size);
- final ShortBuffer greenRampData = rampData.slice();
- rampData.position(2 * size);
- rampData.limit(3 * size);
- final ShortBuffer blueRampData = rampData.slice();
-
- final boolean res = X11Lib.XF86VidModeGetGammaRamp(display,
- X11Lib.DefaultScreen(display),
+ final ShortBuffer rampData = Buffers.newDirectShortBuffer(3 * size);
+ final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size);
+ final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size);
+ final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size);
+
+ final boolean res = X11Lib.XF86VidModeGetGammaRamp(display, screenIdx,
size,
redRampData,
greenRampData,
@@ -634,40 +651,62 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (!res) {
return null;
}
+ if( DEBUG ) {
+ dumpRamp("GET__", size, redRampData, greenRampData, blueRampData);
+ }
return rampData;
}
@Override
- protected final void resetGammaRamp(final Buffer originalGammaRamp) {
+ protected final void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
if (originalGammaRamp == null) {
return; // getGammaRamp failed originally
}
- final long display = getOrCreateSharedDpy(defaultDevice);
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return;
}
+ final int screenIdx = surface.getScreenIndex();
+
+ resetGammaRamp(display, screenIdx, originalGammaRamp);
+ }
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
+ if (originalGammaRamp == null) {
+ return; // getGammaRamp failed originally
+ }
+ final long display = X11Util.openDisplay(deviceScreenID.deviceConnection);
+ if( 0 == display ) {
+ return;
+ }
+ try {
+ resetGammaRamp(display, deviceScreenID.screenIdx, originalGammaRamp);
+ } finally {
+ X11Util.closeDisplay(display);
+ }
+ }
+ private static final void resetGammaRamp(final long display, final int screenIdx, final Buffer originalGammaRamp) {
final ShortBuffer rampData = (ShortBuffer) originalGammaRamp;
final int capacity = rampData.capacity();
if ((capacity % 3) != 0) {
throw new IllegalArgumentException("Must not be the original gamma ramp");
}
final int size = capacity / 3;
- rampData.position(0);
- rampData.limit(size);
- final ShortBuffer redRampData = rampData.slice();
- rampData.position(size);
- rampData.limit(2 * size);
- final ShortBuffer greenRampData = rampData.slice();
- rampData.position(2 * size);
- rampData.limit(3 * size);
- final ShortBuffer blueRampData = rampData.slice();
-
- X11Lib.XF86VidModeSetGammaRamp(display,
- X11Lib.DefaultScreen(display),
- size,
- redRampData,
- greenRampData,
- blueRampData);
+
+ final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size);
+ final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size);
+ final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size);
+ if( DEBUG ) {
+ dumpRamp("RESET", size, redRampData, greenRampData, blueRampData);
+ }
+
+ X11Lib.XF86VidModeSetGammaRamp(display, screenIdx,
+ size,
+ redRampData,
+ greenRampData,
+ blueRampData);
}
+
}