diff options
Diffstat (limited to 'src/jogl/classes/com')
5 files changed, 438 insertions, 114 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java index 88cb3303f..e0bbbc33c 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java @@ -1,3 +1,30 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package com.jogamp.opengl.util; @@ -120,6 +147,17 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData return adc; } + @Override + public void associate(Object obj, boolean enable) { + if(obj instanceof ShaderState) { + if(enable) { + shaderState = (ShaderState)obj; + } else { + shaderState = null; + } + } + } + // // Data read access // @@ -157,7 +195,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData seal(seal); enableBuffer(gl, seal); } - + @Override public void enableBuffer(GL gl, boolean enable) { if( enableBufferAlways || bufferEnabled != enable ) { @@ -166,16 +204,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData // init/generate VBO name if not done yet init_vbo(gl); } - final Object ext; - if(usesGLSL) { - ext = ShaderState.getShaderState(gl); - if(null == ext) { - throw new GLException("A ShaderState must be bound to the GL context, use 'ShaderState.setShaderState(gl)'"); - } - } else { - ext = null; - } - glArrayHandler.enableState(gl, enable, ext); + glArrayHandler.enableState(gl, enable, usesGLSL ? shaderState : null); bufferEnabled = enable; } } @@ -297,6 +326,8 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData ", index "+index+ ", location "+location+ ", isVertexAttribute "+isVertexAttribute+ + ", usesGLSL "+usesGLSL+ + ", usesShaderState "+(null!=shaderState)+ ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ @@ -421,5 +452,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData protected GLArrayHandler glArrayHandler; protected boolean usesGLSL; + protected ShaderState shaderState; + } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java index c9dd98751..7e7d27b36 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java @@ -1,3 +1,30 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package com.jogamp.opengl.util; @@ -332,6 +359,8 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE ", index "+index+ ", location "+location+ ", isVertexAttribute "+isVertexAttribute+ + ", usesGLSL "+usesGLSL+ + ", usesShaderState "+(null!=shaderState)+ ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java index f4a197be1..7d08ad08f 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java @@ -1,3 +1,30 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package com.jogamp.opengl.util; @@ -97,53 +124,91 @@ public class GLArrayDataWrapper implements GLArrayData { return glp.isValidArrayDataType(getIndex(), getComponentCount(), getComponentType(), isVertexAttribute(), throwException); } + @Override + public void associate(Object obj, boolean enable) { + // nop + } + // // Data read access // + @Override public final boolean isVertexAttribute() { return isVertexAttribute; } + @Override public final int getIndex() { return index; } + @Override public final int getLocation() { return location; } - public final void setLocation(int v) { location = v; } + @Override + public final int setLocation(int v) { location = v; return location; } + @Override + public final int setLocation(GL2ES2 gl, int program) { + location = gl.glGetAttribLocation(program, name); + return location; + } + + @Override + public final int setLocation(GL2ES2 gl, int program, int location) { + this.location = location; + gl.glBindAttribLocation(program, location, name); + return location; + } + + @Override public final String getName() { return name; } + @Override public final long getVBOOffset() { return vboEnabled?vboOffset:0; } + @Override public final int getVBOName() { return vboEnabled?vboName:0; } + @Override public final boolean isVBO() { return vboEnabled; } + @Override public final int getVBOUsage() { return vboEnabled?vboUsage:0; } + @Override public final int getVBOTarget() { return vboEnabled?vboTarget:0; } + @Override public final Buffer getBuffer() { return buffer; } + @Override public final int getComponentCount() { return components; } + @Override public final int getComponentType() { return componentType; } + @Override public final int getComponentSizeInBytes() { return componentByteSize; } + @Override public final int getElementCount() { if(null==buffer) return 0; return ( buffer.position()==0 ) ? ( buffer.limit() / components ) : ( buffer.position() / components ) ; } + + @Override public final int getSizeInBytes() { if(null==buffer) return 0; return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ; } + @Override public final boolean getNormalized() { return normalized; } + @Override public final int getStride() { return strideB; } - public final Class getBufferClass() { return componentClazz; } + public final Class<?> getBufferClass() { return componentClazz; } + @Override public void destroy(GL gl) { buffer = null; vboName=0; @@ -152,6 +217,7 @@ public class GLArrayDataWrapper implements GLArrayData { alive = false; } + @Override public String toString() { return "GLArrayDataWrapper["+name+ ", index "+index+ @@ -172,7 +238,7 @@ public class GLArrayDataWrapper implements GLArrayData { "]"; } - public static final Class getBufferClass(int dataType) { + public static final Class<?> getBufferClass(int dataType) { switch(dataType) { case GL.GL_BYTE: case GL.GL_UNSIGNED_BYTE: @@ -189,6 +255,7 @@ public class GLArrayDataWrapper implements GLArrayData { } } + @Override public void setName(String newName) { location = -1; name = newName; @@ -310,14 +377,13 @@ public class GLArrayDataWrapper implements GLArrayData { protected String name; protected int components; protected int componentType; - protected Class componentClazz; + protected Class<?> componentClazz; protected int componentByteSize; protected boolean normalized; protected int strideB; // stride in bytes protected int strideL; // stride in logical components protected Buffer buffer; protected boolean isVertexAttribute; - protected long vboOffset; protected int vboName; protected boolean vboEnabled; diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java index f01896b96..27ce7d8ec 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -35,7 +35,7 @@ import com.jogamp.opengl.util.glsl.ShaderState; * 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> + * 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. @@ -82,13 +82,11 @@ public class ImmModeSink { int glBufferUsage) { return new ImmModeSink(initialElementCount, vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, - false, glBufferUsage); + 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> @@ -104,7 +102,7 @@ public class ImmModeSink { * @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() @@ -114,12 +112,45 @@ public class ImmModeSink { int cComps, int cDataType, int nComps, int nDataType, int tComps, int tDataType, - int glBufferUsage) { + int glBufferUsage, ShaderState st) { return new ImmModeSink(initialElementCount, vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, - true, glBufferUsage); + true, glBufferUsage, st, 0); } + /** + * 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); @@ -330,10 +361,10 @@ public class ImmModeSink { 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); + 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>(); } @@ -349,7 +380,7 @@ public class ImmModeSink { * 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) + * @see #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState) */ public void setResizeElementCount(int v) { vboSet.setResizeElementCount(v); } @@ -369,9 +400,19 @@ public class ImmModeSink { int cComps, int cDataType, int nComps, int nDataType, int tComps, int tDataType, - boolean useGLSL, int glBufferUsage) { + 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); @@ -389,8 +430,6 @@ public class ImmModeSink { this.tDataTypeSigned=GLBuffers.isSignedGLType(tDataType); this.tComps=tComps; this.tCompsBytes=tComps * GLBuffers.sizeOfGLType(tDataType); - this.useGLSL=useGLSL; - this.useVBO = 0 != glBufferUsage; this.vboName = 0; this.vCount=0; @@ -414,6 +453,7 @@ public class ImmModeSink { this.bufferEnabled=false; this.bufferWritten=false; this.bufferWrittenOnce=false; + this.glslLocationSet = false; } protected int getResizeElementCount() { return resizeElementCount; } @@ -423,7 +463,8 @@ public class ImmModeSink { protected final VBOSet regenerate(GL gl) { return new VBOSet(initialElementCount, vComps, - vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL, glBufferUsage); + vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + useGLSL, glBufferUsage, shaderState, shaderProgram); } protected void checkSeal(boolean test) throws GLException { @@ -439,10 +480,27 @@ public class ImmModeSink { } } + 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) { System.err.println("ImmModeSink.draw["+i+"].0 (disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); } @@ -788,6 +846,51 @@ 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); @@ -868,8 +971,13 @@ public class ImmModeSink { checkSeal(true); } bufferEnabled = enable; - if(useGLSL) { - enableBufferGLSL(gl, enable); + if(useGLSL) { + useShaderProgram(gl.getGL2ES2(), true); + if(null != shaderState) { + enableBufferGLSLShaderState(gl, enable); + } else { + enableBufferGLSLSimple(gl, enable); + } } else { enableBufferFixed(gl, enable); } @@ -901,7 +1009,7 @@ public class ImmModeSink { } } - public void enableBufferFixed(GL gl, boolean enable) { + private void enableBufferFixed(GL gl, boolean enable) { GL2ES1 glf = gl.getGL2ES1(); final boolean useV = vComps>0 && vElems>0 ; @@ -969,11 +1077,75 @@ public class ImmModeSink { } } - 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(); + + 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.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); + } + + 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 ; @@ -982,7 +1154,20 @@ public class ImmModeSink { 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+"], "+getElemUseCountStr()+", "+buffer); + 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(enable) { @@ -1000,34 +1185,34 @@ public class ImmModeSink { if(useV) { if(enable) { - st.enableVertexAttribArray(glsl, vArrayData); - st.vertexAttribPointer(glsl, vArrayData); + glsl.glEnableVertexAttribArray(vArrayData.getLocation()); + glsl.glVertexAttribPointer(vArrayData); } else { - st.disableVertexAttribArray(glsl, vArrayData); + glsl.glDisableVertexAttribArray(vArrayData.getLocation()); } } if(useC) { if(enable) { - st.enableVertexAttribArray(glsl, cArrayData); - st.vertexAttribPointer(glsl, cArrayData); + glsl.glEnableVertexAttribArray(cArrayData.getLocation()); + glsl.glVertexAttribPointer(cArrayData); } else { - st.disableVertexAttribArray(glsl, cArrayData); + glsl.glDisableVertexAttribArray(cArrayData.getLocation()); } } if(useN) { if(enable) { - st.enableVertexAttribArray(glsl, nArrayData); - st.vertexAttribPointer(glsl, nArrayData); + glsl.glEnableVertexAttribArray(nArrayData.getLocation()); + glsl.glVertexAttribPointer(nArrayData); } else { - st.disableVertexAttribArray(glsl, nArrayData); + glsl.glDisableVertexAttribArray(nArrayData.getLocation()); } } if(useT) { if(enable) { - st.enableVertexAttribArray(glsl, tArrayData); - st.vertexAttribPointer(glsl, tArrayData); + glsl.glEnableVertexAttribArray(tArrayData.getLocation()); + glsl.glVertexAttribPointer(tArrayData); } else { - st.disableVertexAttribArray(glsl, tArrayData); + glsl.glDisableVertexAttribArray(tArrayData.getLocation()); } } @@ -1036,11 +1221,16 @@ public class ImmModeSink { } if(DEBUG_DRAW) { - System.err.println("ImmModeSink.enableGLSL.X "); + System.err.println("ImmModeSink.enableGLSL.B.X "); } } - + public String toString() { + final String glslS = useGLSL ? + ", useShaderState "+(null!=shaderState)+ + ", shaderProgram "+shaderProgram+ + ", glslLocationSet "+glslLocationSet : ""; + return "VBOSet[mode "+mode+ ", modeOrig "+modeOrig+ ", use/count "+getElemUseCountStr()+ @@ -1049,6 +1239,8 @@ public class ImmModeSink { ", bufferEnabled "+bufferEnabled+ ", bufferWritten "+bufferWritten+" (once "+bufferWrittenOnce+")"+ ", useVBO "+useVBO+", vboName "+vboName+ + ", useGLSL "+useGLSL+ + glslS+ ",\n\t"+vArrayData+ ",\n\t"+cArrayData+ ",\n\t"+nArrayData+ @@ -1264,7 +1456,9 @@ public class ImmModeSink { } final private int glBufferUsage, initialElementCount; - final private boolean useVBO; + final private boolean useVBO, useGLSL; + final private ShaderState shaderState; + private int shaderProgram; private int mode, modeOrig, resizeElementCount; private ByteBuffer buffer; @@ -1286,8 +1480,9 @@ public class ImmModeSink { private Buffer vertexArray, colorArray, normalArray, textCoordArray; private GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData; - private boolean sealed, sealedGL, useGLSL; + private boolean sealed, sealedGL; private boolean bufferEnabled, bufferWritten, bufferWrittenOnce; + private boolean glslLocationSet; } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java index ff8982ddf..9d71ee276 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -35,7 +35,6 @@ import java.util.Iterator; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLArrayData; -import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; @@ -58,7 +57,6 @@ import com.jogamp.opengl.util.GLArrayDataEditable; */ public class ShaderState { public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true); - private static final String currentStateKey = "jogamp.opengl.glsl.ShaderState" ; public ShaderState() { } @@ -68,46 +66,6 @@ public class ShaderState { public void setVerbose(boolean v) { verbose = DEBUG || v; } /** - * Fetches the current shader state from this thread (TLS) current GLContext - * - * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() - */ - public static ShaderState getCurrentShaderState() { - return getShaderState(GLContext.getCurrentGL()); - } - - /** - * Gets the shader state attached to the GL object's GLContext - * - * @param gl the GL object referencing the GLContext - * - * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() - */ - public static ShaderState getShaderState(GL gl) { - return (ShaderState) gl.getContext().getAttachedObject(currentStateKey); - } - - /** - * Attaches the shader state to the GL object's GLContext - * - * @param gl the GL object referencing the GLContext - * - * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() - */ - public final ShaderState setShaderState(GL gl) { - return (ShaderState) gl.getContext().attachObject(currentStateKey, this); - } - - /** * Returns the attached user object for the given name to this ShaderState. */ public final Object getAttachedObject(String name) { @@ -135,19 +93,14 @@ public class ShaderState { /** * Turns the shader program on or off.<br> - * Puts this ShaderState to to the thread local storage (TLS), - * if <code>on</code> is <code>true</code>. * * @throws GLException if no program is attached * * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() */ public synchronized void useProgram(GL2ES2 gl, boolean on) throws GLException { if(null==shaderProgram) { throw new GLException("No program is attached"); } if(on) { - setShaderState(gl); if(shaderProgram.linked()) { shaderProgram.useProgram(gl, true); if(resetAllShaderData) { @@ -332,6 +285,10 @@ public class ShaderState { return activeAttribDataMap.get(name); } + public boolean isActiveAttribute(GLArrayData attribute) { + return attribute == activeAttribDataMap.get(attribute.getName()); + } + /** * Binds or unbinds the {@link GLArrayData} lifecycle to this ShaderState. * @@ -343,11 +300,14 @@ public class ShaderState { * * <p>The data will not be transfered to the GPU, use {@link #vertexAttribPointer(GL2ES2, GLArrayData)} additionally.</p> * + * <p>The data will also be {@link GLArrayData#associate(Object, boolean) associated} with this ShaderState.</p> + * * @param attribute the {@link GLArrayData} which lifecycle shall be managed * @param own true if <i>owning</i> shall be performs, false if <i>disowning</i>. * * @see #bindAttribLocation(GL2ES2, int, String) * @see #getAttribute(String) + * @see GLArrayData#associate(Object, boolean) */ public void ownAttribute(GLArrayData attribute, boolean own) { if(own) { @@ -359,6 +319,7 @@ public class ShaderState { } else { managedAttributes.remove(attribute); } + attribute.associate(this, own); } public boolean ownsAttribute(GLArrayData attribute) { @@ -402,8 +363,12 @@ public class ShaderState { * @see #getAttribute(String) */ public void bindAttribLocation(GL2ES2 gl, int location, GLArrayData data) { - bindAttribLocation(gl, location, data.getName()); - data.setLocation(location); + if(null==shaderProgram) throw new GLException("No program is attached"); + if(shaderProgram.linked()) throw new GLException("Program is already linked"); + final String name = data.getName(); + final Integer loc = new Integer(location); + activeAttribLocationMap.put(name, loc); + data.setLocation(gl, shaderProgram.program(), location); activeAttribDataMap.put(data.getName(), data); } @@ -465,8 +430,27 @@ public class ShaderState { * @see #getAttribute(String) */ public int getAttribLocation(GL2ES2 gl, GLArrayData data) { - int location = getAttribLocation(gl, data.getName()); - data.setLocation(location); + if(null==shaderProgram) throw new GLException("No program is attached"); + final String name = data.getName(); + int location = getCachedAttribLocation(name); + if(0<=location) { + data.setLocation(location); + } else { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + location = data.setLocation(gl, shaderProgram.program()); + if(0<=location) { + Integer idx = new Integer(location); + activeAttribLocationMap.put(name, idx); + if(DEBUG) { + System.err.println("ShaderState: glGetAttribLocation: "+name+", loc: "+location); + } + } else if(verbose) { + System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location); + if(DEBUG) { + Thread.dumpStack(); + } + } + } activeAttribDataMap.put(data.getName(), data); return location; } @@ -873,6 +857,7 @@ public class ShaderState { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); int location = getCachedUniformLocation(name); if(0>location) { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); location = gl.glGetUniformLocation(shaderProgram.program(), name); if(0<=location) { Integer idx = new Integer(location); @@ -886,7 +871,7 @@ public class ShaderState { } return location; } - + /** * Validates and returns the location of a shader uniform.<br> * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid, @@ -908,9 +893,25 @@ public class ShaderState { * @see ShaderProgram#glReplaceShader */ public int getUniformLocation(GL2ES2 gl, GLUniformData data) { - int location = getUniformLocation(gl, data.getName()); - data.setLocation(location); - activeUniformDataMap.put(data.getName(), data); + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + final String name = data.getName(); + int location = getCachedUniformLocation(name); + if(0<=location) { + data.setLocation(location); + } else { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + location = data.setLocation(gl, shaderProgram.program()); + if(0<=location) { + Integer idx = new Integer(location); + activeUniformLocationMap.put(name, idx); + } else if(verbose) { + System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location); + if(DEBUG) { + Thread.dumpStack(); + } + } + } + activeUniformDataMap.put(name, data); return location; } |