From b44288b26e8ac6de0593db349725c2a288bb520a Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 5 Apr 2011 01:05:19 +0200 Subject: Make FBObject more generic, split FBO/tex and depth/stencil attachements. Allow parametrization of each component. --- .../classes/com/jogamp/opengl/util/FBObject.java | 241 +++++++++++++++------ 1 file changed, 174 insertions(+), 67 deletions(-) diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java index 4920ed5f5..ad32b4ffe 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java @@ -36,22 +36,24 @@ package com.jogamp.opengl.util; import javax.media.opengl.*; public class FBObject { - private int width, height, attr; + private int width, height; private int fb, fbo_tex, depth_rb, stencil_rb, vStatus; private int texInternalFormat, texDataFormat, texDataType; public static final int ATTR_DEPTH = 1 << 0; public static final int ATTR_STENCIL = 1 << 1; - - public FBObject(int width, int height, int attributes) { + + public FBObject(int width, int height) { this.width = width; this.height = height; - this.attr = attributes; + this.fb = 0; + this.fbo_tex = 0; + this.depth_rb = 0; + this.stencil_rb = 0; } - public boolean validateStatus(GL gl) { - vStatus = getStatus(gl, fb); + /* vStatus = */ getStatus(gl); switch(vStatus) { case GL.GL_FRAMEBUFFER_COMPLETE: return true; @@ -65,22 +67,30 @@ public class FBObject { //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT: case 0: default: + System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + + " : " + getStatusString(vStatus)); return false; } } + + /** @return {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 */ + public int getStatus() { + return vStatus; + } - public static int getStatus(GL gl, int fb) { + public int getStatus(GL gl) { if(!gl.glIsFramebuffer(fb)) { - return -1; + vStatus = -1; + } else { + vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); } - return gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER); - //return gl.glCheckFramebufferStatus(fb); + return vStatus; } public String getStatusString() { return getStatusString(vStatus); } - + public static String getStatusString(int fbStatus) { switch(fbStatus) { case -1: @@ -111,8 +121,21 @@ public class FBObject { return("GL FBO: incomplete, implementation ERROR"); } } - - public void init(GL gl) { + + /** + * Initializes this FBO's instance with it's texture, + * selecting the texture data type and format automatically. + * + * Leaves the FBO bound! + * + * @param gl the current GL context + * @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 wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return + */ + public boolean init(GL gl, int magFilter, int minFilter, int wrapS, int wrapT) { int textureInternalFormat, textureDataFormat, textureDataType; if(gl.isGL2()) { @@ -128,10 +151,31 @@ public class FBObject { textureDataFormat=GL.GL_RGB; textureDataType=GL.GL_UNSIGNED_BYTE; } - init(gl, textureInternalFormat, textureDataFormat, textureDataType); + return init(gl, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); } - public void init(GL gl, int textureInternalFormat, int textureDataFormat, int textureDataType) { + /** + * Initializes this FBO's instance with it's texture. + * + * Leaves the FBO bound! + * + * @param gl the current GL context + * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param textureDataType 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 wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return true if successful otherwise false + */ + public boolean init(GL gl, int textureInternalFormat, int textureDataFormat, int textureDataType, + int magFilter, int minFilter, int wrapS, int wrapT) { + checkBound(false); + if(0=fb || 0>=fbo_tex) { + throw new GLException("FBO not initialized (fb "+fb+", tex "+fbo_tex+")"); } - - // Check the FBO for completeness - if(validateStatus(gl)) { - System.out.println("Framebuffer " + fb + " is complete"); - } else { - System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + - " : " + getStatusString()); + if(depth_rb != 0) { + throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")"); } - - unbind(gl); + checkBound(true); + int name[] = new int[1]; + gl.glGenRenderbuffers(1, name, 0); + depth_rb = name[0]; + + if(depth_rb==0) { + throw new GLException("null generated renderbuffer"); + } + // Initialize the depth buffer: + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb); + if(!gl.glIsRenderbuffer(depth_rb)) { + System.err.println("not a depthbuffer: "+ depth_rb); + name[0] = depth_rb; + gl.glDeleteRenderbuffers(1, name, 0); + depth_rb=0; + return false; + } + + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height); + // Set up the depth buffer attachment: + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_DEPTH_ATTACHMENT, + GL.GL_RENDERBUFFER, depth_rb); + return validateStatus(gl); + } + + /** + * Assumes a bound FBO + * Leaves the FBO bound! + * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8} + * @return true if successful otherwise false + */ + public boolean attachStencilBuffer(GL gl, int stencilComponentType) { + if(0>=fb || 0>=fbo_tex) { + throw new GLException("FBO not initialized (fb "+fb+", tex "+fbo_tex+")"); + } + if(stencil_rb != 0) { + throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")"); + } + checkBound(true); + int name[] = new int[1]; + gl.glGenRenderbuffers(1, name, 0); + gl.glGenRenderbuffers(1, name, 0); + stencil_rb = name[0]; + if(stencil_rb==0) { + throw new GLException("null generated stencilbuffer"); + } + // Initialize the stencil buffer: + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb); + if(!gl.glIsRenderbuffer(stencil_rb)) { + destroy(gl); + System.err.println("not a stencilbuffer: "+ depth_rb); + return false; + } + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_STENCIL_ATTACHMENT, + GL.GL_RENDERBUFFER, stencil_rb); + return validateStatus(gl); } public void destroy(GL gl) { - unbind(gl); + if(bound) { + unbind(gl); + } int name[] = new int[1]; @@ -238,19 +331,33 @@ public class FBObject { } } + boolean bound = false; + + private final void checkBound(boolean shallBeBound) { + if(bound != shallBeBound) { + final String s0 = shallBeBound ? "not" : "already" ; + throw new GLException("FBO "+s0+" bound "+toString()); + } + } + public void bind(GL gl) { + checkBound(false); gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); + bound = true; } public void unbind(GL gl) { + checkBound(true); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); + bound = false; } public void use(GL gl) { - gl.glBindTexture(GL.GL_TEXTURE_2D, 0); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); + if(bound) { + unbind(gl); + } gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex); // to use it .. } -- cgit v1.2.3