diff options
author | Sven Gothel <[email protected]> | 2014-02-23 14:51:06 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-02-23 14:51:06 +0100 |
commit | 3352601e0860584509adf2b76f993d03893ded4b (patch) | |
tree | 974fccc8c0eb2f5ad9d4ffd741dfc35869ed67b5 /src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java | |
parent | f51933f0ebe9ae030c26c066e59a728ce08b8559 (diff) | |
parent | c67de337a8aaf52e36104c3f13e273aa19d21f1f (diff) |
Merge branch 'master' into stash_glyphcache
Conflicts:
make/scripts/tests.sh
src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
src/jogl/classes/com/jogamp/graph/curve/Region.java
src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java
src/jogl/classes/com/jogamp/graph/font/Font.java
src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java | 1388 |
1 files changed, 957 insertions, 431 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java index 3b817afcf..986f6d8d3 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -1,58 +1,162 @@ package com.jogamp.opengl.util; -import com.jogamp.common.util.*; -import com.jogamp.opengl.util.glsl.ShaderState; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.Iterator; -import javax.media.opengl.*; -import javax.media.opengl.fixedfunc.*; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.fixedfunc.GLPointerFunc; -import java.nio.*; -import java.util.Iterator; -import java.util.ArrayList; +import jogamp.opengl.Debug; -public class ImmModeSink { +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.util.glsl.ShaderState; - public static final boolean DEBUG_BEGIN_END = false; - public static final boolean DEBUG_DRAW = false; +/** + * <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, ShaderState) 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 { + protected static final boolean DEBUG_BEGIN_END; + protected static final boolean DEBUG_DRAW; + protected static final boolean DEBUG_BUFFER; + + static { + Debug.initSingleton(); + DEBUG_BEGIN_END = Debug.isPropertyDefined("jogl.debug.ImmModeSink.BeginEnd", true); + DEBUG_DRAW = Debug.isPropertyDefined("jogl.debug.ImmModeSink.Draw", true); + DEBUG_BUFFER = Debug.isPropertyDefined("jogl.debug.ImmModeSink.Buffer", true); + } - // 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 nComps, int nDataType, - int tComps, int tDataType) { - return new ImmModeSink(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false); + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, + int glBufferUsage) { + return new ImmModeSink(initialElementCount, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + false, glBufferUsage, null, 0); } /** - * Uses a GL2ES2 GLSL shader immediate mode sink. - * To issue the draw() command, - * a ShaderState must be current, using ShaderState.glUseProgram(). + * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given ShaderState. + * <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 + * @param st ShaderState to locate the vertex attributes * @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 nComps, int nDataType, - int tComps, int tDataType) { - return new ImmModeSink(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true); + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, + int glBufferUsage, ShaderState st) { + return new ImmModeSink(initialElementCount, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + true, glBufferUsage, st, 0); } - public static boolean usesVBO() { return vboUsage; } - - public static void setVBOUsage(boolean v) { vboUsage = v; } + /** + * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given shader-program. + * <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 + * @param shaderProgram shader-program name to locate the vertex attributes + * @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(int initialElementCount, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, + int glBufferUsage, int shaderProgram) { + return new ImmModeSink(initialElementCount, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + true, glBufferUsage, null, shaderProgram); + } public void destroy(GL gl) { destroyList(gl); @@ -69,6 +173,7 @@ public class ImmModeSink { vboSet.reset(gl); } + @Override public String toString() { StringBuilder sb = new StringBuilder("ImmModeSink["); sb.append(",\n\tVBO list: "+vboSetList.size()+" ["); @@ -88,45 +193,38 @@ 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(); - } 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; + if(DEBUG_BEGIN_END) { + System.err.println("ImmModeSink.glBegin("+vboSet.modeOrig+" -> "+vboSet.mode+")"); + } vboSet.checkSeal(false); } @@ -144,8 +242,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+")"); } if(immediateDraw) { vboSet.seal(gl, true); @@ -155,7 +252,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+")"); } } @@ -244,10 +344,18 @@ public class ImmModeSink { vboSet.glColor3b(x,y,z); } + public final void glColor3ub(byte x, byte y, byte z) { + vboSet.glColor3ub(x,y,z); + } + public final void glColor4b(byte x, byte y, byte z, byte a) { vboSet.glColor4b(x,y,z,a); } + public final void glColor4ub(byte x, byte y, byte z, byte a) { + vboSet.glColor4ub(x,y,z,a); + } + public final void glTexCoord2b(byte x, byte y) { vboSet.glTexCoord2b(x,y); } @@ -256,50 +364,94 @@ public class ImmModeSink { vboSet.glTexCoord3b(x,y,z); } - protected ImmModeSink(GL gl, int glBufferUsage, int initialElementCount, + protected ImmModeSink(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); + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, + boolean useGLSL, int glBufferUsage, ShaderState st, int shaderProgram) { + vboSet = new VBOSet(initialElementCount, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + useGLSL, glBufferUsage, st, shaderProgram); this.vboSetList = new ArrayList<VBOSet>(); } + public boolean getUseVBO() { return vboSet.getUseVBO(); } + + /** + * Returns the additional element count if buffer resize is required. + * @see #setResizeElementCount(int) + */ + public int getResizeElementCount() { return vboSet.getResizeElementCount(); } + + /** + * Sets the additional element count if buffer resize is required, + * defaults to <code>initialElementCount</code> of factory method. + * @see #createFixed(int, int, int, int, int, int, int, int, int, int) + * @see #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState) + */ + public void setResizeElementCount(int v) { vboSet.setResizeElementCount(v); } + 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, + protected VBOSet (int initialElementCount, int vComps, int vDataType, - int cComps, int cDataType, - int nComps, int nDataType, - int tComps, int tDataType, boolean useGLSL) { - this.gl=gl; + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, + boolean useGLSL, int glBufferUsage, ShaderState st, int shaderProgram) { + // final .. this.glBufferUsage=glBufferUsage; this.initialElementCount=initialElementCount; + this.useVBO = 0 != glBufferUsage; + this.useGLSL=useGLSL; + this.shaderState = st; + this.shaderProgram = shaderProgram; + + if(useGLSL && null == shaderState && 0 == shaderProgram) { + throw new IllegalArgumentException("Using GLSL but neither a valid shader-program nor ShaderState has been passed!"); + } + // variable .. + this.resizeElementCount=initialElementCount; this.vDataType=vDataType; + this.vDataTypeSigned=GLBuffers.isSignedGLType(vDataType); this.vComps=vComps; + this.vCompsBytes=vComps * GLBuffers.sizeOfGLType(vDataType); this.cDataType=cDataType; + this.cDataTypeSigned=GLBuffers.isSignedGLType(cDataType); this.cComps=cComps; + this.cCompsBytes=cComps * GLBuffers.sizeOfGLType(cDataType); this.nDataType=nDataType; + this.nDataTypeSigned=GLBuffers.isSignedGLType(nDataType); this.nComps=nComps; + this.nCompsBytes=nComps * GLBuffers.sizeOfGLType(nDataType); this.tDataType=tDataType; + this.tDataTypeSigned=GLBuffers.isSignedGLType(tDataType); this.tComps=tComps; - this.useGLSL=useGLSL; + this.tCompsBytes=tComps * GLBuffers.sizeOfGLType(tDataType); + 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; - allocateBuffer(initialElementCount); + this.pageSize = Platform.getMachineDescription().pageSizeInBytes(); + + reallocateBuffer(initialElementCount); rewind(); this.sealed=false; @@ -308,304 +460,387 @@ public class ImmModeSink { this.modeOrig = 0; this.bufferEnabled=false; this.bufferWritten=false; + this.bufferWrittenOnce=false; + this.glslLocationSet = false; } - protected final VBOSet regenerate() { - return new VBOSet(gl, glBufferUsage, initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); + protected int getResizeElementCount() { return resizeElementCount; } + protected void setResizeElementCount(int v) { resizeElementCount=v; } + + 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, shaderState, shaderProgram); } protected void checkSeal(boolean test) throws GLException { if(0==mode) { - throw new GLException("No mode set yet, call glBegin(mode) first:\n\t"+this); + throw new GLException("No mode set yet, call glBegin(mode) first:\n\t"+this); } if(sealed!=test) { if(test) { - throw new GLException("Not Sealed yet, call glEnd() first:\n\t"+this); + throw new GLException("Not Sealed yet, call glEnd() first:\n\t"+this); } else { - throw new GLException("Already Sealed, can't modify VBO after glEnd():\n\t"+this); + throw new GLException("Already Sealed, can't modify VBO after glEnd():\n\t"+this); + } + } + } + + private boolean usingShaderProgram = false; + + protected void useShaderProgram(GL2ES2 gl, boolean force) { + if( force || !usingShaderProgram ) { + if(null != shaderState) { + shaderState.useProgram(gl, true); + } else /* if( 0 != shaderProgram) */ { + gl.glUseProgram(shaderProgram); } + usingShaderProgram = true; } } protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i) { + enableBuffer(gl, true); + + if(null != shaderState || 0 != shaderProgram) { + useShaderProgram(gl.getGL2ES2(), false); + } + 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) { - GL2ES1 glf = gl.getGL2ES1(); - if(null==indices) { - glf.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())) { + // FIXME: Impl. VBO usage .. or unroll. + if( !gl.getContext().isCPUDataSourcingAvail() ) { + throw new GLException("CPU data sourcing n/a w/ "+gl.getContext()); + } + final int type; + 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 if(indices instanceof IntBuffer) { + type = GL.GL_UNSIGNED_INT; + } else { + throw new GLException("Given Buffer Class not supported: "+indices.getClass()+", should be ubyte, ushort or uint:\n\t"+this); } - if(0>type) { - throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this); + final int idxLen = indices.remaining(); + final int idx0 = indices.position(); + + if ( GL_QUADS == mode && !gl.isGL2() ) { + if( GL.GL_UNSIGNED_BYTE == type ) { + final ByteBuffer b = (ByteBuffer) indices; + for (int j = 0; j < idxLen; j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0x000000ff & b.get(idx0+j)), 4); + } + } else if( GL.GL_UNSIGNED_SHORT == type ){ + final ShortBuffer b = (ShortBuffer) indices; + for (int j = 0; j < idxLen; j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0x0000ffff & b.get(idx0+j)), 4); + } + } else { + final IntBuffer b = (IntBuffer) indices; + for (int j = 0; j < idxLen; j++) { + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, (int)(0xffffffff & b.get(idx0+j)), 4); + } + } + } else { + ((GL2ES1)gl).glDrawElements(mode, idxLen, type, indices); + // GL2: gl.glDrawRangeElements(mode, 0, idxLen-1, idxLen, type, indices); } - glf.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+")"); + } } public void glVertexv(Buffer v) { checkSeal(false); - GLBuffers.put(vertexArray, v); + Buffers.put(vertexArray, v); } public void glNormalv(Buffer v) { checkSeal(false); - GLBuffers.put(normalArray, v); + Buffers.put(normalArray, v); } public void glColorv(Buffer v) { checkSeal(false); - GLBuffers.put(colorArray, v); + Buffers.put(colorArray, v); } public void glTexCoordv(Buffer v) { checkSeal(false); - GLBuffers.put(textCoordArray, v); + Buffers.put(textCoordArray, v); } public void glVertex2b(byte x, byte y) { checkSeal(false); - growBufferIfNecessary(VERTEX, 2); - if(vComps>0) - GLBuffers.putb(vertexArray, x); - if(vComps>1) - GLBuffers.putb(vertexArray, y); - padding(VERTEX, vComps-2); + growBuffer(VERTEX); + if(vComps>0) + Buffers.putNb(vertexArray, vDataTypeSigned, x, true); + if(vComps>1) + Buffers.putNb(vertexArray, vDataTypeSigned, y, true); + countAndPadding(VERTEX, vComps-2); } public void glVertex3b(byte x, byte y, byte z) { checkSeal(false); - growBufferIfNecessary(VERTEX, 3); - if(vComps>0) - GLBuffers.putb(vertexArray, x); - if(vComps>1) - GLBuffers.putb(vertexArray, y); - if(vComps>2) - GLBuffers.putb(vertexArray, z); - padding(VERTEX, vComps-3); + growBuffer(VERTEX); + if(vComps>0) + Buffers.putNb(vertexArray, vDataTypeSigned, x, true); + if(vComps>1) + Buffers.putNb(vertexArray, vDataTypeSigned, y, true); + if(vComps>2) + Buffers.putNb(vertexArray, vDataTypeSigned, z, true); + countAndPadding(VERTEX, vComps-3); } public void glVertex2s(short x, short y) { checkSeal(false); - growBufferIfNecessary(VERTEX, 2); - if(vComps>0) - GLBuffers.puts(vertexArray, x); - if(vComps>1) - GLBuffers.puts(vertexArray, y); - padding(VERTEX, vComps-2); + growBuffer(VERTEX); + if(vComps>0) + Buffers.putNs(vertexArray, vDataTypeSigned, x, true); + if(vComps>1) + Buffers.putNs(vertexArray, vDataTypeSigned, y, true); + countAndPadding(VERTEX, vComps-2); } public void glVertex3s(short x, short y, short z) { checkSeal(false); - growBufferIfNecessary(VERTEX, 3); - if(vComps>0) - GLBuffers.puts(vertexArray, x); - if(vComps>1) - GLBuffers.puts(vertexArray, y); - if(vComps>2) - GLBuffers.puts(vertexArray, z); - padding(VERTEX, vComps-3); + growBuffer(VERTEX); + if(vComps>0) + Buffers.putNs(vertexArray, vDataTypeSigned, x, true); + if(vComps>1) + Buffers.putNs(vertexArray, vDataTypeSigned, y, true); + if(vComps>2) + Buffers.putNs(vertexArray, vDataTypeSigned, z, true); + countAndPadding(VERTEX, vComps-3); } public void glVertex2f(float x, float y) { checkSeal(false); - growBufferIfNecessary(VERTEX, 2); - if(vComps>0) - GLBuffers.putf(vertexArray, x); - if(vComps>1) - GLBuffers.putf(vertexArray, y); - padding(VERTEX, vComps-2); + growBuffer(VERTEX); + if(vComps>0) + Buffers.putNf(vertexArray, vDataTypeSigned, x); + if(vComps>1) + Buffers.putNf(vertexArray, vDataTypeSigned, y); + countAndPadding(VERTEX, vComps-2); } public void glVertex3f(float x, float y, float z) { checkSeal(false); - growBufferIfNecessary(VERTEX, 3); - if(vComps>0) - GLBuffers.putf(vertexArray, x); - if(vComps>1) - GLBuffers.putf(vertexArray, y); - if(vComps>2) - GLBuffers.putf(vertexArray, z); - padding(VERTEX, vComps-3); + growBuffer(VERTEX); + if(vComps>0) + Buffers.putNf(vertexArray, vDataTypeSigned, x); + if(vComps>1) + Buffers.putNf(vertexArray, vDataTypeSigned, y); + if(vComps>2) + Buffers.putNf(vertexArray, vDataTypeSigned, z); + countAndPadding(VERTEX, vComps-3); } public void glNormal3b(byte x, byte y, byte z) { checkSeal(false); - growBufferIfNecessary(NORMAL, 3); - if(nComps>0) - GLBuffers.putb(normalArray, x); - if(nComps>1) - GLBuffers.putb(normalArray, y); - if(nComps>2) - GLBuffers.putb(normalArray, z); - padding(NORMAL, nComps-3); + growBuffer(NORMAL); + if(nComps>0) + Buffers.putNb(normalArray, nDataTypeSigned, x, true); + if(nComps>1) + Buffers.putNb(normalArray, nDataTypeSigned, y, true); + if(nComps>2) + Buffers.putNb(normalArray, nDataTypeSigned, z, true); + countAndPadding(NORMAL, nComps-3); } public void glNormal3s(short x, short y, short z) { checkSeal(false); - growBufferIfNecessary(NORMAL, 3); - if(nComps>0) - GLBuffers.puts(normalArray, x); - if(nComps>1) - GLBuffers.puts(normalArray, y); - if(nComps>2) - GLBuffers.puts(normalArray, z); - padding(NORMAL, nComps-3); + growBuffer(NORMAL); + if(nComps>0) + Buffers.putNs(normalArray, nDataTypeSigned, x, true); + if(nComps>1) + Buffers.putNs(normalArray, nDataTypeSigned, y, true); + if(nComps>2) + Buffers.putNs(normalArray, nDataTypeSigned, z, true); + countAndPadding(NORMAL, nComps-3); } public void glNormal3f(float x, float y, float z) { checkSeal(false); - growBufferIfNecessary(NORMAL, 3); - if(nComps>0) - GLBuffers.putf(normalArray, x); - if(nComps>1) - GLBuffers.putf(normalArray, y); - if(nComps>2) - GLBuffers.putf(normalArray, z); - padding(NORMAL, nComps-3); + growBuffer(NORMAL); + if(nComps>0) + Buffers.putNf(normalArray, nDataTypeSigned, x); + if(nComps>1) + Buffers.putNf(normalArray, nDataTypeSigned, y); + if(nComps>2) + Buffers.putNf(normalArray, nDataTypeSigned, z); + countAndPadding(NORMAL, nComps-3); } public void glColor3b(byte r, byte g, byte b) { checkSeal(false); - growBufferIfNecessary(COLOR, 3); - if(cComps>0) - GLBuffers.putb(colorArray, r); - if(cComps>1) - GLBuffers.putb(colorArray, g); - if(cComps>2) - GLBuffers.putb(colorArray, b); - padding(COLOR, cComps-3); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNb(colorArray, cDataTypeSigned, r, true); + if(cComps>1) + Buffers.putNb(colorArray, cDataTypeSigned, g, true); + if(cComps>2) + Buffers.putNb(colorArray, cDataTypeSigned, b, true); + countAndPadding(COLOR, cComps-3); + } + public void glColor3ub(byte r, byte g, byte b) { + checkSeal(false); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNb(colorArray, cDataTypeSigned, r, false); + if(cComps>1) + Buffers.putNb(colorArray, cDataTypeSigned, g, false); + if(cComps>2) + Buffers.putNb(colorArray, cDataTypeSigned, b, false); + countAndPadding(COLOR, cComps-3); } public void glColor4b(byte r, byte g, byte b, byte a) { checkSeal(false); - growBufferIfNecessary(COLOR, 4); - if(cComps>0) - GLBuffers.putb(colorArray, r); - if(cComps>1) - GLBuffers.putb(colorArray, g); - if(cComps>2) - GLBuffers.putb(colorArray, b); - if(cComps>3) - GLBuffers.putb(colorArray, a); - padding(COLOR, cComps-4); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNb(colorArray, cDataTypeSigned, r, true); + if(cComps>1) + Buffers.putNb(colorArray, cDataTypeSigned, g, true); + if(cComps>2) + Buffers.putNb(colorArray, cDataTypeSigned, b, true); + if(cComps>3) + Buffers.putNb(colorArray, cDataTypeSigned, a, true); + countAndPadding(COLOR, cComps-4); + } + public void glColor4ub(byte r, byte g, byte b, byte a) { + checkSeal(false); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNb(colorArray, cDataTypeSigned, r, false); + if(cComps>1) + Buffers.putNb(colorArray, cDataTypeSigned, g, false); + if(cComps>2) + Buffers.putNb(colorArray, cDataTypeSigned, b, false); + if(cComps>3) + Buffers.putNb(colorArray, cDataTypeSigned, a, false); + countAndPadding(COLOR, cComps-4); } public void glColor3s(short r, short g, short b) { checkSeal(false); - growBufferIfNecessary(COLOR, 3); - if(cComps>0) - GLBuffers.puts(colorArray, r); - if(cComps>1) - GLBuffers.puts(colorArray, g); - if(cComps>2) - GLBuffers.puts(colorArray, b); - padding(COLOR, cComps-3); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNs(colorArray, cDataTypeSigned, r, true); + if(cComps>1) + Buffers.putNs(colorArray, cDataTypeSigned, g, true); + if(cComps>2) + Buffers.putNs(colorArray, cDataTypeSigned, b, true); + countAndPadding(COLOR, cComps-3); } public void glColor4s(short r, short g, short b, short a) { checkSeal(false); - growBufferIfNecessary(COLOR, 4); - if(cComps>0) - GLBuffers.puts(colorArray, r); - if(cComps>1) - GLBuffers.puts(colorArray, g); - if(cComps>2) - GLBuffers.puts(colorArray, b); - if(cComps>3) - GLBuffers.puts(colorArray, a); - padding(COLOR, cComps-4); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNs(colorArray, cDataTypeSigned, r, true); + if(cComps>1) + Buffers.putNs(colorArray, cDataTypeSigned, g, true); + if(cComps>2) + Buffers.putNs(colorArray, cDataTypeSigned, b, true); + if(cComps>3) + Buffers.putNs(colorArray, cDataTypeSigned, a, true); + countAndPadding(COLOR, cComps-4); } public void glColor3f(float r, float g, float b) { checkSeal(false); - growBufferIfNecessary(COLOR, 3); - if(cComps>0) - GLBuffers.putf(colorArray, r); - if(cComps>1) - GLBuffers.putf(colorArray, g); - if(cComps>2) - GLBuffers.putf(colorArray, b); - padding(COLOR, cComps-3); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNf(colorArray, cDataTypeSigned, r); + if(cComps>1) + Buffers.putNf(colorArray, cDataTypeSigned, g); + if(cComps>2) + Buffers.putNf(colorArray, cDataTypeSigned, b); + countAndPadding(COLOR, cComps-3); } public void glColor4f(float r, float g, float b, float a) { checkSeal(false); - growBufferIfNecessary(COLOR, 4); - if(cComps>0) - GLBuffers.putf(colorArray, r); - if(cComps>1) - GLBuffers.putf(colorArray, g); - if(cComps>2) - GLBuffers.putf(colorArray, b); - if(cComps>3) - GLBuffers.putf(colorArray, a); - padding(COLOR, cComps-4); + growBuffer(COLOR); + if(cComps>0) + Buffers.putNf(colorArray, cDataTypeSigned, r); + if(cComps>1) + Buffers.putNf(colorArray, cDataTypeSigned, g); + if(cComps>2) + Buffers.putNf(colorArray, cDataTypeSigned, b); + if(cComps>3) + Buffers.putNf(colorArray, cDataTypeSigned, a); + countAndPadding(COLOR, cComps-4); } public void glTexCoord2b(byte x, byte y) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 2); - if(tComps>0) - GLBuffers.putb(textCoordArray, x); - if(tComps>1) - GLBuffers.putb(textCoordArray, y); - padding(TEXTCOORD, tComps-2); + growBuffer(TEXTCOORD); + if(tComps>0) + Buffers.putNb(textCoordArray, tDataTypeSigned, x, true); + if(tComps>1) + Buffers.putNb(textCoordArray, tDataTypeSigned, y, true); + countAndPadding(TEXTCOORD, tComps-2); } public void glTexCoord3b(byte x, byte y, byte z) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 3); - if(tComps>0) - GLBuffers.putb(textCoordArray, x); - if(tComps>1) - GLBuffers.putb(textCoordArray, y); - if(tComps>2) - GLBuffers.putb(textCoordArray, z); - padding(TEXTCOORD, tComps-3); + growBuffer(TEXTCOORD); + if(tComps>0) + Buffers.putNb(textCoordArray, tDataTypeSigned, x, true); + if(tComps>1) + Buffers.putNb(textCoordArray, tDataTypeSigned, y, true); + if(tComps>2) + Buffers.putNb(textCoordArray, tDataTypeSigned, z, true); + countAndPadding(TEXTCOORD, tComps-3); } public void glTexCoord2s(short x, short y) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 2); - if(tComps>0) - GLBuffers.puts(textCoordArray, x); - if(tComps>1) - GLBuffers.puts(textCoordArray, y); - padding(TEXTCOORD, tComps-2); + growBuffer(TEXTCOORD); + if(tComps>0) + Buffers.putNs(textCoordArray, tDataTypeSigned, x, true); + if(tComps>1) + Buffers.putNs(textCoordArray, tDataTypeSigned, y, true); + countAndPadding(TEXTCOORD, tComps-2); } public void glTexCoord3s(short x, short y, short z) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 3); - if(tComps>0) - GLBuffers.puts(textCoordArray, x); - if(tComps>1) - GLBuffers.puts(textCoordArray, y); - if(tComps>2) - GLBuffers.puts(textCoordArray, z); - padding(TEXTCOORD, tComps-3); + growBuffer(TEXTCOORD); + if(tComps>0) + Buffers.putNs(textCoordArray, tDataTypeSigned, x, true); + if(tComps>1) + Buffers.putNs(textCoordArray, tDataTypeSigned, y, true); + if(tComps>2) + Buffers.putNs(textCoordArray, tDataTypeSigned, z, true); + countAndPadding(TEXTCOORD, tComps-3); } public void glTexCoord2f(float x, float y) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 2); - if(tComps>0) - GLBuffers.putf(textCoordArray, x); - if(tComps>1) - GLBuffers.putf(textCoordArray, y); - padding(TEXTCOORD, tComps-2); + growBuffer(TEXTCOORD); + if(tComps>0) + Buffers.putNf(textCoordArray, tDataTypeSigned, x); + if(tComps>1) + Buffers.putNf(textCoordArray, tDataTypeSigned, y); + countAndPadding(TEXTCOORD, tComps-2); } public void glTexCoord3f(float x, float y, float z) { checkSeal(false); - growBufferIfNecessary(TEXTCOORD, 3); - if(tComps>0) - GLBuffers.putf(textCoordArray, x); - if(tComps>1) - GLBuffers.putf(textCoordArray, y); - if(tComps>2) - GLBuffers.putf(textCoordArray, z); - padding(TEXTCOORD, tComps-3); + growBuffer(TEXTCOORD); + if(tComps>0) + Buffers.putNf(textCoordArray, tDataTypeSigned, x); + if(tComps>1) + Buffers.putNf(textCoordArray, tDataTypeSigned, y); + if(tComps>2) + Buffers.putNf(textCoordArray, tDataTypeSigned, z); + countAndPadding(TEXTCOORD, tComps-3); } public void rewind() { @@ -623,13 +858,58 @@ public class ImmModeSink { } } + public void setShaderProgram(int program) { + if(null == shaderState && 0 == program) { + throw new IllegalArgumentException("Not allowed to zero shader program if no ShaderState is set"); + } + shaderProgram = program; + glslLocationSet = false; // enforce location reset! + } + + /** + * @param gl + * @return true if all locations for all used arrays are found (min 1 array), otherwise false. + * Also sets 'glslLocationSet' to the return value! + */ + private boolean resetGLSLArrayLocation(GL2ES2 gl) { + int iA = 0; + int iL = 0; + + if(null != vArrayData) { + iA++; + if( vArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + if(null != cArrayData) { + iA++; + if( cArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + if(null != nArrayData) { + iA++; + if( nArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + if(null != tArrayData) { + iA++; + if( tArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + glslLocationSet = iA == iL; + return glslLocationSet; + } + 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) { @@ -646,8 +926,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) @@ -657,19 +942,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); @@ -682,126 +973,287 @@ 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); } - if(useGLSL) { - enableBufferGLSL(gl, enable); + bufferEnabled = enable; + if(useGLSL) { + useShaderProgram(gl.getGL2ES2(), true); + if(null != shaderState) { + enableBufferGLSLShaderState(gl, enable); + } else { + enableBufferGLSLSimple(gl, enable); + } } else { enableBufferFixed(gl, enable); } - bufferEnabled = enable; } } - public void enableBufferFixed(GL gl, boolean enable) { + private final void writeBuffer(GL gl) { + final int vBytes = vElems * vCompsBytes; + final int cBytes = cElems * cCompsBytes; + final int nBytes = nElems * nCompsBytes; + final int tBytes = tElems * tCompsBytes; + final int delta = buffer.limit() - (vBytes+cBytes+nBytes+tBytes); + if( bufferWrittenOnce && delta > pageSize ) { + if(0 < vBytes) { + gl.glBufferSubData(GL.GL_ARRAY_BUFFER, vOffset, vBytes, vertexArray); + } + if(0 < cBytes) { + gl.glBufferSubData(GL.GL_ARRAY_BUFFER, cOffset, cBytes, colorArray); + } + if(0 < nBytes) { + gl.glBufferSubData(GL.GL_ARRAY_BUFFER, nOffset, nBytes, normalArray); + } + if(0 < tBytes) { + gl.glBufferSubData(GL.GL_ARRAY_BUFFER, tOffset, tBytes, textCoordArray); + } + } else { + gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, glBufferUsage); + bufferWrittenOnce = true; + } + } + + private 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+"], "+getElemUseCountStr()+", "+buffer); + } + if(enable) { - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(useVBO) { + if(0 == vboName) { + throw new InternalError("Using VBO but no vboName"); + } + glf.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); - if(!bufferWritten) { - gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW); - bufferWritten=true; + if(!bufferWritten) { + writeBuffer(gl); + } } + 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 "); } } - public void enableBufferGLSL(GL gl, boolean enable) { - ShaderState st = ShaderState.getShaderState(gl); - if(null==st) { - throw new GLException("No ShaderState in "+gl); - } + private void enableBufferGLSLShaderState(GL gl, boolean enable) { GL2ES2 glsl = gl.getGL2ES2(); - - 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; - } + 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(vComps>0) { - st.enableVertexAttribArray(glsl, vArrayData); - st.vertexAttribPointer(glsl, vArrayData); - } - if(cComps>0) { - st.enableVertexAttribArray(glsl, cArrayData); - st.vertexAttribPointer(glsl, cArrayData); - } - if(nComps>0) { - st.enableVertexAttribArray(glsl, nArrayData); - st.vertexAttribPointer(glsl, nArrayData); - } - if(tComps>0) { - st.enableVertexAttribArray(glsl, tArrayData); - st.vertexAttribPointer(glsl, tArrayData); + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.A.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer); + } + + if(enable) { + if(useVBO) { + if(0 == vboName) { + throw new InternalError("Using VBO but no vboName"); + } + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(!bufferWritten) { + writeBuffer(gl); + } } + bufferWritten=true; + } + + if(useV) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, vArrayData); + shaderState.vertexAttribPointer(glsl, vArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, vArrayData); + } + } + if(useC) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, cArrayData); + shaderState.vertexAttribPointer(glsl, cArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, cArrayData); + } + } + if(useN) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, nArrayData); + shaderState.vertexAttribPointer(glsl, nArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, nArrayData); + } + } + if(useT) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, tArrayData); + shaderState.vertexAttribPointer(glsl, tArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, tArrayData); + } + } + glslLocationSet = true; // ShaderState does set the location implicit + if(enable && useVBO) { 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(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.A.X "); + } + } + + private void enableBufferGLSLSimple(GL gl, boolean enable) { + 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.B.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer); + } + + if(!glslLocationSet) { + if( !resetGLSLArrayLocation(glsl) ) { + if(DEBUG_DRAW) { + final int vLoc = null != vArrayData ? vArrayData.getLocation() : -1; + final int cLoc = null != cArrayData ? cArrayData.getLocation() : -1; + final int nLoc = null != nArrayData ? nArrayData.getLocation() : -1; + final int tLoc = null != tArrayData ? tArrayData.getLocation() : -1; + System.err.println("ImmModeSink.enableGLSL.B.X attribute locations in shader program "+shaderProgram+", incomplete ["+vLoc+", "+cLoc+", "+nLoc+", "+tLoc+"] - glslLocationSet "+glslLocationSet); + } + return; } - if(tComps>0) { - st.disableVertexAttribArray(glsl, tArrayData); + } + + if(enable) { + if(useVBO) { + if(0 == vboName) { + throw new InternalError("Using VBO but no vboName"); + } + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(!bufferWritten) { + writeBuffer(gl); + } } + bufferWritten=true; + } + + if(useV) { + if(enable) { + glsl.glEnableVertexAttribArray(vArrayData.getLocation()); + glsl.glVertexAttribPointer(vArrayData); + } else { + glsl.glDisableVertexAttribArray(vArrayData.getLocation()); + } + } + if(useC) { + if(enable) { + glsl.glEnableVertexAttribArray(cArrayData.getLocation()); + glsl.glVertexAttribPointer(cArrayData); + } else { + glsl.glDisableVertexAttribArray(cArrayData.getLocation()); + } + } + if(useN) { + if(enable) { + glsl.glEnableVertexAttribArray(nArrayData.getLocation()); + glsl.glVertexAttribPointer(nArrayData); + } else { + glsl.glDisableVertexAttribArray(nArrayData.getLocation()); + } + } + if(useT) { + if(enable) { + glsl.glEnableVertexAttribArray(tArrayData.getLocation()); + glsl.glVertexAttribPointer(tArrayData); + } else { + glsl.glDisableVertexAttribArray(tArrayData.getLocation()); + } + } + + if(enable && useVBO) { + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.B.X "); } } + @Override public String toString() { - return "VBOSet[mode "+mode+ - ", modeOrig "+modeOrig+ - ", sealed "+sealed+ - ", bufferEnabled "+bufferEnabled+ - ", bufferWritten "+bufferWritten+ + final String glslS = useGLSL ? + ", useShaderState "+(null!=shaderState)+ + ", shaderProgram "+shaderProgram+ + ", glslLocationSet "+glslLocationSet : ""; + + return "VBOSet[mode "+mode+ + ", modeOrig "+modeOrig+ + ", use/count "+getElemUseCountStr()+ + ", sealed "+sealed+ + ", sealedGL "+sealedGL+ + ", bufferEnabled "+bufferEnabled+ + ", bufferWritten "+bufferWritten+" (once "+bufferWrittenOnce+")"+ + ", useVBO "+useVBO+", vboName "+vboName+ + ", useGLSL "+useGLSL+ + glslS+ ",\n\t"+vArrayData+ ",\n\t"+cArrayData+ ",\n\t"+nArrayData+ @@ -811,165 +1263,239 @@ 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); + protected String getElemUseCountStr() { + return "[v "+vElems+"/"+vCount+", c "+cElems+"/"+cCount+", n "+nElems+"/"+nCount+", t "+tElems+"/"+tCount+"]"; + } - count = elementCount; - bSize = count * ( vWidth + cWidth + nWidth + tWidth ) ; + protected boolean fitElementInBuffer(int type) { + final int addElems = 1; + switch (type) { + case VERTEX: + return ( vCount - vElems ) >= addElems ; + case COLOR: + return ( cCount - cElems ) >= addElems ; + case NORMAL: + return ( nCount - nElems ) >= addElems ; + case TEXTCOORD: + return ( tCount - tElems ) >= addElems ; + default: + throw new InternalError("XXX"); + } + } + + 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 vBytes = vCount * vCompsBytes; + final int cBytes = cCount * cCompsBytes; + final int nBytes = nCount * nCompsBytes; + final int tBytes = tCount * tCompsBytes; - buffer = GLBuffers.newDirectByteBuffer(bSize); + buffer = Buffers.newDirectByteBuffer( vBytes + cBytes + nBytes + tBytes ); + vOffset = 0; - int pos = 0; - int size= count * vWidth ; - if(size>0) { - vertexArray = GLBuffers.sliceGLBuffer(buffer, pos, size, vDataType); + if(vBytes>0) { + vertexArray = GLBuffers.sliceGLBuffer(buffer, vOffset, vBytes, vDataType); } else { vertexArray = null; } - vOffset = pos; - pos+=size; + cOffset=vOffset+vBytes; - size= count * cWidth ; - if(size>0) { - colorArray = GLBuffers.sliceGLBuffer(buffer, pos, size, cDataType); + if(cBytes>0) { + colorArray = GLBuffers.sliceGLBuffer(buffer, cOffset, cBytes, cDataType); } else { colorArray = null; } - cOffset = pos; - pos+=size; + nOffset=cOffset+cBytes; - size= count * nWidth ; - if(size>0) { - normalArray = GLBuffers.sliceGLBuffer(buffer, pos, size, nDataType); + if(nBytes>0) { + normalArray = GLBuffers.sliceGLBuffer(buffer, nOffset, nBytes, nDataType); } else { normalArray = null; } - nOffset = pos; - pos+=size; + tOffset=nOffset+nBytes; - size= count * tWidth ; - if(size>0) { - textCoordArray = GLBuffers.sliceGLBuffer(buffer, pos, size, tDataType); + if(tBytes>0) { + textCoordArray = GLBuffers.sliceGLBuffer(buffer, tOffset, tBytes, tDataType); } else { textCoordArray = null; } - tOffset = pos; - pos+=size; - buffer.position(pos); + buffer.position(tOffset+tBytes); buffer.flip(); if(vComps>0) { - vArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, vComps, vDataType, false, 0, + vArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, vComps, + vDataType, GLBuffers.isGLTypeFixedPoint(vDataType), 0, vertexArray, 0, vOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER); } else { vArrayData = null; } if(cComps>0) { - cArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_COLOR_ARRAY, cComps, cDataType, false, 0, + cArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_COLOR_ARRAY, cComps, + cDataType, GLBuffers.isGLTypeFixedPoint(cDataType), 0, colorArray, 0, cOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER); } else { cArrayData = null; } if(nComps>0) { - nArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_NORMAL_ARRAY, nComps, nDataType, false, 0, + nArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_NORMAL_ARRAY, nComps, + nDataType, GLBuffers.isGLTypeFixedPoint(nDataType), 0, normalArray, 0, nOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER); } else { nArrayData = null; } if(tComps>0) { - tArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, tComps, tDataType, false, 0, + tArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, tComps, + tDataType, GLBuffers.isGLTypeFixedPoint(tDataType), 0, textCoordArray, 0, tOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER); } else { tArrayData = null; } - } + bufferWrittenOnce = false; // new buffer data storage size! - 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); + /** grow buffer by initialElementCount if there is no space for one more element in the designated buffer */ + protected final boolean growBuffer(int type) { + if( null !=buffer && !sealed ) { + if( !fitElementInBuffer(type) ) { + // save olde values .. + final Buffer _vertexArray=vertexArray, _colorArray=colorArray, _normalArray=normalArray, _textCoordArray=textCoordArray; + + if ( reallocateBuffer(resizeElementCount) ) { + if(null!=_vertexArray) { + _vertexArray.flip(); + Buffers.put(vertexArray, _vertexArray); + } + if(null!=_colorArray) { + _colorArray.flip(); + Buffers.put(colorArray, _colorArray); + } + if(null!=_normalArray) { + _normalArray.flip(); + Buffers.put(normalArray, _normalArray); + } + if(null!=_textCoordArray) { + _textCoordArray.flip(); + Buffers.put(textCoordArray, _textCoordArray); + } + return true; + } + } } + return false; } - protected void padding(int type, int fill) { + /** + * Fourth element default value for color (alpha), vertex (w) is '1', + * as specified w/ VertexAttributes (ES2/GL3). + * <p> + * vec4 v = vec4(0, 0, 0, 1); + * vec4 c = vec4(0, 0, 0, 1); + * </p> + * + * @param type + * @param fill + */ + private void countAndPadding(int type, int fill) { if ( sealed ) return; - Buffer dest = null; + final Buffer dest; + final boolean dSigned; + final int e; // either 0 or 1 switch (type) { case VERTEX: dest = vertexArray; + dSigned = vDataTypeSigned; + e = 4 == vComps ? 1 : 0; + vElems++; break; case COLOR: dest = colorArray; + dSigned = cDataTypeSigned; + e = 4 == cComps ? 1 : 0; + cElems++; break; case NORMAL: dest = normalArray; + dSigned = nDataTypeSigned; + e = 0; + nElems++; break; case TEXTCOORD: dest = textCoordArray; + dSigned = tDataTypeSigned; + e = 0; + tElems++; break; + default: throw new InternalError("Invalid type "+type); } if ( null==dest ) return; - while((fill--)>0) { - GLBuffers.putb(dest, (byte)0); + while( fill > e ) { + fill--; + Buffers.putNf(dest, dSigned, 0f); + } + if( fill > 0 ) { // e == 1, add missing '1f end component' + Buffers.putNf(dest, dSigned, 1f); } } - protected int mode, modeOrig; - protected int glBufferUsage, initialElementCount; - - protected ByteBuffer buffer; - protected int bSize, count, 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 vComps, cComps, nComps, tComps; - 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; + final private int glBufferUsage, initialElementCount; + final private boolean useVBO, useGLSL; + final private ShaderState shaderState; + private int shaderProgram; + private int mode, modeOrig, resizeElementCount; + + private ByteBuffer buffer; + private int vboName; + + private static final int VERTEX = 0; + private static final int COLOR = 1; + private static final int NORMAL = 2; + private static final int TEXTCOORD = 3; + + private int vCount, cCount, nCount, tCount; // number of elements fit in each buffer + private int vOffset, cOffset, nOffset, tOffset; // offset of specific array in common buffer + private int vElems, cElems, nElems, tElems; // number of used elements in each buffer + private final int vComps, cComps, nComps, tComps; // number of components for each elements [2, 3, 4] + private final int vCompsBytes, cCompsBytes, nCompsBytes, tCompsBytes; // byte size of all components + private final int vDataType, cDataType, nDataType, tDataType; + private final boolean vDataTypeSigned, cDataTypeSigned, nDataTypeSigned, tDataTypeSigned; + private final int pageSize; + private Buffer vertexArray, colorArray, normalArray, textCoordArray; + private GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData; + + private boolean sealed, sealedGL; + private boolean bufferEnabled, bufferWritten, bufferWrittenOnce; + private boolean glslLocationSet; } } |