aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-09-20 02:51:44 +0200
committerSven Gothel <[email protected]>2014-09-20 02:51:44 +0200
commit711757aa4e087d97c3103489c47fbd7d76bcac3d (patch)
tree89c0b2b8cfc49aa1f3aef93ea23e0643d9c1808f /src
parenta7ff8b898780762b763c0b4544728067375955b6 (diff)
FBObject: Simplify API (init/reset); Only issue automatic resetSamplingSink(..) if required; Fix resetSamplingSink(..), isBound(), ..
- Simplify API (init/reset) - use new unique methods for init and reset: - void init(final GL gl, final int newWidth, final int newHeight, final int newSamples) - does not issue resetSamplingSink(..) - boolean reset(final GL gl, final int newWidth, final int newHeight, final int newSamples) - always issues resetSamplingSink(..) - deprecated dual-use (init/reset): - boolean reset(final GL gl, final int newWidth, final int newHeight) - boolean reset(final GL gl, int newWidth, int newHeight, int newSamples, final boolean resetSamplingSink) - reset(..) no more creates a dummy 'samplingSink' instance if sampling > 0, left up to resetSamplingSink(..) - Track 'modified' state of FBObject, if size, format or any attachment has been changed since last - use(..) - syncSamplingSink(..) - resetSamplingSink(..) - Only issue resetSamplingSink(..) from syncSamplingSink(..)/use(..) if 'modified == true' +++ - Fix setSamplingSink(..), i.e. samplingSink state handling: - Validated whether given samplingSink is initialized, throws Exception if not. - Fix resetSamplingSink(..) - resets the bound state, i.e. leaves it untouched - also unbinds the samplingSink - sampleSinkDepthStencilMismatch() also returns true if this.depth/stencil == null, but samplingSink is not. - Newly created colorbuffer/-texture matches exiting colorbuffer's internal-format, if exists. - Using simplified resetSizeImpl(..) for size mismatch - Simplified samplingColorSink init check - Fix isBound() was: 'bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)' fix: 'bound = bound && fbName == gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)' - Fix detachRenderbuffer(..) validates whether detachment was successful, similar to detachColorbuffer(..)
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FBObject.java533
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java6
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java4
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java4
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java45
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java4
10 files changed, 416 insertions, 206 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
index bcdb29e8c..c845b46ad 100644
--- a/src/jogl/classes/com/jogamp/opengl/FBObject.java
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -623,7 +623,7 @@ public class FBObject {
* <p>
* For GLES3, sampling-sink format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer},
* see details below. Implementation aligns w/ {@link #createColorAttachment(boolean)}
- * and is enforced via {@link #sampleSinkFormatMismatch(GL)}.
+ * and is enforced via {@link #sampleSinkExFormatMismatch(GL)}.
* </p>
* <p>
* ES3 BlitFramebuffer Requirements: OpenGL ES 3.0.2 p194: 4.3.2 Copying Pixels
@@ -664,23 +664,40 @@ public class FBObject {
*/
public static final TextureAttachment createColorTextureAttachment(final GL gl, final boolean alpha, final int width, final int height,
final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
- final int textureInternalFormat, textureDataFormat, textureDataType;
+ final int internalFormat, dataFormat, dataType;
if(gl.isGLES3()) {
- textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
- textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
- textureDataType = GL.GL_UNSIGNED_BYTE;
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
} else if(gl.isGLES()) {
- textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
- textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
- textureDataType = GL.GL_UNSIGNED_BYTE;
+ internalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
} else {
- textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
// textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
// textureInternalFormat = alpha ? 4 : 3;
- textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
- textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ dataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ dataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
}
- return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ return createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ public static final TextureAttachment createColorTextureAttachment(final GL gl, final int internalFormat, final int width, final int height,
+ final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
+ final int dataFormat, dataType;
+ final boolean alpha = hasAlpha(internalFormat);
+ if( gl.isGLES3() ) {
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
+ } else if( gl.isGLES() ) {
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ dataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ dataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT);
}
/**
@@ -738,6 +755,7 @@ public class FBObject {
private int textureAttachmentCount;
private Colorbuffer[] colorbufferAttachments; // colorbuffer attachment points
private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
+ private boolean modified; // size, sampleCount, or any attachment modified
private FBObject samplingSink; // MSAA sink
private Colorbuffer samplingColorSink;
@@ -752,44 +770,59 @@ public class FBObject {
throw new GLException("FBO not initialized");
}
if(maxColorAttachments != colorbufferAttachments.length) {
- throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.length "+colorbufferAttachments.length);
+ throw new InternalError(String.format("maxColorAttachments %d, array.length %d",
+ maxColorAttachments, colorbufferAttachments.length) );
}
if(0 > point || point >= maxColorAttachments) {
- throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"], "+this);
+ throw new IllegalArgumentException(String.format("attachment point out of range: %d, should be within [0..%d], %s",
+ point, maxColorAttachments-1, this.toString() ) );
}
}
private final void validateAddColorAttachment(final int point, final Colorbuffer ca) {
validateColorAttachmentPointRange(point);
if( null != colorbufferAttachments[point] ) {
- throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorbufferAttachments[point]+", "+this);
+ throw new IllegalStateException(String.format("Cannot attach %s at %d, attachment point already in use by %s, %s",
+ ca.toString(), point, colorbufferAttachments[point].toString(), this.toString() ) );
}
}
- private final void addColorAttachment(final int point, final Colorbuffer ca) {
- validateColorAttachmentPointRange(point);
+ private final void addColorAttachment(final int point, final Colorbuffer ca, final boolean validate) {
final Colorbuffer c = colorbufferAttachments[point];
- if( null != c && c != ca ) {
- throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ if( validate ) {
+ validateColorAttachmentPointRange(point);
+ if( null == ca ) {
+ throw new IllegalArgumentException("Colorbuffer is null");
+ }
+ if( null != c ) {
+ throw new IllegalStateException(String.format("Cannot attach %s at %d, attachment point already in use by %s, %s",
+ ca.toString(), point, c.toString(), this.toString() ) );
+ }
}
colorbufferAttachments[point] = ca;
colorbufferCount++;
if( ca.isTextureAttachment() ) {
textureAttachmentCount++;
}
+ modified = true;
}
private final void removeColorAttachment(final int point, final Colorbuffer ca) {
validateColorAttachmentPointRange(point);
+ if( null == ca ) {
+ throw new IllegalArgumentException("Colorbuffer is null");
+ }
final Colorbuffer c = colorbufferAttachments[point];
- if( null != c && c != ca ) {
- throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ if( c != ca ) {
+ throw new IllegalStateException(String.format("Cannot detach %s at %d, slot is holding other: %s, %s",
+ ca.toString(), point, c.toString(), this.toString() ) );
}
colorbufferAttachments[point] = null;
colorbufferCount--;
if( ca.isTextureAttachment() ) {
textureAttachmentCount--;
}
+ modified = true;
}
/**
@@ -899,15 +932,32 @@ public class FBObject {
this.textureAttachmentCount = 0;
this.depth = null;
this.stencil = null;
+ this.modified = true;
this.samplingSink = null;
this.samplingColorSink = null;
this.samplingSinkDirty = true;
}
- private void init(final GL gl, int width, int height, final int samples) throws GLException {
- if(initialized) {
- throw new GLException("FBO already initialized");
+ /**
+ * Initializes this FBO's instance.
+ * <p>
+ * The sampling sink is not initializes, allowing manual assignment via {@link #setSamplingSink(FBObject)}
+ * if {@code newSamples > 0}.
+ * </p>
+ *
+ * <p>Leaves the FBO bound</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth the initial width, it's minimum is capped to 1
+ * @param newHeight the initial height, it's minimum is capped to 1
+ * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}.
+ * @throws IllegalStateException if already initialized
+ * @throws GLException in case of an error, i.e. size too big, etc ..
+ */
+ public void init(final GL gl, final int newWidth, final int newHeight, final int newSamples) throws IllegalStateException, GLException {
+ if( initialized ) {
+ throw new IllegalStateException("FBO already initialized");
}
if( !gl.hasBasicFBOSupport() ) {
throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this);
@@ -960,14 +1010,12 @@ public class FBObject {
checkPreGLError(gl);
- if( 0 >= width ) { width = 1; }
- if( 0 >= height ) { height = 1; }
- this.width = width;
- this.height = height;
- this.samples = samples <= maxSamples ? samples : maxSamples;
+ this.width = 0 < newWidth ? newWidth : 1;
+ this.height = 0 < newHeight ? newHeight : 1;
+ this.samples = newSamples <= maxSamples ? newSamples : maxSamples;
if(DEBUG) {
- System.err.println("FBObject.init() START: "+width+"x"+height+", "+samples+" -> "+this.samples+" samples");
+ System.err.println("FBObject.init() START: "+width+"x"+height+", "+newSamples+" -> "+this.samples+" samples");
System.err.println("fullFBOSupport: "+fullFBOSupport);
System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]");
System.err.println("maxSamples: "+maxSamples);
@@ -988,14 +1036,12 @@ public class FBObject {
checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error
- if( textureAttachmentCount > 0 && ( width > 2 + maxTextureSize || height > 2 + maxTextureSize ) ) {
- throw new GLException("Size "+width+"x"+height+" exceeds on of the maximum texture size "+maxTextureSize+": \n\t"+this);
- }
if( width > maxRenderbufferSize || height > maxRenderbufferSize ) {
throw new GLException("Size "+width+"x"+height+" exceeds on of the maxima renderbuffer size "+maxRenderbufferSize+": \n\t"+this);
}
- resetSamplingSink(gl);
+ modified = true;
+ samplingSinkDirty = true;
// generate fbo ..
gl.glGenFramebuffers(1, val, 0);
@@ -1011,7 +1057,6 @@ public class FBObject {
checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
}
bound = true;
- samplingSinkDirty = true;
initialized = true;
vStatus = GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // always incomplete w/o attachments!
@@ -1022,15 +1067,41 @@ public class FBObject {
}
/**
- * Initializes or resets this FBO's instance.
+ * Resets this FBO's instance.
* <p>
* In case the new parameters are compatible with the current ones
- * no action will be performed. Otherwise all attachments will be recreated
+ * no action will be performed and method returns immediately.<br>
+ * Otherwise all attachments will be recreated
* to match the new given parameters.
* </p>
* <p>
- * Incompatibility and hence recreation is forced if
- * the size or sample count doesn't match for subsequent calls.
+ * {@link #resetSamplingSink(GL)} is being issued immediately
+ * to match the new configuration.
+ * </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth the new width, it's minimum is capped to 1
+ * @param newHeight the new height, it's minimum is capped to 1
+ * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}.
+ * @return {@code true} if this instance has been modified, otherwise {@code false}.
+ * @throws IllegalStateException if not initialized via {@link #init(GL, int, int, int)}.
+ * @throws GLException in case of an error, i.e. size too big, etc ..
+ */
+ public final boolean reset(final GL gl, final int newWidth, final int newHeight, final int newSamples) throws GLException, IllegalStateException {
+ if( !initialized ) {
+ throw new IllegalStateException("FBO not initialized");
+ }
+ return reset(gl, newWidth, newHeight, newSamples, true);
+ }
+
+ /**
+ * Initializes or resets this FBO's instance.
+ * <p>
+ * In case the new parameters are compatible with the current ones
+ * no action will be performed. Otherwise all attachments will be recreated
+ * to match the new given parameters.
* </p>
*
* <p>Leaves the FBO bound state untouched</p>
@@ -1040,6 +1111,7 @@ public class FBObject {
* @param newHeight
* @return {@code true} if this instance has been modified, otherwise {@code false}.
* @throws GLException in case of an error
+ * @deprecated Use {@link #init(GL, int, int, int)} or {@link #reset(GL, int, int, int)}
*/
public final boolean reset(final GL gl, final int newWidth, final int newHeight) {
return reset(gl, newWidth, newHeight, 0, false);
@@ -1052,10 +1124,6 @@ public class FBObject {
* no action will be performed. Otherwise all attachments will be recreated
* to match the new given parameters.
* </p>
- * <p>
- * Currently incompatibility and hence recreation of the attachments will be performed
- * if the size or sample count doesn't match for subsequent calls.
- * </p>
*
* <p>Leaves the FBO bound state untouched</p>
*
@@ -1069,6 +1137,7 @@ public class FBObject {
* from implicit double buffering while resetting the sink just before it's being used, eg. at swap-buffer.
* @return {@code true} if this instance has been modified, otherwise {@code false}.
* @throws GLException in case of an error, i.e. size too big, etc ..
+ * @deprecated Use {@link #init(GL, int, int, int)} or {@link #reset(GL, int, int, int)}
*/
public final boolean reset(final GL gl, int newWidth, int newHeight, int newSamples, final boolean resetSamplingSink) {
if( !initialized ) {
@@ -1108,24 +1177,20 @@ public class FBObject {
height = newHeight;
samples = newSamples;
- if(0 < samples && null == samplingSink ) {
- // needs valid samplingSink for detach*() -> bind()
- samplingSink = new FBObject();
- samplingSink.init(gl, width, height, 0);
- }
+ modified = true;
+ samplingSinkDirty = true;
+
detachAllImpl(gl, true, true, sampleCountChange);
- if(resetSamplingSink) {
+ if( resetSamplingSink ) {
resetSamplingSink(gl);
}
- samplingSinkDirty = true;
-
if(!wasBound) {
unbind(gl);
}
if(DEBUG) {
- System.err.println("FBObject.reset - END - "+this);
+ System.err.println("FBObject.reset - END - wasBound, "+wasBound+", "+this);
}
return true;
} else {
@@ -1133,6 +1198,34 @@ public class FBObject {
}
}
+ /**
+ * Simply resets this instance's size only, w/o validation.
+ *
+ * <p>Leaves the FBO bound</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth the new width, it's minimum is capped to 1
+ * @param newHeight the new height, it's minimum is capped to 1
+ */
+ private final void resetSizeImpl(final GL gl, final int newWidth, final int newHeight) {
+ if(DEBUG) {
+ System.err.println("FBObject.resetSize - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight);
+ }
+
+ final int sampleCountChange = 0; // keep MSAA settings
+ width = newWidth;
+ height = newHeight;
+
+ modified = true;
+ samplingSinkDirty = true;
+
+ detachAllImpl(gl, true, true, sampleCountChange);
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetSize - END - "+this);
+ }
+ }
+
private void validateAttachmentSize(final Attachment a) {
final int aWidth = a.getWidth();
final int aHeight = a.getHeight();
@@ -1353,7 +1446,7 @@ public class FBObject {
* <p>
* For GLES3, sampling-sink {@link Colorbuffer} format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
* Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)}
- * and is enforced via {@link #sampleSinkFormatMismatch(GL)}.
+ * and is enforced via {@link #sampleSinkExFormatMismatch(GL)}.
* </p>
*
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
@@ -1375,7 +1468,7 @@ public class FBObject {
* <p>
* For GLES3, sampling-sink {@link Colorbuffer} format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
* Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)}
- * and is enforced via {@link #sampleSinkFormatMismatch(GL)}.
+ * and is enforced via {@link #sampleSinkExFormatMismatch(GL)}.
* </p>
*
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
@@ -1390,8 +1483,11 @@ public class FBObject {
}
/**
- * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point,
- * selecting the format automatically.
+ * Attaches a newly created and {@link Colorbuffer#initialize(GL) initialized} {@link Colorbuffer}, i.e. a {@link ColorAttachment},
+ * at the given attachment point.
+ * <p>
+ * The {@link ColorAttachment} is created using {@code alpha} if {@code true} and current {@code sample count} and {@code size}.
+ * </p>
*
* <p>Leaves the FBO bound.</p>
*
@@ -1407,7 +1503,11 @@ public class FBObject {
}
/**
- * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point.
+ * Attaches a newly created and {@link Colorbuffer#initialize(GL) initialized} {@link Colorbuffer}, i.e. a {@link ColorAttachment},
+ * at the given attachment point.
+ * <p>
+ * The {@link ColorAttachment} is created using the given {@code internalFormat} and current {@code sample count} and {@code size}.
+ * </p>
*
* <p>Leaves the FBO bound.</p>
*
@@ -1428,9 +1528,11 @@ public class FBObject {
}
/**
- * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment},
- * to this FBO's instance at the given attachment point.
- *
+ * Attaches a {@link Colorbuffer} at the given attachment point
+ * and {@link Colorbuffer#initialize(GL) initializes} it, if not done yet.
+ * <p>
+ * {@link Colorbuffer} may be a {@link ColorAttachment} or {@link TextureAttachment}.
+ * </p>
* <p>
* If {@link Colorbuffer} is a {@link TextureAttachment} and is uninitialized, i.e. it's texture name is <code>zero</code>,
* a new texture name is generated and setup w/ the texture parameter.<br/>
@@ -1443,7 +1545,7 @@ public class FBObject {
* @param gl
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
* @param colbuf the to be attached {@link Colorbuffer}
- * @return newly attached {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown
+ * @return given {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment}
*/
public final Colorbuffer attachColorbuffer(final GL gl, final int attachmentPoint, final Colorbuffer colbuf) throws GLException {
@@ -1453,10 +1555,10 @@ public class FBObject {
private final Colorbuffer attachColorbufferImpl(final GL gl, final int attachmentPoint, final Colorbuffer colbuf) throws GLException {
validateAddColorAttachment(attachmentPoint, colbuf);
-
validateAttachmentSize((Attachment)colbuf);
+
final boolean initializedColorbuf = colbuf.initialize(gl);
- addColorAttachment(attachmentPoint, colbuf);
+ addColorAttachment(attachmentPoint, colbuf, false);
if( colbuf.isTextureAttachment() ) {
final TextureAttachment texA = colbuf.getTextureAttachment();
@@ -1634,6 +1736,7 @@ public class FBObject {
}
private final void attachRenderbufferImpl2(final GL gl, final Attachment.Type atype, final int internalFormat) throws GLException {
+ // atype and current depth and stencil instance are already validated in 'attachRenderbufferImpl(..)'
if( Attachment.Type.DEPTH == atype ) {
if(null == depth) {
depth = createRenderAttachment(Type.DEPTH, internalFormat, samples, width, height);
@@ -1678,6 +1781,8 @@ public class FBObject {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
}
+ modified = true;
+
if(!ignoreStatus) {
updateStatus(gl);
if( !isStatusValid() ) {
@@ -1715,16 +1820,16 @@ public class FBObject {
}
private final Colorbuffer detachColorbufferImpl(final GL gl, final int attachmentPoint, final DetachAction detachAction, final int sampleCountChange) {
- Colorbuffer colbuf = colorbufferAttachments[attachmentPoint]; // shortcut, don't validate here
+ final Colorbuffer colbufOld = colorbufferAttachments[attachmentPoint]; // shortcut, don't validate here
- if(null == colbuf) {
+ if(null == colbufOld) {
return null;
}
- removeColorAttachment(attachmentPoint, colbuf);
+ removeColorAttachment(attachmentPoint, colbufOld);
- if( colbuf.isTextureAttachment() ) {
- final TextureAttachment texA = colbuf.getTextureAttachment();
+ if( colbufOld.isTextureAttachment() ) {
+ final TextureAttachment texA = colbufOld.getTextureAttachment();
if( 0 != texA.getName() ) {
gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
@@ -1739,17 +1844,19 @@ public class FBObject {
}
}
if(DetachAction.RECREATE == detachAction) {
+ final Colorbuffer colbufNew;
if( 0 < sampleCountChange ) {
// switch to MSAA: TextureAttachment -> ColorAttachment
- colbuf = createColorAttachment(hasAlpha(texA.format));
+ colbufNew = createColorAttachment(hasAlpha(texA.format));
} else {
// keep MSAA settings
texA.setSize(width, height);
+ colbufNew = texA;
}
- attachColorbufferImpl(gl, attachmentPoint, colbuf);
+ attachColorbufferImpl(gl, attachmentPoint, colbufNew);
}
} else {
- final ColorAttachment colA = colbuf.getColorAttachment();
+ final ColorAttachment colA = colbufOld.getColorAttachment();
if( 0 != colA.getName() ) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
GL.GL_COLOR_ATTACHMENT0+attachmentPoint,
@@ -1763,28 +1870,30 @@ public class FBObject {
}
}
if(DetachAction.RECREATE == detachAction) {
+ final Colorbuffer colbufNew;
if( 0 <= sampleCountChange || null == samplingColorSink ) {
// keep ColorAttachment,
// including 'switch to non-MSAA' if no samplingColorSink is available
// to determine whether a TextureAttachment or ColorAttachment is desired!
colA.setSize(width, height);
colA.setSamples(samples);
+ colbufNew = colA;
} else {
// switch to non MSAA
if( samplingColorSink.isTextureAttachment() ) {
final TextureAttachment samplingTextureSink = samplingColorSink.getTextureAttachment();
- colbuf = createColorTextureAttachment(samplingTextureSink.format, width, height,
- samplingTextureSink.dataFormat, samplingTextureSink.dataType,
- samplingTextureSink.magFilter, samplingTextureSink.minFilter,
- samplingTextureSink.wrapS, samplingTextureSink.wrapT);
+ colbufNew = createColorTextureAttachment(samplingTextureSink.format, width, height,
+ samplingTextureSink.dataFormat, samplingTextureSink.dataType,
+ samplingTextureSink.magFilter, samplingTextureSink.minFilter,
+ samplingTextureSink.wrapS, samplingTextureSink.wrapT);
} else {
- colbuf = createColorAttachment(samplingColorSink.getFormat(), 0, width, height);
+ colbufNew = createColorAttachment(samplingColorSink.getFormat(), 0, width, height);
}
}
- attachColorbuffer(gl, attachmentPoint, colbuf);
+ attachColorbuffer(gl, attachmentPoint, colbufNew);
}
}
- return colbuf;
+ return colbufOld;
}
private final void freeAllColorbufferImpl(final GL gl) {
@@ -1824,7 +1933,10 @@ public class FBObject {
*/
public final void detachRenderbuffer(final GL gl, final Attachment.Type atype, final boolean dispose) throws IllegalArgumentException {
bind(gl);
- detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE);
+ final RenderAttachment res = detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE);
+ if(null == res) {
+ throw new IllegalArgumentException("RenderAttachment type "+atype+", not attached, "+this);
+ }
if(DEBUG) {
System.err.println("FBObject.detachRenderbuffer.X: [attachmentType "+atype+", dispose "+dispose+"]: "+this);
}
@@ -1844,7 +1956,7 @@ public class FBObject {
return res;
}
- private final void detachRenderbufferImpl(final GL gl, Attachment.Type atype, final DetachAction detachAction) throws IllegalArgumentException {
+ private final RenderAttachment detachRenderbufferImpl(final GL gl, Attachment.Type atype, final DetachAction detachAction) throws IllegalArgumentException {
switch ( atype ) {
case DEPTH:
case STENCIL:
@@ -1854,23 +1966,25 @@ public class FBObject {
throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
}
if( null == depth && null == stencil ) {
- return ; // nop
+ return null; // nop
}
final boolean packed = isDepthStencilPackedFormat();
if( packed ) {
// Note: DEPTH_STENCIL shares buffer w/ depth and stencil
atype = Attachment.Type.DEPTH_STENCIL;
}
+ final RenderAttachment renderOld;
switch ( atype ) {
case DEPTH:
- if( null != depth ) {
- final int format = depth.format;
- if( 0 != depth.getName() ) {
+ renderOld = depth;
+ if( null != renderOld ) {
+ final int format = renderOld.format;
+ if( 0 != renderOld.getName() ) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
switch(detachAction) {
case DISPOSE:
case RECREATE:
- depth.free(gl);
+ renderOld.free(gl);
break;
default:
}
@@ -1883,14 +1997,15 @@ public class FBObject {
}
break;
case STENCIL:
- if( null != stencil ) {
- final int format = stencil.format;
- if(0 != stencil.getName()) {
+ renderOld = stencil;
+ if( null != renderOld ) {
+ final int format = renderOld.format;
+ if(0 != renderOld.getName()) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
switch(detachAction) {
case DISPOSE:
case RECREATE:
- stencil.free(gl);
+ renderOld.free(gl);
break;
default:
}
@@ -1903,9 +2018,10 @@ public class FBObject {
}
break;
case DEPTH_STENCIL:
- if( null != depth ) {
- final int format = depth.format;
- if(0 != depth.getName()) {
+ renderOld = depth;
+ if( null != renderOld ) {
+ final int format = renderOld.format;
+ if(0 != renderOld.getName()) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
if(packed) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
@@ -1913,7 +2029,7 @@ public class FBObject {
switch(detachAction) {
case DISPOSE:
case RECREATE:
- depth.free(gl);
+ renderOld.free(gl);
break;
default:
}
@@ -1946,8 +2062,11 @@ public class FBObject {
}
}
break;
- default: // handled
+ default:
+ throw new InternalError("XXX"); // handled by caller
}
+ modified = true;
+ return renderOld;
}
private final void freeAllRenderbufferImpl(final GL gl) throws IllegalArgumentException {
@@ -2117,41 +2236,50 @@ public class FBObject {
private final boolean sampleSinkSizeMismatch() {
return samplingSink.getWidth() != width || samplingSink.getHeight() != height ;
}
- private final boolean sampleColorsinkUninit() {
- return null != samplingColorSink && 0 == samplingColorSink.getName() ;
- }
private final boolean sampleSinkDepthStencilMismatch() {
- final boolean depthMismatch = null != depth &&
- ( null == samplingSink.depth ||
- depth.format != samplingSink.depth.format );
+ if ( ( null != depth && ( null == samplingSink.depth || depth.format != samplingSink.depth.format ) )
+ ||
+ ( null == depth && null != samplingSink.depth )
+ ) {
+ return true;
+ }
- final boolean stencilMismatch = null != stencil &&
- ( null == samplingSink.stencil ||
- stencil.format != samplingSink.stencil.format );
+ if ( ( null != stencil && ( null == samplingSink.stencil || stencil.format != samplingSink.stencil.format ) )
+ ||
+ ( null == stencil && null != samplingSink.stencil )
+ ) {
+ return true;
+ }
- return depthMismatch || stencilMismatch;
+ return false;
}
/**
- * For GLES3, sampling-sink {@link Colorbuffer} format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
+ * For GLES3, sampling-sink {@link Colorbuffer} <i>internal format</i> <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
* Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)}
* and {@link #createColorAttachment(boolean)}.
*/
- private final boolean sampleSinkFormatMismatch(final GL gl) {
+ private final boolean sampleSinkExFormatMismatch(final GL gl) {
if( null != samplingColorSink && getColorbufferCount() > 0 && gl.isGL2ES3() ) {
final Attachment ca = (Attachment)getColorbuffer(0); // should be at attachment-point 0
- return ( null != ca && ca.format != samplingColorSink.getFormat() ) ||
- hasAlpha(samplingColorSink.getFormat()) != hasAttachmentUsingAlpha();
+ // We cannot comply w/ attachment's format other than attachment point 0!
+ // return ( null != ca && ca.format != samplingColorSink.getFormat() ) ||
+ // hasAlpha(samplingColorSink.getFormat()) != hasAttachmentUsingAlpha();
+ return null != ca && ca.format != samplingColorSink.getFormat();
}
return false;
}
/**
- * Manually reset the MSAA sampling sink, if used.
+ * Manually validates the MSAA sampling sink, if used.
* <p>
* If MSAA is being used and no sampling sink is attached via {@link #setSamplingSink(FBObject)}
* a new sampling sink is being created.
* </p>
* <p>
+ * If the sampling sink size or attributes differs from the source, its attachments are reset
+ * to match the source.
+ * </p>
+ * <p>
* Automatically called by {@link #reset(GL, int, int, int, boolean)}
* and {@link #syncSamplingSink(GL)}.
* </p>
@@ -2159,6 +2287,9 @@ public class FBObject {
* It is recommended to call this method after initializing the FBO and attaching renderbuffer etc for the 1st time
* if access to sampling sink resources is required.
* </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
* @param gl the current GL context
* @return {@code true} if this instance has been modified, otherwise {@code false}.
* @throws GLException in case of an error, i.e. size too big, etc ..
@@ -2166,126 +2297,172 @@ public class FBObject {
public final boolean resetSamplingSink(final GL gl) throws GLException {
if(DEBUG) {
System.err.println("FBObject.resetSamplingSink.0");
+ Thread.dumpStack();
}
+
if( 0 == samples ) {
- final boolean res;
+ final boolean modifiedInstance;
// MSAA off
- if(null != samplingSink && samplingSink.initialized) {
+ if( null != samplingSink ) {
// cleanup
- samplingSink.detachAll(gl);
- res = true;
+ if( samplingSink.initialized ) {
+ samplingSink.detachAll(gl);
+ }
+ samplingSink = null;
+ samplingColorSink = null;
+ modifiedInstance = true;
} else {
- res = false;
+ modifiedInstance = false;
}
+ this.modified = false;
if(DEBUG) {
- System.err.println("FBObject.resetSamplingSink.X1: zero samples, mod "+res+"\n\tTHIS "+this);
+ System.err.println("FBObject.resetSamplingSink.X1: zero samples, mod "+modifiedInstance+"\n\tTHIS "+this);
}
- return res;
+ return modifiedInstance;
}
- boolean res = false;
+ boolean modifiedInstance = false;
if( null == samplingSink ) {
samplingSink = new FBObject();
- res = true;
- }
- if( !samplingSink.initialized ) {
samplingSink.init(gl, width, height, 0);
- res = true;
+ samplingColorSink = null;
+ modifiedInstance = true;
+ } else if( !samplingSink.initialized ) {
+ throw new InternalError("InitState Mismatch: samplingSink set, but not initialized "+samplingSink);
+ } else if( null == samplingColorSink || 0 == samplingColorSink.getName() ) {
+ throw new InternalError("InitState Mismatch: samplingColorSink set, but not initialized "+samplingColorSink+", "+samplingSink);
}
if(DEBUG) {
- System.err.println("FBObject.resetSamplingSink.1: mod "+res+"\n\tTHIS "+this+",\n\tSINK "+samplingSink);
+ System.err.println("FBObject.resetSamplingSink.1: mod "+modifiedInstance+"\n\tTHIS "+this+",\n\tSINK "+samplingSink);
}
- boolean sampleSinkFormatMismatch = sampleSinkFormatMismatch(gl);
+ boolean sampleSinkExFormatMismatch = sampleSinkExFormatMismatch(gl);
boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch();
boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
- boolean sampleColorsinkUninit = sampleColorsinkUninit();
- if(!sampleSinkFormatMismatch && !sampleSinkSizeMismatch && !sampleColorsinkUninit && !sampleSinkDepthStencilMismatch) {
- if(DEBUG) {
- System.err.println("FBObject.resetSamplingSink.X2: Matching: format "+!sampleSinkFormatMismatch+", size "+!sampleSinkSizeMismatch +", csUninit "+!sampleColorsinkUninit +", depthStencil "+!sampleSinkDepthStencilMismatch+", mod "+res);
+ if( modifiedInstance ) {
+ // samplingColorSink == null
+ // must match size, format and colorbuffer do not exist yet
+ if( sampleSinkExFormatMismatch || sampleSinkSizeMismatch ) {
+ throw new InternalError("InitState Mismatch: Matching exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", "+this);
+ }
+ } else {
+ // samplingColorSink != null
+ if(!sampleSinkExFormatMismatch && !sampleSinkSizeMismatch && !sampleSinkDepthStencilMismatch) {
+ if(DEBUG) {
+ System.err.println("FBObject.resetSamplingSink.X2: Matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch+
+ ", mod "+modifiedInstance);
+ }
+ // all properties match ..
+ samplingSink.modified = false;
+ this.modified = false;
+ return modifiedInstance;
}
- // all properties match ..
- return res;
}
- unbind(gl);
+ final boolean wasBound;
+ if( isBound() ) {
+ markUnbound(); // automatic GL unbind by sampleSink binding
+ wasBound = true;
+ } else {
+ wasBound = false;
+ }
if(DEBUG) {
- System.err.println("FBObject.resetSamplingSink.2: Mismatch. Matching: format "+!sampleSinkFormatMismatch+", size "+!sampleSinkSizeMismatch +", csUninit "+!sampleColorsinkUninit +", depthStencil "+!sampleSinkDepthStencilMismatch);
- Thread.dumpStack();
+ System.err.println("FBObject.resetSamplingSink.2: wasBound "+wasBound+", matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch);
}
- if( sampleSinkDepthStencilMismatch ) {
+ modifiedInstance = true;
+
+ if( sampleSinkDepthStencilMismatch ) { // includes 1st init
samplingSink.detachAllRenderbuffer(gl);
- res = true;
}
- final Colorbuffer preSamplingColorSink = samplingColorSink;
- final boolean samplingColorSinkShallBeTA = null == preSamplingColorSink || preSamplingColorSink.isTextureAttachment();
+ final boolean samplingColorSinkShallBeTA = null == samplingColorSink || samplingColorSink.isTextureAttachment();
- if( sampleSinkFormatMismatch ) {
+ if( sampleSinkExFormatMismatch ) {
samplingSink.detachAllColorbuffer(gl);
samplingColorSink = null;
- res = true;
} else if( sampleSinkSizeMismatch ) {
- samplingSink.reset(gl, width, height);
- res = true;
- }
-
- if(null == samplingColorSink) {
- final boolean hasAlpha = hasAttachmentUsingAlpha();
- if( samplingColorSinkShallBeTA ) {
- samplingColorSink = samplingSink.attachTexture2D(gl, 0, hasAlpha);
+ samplingSink.resetSizeImpl(gl, width, height);
+ samplingColorSink = samplingSink.getColorbuffer(0);
+ }
+
+ if( null == samplingColorSink ) { // sampleSinkFormatMismatch || 1st init
+ final Colorbuffer cb0 = getColorbuffer(0); // align with colorbuffer at attachment-point 0
+ if( null != cb0 ) {
+ // match pre-existing format
+ if( samplingColorSinkShallBeTA ) {
+ samplingColorSink = createColorTextureAttachment(gl, cb0.getFormat(), width, height,
+ GL.GL_NEAREST, GL.GL_NEAREST,
+ GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ } else {
+ samplingColorSink = createColorAttachment(cb0.getFormat(), 0, width, height);
+ }
+ samplingSink.attachColorbuffer(gl, 0, samplingColorSink);
} else {
- samplingColorSink = samplingSink.attachColorbuffer(gl, 0, hasAlpha);
+ // match default format
+ final boolean hasAlpha = hasAttachmentUsingAlpha();
+ if( samplingColorSinkShallBeTA ) {
+ samplingColorSink = samplingSink.attachTexture2D(gl, 0, hasAlpha);
+ } else {
+ samplingColorSink = samplingSink.attachColorbuffer(gl, 0, hasAlpha);
+ }
}
- res = true;
- } else if( 0 == samplingColorSink.getName() ) {
- // final boolean dispose = true;
- // detachColorbufferImpl(gl, 0, dispose ? DetachAction.DISPOSE : DetachAction.NONE);
- ((Attachment)samplingColorSink).setSize(width, height);
- samplingSink.attachColorbuffer(gl, 0, samplingColorSink);
- res = true;
}
- if( sampleSinkDepthStencilMismatch ) {
+ if( sampleSinkDepthStencilMismatch ) { // includes 1st init
samplingSink.attachRenderbuffer(gl, depth.format);
if( null != stencil && !isDepthStencilPackedFormat() ) {
samplingSink.attachRenderbuffer(gl, stencil.format);
}
- res = true;
}
- sampleSinkFormatMismatch = sampleSinkFormatMismatch(gl);
+ sampleSinkExFormatMismatch = sampleSinkExFormatMismatch(gl);
sampleSinkSizeMismatch = sampleSinkSizeMismatch();
sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
- sampleColorsinkUninit = sampleColorsinkUninit();
- if(sampleSinkFormatMismatch || sampleSinkSizeMismatch || sampleColorsinkUninit || sampleSinkDepthStencilMismatch) {
+ if(sampleSinkExFormatMismatch || sampleSinkSizeMismatch || sampleSinkDepthStencilMismatch) {
throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplingSink+
- "\n\t Mismatch. Matching: format "+!sampleSinkFormatMismatch+", size "+!sampleSinkSizeMismatch +", csUninit "+!sampleColorsinkUninit +", depthStencil "+!sampleSinkDepthStencilMismatch);
+ "\n\t Mismatch. Matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch);
+ }
+
+ samplingSink.modified = false;
+ samplingSink.unbind(gl);
+ this.modified = false;
+
+ if(wasBound) {
+ bind(gl);
}
if(DEBUG) {
- System.err.println("FBObject.resetSamplingSink.XX: END mod "+res+"\n\tTHIS "+this+",\n\tSINK "+samplingSink+
- "\n\t Matching: format "+!sampleSinkFormatMismatch+", size "+!sampleSinkSizeMismatch +", csUninit "+!sampleColorsinkUninit +", depthStencil "+!sampleSinkDepthStencilMismatch);
+ System.err.println("FBObject.resetSamplingSink.XX: END mod "+modifiedInstance+"\n\tTHIS "+this+",\n\tSINK "+samplingSink+
+ "\n\t Matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch);
}
- return res;
+ return modifiedInstance;
}
/**
* Setting this FBO sampling sink.
- * @param newSamplingSink the new FBO sampling sink to use, or null to remove current sampling sink
+ * @param newSamplingSink the new and initialized FBO sampling sink to use, or null to remove current sampling sink
* @return the previous sampling sink or null if none was attached
* @throws GLException if this FBO doesn't use MSAA or the given sink uses MSAA itself
+ * @throws IllegalStateException if the {@code newSamplingSink} is not null and not initialized
*/
- public FBObject setSamplingSink(final FBObject newSamplingSink) throws GLException {
+ public FBObject setSamplingSink(final FBObject newSamplingSink) throws /* IllegalStateException, */ GLException {
final FBObject prev = samplingSink;
if( null == newSamplingSink) {
samplingSink = null;
samplingColorSink = null;
} else if( samples > 0 ) {
+ if( !newSamplingSink.isInitialized() ) {
+ throw new IllegalStateException("SamplingSink not initialized: "+newSamplingSink);
+ }
if( newSamplingSink.getNumSamples() > 0 ) {
throw new GLException("SamplingSink FBO cannot use MSAA itself: "+newSamplingSink);
}
@@ -2294,6 +2471,7 @@ public class FBObject {
} else {
throw new GLException("Setting SamplingSink for non MSAA FBO not allowed: "+this);
}
+ modified = true;
samplingSinkDirty = true;
return prev;
}
@@ -2367,7 +2545,7 @@ public class FBObject {
* @param gl the current GL context
*/
public final boolean isBound(final GL gl) {
- bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ;
+ bound = bound && fbName == gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ;
return bound;
}
@@ -2402,13 +2580,17 @@ public class FBObject {
markUnbound();
if(samples>0 && samplingSinkDirty) { // implies fullFBOSupport
samplingSinkDirty = false;
- resetSamplingSink(gl);
+ if( isModified() ) {
+ resetSamplingSink(gl);
+ }
checkPreGLError(gl);
gl.glBindFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER, fbName); // read from this MSAA fb
gl.glBindFramebuffer(GL2ES3.GL_DRAW_FRAMEBUFFER, samplingSink.getWriteFramebuffer()); // write to sampling sink
((GL2ES3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2ES3 is OK
GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST);
checkNoError(null, gl.glGetError(), "FBObject syncSampleSink"); // throws GLException if error
+ } else {
+ modified = false;
}
if(fullFBOSupport) {
// default read/draw buffers, may utilize GLContext/GLDrawable override of
@@ -2523,7 +2705,9 @@ public class FBObject {
/** Returns the framebuffer name to render to. */
public final int getWriteFramebuffer() { return fbName; }
/** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
- public final int getReadFramebuffer() { return ( samples > 0 ) ? samplingSink.getReadFramebuffer() : fbName; }
+ public final int getReadFramebuffer() {
+ return 0 < samples ? ( null != samplingSink ? samplingSink.getReadFramebuffer() : 0 ) : fbName;
+ }
public final int getDefaultReadBuffer() { return GL.GL_COLOR_ATTACHMENT0; }
/** Return the number of attached {@link Colorbuffer}s */
public final int getColorbufferCount() { return colorbufferCount; }
@@ -2547,13 +2731,24 @@ public class FBObject {
*/
public final boolean isSamplingBufferDirty() { return samplingSinkDirty; }
+ /**
+ * Returns <code>true</code> if size, sample-count or any attachment of this instance
+ * or its {@link #getSamplingSink() sampling-sink} has been modified since last {@link #syncSamplingSink(GL) sync},
+ * {@link #use(GL, TextureAttachment) use}, {@link #reset(GL, int, int, int) reset}
+ * or {@link #resetSamplingSink(GL) resetSamplingSink}.
+ * <p>
+ * Otherwise method returns <code>false</code>.
+ * </p>
+ */
+ public final boolean isModified() { return modified || ( null != samplingSink && samplingSink.modified ); }
+
int objectHashCode() { return super.hashCode(); }
@Override
public final String toString() {
final String caps = null != colorbufferAttachments ? Arrays.asList(colorbufferAttachments).toString() : null ;
return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+
- ", samples "+samples+"/"+maxSamples+", depth "+depth+", stencil "+stencil+
+ ", samples "+samples+"/"+maxSamples+", modified "+modified+"/"+isModified()+", depth "+depth+", stencil "+stencil+
", colorbuffer attachments: "+colorbufferCount+"/"+maxColorAttachments+", with "+textureAttachmentCount+" textures"+
": "+caps+", msaa["+samplingColorSink+", hasSink "+(null != samplingSink)+
", dirty "+samplingSinkDirty+"], state "+getStatusString()+", obj "+toHexString(objectHashCode())+"]";
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
index 8bcce71a9..8b00aefb7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
@@ -87,7 +87,7 @@ public class StereoClientRenderer implements GLEventListener {
private void initFBOs(final GL gl, final DimensionImmutable size) {
for(int i=0; i<fbos.length; i++) {
- fbos[i].reset(gl, size.getWidth(), size.getHeight(), numSamples, false);
+ fbos[i].init(gl, size.getWidth(), size.getHeight(), numSamples);
if( i>0 && fbos[i-1].getNumSamples() != fbos[i].getNumSamples()) {
throw new InternalError("sample size mismatch: \n\t0: "+fbos[i-1]+"\n\t1: "+fbos[i]);
}
@@ -98,7 +98,7 @@ public class StereoClientRenderer implements GLEventListener {
fbos[i].attachRenderbuffer(gl, Type.DEPTH, 24);
final FBObject ssink = new FBObject();
{
- ssink.reset(gl, size.getWidth(), size.getHeight());
+ ssink.init(gl, size.getWidth(), size.getHeight(), 0);
ssink.attachTexture2D(gl, 0, false, magFilter, minFilter, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
}
@@ -118,7 +118,7 @@ public class StereoClientRenderer implements GLEventListener {
@SuppressWarnings("unused")
private void resetFBOs(final GL gl, final DimensionImmutable size) {
for(int i=0; i<fbos.length; i++) {
- fbos[i].reset(gl, size.getWidth(), size.getHeight(), numSamples, true);
+ fbos[i].reset(gl, size.getWidth(), size.getHeight(), numSamples);
if( i>0 && fbos[i-1].getNumSamples() != fbos[i].getNumSamples()) {
throw new InternalError("sample size mismatch: \n\t0: "+fbos[i-1]+"\n\t1: "+fbos[i]);
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index ac091e4de..132367102 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -1692,7 +1692,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
try {
fboFlipped = new FBObject();
- fboFlipped.reset(gl, panelWidth, panelHeight, 0, false);
+ fboFlipped.init(gl, panelWidth, panelHeight, 0);
fboFlipped.attachColorbuffer(gl, 0, chosenCaps.getAlphaBits()>0);
// fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
gl.glClear(GL.GL_COLOR_BUFFER_BIT); // Bug 1020 (see above), cannot do in FBObject due to unknown 'first bind' state.
@@ -2038,7 +2038,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
try {
final GL gl = offscreenContext.getGL();
- fboFlipped.reset(gl, panelWidth, panelHeight, 0, false);
+ fboFlipped.reset(gl, panelWidth, panelHeight, 0);
glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
} finally {
offscreenContext.release();
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
index ca50b5d2d..422714ac5 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
@@ -454,7 +454,7 @@ 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);
if( !blendingEnabled ) {
@@ -463,7 +463,7 @@ public class VBORegion2PMSAAES2 extends GLRegion {
}
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);
@@ -478,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..5251ade39 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
@@ -573,7 +573,7 @@ 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);
@@ -586,7 +586,7 @@ public class VBORegion2PVBAAES2 extends GLRegion {
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/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index f3954b7b6..1bdc99a9b 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -107,7 +107,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
final FBObject fbo = new FBObject();
fbos[idx] = fbo;
- fbo.reset(gl, width, height, samples, false);
+ fbo.init(gl, width, height, samples);
if(fbo.getNumSamples() != samples) {
throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbo);
}
@@ -128,7 +128,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
if(samples > 0) {
final FBObject ssink = new FBObject();
{
- ssink.reset(gl, width, height);
+ ssink.init(gl, width, height, 0);
if( !useTexture ) {
ssink.attachColorbuffer(gl, 0, useAlpha);
} else {
@@ -243,7 +243,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
final boolean useDepth = 0 != ( FBOMODE_USE_DEPTH & fboModeBits );
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]);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
index 9e38b0d50..a66eddfdc 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
@@ -167,7 +167,7 @@ public class TestFBOMRTNEWT01 extends UITestCase {
// FBO w/ 2 texture2D color buffers
final FBObject fbo_mrt = new FBObject();
- fbo_mrt.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ fbo_mrt.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0);
final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
final TextureAttachment texA1;
if(fbo_mrt.getMaxColorAttachments() > 1) {
@@ -257,7 +257,7 @@ public class TestFBOMRTNEWT01 extends UITestCase {
final int w = width/step * j;
final int h = height/step * j;
System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h);
- fbo_mrt.reset(gl, w, h);
+ fbo_mrt.reset(gl, w, h, 0);
winctx.window.setSize(w, h);
step_i = j;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
index f8feefdcf..5eebf9cdd 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
@@ -62,14 +62,14 @@ import org.junit.runners.MethodSorters;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestFBOMix2DemosES2NEWT extends UITestCase {
- static long duration = 500; // ms
+ static long duration = 1000; // ms
static int swapInterval = 1;
static boolean showFPS = false;
static boolean forceES2 = false;
static boolean doRotate = true;
static boolean demo0Only = false;
static int globalNumSamples = 0;
- static boolean mainRun = false;
+ static boolean manual = false;
@AfterClass
public static void releaseClass() {
@@ -81,7 +81,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
- if(mainRun) {
+ if(manual) {
glWindow.setSize(512, 512);
} else {
glWindow.setSize(128, 128);
@@ -100,7 +100,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
}
public void dispose(final GLAutoDrawable drawable) {}
public void display(final GLAutoDrawable drawable) {
- if(mainRun) return;
+ if(manual) return;
final int dw = drawable.getSurfaceWidth();
final int dh = drawable.getSurfaceHeight();
@@ -112,18 +112,24 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null);
}
if( 3 == c ) {
+ demo.setMSAA(4);
+ } else if( 6 == c ) {
new Thread() {
@Override
public void run() {
- demo.setMSAA(4);
+ glWindow.setSize(dw+64, dh+64);
} }.start();
- } else if( 6 == c ) {
+ } else if( 9 == c ) {
+ demo.setMSAA(8);
+ } else if( 12 == c ) {
+ demo.setMSAA(0);
+ } else if( 15 == c ) {
new Thread() {
@Override
public void run() {
- demo.setMSAA(8);
+ glWindow.setSize(dw+128, dh+128);
} }.start();
- } else if(9 == c) {
+ } else if( 18 == c ) {
c=0;
new Thread() {
@Override
@@ -203,8 +209,8 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
}
@Test
- public void test01_Main() throws InterruptedException {
- if( mainRun ) {
+ public void test00_Manual() throws InterruptedException {
+ if( manual ) {
final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
caps.setAlphaBits(1);
runTestGL(caps, globalNumSamples);
@@ -212,17 +218,25 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
}
@Test
- public void test01() throws InterruptedException {
- if( mainRun ) return ;
+ public void test01_startMSAA0() throws InterruptedException {
+ if( manual ) return ;
final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
caps.setAlphaBits(1);
runTestGL(caps, 0);
}
+ @Test
+ public void test02_startMSAA4() throws InterruptedException {
+ if( manual ) return ;
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ caps.setAlphaBits(1);
+ runTestGL(caps, 4);
+ }
+
public static void main(final String args[]) throws IOException {
boolean waitForKey = false;
- mainRun = true;
+ manual = false;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
@@ -244,13 +258,14 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
demo0Only = true;
} else if(args[i].equals("-wait")) {
waitForKey = true;
- } else if(args[i].equals("-nomain")) {
- mainRun = false;
+ } else if(args[i].equals("-manual")) {
+ manual = true;
}
}
System.err.println("swapInterval "+swapInterval);
System.err.println("forceES2 "+forceES2);
+ System.err.println("manual "+manual);
if(waitForKey) {
final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
index 4df959333..d99cba50b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
@@ -49,7 +49,7 @@ public class FBOMix2DemosES2 implements GLEventListener {
private final GearsES2 demo0;
private final RedSquareES2 demo1;
private final int swapInterval;
- private int numSamples;
+ private volatile int numSamples;
private boolean demo0Only;
@@ -156,8 +156,8 @@ public class FBOMix2DemosES2 implements GLEventListener {
}
private void initFBOs(final GL gl, final GLAutoDrawable drawable) {
- fbo0.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples, false);
- fbo1.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples, false);
+ fbo0.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
+ fbo1.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
if(fbo0.getNumSamples() != fbo1.getNumSamples()) {
throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1);
}
@@ -182,8 +182,8 @@ public class FBOMix2DemosES2 implements GLEventListener {
}
private void resetFBOs(final GL gl, final GLAutoDrawable drawable) {
- fbo0.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples, true);
- fbo1.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples, true);
+ fbo0.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
+ fbo1.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
if(fbo0.getNumSamples() != fbo1.getNumSamples()) {
throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java
index 69319561d..066003956 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java
@@ -144,7 +144,7 @@ public class TextureDraw02ES2ListenerFBO implements GLEventListener {
}
private void initFBOs(final GL gl, final int width, final int height) {
- fbo0.reset(gl, width, height, numSamples, false);
+ fbo0.init(gl, width, height, numSamples);
numSamples = fbo0.getNumSamples();
if(numSamples>0) {
@@ -160,7 +160,7 @@ public class TextureDraw02ES2ListenerFBO implements GLEventListener {
}
private void resetFBOs(final GL gl, final int width, final int height) {
- fbo0.reset(gl, width, height, numSamples, true);
+ fbo0.reset(gl, width, height, numSamples);
numSamples = fbo0.getNumSamples();
if(numSamples>0) {
fbo0Tex = fbo0.getSamplingSink().getTextureAttachment();