diff options
author | Sven Gothel <[email protected]> | 2012-10-10 16:36:46 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-10-10 16:36:46 +0200 |
commit | 34d7e1f13a107e63bd234e4b31782cfb46feb4c0 (patch) | |
tree | 43e454156a098b1d17ac9717b115dd12227b8d9d /src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java | |
parent | 13402255253dcfc64aa773f0756201ec805ec063 (diff) |
ImmModeSink: Fix bugs (use glBufferUsage, vboUsage, GL_POLYGON, GL_QUADS) and add API docs. (API Change)
- Changed create*(..) factory methods (API Change)
- Drop passing GL instance, not needed
- allows creation of ImmModeSink as final field w/o GL context
- Use 'glBufferUsage' to determine whether to use VBO or not ( 0 == glBufferUsage )
- Use glBufferUsage in glBufferData(..) call (oops)
- Toggle vboUsage per object ( 0 == glBufferUsage ? nonVBO : VBO )
remove static VBO usage flag
- Fix render mode
- GL_POLYGON -> GL_TRIANGLE_FAN (not GL_LINES)
- GL_QUADS -> Looped GL_TRIANGLE_FAN (is !GL2) in draw(..) w/ and w/o indices
- Buffer usage
- documented
- allow creating sink w/ all components (vertices, color, normal and texCoords)
bit render and grow only used parts.
This allows proper usage of sink where it is not known
which types are being used.
- Added test case
- Manually tested w/ Jake2 ES1
Jake2 uses the FFP immediate mode rendering, where we utilize this sink
w/o rendering artifacts.
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java | 641 |
1 files changed, 408 insertions, 233 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java index cf0373044..238e402d1 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -13,52 +13,107 @@ import javax.media.opengl.GL2ES2; import javax.media.opengl.GLException; import javax.media.opengl.fixedfunc.GLPointerFunc; -import com.jogamp.common.util.ReflectionUtil; import com.jogamp.opengl.util.glsl.ShaderState; +/** + * <p> + * Immediate mode sink, implementing OpenGL fixed function subset of immediate mode operations, i.e. + * <pre> + * glBegin(); + * glVertex3f(1f, 1f, 1f); + * glColor4f(1f, 1f, 1f, 1f); + * ... + * glEnd(); + * </pre> + * Implementation buffers all vertex, colors, normal and texture-coord elements in their respective buffers + * to be either rendered directly via {@link #glEnd(GL)} or to be added to an internal display list + * via {@link #glEnd(GL, boolean) glEnd(gl, false)} for deferred rendering via {@link #draw(GL, boolean)}. + * </p> + * <a name="storageDetails"><h5>Buffer storage and it's creation via {@link #createFixed(int, int, int, int, int, int, int, int, int, int) createFixed(..)} + * and {@link #createGLSL(int, int, int, int, int, int, int, int, int, int) createGLSL(..)}</h5></a> + * <p> + * If unsure whether <i>colors</i>, <i>normals</i> and <i>textures</i> will be used, + * simply add them with an expected component count. + * This implementation will only render buffers which are being filled.<br/> + * The buffer growing implementation will only grow the exceeded buffers, unused buffers are not resized. + * </p> + * <p> + * Note: Optional types, i.e. color, must be either not used or used w/ the same element count as vertex, etc. + * This is a semantic constraint, same as in the original OpenGL spec. + * </p> + */ public class ImmModeSink { public static final boolean DEBUG_BEGIN_END = false; public static final boolean DEBUG_DRAW = false; + public static final boolean DEBUG_BUFFER = false; - // public static final int GL_QUADS = 0x0007; // Needs data manipulation + public static final int GL_QUADS = 0x0007; // Needs data manipulation on ES1/ES2 public static final int GL_QUAD_STRIP = 0x0008; public static final int GL_POLYGON = 0x0009; /** * Uses a GL2ES1, or ES2 fixed function emulation immediate mode sink + * <p> + * See <a href="#storageDetails"> buffer storage details</a>. + * </p> + * + * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size. + * @param vComps mandatory vertex component count, should be 2, 3 or 4. + * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT} + * @param cComps optional color component count, may be 0, 3 or 4 + * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT} + * @param nComps optional normal component count, may be 0, 3 or 4 + * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT} + * @param tComps optional texture-coordinate component count, may be 0, 2 or 3 + * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT} + * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW}, + * set to <code>0</code> for no VBO usage */ - public static ImmModeSink createFixed(GL gl, int glBufferUsage, int initialElementCount, + public static ImmModeSink createFixed(int initialElementCount, int vComps, int vDataType, - int cComps, int cDataType, + int cComps, int cDataType, int nComps, int nDataType, - int tComps, int tDataType) { - return new ImmModeSink(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false); + int tComps, int tDataType, + int glBufferUsage) { + return new ImmModeSink(initialElementCount, vComps, + vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false, glBufferUsage); } /** * Uses a GL2ES2 GLSL shader immediate mode sink. * To issue the draw() command, * a ShaderState must be current, using ShaderState.glUseProgram(). - * + * <p> + * See <a href="#storageDetails"> buffer storage details</a>. + * </p> + * + * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size. + * @param vComps mandatory vertex component count, should be 2, 3 or 4. + * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT} + * @param cComps optional color component count, may be 0, 3 or 4 + * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT} + * @param nComps optional normal component count, may be 0, 3 or 4 + * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT} + * @param tComps optional texture-coordinate component count, may be 0, 2 or 3 + * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT} + * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW}, + * set to <code>0</code> for no VBO usage + * * @see #draw(GL, boolean) * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() */ - public static ImmModeSink createGLSL(GL gl, int glBufferUsage, int initialElementCount, + public static ImmModeSink createGLSL(int initialElementCount, int vComps, int vDataType, - int cComps, int cDataType, + int cComps, int cDataType, int nComps, int nDataType, - int tComps, int tDataType) { - return new ImmModeSink(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true); + int tComps, int tDataType, + int glBufferUsage) { + return new ImmModeSink(initialElementCount, vComps, + vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true, glBufferUsage); } - public static boolean usesVBO() { return vboUsage; } - - public static void setVBOUsage(boolean v) { vboUsage = v; } - public void destroy(GL gl) { destroyList(gl); @@ -93,42 +148,35 @@ public class ImmModeSink { public void draw(GL gl, boolean disableBufferAfterDraw) { if(DEBUG_DRAW) { - Exception e = new Exception("Info: ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); - e.printStackTrace(); + System.err.println("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); } int n=0; - for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; n++) { - i.next().draw(gl, null, disableBufferAfterDraw, n); + for(int i=0; i<vboSetList.size(); i++, n++) { + vboSetList.get(i).draw(gl, null, disableBufferAfterDraw, n); } } public void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw) { if(DEBUG_DRAW) { - Exception e = new Exception("Info: ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); - e.printStackTrace(); + System.err.println("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); } int n=0; - for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; n++) { - i.next().draw(gl, indices, disableBufferAfterDraw, n); + for(int i=0; i<vboSetList.size(); i++, n++) { + vboSetList.get(i).draw(gl, indices, disableBufferAfterDraw, n); } } public void glBegin(int mode) { if(DEBUG_BEGIN_END) { - Exception e = new Exception("Info: ImmModeSink.glBegin("+vboSet.mode+"):\n\t"+this); - e.printStackTrace(); + System.err.println("ImmModeSink.glBegin("+vboSet.mode+"):\n\t"+this); } vboSet.modeOrig = mode; switch(mode) { - // Needs data manipulation .. - //case GL_QUADS: - // mode=GL.GL_LINES; - // break; case GL_QUAD_STRIP: mode=GL.GL_TRIANGLE_STRIP; break; case GL_POLYGON: - mode=GL.GL_LINES; + mode=GL.GL_TRIANGLE_FAN; break; } vboSet.mode = mode; @@ -149,8 +197,7 @@ public class ImmModeSink { private void glEnd(GL gl, Buffer indices, boolean immediateDraw) { if(DEBUG_BEGIN_END) { - Exception e = new Exception("Info: ImmModeSink START glEnd(immediate: "+immediateDraw+"):\n\t"+this); - e.printStackTrace(); + System.err.println("ImmModeSink START glEnd(immediate: "+immediateDraw+"):\n\t"+this); } if(immediateDraw) { vboSet.seal(gl, true); @@ -160,7 +207,10 @@ public class ImmModeSink { vboSet.seal(gl, true); vboSet.enableBuffer(gl, false); vboSetList.add(vboSet); - vboSet = vboSet.regenerate(); + vboSet = vboSet.regenerate(gl); + } + if(DEBUG_BEGIN_END) { + System.err.println("ImmModeSink END glEnd(immediate: "+immediateDraw+"):\n\t"+this); } } @@ -261,37 +311,34 @@ public class ImmModeSink { vboSet.glTexCoord3b(x,y,z); } - protected ImmModeSink(GL gl, int glBufferUsage, int initialElementCount, - int vComps, int vDataType, - int cComps, int cDataType, - int nComps, int nDataType, - int tComps, int tDataType, boolean useGLSL) { - if(useGLSL && !gl.hasGLSL()) { - throw new GLException("ImmModeSink GLSL usage not supported: "+gl); - } - vboSet = new VBOSet(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); + protected ImmModeSink(int initialElementCount, int vComps, + int vDataType, int cComps, + int cDataType, int nComps, + int nDataType, int tComps, + int tDataType, boolean useGLSL, int glBufferUsage) { + vboSet = new VBOSet(initialElementCount, vComps, + vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL, glBufferUsage); this.vboSetList = new ArrayList<VBOSet>(); } - + + public boolean getUseVBO() { return vboSet.getUseVBO(); } + private void destroyList(GL gl) { - for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; ) { - i.next().destroy(gl); + for(int i=0; i<vboSetList.size(); i++) { + vboSetList.get(i).destroy(gl); } vboSetList.clear(); } private VBOSet vboSet; - private ArrayList<VBOSet> vboSetList; - private static boolean vboUsage = true; + private final ArrayList<VBOSet> vboSetList; protected static class VBOSet { - protected VBOSet (GL gl, int glBufferUsage, int initialElementCount, - int vComps, int vDataType, - int cComps, int cDataType, - int nComps, int nDataType, - int tComps, int tDataType, boolean useGLSL) { - this.gl=gl; + protected VBOSet (int initialElementCount, int vComps, + int vDataType, int cComps, + int cDataType, int nComps, + int nDataType, int tComps, + int tDataType, boolean useGLSL, int glBufferUsage) { this.glBufferUsage=glBufferUsage; this.initialElementCount=initialElementCount; this.vDataType=vDataType; @@ -303,8 +350,19 @@ public class ImmModeSink { this.tDataType=tDataType; this.tComps=tComps; this.useGLSL=useGLSL; - - allocateBuffer(initialElementCount); + this.useVBO = 0 != glBufferUsage; + this.vboName = 0; + + this.vCount=0; + this.cCount=0; + this.nCount=0; + this.tCount=0; + this.vElems=0; + this.cElems=0; + this.nElems=0; + this.tElems=0; + + reallocateBuffer(initialElementCount); rewind(); this.sealed=false; @@ -315,9 +373,11 @@ public class ImmModeSink { this.bufferWritten=false; } - protected final VBOSet regenerate() { - return new VBOSet(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); + protected boolean getUseVBO() { return useVBO; } + + protected final VBOSet regenerate(GL gl) { + return new VBOSet(initialElementCount, vComps, + vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL, glBufferUsage); } protected void checkSeal(boolean test) throws GLException { @@ -336,33 +396,55 @@ public class ImmModeSink { protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i) { if(DEBUG_DRAW) { - Exception e = new Exception("Info: ImmModeSink.draw["+i+"](disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); - e.printStackTrace(); + System.err.println("ImmModeSink.draw["+i+"].0 (disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); } enableBuffer(gl, true); if (buffer!=null) { if(null==indices) { - gl.glDrawArrays(mode, 0, count); + if ( GL_QUADS == mode && !gl.isGL2() ) { + for (int j = 0; j < vElems - 3; j += 4) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, j, 4); + } + } else { + gl.glDrawArrays(mode, 0, vElems); + } } else { - Class<?> clazz = indices.getClass(); int type=-1; - if(ReflectionUtil.instanceOf(clazz, ByteBuffer.class.getName())) { + if(indices instanceof ByteBuffer) { type = GL.GL_UNSIGNED_BYTE; - } else if(ReflectionUtil.instanceOf(clazz, ShortBuffer.class.getName())) { + } else if(indices instanceof ShortBuffer) { type = GL.GL_UNSIGNED_SHORT; + } else { + throw new GLException("Given Buffer Class not supported: "+indices.getClass()+", should be ubyte or ushort:\n\t"+this); } - if(0>type) { - throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this); + + if ( GL_QUADS == mode && !gl.isGL2() ) { + if( GL.GL_UNSIGNED_BYTE == type ) { + final ByteBuffer b = (ByteBuffer) indices; + for (int j = 0; j < b.remaining(); j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0x000000ff & b.get(j)), 4); + } + } else { + final ShortBuffer b = (ShortBuffer) indices; + for (int j = 0; j < b.remaining(); j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0x0000ffff & b.get(j)), 4); + } + } + } else { + gl.glDrawElements(mode, indices.remaining(), type, indices); + // GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices); } - gl.glDrawElements(mode, indices.remaining(), type, indices); - // GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices); } } if(disableBufferAfterDraw) { enableBuffer(gl, false); } + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.draw["+i+"].X (disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); + } } public void glVertexv(Buffer v) { @@ -384,7 +466,7 @@ public class ImmModeSink { public void glVertex2b(byte x, byte y) { checkSeal(false); - growBufferIfNecessary(VERTEX, 2); + growBuffer(VERTEX, 2); if(vComps>0) GLBuffers.putb(vertexArray, x); if(vComps>1) @@ -393,7 +475,7 @@ public class ImmModeSink { } public void glVertex3b(byte x, byte y, byte z) { checkSeal(false); - growBufferIfNecessary(VERTEX, 3); + growBuffer(VERTEX, 3); if(vComps>0) GLBuffers.putb(vertexArray, x); if(vComps>1) @@ -404,7 +486,7 @@ public class ImmModeSink { } public void glVertex2s(short x, short y) { checkSeal(false); - growBufferIfNecessary(VERTEX, 2); + growBuffer(VERTEX, 2); if(vComps>0) GLBuffers.puts(vertexArray, x); if(vComps>1) @@ -413,7 +495,7 @@ public class ImmModeSink { } public void glVertex3s(short x, short y, short z) { checkSeal(false); - growBufferIfNecessary(VERTEX, 3); + growBuffer(VERTEX, 3); if(vComps>0) GLBuffers.puts(vertexArray, x); if(vComps>1) @@ -424,7 +506,7 @@ public class ImmModeSink { } public void glVertex2f(float x, float y) { checkSeal(false); - growBufferIfNecessary(VERTEX, 2); + growBuffer(VERTEX, 2); if(vComps>0) GLBuffers.putf(vertexArray, x); if(vComps>1) @@ -433,7 +515,7 @@ public class ImmModeSink { } public void glVertex3f(float x, float y, float z) { checkSeal(false); - growBufferIfNecessary(VERTEX, 3); + growBuffer(VERTEX, 3); if(vComps>0) GLBuffers.putf(vertexArray, x); if(vComps>1) @@ -445,7 +527,7 @@ public class ImmModeSink { public void glNormal3b(byte x, byte y, byte z) { checkSeal(false); - growBufferIfNecessary(NORMAL, 3); + growBuffer(NORMAL, 3); if(nComps>0) GLBuffers.putb(normalArray, x); if(nComps>1) @@ -456,7 +538,7 @@ public class ImmModeSink { } public void glNormal3s(short x, short y, short z) { checkSeal(false); - growBufferIfNecessary(NORMAL, 3); + growBuffer(NORMAL, 3); if(nComps>0) GLBuffers.puts(normalArray, x); if(nComps>1) @@ -467,7 +549,7 @@ public class ImmModeSink { } public void glNormal3f(float x, float y, float z) { checkSeal(false); - growBufferIfNecessary(NORMAL, 3); + growBuffer(NORMAL, 3); if(nComps>0) GLBuffers.putf(normalArray, x); if(nComps>1) @@ -479,7 +561,7 @@ public class ImmModeSink { public void glColor3b(byte r, byte g, byte b) { checkSeal(false); - growBufferIfNecessary(COLOR, 3); + growBuffer(COLOR, 3); if(cComps>0) GLBuffers.putb(colorArray, r); if(cComps>1) @@ -490,7 +572,7 @@ public class ImmModeSink { } public void glColor4b(byte r, byte g, byte b, byte a) { checkSeal(false); - growBufferIfNecessary(COLOR, 4); + growBuffer(COLOR, 4); if(cComps>0) GLBuffers.putb(colorArray, r); if(cComps>1) @@ -503,7 +585,7 @@ public class ImmModeSink { } public void glColor3s(short r, short g, short b) { checkSeal(false); - growBufferIfNecessary(COLOR, 3); + growBuffer(COLOR, 3); if(cComps>0) GLBuffers.puts(colorArray, r); if(cComps>1) @@ -514,7 +596,7 @@ public class ImmModeSink { } public void glColor4s(short r, short g, short b, short a) { checkSeal(false); - growBufferIfNecessary(COLOR, 4); + growBuffer(COLOR, 4); if(cComps>0) GLBuffers.puts(colorArray, r); if(cComps>1) @@ -527,7 +609,7 @@ public class ImmModeSink { } public void glColor3f(float r, float g, float b) { checkSeal(false); - growBufferIfNecessary(COLOR, 3); + growBuffer(COLOR, 3); if(cComps>0) GLBuffers.putf(colorArray, r); if(cComps>1) @@ -538,7 +620,7 @@ public class ImmModeSink { } public void glColor4f(float r, float g, float b, float a) { checkSeal(false); - growBufferIfNecessary(COLOR, 4); + growBuffer(COLOR, 4); if(cComps>0) GLBuffers.putf(colorArray, r); if(cComps>1) @@ -552,7 +634,7 @@ public class ImmModeSink { public void glTexCoord2b(byte x, byte y) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 2); + growBuffer(TEXTCOORD, 2); if(tComps>0) GLBuffers.putb(textCoordArray, x); if(tComps>1) @@ -561,7 +643,7 @@ public class ImmModeSink { } public void glTexCoord3b(byte x, byte y, byte z) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 3); + growBuffer(TEXTCOORD, 3); if(tComps>0) GLBuffers.putb(textCoordArray, x); if(tComps>1) @@ -572,7 +654,7 @@ public class ImmModeSink { } public void glTexCoord2s(short x, short y) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 2); + growBuffer(TEXTCOORD, 2); if(tComps>0) GLBuffers.puts(textCoordArray, x); if(tComps>1) @@ -581,7 +663,7 @@ public class ImmModeSink { } public void glTexCoord3s(short x, short y, short z) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 3); + growBuffer(TEXTCOORD, 3); if(tComps>0) GLBuffers.puts(textCoordArray, x); if(tComps>1) @@ -592,7 +674,7 @@ public class ImmModeSink { } public void glTexCoord2f(float x, float y) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 2); + growBuffer(TEXTCOORD, 2); if(tComps>0) GLBuffers.putf(textCoordArray, x); if(tComps>1) @@ -601,7 +683,7 @@ public class ImmModeSink { } public void glTexCoord3f(float x, float y, float z) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 3); + growBuffer(TEXTCOORD, 3); if(tComps>0) GLBuffers.putf(textCoordArray, x); if(tComps>1) @@ -629,10 +711,10 @@ public class ImmModeSink { public void destroy(GL gl) { reset(gl); + vCount=0; cCount=0; nCount=0; tCount=0; vertexArray=null; colorArray=null; normalArray=null; textCoordArray=null; vArrayData=null; cArrayData=null; nArrayData=null; tArrayData=null; buffer=null; - bSize=0; count=0; } public void reset(GL gl) { @@ -649,8 +731,13 @@ public class ImmModeSink { this.mode = 0; this.modeOrig = 0; this.sealed=false; + this.sealedGL=false; this.bufferEnabled=false; this.bufferWritten=false; + this.vElems=0; + this.cElems=0; + this.nElems=0; + this.tElems=0; } public void seal(GL glObj, boolean seal) @@ -660,19 +747,25 @@ public class ImmModeSink { sealedGL = seal; GL gl = glObj.getGL(); if(seal) { - if(vboUsage && vboName==0) { - int[] tmp = new int[1]; - gl.glGenBuffers(1, tmp, 0); - vboName = tmp[0]; + if(useVBO) { + if(0 == vboName) { + int[] tmp = new int[1]; + gl.glGenBuffers(1, tmp, 0); + vboName = tmp[0]; + } + if(null!=vArrayData) { + vArrayData.setVBOName(vboName); + } + if(null!=cArrayData) { + cArrayData.setVBOName(vboName); + } + if(null!=nArrayData) { + nArrayData.setVBOName(vboName); + } + if(null!=tArrayData) { + tArrayData.setVBOName(vboName); + } } - if(null!=vArrayData) - vArrayData.setVBOName(vboName); - if(null!=cArrayData) - cArrayData.setVBOName(vboName); - if(null!=nArrayData) - nArrayData.setVBOName(vboName); - if(null!=tArrayData) - tArrayData.setVBOName(vboName); enableBuffer(gl, true); } else { enableBuffer(gl, false); @@ -685,68 +778,89 @@ public class ImmModeSink { sealed = seal; if(seal) { bufferWritten=false; + rewind(); } } public void enableBuffer(GL gl, boolean enable) { - /* if(enableBufferAlways && enable) { - bufferEnabled = false; - } */ - if( bufferEnabled != enable && count>0 ) { + if( bufferEnabled != enable && vElems>0 ) { if(enable) { checkSeal(true); } + bufferEnabled = enable; if(useGLSL) { enableBufferGLSL(gl, enable); } else { enableBufferFixed(gl, enable); } - bufferEnabled = enable; } } public void enableBufferFixed(GL gl, boolean enable) { GL2ES1 glf = gl.getGL2ES1(); + + final boolean useV = vComps>0 && vElems>0 ; + final boolean useC = cComps>0 && cElems>0 ; + final boolean useN = nComps>0 && nElems>0 ; + final boolean useT = tComps>0 && tElems>0 ; + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableFixed.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"]"); + } if(enable) { - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); - - if(!bufferWritten) { - gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW); - bufferWritten=true; + if(useVBO) { + if(0 == vboName) { + throw new InternalError("Using VBO but no vboName"); + } + glf.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + + if(!bufferWritten) { + glf.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, glBufferUsage); + } } + bufferWritten=true; + } - if(vComps>0) { + if(useV) { + if(enable) { glf.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY); glf.glVertexPointer(vArrayData); - } - if(cComps>0) { + } else { + glf.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY); + } + } + if(useC) { + if(enable) { glf.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY); glf.glColorPointer(cArrayData); - } - if(nComps>0) { + } else { + glf.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY); + } + } + if(useN) { + if(enable) { glf.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY); glf.glNormalPointer(nArrayData); - } - if(tComps>0) { + } else { + glf.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY); + } + } + if(useT) { + if(enable) { glf.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY); glf.glTexCoordPointer(tArrayData); - } + } else { + glf.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY); + } + } + if(enable && useVBO) { gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); - } else { - if(vComps>0) { - glf.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY); - } - if(cComps>0) { - glf.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY); - } - if(nComps>0) { - glf.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY); - } - if(tComps>0) { - glf.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY); - } + } + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableFixed.X "+this); } } @@ -757,54 +871,79 @@ public class ImmModeSink { } GL2ES2 glsl = gl.getGL2ES2(); + final boolean useV = vComps>0 && vElems>0 ; + final boolean useC = cComps>0 && cElems>0 ; + final boolean useN = nComps>0 && nElems>0 ; + final boolean useT = tComps>0 && tElems>0 ; + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"]"); + } + if(enable) { - glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); - - if(!bufferWritten) { - glsl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW); - bufferWritten=true; + if(useVBO) { + if(0 == vboName) { + throw new InternalError("Using VBO but no vboName"); + } + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(!bufferWritten) { + glsl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW); + } } + bufferWritten=true; + } - if(vComps>0) { + if(useV) { + if(enable) { st.enableVertexAttribArray(glsl, vArrayData); st.vertexAttribPointer(glsl, vArrayData); - } - if(cComps>0) { + } else { + st.disableVertexAttribArray(glsl, vArrayData); + } + } + if(useC) { + if(enable) { st.enableVertexAttribArray(glsl, cArrayData); st.vertexAttribPointer(glsl, cArrayData); - } - if(nComps>0) { + } else { + st.disableVertexAttribArray(glsl, cArrayData); + } + } + if(useN) { + if(enable) { st.enableVertexAttribArray(glsl, nArrayData); st.vertexAttribPointer(glsl, nArrayData); - } - if(tComps>0) { + } else { + st.disableVertexAttribArray(glsl, nArrayData); + } + } + if(useT) { + if(enable) { st.enableVertexAttribArray(glsl, tArrayData); st.vertexAttribPointer(glsl, tArrayData); - } - - glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); - } else { - if(vComps>0) { - st.disableVertexAttribArray(glsl, vArrayData); - } - if(cComps>0) { - st.disableVertexAttribArray(glsl, cArrayData); - } - if(nComps>0) { - st.disableVertexAttribArray(glsl, nArrayData); - } - if(tComps>0) { + } else { st.disableVertexAttribArray(glsl, tArrayData); - } + } + } + + if(enable && useVBO) { + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.X "+this); } } public String toString() { return "VBOSet[mode "+mode+ ", modeOrig "+modeOrig+ + ", use/count "+getElemUseCountStr()+ ", sealed "+sealed+ + ", sealedGL "+sealedGL+ ", bufferEnabled "+bufferEnabled+ - ", bufferWritten "+bufferWritten+ + ", bufferWritten "+bufferWritten+ + ", useVBO "+useVBO+", vboName "+vboName+ ",\n\t"+vArrayData+ ",\n\t"+cArrayData+ ",\n\t"+nArrayData+ @@ -814,55 +953,84 @@ public class ImmModeSink { // non public matters - protected void allocateBuffer(int elementCount) { - int vWidth = vComps * GLBuffers.sizeOfGLType(vDataType); - int cWidth = cComps * GLBuffers.sizeOfGLType(cDataType); - int nWidth = nComps * GLBuffers.sizeOfGLType(nDataType); - int tWidth = tComps * GLBuffers.sizeOfGLType(tDataType); - - count = elementCount; - bSize = count * ( vWidth + cWidth + nWidth + tWidth ) ; - - buffer = GLBuffers.newDirectByteBuffer(bSize); - - int pos = 0; - int size= count * vWidth ; - if(size>0) { - vertexArray = GLBuffers.sliceGLBuffer(buffer, pos, size, vDataType); + protected String getElemUseCountStr() { + return "[v "+vElems+"/"+vCount+", c "+cElems+"/"+cCount+", n "+nElems+"/"+nCount+", t "+tElems+"/"+tCount+"]"; + } + + protected boolean fitElemsInBuffers(int addElems) { + final int vAdd = addElems - ( vCount - vElems ); + final int cAdd = addElems - ( cCount - cElems ); + final int nAdd = addElems - ( nCount - nElems ); + final int tAdd = addElems - ( tCount - tElems ); + final boolean res = 0>=vAdd && 0>=cAdd && 0>=nAdd && 0>=tAdd; + /* if(DEBUG_BUFFER) { + System.err.println("ImmModeSink.fitElemsInBuffer: "+getElemUseCountStr()+" + "+addElems+" -> "+res); + } */ + return res; + } + + protected boolean reallocateBuffer(int addElems) { + final int vAdd = addElems - ( vCount - vElems ); + final int cAdd = addElems - ( cCount - cElems ); + final int nAdd = addElems - ( nCount - nElems ); + final int tAdd = addElems - ( tCount - tElems ); + + if( 0>=vAdd && 0>=cAdd && 0>=nAdd && 0>=tAdd) { + if(DEBUG_BUFFER) { + System.err.println("ImmModeSink.realloc: "+getElemUseCountStr()+" + "+addElems+" -> NOP"); + } + return false; + } + + if(DEBUG_BUFFER) { + System.err.println("ImmModeSink.realloc: "+getElemUseCountStr()+" + "+addElems); + } + vCount += vAdd; + cCount += cAdd; + nCount += nAdd; + tCount += tAdd; + + final int vWidth = vComps * GLBuffers.sizeOfGLType(vDataType); + final int cWidth = cComps * GLBuffers.sizeOfGLType(cDataType); + final int nWidth = nComps * GLBuffers.sizeOfGLType(nDataType); + final int tWidth = tComps * GLBuffers.sizeOfGLType(tDataType); + + final int bSizeV = vCount * vWidth; + final int bSizeC = cCount * cWidth; + final int bSizeN = nCount * nWidth; + final int bSizeT = tCount * tWidth; + + buffer = GLBuffers.newDirectByteBuffer( bSizeV + bSizeC + bSizeN + bSizeT ); + vOffset = 0; + + if(bSizeV>0) { + vertexArray = GLBuffers.sliceGLBuffer(buffer, vOffset, bSizeV, vDataType); } else { vertexArray = null; - } - vOffset = pos; - pos+=size; + } + cOffset=vOffset+bSizeV; - size= count * cWidth ; - if(size>0) { - colorArray = GLBuffers.sliceGLBuffer(buffer, pos, size, cDataType); + if(bSizeC>0) { + colorArray = GLBuffers.sliceGLBuffer(buffer, cOffset, bSizeC, cDataType); } else { colorArray = null; } - cOffset = pos; - pos+=size; + nOffset=cOffset+bSizeC; - size= count * nWidth ; - if(size>0) { - normalArray = GLBuffers.sliceGLBuffer(buffer, pos, size, nDataType); + if(bSizeN>0) { + normalArray = GLBuffers.sliceGLBuffer(buffer, nOffset, bSizeN, nDataType); } else { normalArray = null; } - nOffset = pos; - pos+=size; + tOffset=nOffset+bSizeN; - size= count * tWidth ; - if(size>0) { - textCoordArray = GLBuffers.sliceGLBuffer(buffer, pos, size, tDataType); + if(bSizeT>0) { + textCoordArray = GLBuffers.sliceGLBuffer(buffer, tOffset, bSizeT, tDataType); } else { textCoordArray = null; } - tOffset = pos; - pos+=size; - buffer.position(pos); + buffer.position(tOffset+bSizeT); buffer.flip(); if(vComps>0) { @@ -889,41 +1057,42 @@ public class ImmModeSink { } else { tArrayData = null; } - - } - - protected final boolean growBufferIfNecessary(int type, int spare) { - if(buffer==null || count < spare) { - growBuffer(type, initialElementCount); - return true; + + if(DEBUG_BUFFER) { + System.err.println("ImmModeSink.realloc.X: "+this.toString()); + Thread.dumpStack(); } - return false; + return true; } - protected final void growBuffer(int type, int additional) { - if(sealed || 0==additional) return; - - // save olde values .. - Buffer _vertexArray=vertexArray, _colorArray=colorArray, _normalArray=normalArray, _textCoordArray=textCoordArray; - - allocateBuffer(count+additional); - - if(null!=_vertexArray) { - _vertexArray.flip(); - GLBuffers.put(vertexArray, _vertexArray); - } - if(null!=_colorArray) { - _colorArray.flip(); - GLBuffers.put(colorArray, _colorArray); - } - if(null!=_normalArray) { - _normalArray.flip(); - GLBuffers.put(normalArray, _normalArray); - } - if(null!=_textCoordArray) { - _textCoordArray.flip(); - GLBuffers.put(textCoordArray, _textCoordArray); + protected final boolean growBuffer(int type, int additional) { + if( null !=buffer && !sealed && 0<additional) { + if( !fitElemsInBuffers(additional) ) { + // save olde values .. + final Buffer _vertexArray=vertexArray, _colorArray=colorArray, _normalArray=normalArray, _textCoordArray=textCoordArray; + + if ( reallocateBuffer(initialElementCount) ) { + if(null!=_vertexArray) { + _vertexArray.flip(); + GLBuffers.put(vertexArray, _vertexArray); + } + if(null!=_colorArray) { + _colorArray.flip(); + GLBuffers.put(colorArray, _colorArray); + } + if(null!=_normalArray) { + _normalArray.flip(); + GLBuffers.put(normalArray, _normalArray); + } + if(null!=_textCoordArray) { + _textCoordArray.flip(); + GLBuffers.put(textCoordArray, _textCoordArray); + } + return true; + } + } } + return false; } protected void padding(int type, int fill) { @@ -934,15 +1103,19 @@ public class ImmModeSink { switch (type) { case VERTEX: dest = vertexArray; + vElems++; break; case COLOR: dest = colorArray; + cElems++; break; case NORMAL: dest = normalArray; + nElems++; break; case TEXTCOORD: dest = textCoordArray; + tElems++; break; } @@ -953,26 +1126,28 @@ public class ImmModeSink { } } + final protected int glBufferUsage, initialElementCount; + final protected boolean useVBO; protected int mode, modeOrig; - protected int glBufferUsage, initialElementCount; protected ByteBuffer buffer; - protected int bSize, count, vboName; + protected int vboName; public static final int VERTEX = 0; public static final int COLOR = 1; public static final int NORMAL = 2; public static final int TEXTCOORD = 3; - protected int vOffset, cOffset, nOffset, tOffset; + protected int vCount, cCount, nCount, tCount; + protected int vOffset, cOffset, nOffset, tOffset; protected int vComps, cComps, nComps, tComps; + protected int vElems, cElems, nElems, tElems; protected int vDataType, cDataType, nDataType, tDataType; protected Buffer vertexArray, colorArray, normalArray, textCoordArray; protected GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData; protected boolean sealed, sealedGL, useGLSL; protected boolean bufferEnabled, bufferWritten; - protected GL gl; } } |