diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/FBObject.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/FBObject.java | 790 |
1 files changed, 397 insertions, 393 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 7060bb7d1..72041a389 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -46,7 +46,7 @@ import com.jogamp.opengl.FBObject.Attachment.Type; /** * Core utility class simplifying usage of framebuffer objects (FBO) - * with all {@link GLProfile}s. + * with all {@link GLProfile}s. * <p> * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int, boolean)} * while preserving the {@link Attachment} references. @@ -55,50 +55,50 @@ import com.jogamp.opengl.FBObject.Attachment.Type; * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()}, * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (<code>zero</code>) framebuffer is selected. * </p> - * + * * <p>FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .</p> */ public class FBObject { protected static final boolean DEBUG = Debug.debug("FBObject"); private static final boolean FBOResizeQuirk = false; - + private static enum DetachAction { NONE, DISPOSE, RECREATE }; - - /** + + /** * Marker interface, denotes a color buffer attachment. * <p>Always an instance of {@link Attachment}.</p> - * <p>Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.</b> + * <p>Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.</b> */ - public static interface Colorbuffer { - /** + public static interface Colorbuffer { + /** * Initializes the color buffer and set it's parameter, if uninitialized, i.e. name is <code>zero</code>. * @return <code>true</code> if newly initialized, otherwise <code>false</code>. - * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. */ public boolean initialize(GL gl) throws GLException; - - /** + + /** * Releases the color buffer if initialized, i.e. name is not <code>zero</code>. - * @throws GLException if buffer release fails. + * @throws GLException if buffer release fails. */ public void free(GL gl) throws GLException; - + /** * Writes the internal format to the given GLCapabilities object. * @param caps the destination for format bits * @param rgba8Avail whether rgba8 is available */ - public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail); + public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail); } - + /** Common super class of all attachments */ public static abstract class Attachment { - public enum Type { + public enum Type { NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE; - - /** + + /** * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL} - * @throws IllegalArgumentException if <code>format</code> cannot be handled. + * @throws IllegalArgumentException if <code>format</code> cannot be handled. */ public static Type determine(int format) throws IllegalArgumentException { switch(format) { @@ -120,20 +120,20 @@ public class FBObject { return Type.DEPTH_STENCIL; default: throw new IllegalArgumentException("format invalid: "+toHexString(format)); - } + } } }; - + /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */ public final Type type; - + /** immutable the internal format */ public final int format; - + private int width, height; - + private int name; - + protected Attachment(Type type, int iFormat, int width, int height, int name) { this.type = type; this.format = iFormat; @@ -141,18 +141,18 @@ public class FBObject { this.height = height; this.name = name; } - + /** * Writes the internal format to the given GLCapabilities object. * @param caps the destination for format bits * @param rgba8Avail whether rgba8 is available */ - public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) { + public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) { final int _format; switch(format) { case GL.GL_RGBA: case 4: - _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4; + _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4; break; case GL.GL_RGB: case 3: @@ -191,7 +191,7 @@ public class FBObject { caps.setGreenBits(8); caps.setBlueBits(8); caps.setAlphaBits(8); - break; + break; case GL.GL_DEPTH_COMPONENT16: caps.setDepthBits(16); break; @@ -218,18 +218,18 @@ public class FBObject { throw new IllegalArgumentException("format invalid: "+toHexString(format)); } } - + /** width of attachment */ public final int getWidth() { return width; } /** height of attachment */ public final int getHeight() { return height; } /* pp */ final void setSize(int w, int h) { width = w; height = h; } - + /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */ - public final int getName() { return name; } + public final int getName() { return name; } /* pp */ final void setName(int n) { name = n; } - - /** + + /** * Initializes the attachment and set it's parameter, if uninitialized, i.e. name is <code>zero</code>. * <pre> final boolean init = 0 == name; @@ -239,11 +239,11 @@ public class FBObject { return init; * </pre> * @return <code>true</code> if newly initialized, otherwise <code>false</code>. - * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. */ public abstract boolean initialize(GL gl) throws GLException; - - /** + + /** * Releases the attachment if initialized, i.e. name is not <code>zero</code>. * <pre> if(0 != name) { @@ -251,10 +251,10 @@ public class FBObject { name = 0; } * </pre> - * @throws GLException if buffer release fails. + * @throws GLException if buffer release fails. */ public abstract void free(GL gl) throws GLException; - + /** * <p> * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. @@ -272,7 +272,7 @@ public class FBObject { height== a.height && name == a.name ; } - + /** * <p> * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. @@ -289,14 +289,15 @@ public class FBObject { hash = ((hash << 5) - hash) + name; return hash; } - + int objectHashCode() { return super.hashCode(); } - + + @Override public String toString() { return getClass().getSimpleName()+"[type "+type+", format "+toHexString(format)+", "+width+"x"+height+ "; name "+toHexString(name)+", obj "+toHexString(objectHashCode())+"]"; } - + public static Type getType(int attachmentPoint, int maxColorAttachments) { if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) { return Type.COLOR; @@ -304,9 +305,9 @@ public class FBObject { switch(attachmentPoint) { case GL.GL_DEPTH_ATTACHMENT: return Type.DEPTH; - case GL.GL_STENCIL_ATTACHMENT: + case GL.GL_STENCIL_ATTACHMENT: return Type.STENCIL; - default: + default: throw new IllegalArgumentException("Invalid attachment point "+toHexString(attachmentPoint)); } } @@ -315,7 +316,7 @@ public class FBObject { /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ public static class RenderAttachment extends Attachment { private int samples; - + /** * @param type allowed types are {@link Type#DEPTH_STENCIL} {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR} * @param iFormat @@ -328,11 +329,11 @@ public class FBObject { super(validateType(type), iFormat, width, height, name); this.samples = samples; } - + /** number of samples, or zero for no multisampling */ public final int getSamples() { return samples; } /* pp */ final void setSamples(int s) { samples = s; } - + private static Type validateType(Type type) { switch(type) { case DEPTH_STENCIL: @@ -340,11 +341,11 @@ public class FBObject { case STENCIL: case COLOR: return type; - default: + default: throw new IllegalArgumentException("Invalid type: "+type); } } - + /** * <p> * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. @@ -358,7 +359,7 @@ public class FBObject { return super.equals(o) && samples == ((RenderAttachment)o).samples; } - + /** * <p> * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. @@ -378,14 +379,14 @@ public class FBObject { final boolean init = 0 == getName(); if( init ) { checkPreGLError(gl); - + final int[] name = new int[] { -1 }; gl.glGenRenderbuffers(1, name, 0); setName(name[0]); - + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); if( samples > 0 ) { - ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); + ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); } else { gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); } @@ -401,7 +402,7 @@ public class FBObject { } return init; } - + @Override public void free(GL gl) { final int[] name = new int[] { getName() }; @@ -413,20 +414,21 @@ public class FBObject { setName(0); } } - + + @Override public String toString() { return getClass().getSimpleName()+"[type "+type+", format "+toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ ", name "+toHexString(getName())+", obj "+toHexString(objectHashCode())+"]"; } } - + /** Color render buffer attachment */ public static class ColorAttachment extends RenderAttachment implements Colorbuffer { public ColorAttachment(int iFormat, int samples, int width, int height, int name) { super(Type.COLOR, iFormat, samples, width, height, name); - } + } } - + /** Texture attachment */ public static class TextureAttachment extends Attachment implements Colorbuffer { /** details of the texture setup */ @@ -445,7 +447,7 @@ public class FBObject { * @param wrapT * @param name */ - public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType, + public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType, int magFilter, int minFilter, int wrapS, int wrapT, int name) { super(validateType(type), iFormat, width, height, name); this.dataFormat = dataFormat; @@ -455,35 +457,35 @@ public class FBObject { this.wrapS = wrapS; this.wrapT = wrapT; } - + private static Type validateType(Type type) { switch(type) { case COLOR_TEXTURE: case DEPTH_TEXTURE: case STENCIL_TEXTURE: return type; - default: + default: throw new IllegalArgumentException("Invalid type: "+type); } } - - /** + + /** * Initializes the texture and set it's parameter, if uninitialized, i.e. name is <code>zero</code>. - * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. + * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. */ @Override public boolean initialize(GL gl) throws GLException { final boolean init = 0 == getName(); if( init ) { checkPreGLError(gl); - - final int[] name = new int[] { -1 }; + + final int[] name = new int[] { -1 }; gl.glGenTextures(1, name, 0); if(0 == name[0]) { throw new GLException("null texture, "+this); } setName(name[0]); - + gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]); if( 0 < magFilter ) { gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); @@ -495,7 +497,7 @@ public class FBObject { gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); } if( 0 < wrapT ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); } boolean preTexImage2D = true; int glerr = gl.glGetError(); @@ -527,6 +529,7 @@ public class FBObject { setName(0); } } + @Override public String toString() { return getClass().getSimpleName()+"[type "+type+", target GL_TEXTURE_2D, level 0, format "+toHexString(format)+ ", "+getWidth()+"x"+getHeight()+", border 0, dataFormat "+toHexString(dataFormat)+ @@ -534,50 +537,50 @@ public class FBObject { "; min/mag "+toHexString(minFilter)+"/"+toHexString(magFilter)+ ", wrap S/T "+toHexString(wrapS)+"/"+toHexString(wrapT)+ "; name "+toHexString(getName())+", obj "+toHexString(objectHashCode())+"]"; - } + } } static String toHexString(int v) { return "0x"+Integer.toHexString(v); } - + /** - * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, * selecting the texture data type and format automatically. - * + * * <p>Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.</p> - * + * * @param glp the chosen {@link GLProfile} * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>; - * @param width texture width + * @param width texture width * @param height texture height * @return the created and uninitialized color {@link TextureAttachment} */ public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) { return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); } - + /** - * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, * selecting the texture data type and format automatically. - * + * * @param glp the chosen {@link GLProfile} * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>; - * @param width texture width + * @param width texture width * @param height texture height * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return the created and uninitialized color {@link TextureAttachment} */ - public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height, + public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height, int magFilter, int minFilter, int wrapS, int wrapT) { final int textureInternalFormat, textureDataFormat, textureDataType; - if(glp.isGLES()) { + if(glp.isGLES()) { textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; textureDataType = GL.GL_UNSIGNED_BYTE; - } else { + } else { textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; // textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; // textureInternalFormat = alpha ? 4 : 3; @@ -586,27 +589,27 @@ public class FBObject { } return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); } - + /** - * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}. + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}. * * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param width texture width + * @param width texture width * @param height texture height * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return the created and uninitialized color {@link TextureAttachment} */ public static final TextureAttachment createColorTextureAttachment(int internalFormat, int width, int height, int dataFormat, int dataType, int magFilter, int minFilter, int wrapS, int wrapT) { - return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT, 0 /* name */); } - + private static boolean hasAlpha(int format) { switch(format) { case GL.GL_RGBA8: @@ -619,7 +622,7 @@ public class FBObject { return false; } } - + private boolean initialized; private boolean fullFBOSupport; private boolean rgba8Avail; @@ -629,7 +632,7 @@ public class FBObject { private boolean stencil04Avail; private boolean stencil08Avail; private boolean stencil16Avail; - private boolean packedDepthStencilAvail; + private boolean packedDepthStencilAvail; private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize; private int width, height, samples; @@ -639,21 +642,21 @@ public class FBObject { private boolean bound; private int colorAttachmentCount; - private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points + private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil private FBObject samplingSink; // MSAA sink - private TextureAttachment samplingSinkTexture; + private TextureAttachment samplingSinkTexture; private boolean samplingSinkDirty; // // ColorAttachment helper .. // - + private final void validateColorAttachmentPointRange(int point) { if(!initialized) { throw new GLException("FBO not initialized"); - } + } if(maxColorAttachments != colorAttachmentPoints.length) { throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints); } @@ -661,14 +664,14 @@ public class FBObject { throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"], "+this); } } - + private final void validateAddColorAttachment(int point, Colorbuffer ca) { validateColorAttachmentPointRange(point); if( null != colorAttachmentPoints[point] ) { throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]+", "+this); - } + } } - + private final void addColorAttachment(int point, Colorbuffer ca) { validateColorAttachmentPointRange(point); final Colorbuffer c = colorAttachmentPoints[point]; @@ -678,7 +681,7 @@ public class FBObject { colorAttachmentPoints[point] = ca; colorAttachmentCount++; } - + private final void removeColorAttachment(int point, Colorbuffer ca) { validateColorAttachmentPointRange(point); final Colorbuffer c = colorAttachmentPoints[point]; @@ -688,20 +691,20 @@ public class FBObject { colorAttachmentPoints[point] = null; colorAttachmentCount--; } - + /** * Return the {@link Colorbuffer} attachment at <code>attachmentPoint</code> if it is attached to this FBO, otherwise null. - * + * * @see #attachColorbuffer(GL, boolean) * @see #attachColorbuffer(GL, boolean) * @see #attachTexture2D(GL, int, boolean, int, int, int, int) - * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) */ public final Colorbuffer getColorbuffer(int attachmentPoint) { - validateColorAttachmentPointRange(attachmentPoint); + validateColorAttachmentPointRange(attachmentPoint); return colorAttachmentPoints[attachmentPoint]; } - + /** * Finds the passed {@link Colorbuffer} within the valid range of attachment points * using <i>reference</i> comparison only. @@ -709,36 +712,36 @@ public class FBObject { * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap. * </p> * @param ca the {@link Colorbuffer} to look for. - * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1] + * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1] */ public final int getColorbufferAttachmentPoint(Colorbuffer ca) { for(int i=0; i<colorAttachmentPoints.length; i++) { if( colorAttachmentPoints[i] == ca ) { - return i; + return i; } } return -1; } - + /** * Returns the passed {@link Colorbuffer} if it is attached to this FBO, otherwise null. * Implementation compares the <i>reference</i> only. - * + * * <p> * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point * to be used for {@link #getColorbuffer(int)} * </p> - * + * * @see #attachColorbuffer(GL, boolean) * @see #attachColorbuffer(GL, boolean) * @see #attachTexture2D(GL, int, boolean, int, int, int, int) - * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) */ public final Colorbuffer getColorbuffer(Colorbuffer ca) { final int p = getColorbufferAttachmentPoint(ca); return p>=0 ? getColorbuffer(p) : null; } - + /** * Creates an uninitialized FBObject instance. * <p> @@ -747,7 +750,7 @@ public class FBObject { */ public FBObject() { this.initialized = false; - + // TBD @ init this.fullFBOSupport = false; this.rgba8Avail = false; @@ -762,7 +765,7 @@ public class FBObject { this.maxSamples=-1; this.maxTextureSize = 0; this.maxRenderbufferSize = 0; - + this.width = 0; this.height = 0; this.samples = 0; @@ -770,17 +773,17 @@ public class FBObject { this.ignoreStatus = false; this.fbName = 0; this.bound = false; - + this.colorAttachmentPoints = null; // at init .. this.colorAttachmentCount = 0; this.depth = null; - this.stencil = null; - + this.stencil = null; + this.samplingSink = null; this.samplingSinkTexture = null; this.samplingSinkDirty = true; } - + private void init(GL gl, int width, int height, int samples) throws GLException { if(initialized) { throw new GLException("FBO already initialized"); @@ -788,8 +791,8 @@ public class FBObject { if( !gl.hasBasicFBOSupport() ) { throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); } - fullFBOSupport = gl.hasFullFBOSupport(); - + fullFBOSupport = gl.hasFullFBOSupport(); + rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32); @@ -797,15 +800,15 @@ public class FBObject { stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4); stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8); stencil16Avail = fullFBOSupport; - + packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil) || gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ; - + final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments); - + int val[] = new int[1]; - + checkPreGLError(gl); int realMaxColorAttachments = 1; @@ -818,24 +821,24 @@ public class FBObject { } catch (GLException gle) { gle.printStackTrace(); } } maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size - + colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; colorAttachmentCount = 0; - + maxSamples = gl.getMaxRenderbufferSamples(); gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); maxTextureSize = val[0]; gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); maxRenderbufferSize = val[0]; - + checkPreGLError(gl); - + if( 0 >= width ) { width = 1; } if( 0 >= height ) { height = 1; } this.width = width; this.height = height; this.samples = samples <= maxSamples ? samples : maxSamples; - + if(DEBUG) { System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples"); System.err.println("fullFBOSupport: "+fullFBOSupport); @@ -856,16 +859,16 @@ public class FBObject { System.err.println(JoglVersion.getGLStrings(gl, null).toString()); System.err.println(gl.getContext()); } - + checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error - + if(width > 2 + maxTextureSize || height> 2 + maxTextureSize || width > maxRenderbufferSize || height> maxRenderbufferSize ) { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } resetSamplingSink(gl); - + // generate fbo .. gl.glGenFramebuffers(1, val, 0); fbName = val[0]; @@ -874,15 +877,15 @@ public class FBObject { } // bind fbo .. - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName); + checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error if(!gl.glIsFramebuffer(fbName)) { 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! if(DEBUG) { System.err.println("FBObject.init(): "+this); @@ -900,9 +903,9 @@ public class FBObject { * Incompatibility and hence recreation is forced if * the size or sample count doesn't match for subsequent calls. * </p> - * + * * <p>Leaves the FBO bound state untouched</p> - * + * * @param gl the current GL context * @param newWidth * @param newHeight @@ -911,7 +914,7 @@ public class FBObject { public final void reset(GL gl, int newWidth, int newHeight) { reset(gl, newWidth, newHeight, 0, false); } - + /** * Initializes or resets this FBO's instance. * <p> @@ -920,21 +923,21 @@ public class FBObject { * to match the new given parameters. * </p> * <p> - * Currently incompatibility and hence recreation of the attachments will be performed + * 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> - * + * * @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()}. - * @param resetSamplingSink <code>true</code> calls {@link #resetSamplingSink(GL)} immediatly. + * @param resetSamplingSink <code>true</code> calls {@link #resetSamplingSink(GL)} immediatly. * <code>false</code> postpones resetting the sampling sink until {@link #use(GL, TextureAttachment)} or {@link #syncSamplingSink(GL)}, - * allowing to use the samples sink's FBO and texture until then. The latter is useful to benefit - * from implicit double buffering while resetting the sink just before it's being used, eg. at swap-buffer. - * + * allowing to use the samples sink's FBO and texture until then. The latter is useful to benefit + * from implicit double buffering while resetting the sink just before it's being used, eg. at swap-buffer. + * * @throws GLException in case of an error, i.e. size too big, etc .. */ public final void reset(GL gl, int newWidth, int newHeight, int newSamples, boolean resetSamplingSink) { @@ -942,9 +945,9 @@ public class FBObject { init(gl, newWidth, newHeight, newSamples); return; } - + newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp - + if( newWidth != width || newHeight != height || newSamples != samples ) { if( 0 >= newWidth ) { newWidth = 1; } if( 0 >= newHeight ) { newHeight = 1; } @@ -952,39 +955,39 @@ public class FBObject { newWidth > maxRenderbufferSize || newHeight > maxRenderbufferSize ) { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } - + if(DEBUG) { System.err.println("FBObject.reset - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight+", "+newSamples+"; "+this); - } - + } + final boolean wasBound = isBound(); - + width = newWidth; height = newHeight; samples = newSamples; - + if(0 < samples && null == samplingSink ) { // needs valid samplingSink for detach*() -> bind() samplingSink = new FBObject(); samplingSink.init(gl, width, height, 0); } - detachAllImpl(gl, true , true); + detachAllImpl(gl, true , true); if(resetSamplingSink) { resetSamplingSink(gl); } - + samplingSinkDirty = true; if(!wasBound) { unbind(gl); } - + if(DEBUG) { System.err.println("FBObject.reset - END - "+this); } - } + } } - + /** * Writes the internal format of the attachments to the given GLCapabilities object. * @param caps the destination for format bits @@ -994,11 +997,11 @@ public class FBObject { caps.setNumSamples(samples); caps.setDepthBits(0); caps.setStencilBits(0); - + final Colorbuffer cb = samples > 0 ? getSamplingSink() : getColorbuffer(0); if(null != cb) { cb.formatToGLCapabilities(caps, rgba8Avail); - } + } if(null != depth) { depth.formatToGLCapabilities(caps, rgba8Avail); } @@ -1006,11 +1009,11 @@ public class FBObject { stencil.formatToGLCapabilities(caps, rgba8Avail); } } - - /** + + /** * Note that the status may reflect an incomplete state during transition of attachments. * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 - * @see #validateStatus() + * @see #validateStatus() */ public final int getStatus() { return vStatus; @@ -1020,15 +1023,15 @@ public class FBObject { public final String getStatusString() { return getStatusString(vStatus); } - + public static final String getStatusString(int fbStatus) { switch(fbStatus) { case -1: return "NOT A FBO"; - + case GL.GL_FRAMEBUFFER_COMPLETE: return "OK"; - + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return("FBO incomplete attachment\n"); case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: @@ -1043,21 +1046,21 @@ public class FBObject { return("FBO missing read buffer"); case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return("FBO missing multisample buffer"); - case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: return("FBO missing layer targets"); - + case GL.GL_FRAMEBUFFER_UNSUPPORTED: return("Unsupported FBO format"); case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: return("FBO undefined"); - + case 0: return("FBO implementation fault"); default: return("FBO incomplete, implementation ERROR "+toHexString(fbStatus)); } } - + /** * The status may even be valid if incomplete during transition of attachments. * @see #getStatus() @@ -1066,7 +1069,7 @@ public class FBObject { switch(vStatus) { case GL.GL_FRAMEBUFFER_COMPLETE: return true; - + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: @@ -1079,29 +1082,29 @@ public class FBObject { // we are in transition return true; } - + case GL.GL_FRAMEBUFFER_UNSUPPORTED: case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: - - case 0: + + case 0: default: if(DEBUG) { - System.err.println("Framebuffer " + fbName + " is incomplete, status = " + toHexString(vStatus) + + System.err.println("Framebuffer " + fbName + " is incomplete, status = " + toHexString(vStatus) + " : " + getStatusString(vStatus)); } return false; } } - + private static int checkPreGLError(GL gl) { int glerr = gl.glGetError(); if(DEBUG && GL.GL_NO_ERROR != glerr) { System.err.println("Pre-existing GL error: "+toHexString(glerr)); Thread.dumpStack(); } - return glerr; + return glerr; } - + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { if(GL.GL_NO_ERROR != err) { if(null != gl) { @@ -1118,17 +1121,17 @@ public class FBObject { private final void checkInitialized() throws GLException { if(!initialized) { throw new GLException("FBO not initialized, call init(GL) first."); - } + } } - + /** * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. - * + * * <p>Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.</p> - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl the current GL context * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>; @@ -1140,18 +1143,18 @@ public class FBObject { return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, createColorTextureAttachment(gl.getGLProfile(), alpha, width, height)); } - + /** * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl the current GL context * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>; * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown @@ -1162,19 +1165,19 @@ public class FBObject { return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT)); } - + /** * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point. - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl the current GL context * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown @@ -1187,10 +1190,10 @@ public class FBObject { return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT)); } - + /** * Creates a {@link ColorAttachment}, selecting the format automatically. - * + * * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>; * @return uninitialized ColorAttachment instance describing the new attached colorbuffer */ @@ -1203,13 +1206,13 @@ public class FBObject { } return new ColorAttachment(internalFormat, samples, width, height, 0); } - + /** * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point, * selecting the format automatically. - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl the current GL context * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>; @@ -1220,15 +1223,15 @@ public class FBObject { public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException { return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha)); } - + /** * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point. - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl the current GL context * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8} + * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8} * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the colorbuffer couldn't be allocated * @throws IllegalArgumentException if <code>internalFormat</code> doesn't reflect a colorbuffer @@ -1238,28 +1241,28 @@ public class FBObject { if( Attachment.Type.COLOR != atype ) { throw new IllegalArgumentException("colorformat invalid: "+toHexString(internalFormat)+", "+this); } - + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); } - + /** - * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}, + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}, * to this FBO's instance at the given attachment point. - * + * * <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/> * Otherwise, i.e. texture name is not <code>zero</code>, the passed TextureAttachment <code>texA</code> is - * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. + * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. * </p> - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param colbuf the to be attached {@link Colorbuffer} + * @param colbuf the to be attached {@link Colorbuffer} * @return newly attached {@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} + * @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(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException { bind(gl); @@ -1268,13 +1271,13 @@ public class FBObject { private final Colorbuffer attachColorbufferImpl(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException { validateAddColorAttachment(attachmentPoint, colbuf); - + final boolean initializedColorbuf = colbuf.initialize(gl); addColorAttachment(attachmentPoint, colbuf); - + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; - + if(samples>0) { removeColorAttachment(attachmentPoint, texA); if(initializedColorbuf) { @@ -1282,14 +1285,14 @@ public class FBObject { } throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); } - + // Set up the color buffer for use as a renderable texture: gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, GL.GL_TEXTURE_2D, texA.getName(), 0); - + if(!ignoreStatus) { - updateStatus(gl); + updateStatus(gl); if(!isStatusValid()) { detachColorbuffer(gl, attachmentPoint, true); throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); @@ -1297,12 +1300,12 @@ public class FBObject { } } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; - + // Attach the color buffer - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, GL.GL_RENDERBUFFER, colA.getName()); - + if(!ignoreStatus) { updateStatus(gl); if(!isStatusValid()) { @@ -1316,7 +1319,7 @@ public class FBObject { } return colbuf; } - + /** * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, * selecting the internalFormat automatically. @@ -1325,30 +1328,30 @@ public class FBObject { * </p> * <p> * In case the desired type or bit-number is not supported, the next available one is chosen. - * </p> + * </p> * <p> * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details * about the attached buffer. The details cannot be returned, since it's possible 2 buffers * are being created, depth and stencil. * </p> - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl - * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL} + * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL} * @param reqBits desired bits for depth or -1 for default (24 bits) * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. * @throws IllegalArgumentException * @see #getDepthAttachment() * @see #getStencilAttachment() */ - public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException { + public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException { if( 0 > reqBits ) { reqBits = 24; - } + } final int internalFormat; int internalStencilFormat = -1; - + switch ( atype ) { case DEPTH: if( 32 <= reqBits && depth32Avail ) { @@ -1356,10 +1359,10 @@ public class FBObject { } else if( 24 <= reqBits && depth24Avail ) { internalFormat = GL.GL_DEPTH_COMPONENT24; } else { - internalFormat = GL.GL_DEPTH_COMPONENT16; + internalFormat = GL.GL_DEPTH_COMPONENT16; } break; - + case STENCIL: if( 16 <= reqBits && stencil16Avail ) { internalFormat = GL2GL3.GL_STENCIL_INDEX16; @@ -1370,10 +1373,10 @@ public class FBObject { } else if( 1 <= reqBits && stencil01Avail ) { internalFormat = GL.GL_STENCIL_INDEX1; } else { - throw new GLException("stencil buffer n/a"); + throw new GLException("stencil buffer n/a"); } break; - + case DEPTH_STENCIL: if( packedDepthStencilAvail ) { internalFormat = GL.GL_DEPTH24_STENCIL8; @@ -1381,7 +1384,7 @@ public class FBObject { if( 24 <= reqBits && depth24Avail ) { internalFormat = GL.GL_DEPTH_COMPONENT24; } else { - internalFormat = GL.GL_DEPTH_COMPONENT16; + internalFormat = GL.GL_DEPTH_COMPONENT16; } if( stencil08Avail ) { internalStencilFormat = GL.GL_STENCIL_INDEX8; @@ -1397,17 +1400,17 @@ public class FBObject { default: throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); } - + attachRenderbufferImpl(gl, atype, internalFormat); - + if(0<=internalStencilFormat) { attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat); } } - + /** * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, - * depending on the <code>internalFormat</code>. + * depending on the <code>internalFormat</code>. * <p> * Stencil and depth buffer can be attached only once. * </p> @@ -1416,9 +1419,9 @@ public class FBObject { * about the attached buffer. The details cannot be returned, since it's possible 2 buffers * are being created, depth and stencil. * </p> - * + * * <p>Leaves the FBO bound.</p> - * + * * @param gl the current GL context * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32}, * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} @@ -1435,19 +1438,19 @@ public class FBObject { } attachRenderbufferImpl(gl, atype, internalFormat); } - + protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException { if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", "+toHexString(internalFormat)+", "+this); - } + } if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", "+toHexString(internalFormat)+", "+this); } bind(gl); - + attachRenderbufferImpl2(gl, atype, internalFormat); } - + private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException { if( Attachment.Type.DEPTH == atype ) { if(null == depth) { @@ -1486,10 +1489,10 @@ public class FBObject { } else if( Attachment.Type.STENCIL == atype ) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); } else if( Attachment.Type.DEPTH_STENCIL == atype ) { - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); } - + if(!ignoreStatus) { updateStatus(gl); if( !isStatusValid() ) { @@ -1500,13 +1503,13 @@ public class FBObject { if(DEBUG) { System.err.println("FBObject.attachRenderbuffer.X: [attachmentType "+atype+", iformat "+toHexString(internalFormat)+"]: "+this); - } + } } - + /** - * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}. + * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}. * <p>Leaves the FBO bound!</p> - * + * * @param gl * @param attachmentPoint * @param dispose true if the Colorbuffer shall be disposed @@ -1515,26 +1518,26 @@ public class FBObject { */ public final Colorbuffer detachColorbuffer(GL gl, int attachmentPoint, boolean dispose) throws IllegalArgumentException { bind(gl); - + final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE); if(null == res) { - throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); + throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); } if(DEBUG) { System.err.println("FBObject.detachColorbuffer.X: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this); } return res; } - + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, DetachAction detachAction) { Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here - + if(null == colbuf) { return null; } - + removeColorAttachment(attachmentPoint, colbuf); - + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; if( 0 != texA.getName() ) { @@ -1553,7 +1556,7 @@ public class FBObject { if(DetachAction.RECREATE == detachAction) { if(samples == 0) { // stay non MSAA - texA.setSize(width, height); + texA.setSize(width, height); } else { // switch to MSAA colbuf = createColorAttachment(hasAlpha(texA.format)); @@ -1563,8 +1566,8 @@ public class FBObject { } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; if( 0 != colA.getName() ) { - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0+attachmentPoint, + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0+attachmentPoint, GL.GL_RENDERBUFFER, 0); switch(detachAction) { case DISPOSE: @@ -1582,9 +1585,9 @@ public class FBObject { } else { // switch to non MSAA if(null != samplingSinkTexture) { - colbuf = createColorTextureAttachment(samplingSinkTexture.format, width, height, - samplingSinkTexture.dataFormat, samplingSinkTexture.dataType, - samplingSinkTexture.magFilter, samplingSinkTexture.minFilter, + colbuf = createColorTextureAttachment(samplingSinkTexture.format, width, height, + samplingSinkTexture.dataFormat, samplingSinkTexture.dataType, + samplingSinkTexture.magFilter, samplingSinkTexture.minFilter, samplingSinkTexture.wrapS, samplingSinkTexture.wrapT); } else { colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height); @@ -1595,15 +1598,15 @@ public class FBObject { } return colbuf; } - + private final void freeAllColorbufferImpl(GL gl) { for(int i=0; i<maxColorAttachments; i++) { final Colorbuffer colbuf = colorAttachmentPoints[i]; // shortcut, don't validate here - + if(null == colbuf) { return; } - + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; if( 0 != texA.getName() ) { @@ -1616,29 +1619,29 @@ public class FBObject { } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; if( 0 != colA.getName() ) { - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + i, + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + i, GL.GL_RENDERBUFFER, 0); } colA.free(gl); } } } - + /** - * + * * @param gl * @param dispose true if the Colorbuffer shall be disposed - * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} + * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} */ public final void detachRenderbuffer(GL gl, Attachment.Type atype, boolean dispose) throws IllegalArgumentException { - bind(gl); + bind(gl); detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE); if(DEBUG) { System.err.println("FBObject.detachRenderbuffer.X: [attachmentType "+atype+", dispose "+dispose+"]: "+this); - } + } } - + public final boolean isDepthStencilPackedFormat() { final boolean res = null != depth && null != stencil && depth.format == stencil.format ; @@ -1652,19 +1655,19 @@ public class FBObject { } return res; } - + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, DetachAction detachAction) throws IllegalArgumentException { switch ( atype ) { case DEPTH: case STENCIL: - case DEPTH_STENCIL: + case DEPTH_STENCIL: break; default: throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); - } + } if( null == depth && null == stencil ) { return ; // nop - } + } final boolean packed = isDepthStencilPackedFormat(); if( packed ) { // Note: DEPTH_STENCIL shares buffer w/ depth and stencil @@ -1734,7 +1737,7 @@ public class FBObject { if(packed) { stencil = null; } - } + } } if( !packed && null != stencil ) { final int format = stencil.format; @@ -1756,17 +1759,17 @@ public class FBObject { } break; default: // handled - } + } } - + private final void freeAllRenderbufferImpl(GL gl) throws IllegalArgumentException { // Note: DEPTH_STENCIL shares buffer w/ depth and stencil final boolean packed = isDepthStencilPackedFormat(); - if( null != depth ) { + if( null != depth ) { if(0 != depth.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); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } depth.free(gl); } @@ -1774,49 +1777,49 @@ public class FBObject { if( !packed && null != stencil ) { if(0 != stencil.getName()) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); - stencil.free(gl); + stencil.free(gl); } } } - - /** + + /** * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s * and disposes them. * <p>Leaves the FBO bound, if initialized!</p> * <p> * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. - * </p> + * </p> * @param gl the current GL context */ public final void detachAll(GL gl) { if(null != samplingSink) { samplingSink.detachAll(gl); - } + } detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */); } - - /** - * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s + + /** + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s * and disposes them. * <p>Leaves the FBO bound, if initialized!</p> * <p> * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. - * </p> + * </p> * @param gl the current GL context */ public final void detachAllColorbuffer(GL gl) { if(null != samplingSink) { samplingSink.detachAllColorbuffer(gl); - } + } detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */); } - - /** + + /** * Detaches all {@link TextureAttachment}s and disposes them. * <p>Leaves the FBO bound, if initialized!</p> * <p> * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. - * </p> + * </p> * @param gl the current GL context */ public final void detachAllTexturebuffer(GL gl) { @@ -1826,7 +1829,7 @@ public class FBObject { if(null != samplingSink) { samplingSink.detachAllTexturebuffer(gl); } - bind(gl); + bind(gl); for(int i=0; i<maxColorAttachments; i++) { if(colorAttachmentPoints[i] instanceof TextureAttachment) { detachColorbufferImpl(gl, i, DetachAction.DISPOSE); @@ -1836,7 +1839,7 @@ public class FBObject { System.err.println("FBObject.detachAllTexturebuffer.X: "+this); } } - + public final void detachAllRenderbuffer(GL gl) { if( !isInitialized() ) { return; @@ -1844,10 +1847,10 @@ public class FBObject { if(null != samplingSink) { samplingSink.detachAllRenderbuffer(gl); } - bind(gl); + bind(gl); detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, DetachAction.DISPOSE); } - + private final void detachAllImpl(GL gl, boolean detachNonColorbuffer, boolean recreate) { if( !isInitialized() ) { return; @@ -1868,7 +1871,7 @@ public class FBObject { if( !recreate && colorAttachmentCount>0 ) { throw new InternalError("Non zero ColorAttachments "+this); } - + if(detachNonColorbuffer) { detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate ? DetachAction.RECREATE : DetachAction.DISPOSE); } @@ -1888,7 +1891,7 @@ public class FBObject { System.err.println("FBObject.detachAll.X: [resetNonColorbuffer "+detachNonColorbuffer+", recreate "+recreate+"]: "+this); } } - + /** * @param gl the current GL context */ @@ -1903,9 +1906,9 @@ public class FBObject { if( null != samplingSink && samplingSink.isInitialized() ) { samplingSink.destroy(gl); } - + detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */); - + // cache FB names, preset exposed to zero, // braking ties w/ GL/GLContext link to getReadFramebuffer()/getWriteFramebuffer() final int fb_cache = fbName; @@ -1915,7 +1918,7 @@ public class FBObject { if(0!=fb_cache) { name[0] = fb_cache; gl.glDeleteFramebuffers(1, name, 0); - } + } initialized = false; bound = false; if(DEBUG) { @@ -1933,14 +1936,14 @@ public class FBObject { final boolean depthMismatch = ( null != depth && null == samplingSink.depth ) || ( null != depth && null != samplingSink.depth && depth.format != samplingSink.depth.format ); - + final boolean stencilMismatch = ( null != stencil && null == samplingSink.stencil ) || ( null != stencil && null != samplingSink.stencil && - stencil.format != samplingSink.stencil.format ); - - return depthMismatch || stencilMismatch; + stencil.format != samplingSink.stencil.format ); + + return depthMismatch || stencilMismatch; } - + /** * Manually reset the MSAA sampling sink, if used. * <p> @@ -1948,7 +1951,7 @@ public class FBObject { * a new sampling sink is being created. * </p> * <p> - * Automatically called by {@link #reset(GL, int, int, int, boolean)} + * Automatically called by {@link #reset(GL, int, int, int, boolean)} * and {@link #syncSamplingSink(GL)}. * </p> * <p> @@ -1967,58 +1970,58 @@ public class FBObject { } return; } - + if(null == samplingSink ) { samplingSink = new FBObject(); } - + if(!samplingSink.initialized) { samplingSink.init(gl, width, height, 0); } - + boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch(); boolean sampleSinkTexMismatch = sampleSinkTexMismatch(); boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); - + /** if(DEBUG) { System.err.println("FBObject.resetSamplingSink.0: \n\tTHIS "+this+",\n\tSINK "+samplesSink+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } */ - + if(!sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) { - // all properties match .. - return; + // all properties match .. + return; } - + unbind(gl); - + if(DEBUG) { System.err.println("FBObject.resetSamplingSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplingSink+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } - + if( sampleSinkDepthStencilMismatch ) { samplingSink.detachAllRenderbuffer(gl); } - + if( sampleSinkSizeMismatch ) { samplingSink.reset(gl, width, height); } - + if(null == samplingSinkTexture) { samplingSinkTexture = samplingSink.attachTexture2D(gl, 0, true); } else if( 0 == samplingSinkTexture.getName() ) { samplingSinkTexture.setSize(width, height); samplingSink.attachColorbuffer(gl, 0, samplingSinkTexture); } - + if( sampleSinkDepthStencilMismatch ) { samplingSink.attachRenderbuffer(gl, depth.format); if( null != stencil && !isDepthStencilPackedFormat() ) { samplingSink.attachRenderbuffer(gl, stencil.format); } - } - + } + sampleSinkSizeMismatch = sampleSinkSizeMismatch(); sampleSinkTexMismatch = sampleSinkTexMismatch(); sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); @@ -2026,21 +2029,21 @@ public class FBObject { throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplingSink+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } - + if(DEBUG) { System.err.println("FBObject.resetSamplingSink: END\n\tTHIS "+this+",\n\tSINK "+samplingSink+ "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); } } - + /** * Setting this FBO sampling sink. * @param newSamplingSink the new FBO sampling sink to use, or null to remove current sampling sink - * @return the previous sampling sink or null if none was attached + * @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 */ public FBObject setSamplingSink(FBObject newSamplingSink) throws GLException { - final FBObject prev = samplingSink; + final FBObject prev = samplingSink; if( null == newSamplingSink) { samplingSink = null; samplingSinkTexture = null; @@ -2056,14 +2059,14 @@ public class FBObject { samplingSinkDirty = true; return prev; } - - /** + + /** * Bind this FBO, i.e. bind write framebuffer to {@link #getWriteFramebuffer()}. - * - * <p>If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}, + * + * <p>If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}, * if full FBO is supported.</p> - * - * <p> + * + * <p> * In case you have attached more than one color buffer, * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}. * </p> @@ -2079,7 +2082,7 @@ public class FBObject { gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer()); } else { // one for all - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); } bound = true; @@ -2087,29 +2090,29 @@ public class FBObject { } } - /** + /** * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}. - * - * <p>If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing + * + * <p>If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}</p> - * + * * @param gl the current GL context * @throws GLException */ public final void unbind(GL gl) throws GLException { if(bound) { if(fullFBOSupport) { - // default read/draw buffers, may utilize GLContext/GLDrawable override of + // default read/draw buffers, may utilize GLContext/GLDrawable override of // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); } else { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer } bound = false; } } - + /** * Method simply marks this FBO unbound w/o interfering w/ the bound framebuffer as perfomed by {@link #unbind(GL)}. * <p> @@ -2121,22 +2124,22 @@ public class FBObject { bound = false; } - /** + /** * Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>. * <p> * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}. * </p> * @param gl the current GL context */ - public final boolean isBound(GL gl) { + public final boolean isBound(GL gl) { bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ; return bound; } - + /** Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>. */ public final boolean isBound() { return bound; } - - /** + + /** * If multisampling is being used and flagged dirty by a previous call of {@link #bind(GL)} or after initialization, * the msaa-buffers are sampled to it's sink {@link #getSamplingSink()}. * <p> @@ -2147,7 +2150,7 @@ public class FBObject { * </p> * <p> * Method always resets the framebuffer binding to default in the end. - * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()} * </p> * <p> @@ -2155,10 +2158,10 @@ public class FBObject { * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); * </p> * <p>Leaves the FBO unbound.</p> - * + * * @param gl the current GL context * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} - * @throws IllegalArgumentException + * @throws IllegalArgumentException */ public final void syncSamplingSink(GL gl) { markUnbound(); @@ -2170,30 +2173,30 @@ public class FBObject { gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplingSink.getWriteFramebuffer()); ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2GL3 is OK GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST); - checkNoError(null, gl.glGetError(), "FBObject syncSampleSink"); // throws GLException if error + checkNoError(null, gl.glGetError(), "FBObject syncSampleSink"); // throws GLException if error } if(fullFBOSupport) { - // default read/draw buffers, may utilize GLContext/GLDrawable override of + // default read/draw buffers, may utilize GLContext/GLDrawable override of // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); } else { - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer } } - - /** + + /** * Bind the given texture colorbuffer. - * + * * <p>If using multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first!</p> - * + * * <p>{@link #syncSamplingSink(GL)} is being called</p> - * + * * <p>Leaves the FBO unbound!</p> - * + * * @param gl the current GL context * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} - * @throws IllegalArgumentException + * @throws IllegalArgumentException */ public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { if(null == ta) { throw new IllegalArgumentException("Null TextureAttachment, this: "+toString()); } @@ -2201,26 +2204,26 @@ public class FBObject { gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. } - /** + /** * Unbind texture, ie bind 'non' texture 0 - * + * * <p>Leaves the FBO unbound.</p> - */ + */ public final void unuse(GL gl) { unbind(gl); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it } - /** @see GL#hasFullFBOSupport() */ + /** @see GL#hasFullFBOSupport() */ public final boolean hasFullFBOSupport() throws GLException { checkInitialized(); return this.fullFBOSupport; } - - /** + + /** * Returns <code>true</code> if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise <code>false</code>. * @throws GLException if {@link #init(GL)} hasn't been called. */ public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; } - - /** + + /** * Returns <code>true</code> if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise <code>false</code>. * @param bits 16, 24 or 32 bits * @throws GLException if {@link #init(GL)} hasn't been called. @@ -2228,14 +2231,14 @@ public class FBObject { public final boolean supportsDepth(int bits) throws GLException { checkInitialized(); switch(bits) { - case 16: return true; + case 16: return true; case 24: return depth24Avail; case 32: return depth32Avail; - default: return false; + default: return false; } } - - /** + + /** * Returns <code>true</code> if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise <code>false</code>. * @param bits 1, 4, 8 or 16 bits * @throws GLException if {@link #init(GL)} hasn't been called. @@ -2243,34 +2246,34 @@ public class FBObject { public final boolean supportsStencil(int bits) throws GLException { checkInitialized(); switch(bits) { - case 1: return stencil01Avail; + case 1: return stencil01Avail; case 4: return stencil04Avail; case 8: return stencil08Avail; case 16: return stencil16Avail; - default: return false; + default: return false; } } - - /** + + /** * Returns <code>true</code> if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise <code>false</code>. * @throws GLException if {@link #init(GL)} hasn't been called. */ public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; } - + /** * Returns the maximum number of colorbuffer attachments. * @throws GLException if {@link #init(GL)} hasn't been called. */ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; } - + public final int getMaxTextureSize() throws GLException { checkInitialized(); return this.maxTextureSize; } public final int getMaxRenderbufferSize() throws GLException { checkInitialized(); return this.maxRenderbufferSize; } - + /** @see GL#getMaxRenderbufferSamples() */ public final int getMaxSamples() throws GLException { checkInitialized(); return this.maxSamples; } - + /** - * Returns <code>true</code> if this instance has been initialized with {@link #reset(GL, int, int)} + * Returns <code>true</code> if this instance has been initialized with {@link #reset(GL, int, int)} * or {@link #reset(GL, int, int, int, boolean)}, otherwise <code>false</code> */ public final boolean isInitialized() { return initialized; } @@ -2283,43 +2286,44 @@ 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 getDefaultReadBuffer() { return GL.GL_COLOR_ATTACHMENT0; } + public final int getReadFramebuffer() { return ( samples > 0 ) ? samplingSink.getReadFramebuffer() : fbName; } + public final int getDefaultReadBuffer() { return GL.GL_COLOR_ATTACHMENT0; } /** Return the number of color/texture attachments */ public final int getColorAttachmentCount() { return colorAttachmentCount; } - /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */ + /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */ public final RenderAttachment getStencilAttachment() { return stencil; } - /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */ + /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */ public final RenderAttachment getDepthAttachment() { return depth; } - - /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */ + + /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */ public final FBObject getSamplingSinkFBO() { return samplingSink; } - - /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */ + + /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */ public final TextureAttachment getSamplingSink() { return samplingSinkTexture; } - /** - * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer) + /** + * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer) * has been flagged dirty by a previous call of {@link #bind(GL)}, * otherwise <code>false</code>. */ public final boolean isSamplingBufferDirty() { return samplingSinkDirty; } - + int objectHashCode() { return super.hashCode(); } - + + @Override public final String toString() { - final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ; + final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ; return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+ ", samples "+samples+"/"+maxSamples+", depth "+depth+", stencil "+stencil+ ", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+ ": "+caps+", msaa-sink "+samplingSinkTexture+", hasSamplesSink "+(null != samplingSink)+ ", state "+getStatusString()+", obj "+toHexString(objectHashCode())+"]"; } - + private final void updateStatus(GL gl) { if( 0 == fbName ) { vStatus = -1; } else { vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); } - } + } } |