diff options
author | Sven Gothel <[email protected]> | 2012-12-16 02:55:07 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-12-16 02:55:07 +0100 |
commit | b8a8fc24a3afb0cb06a31504bdea1a98b8f00ef4 (patch) | |
tree | 37bd8b49f7e4fd547ff58656dff09b5a88e65c47 /src/jogl | |
parent | e7064ece049705e013d80985eae698ce0ee3c4e3 (diff) |
GLArrayData/ImmModeSink: Remove implicit dependency on ShaderState - allow operating w/o it; ShaderState: Remove notion of GL context attachment, use pass-through or object association; GLArrayData/GLUniformData: Add basic GLSL location methods
- GLArrayData/GLUniformData: Add basic GLSL location methods
- GLArrayData
- add: setLocation(..) for attribute location/index retrieval (post link) and binding (pre link)
- GLUniformData
- add: setLocation(..) for attribute location/index retrieval (post link)
- GLArrayData/ImmModeSink: Remove implicit dependency on ShaderState - allow operating w/o it
- GLArrayData
- add: 'public void associate(Object obj, boolean enable)', allows setting ShaderState usage
- ShaderState: Remove notion of GL context attachment, use pass-through or object association
- ownsAttribute(..) associates the attribute w/ ShaderState
- removed GL context ShaderState attachment
Tested:
- ImmModeSink w/ GLSL/ES2 w/ and w/o ShaderState
- GLArrayData* w/ and w/o ShaderState
Diffstat (limited to 'src/jogl')
11 files changed, 621 insertions, 153 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; } diff --git a/src/jogl/classes/javax/media/opengl/GLArrayData.java b/src/jogl/classes/javax/media/opengl/GLArrayData.java index 5d17f6874..8e1383031 100644 --- a/src/jogl/classes/javax/media/opengl/GLArrayData.java +++ b/src/jogl/classes/javax/media/opengl/GLArrayData.java @@ -30,6 +30,8 @@ package javax.media.opengl; import java.nio.Buffer; +import javax.media.opengl.fixedfunc.GLPointerFunc; + /** * * The total number of bytes hold by the referenced buffer is: @@ -38,6 +40,19 @@ import java.nio.Buffer; */ public interface GLArrayData { /** + * Implementation and type dependent object association. + * <p> + * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState} + * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's + * data persistence, location and state change.<br/> + * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}. + * </p> + * @param obj implementation and type dependent association + * @param enable pass true to enable the association and false to disable it. + */ + public void associate(Object obj, boolean enable); + + /** * Returns true if this data set is intended for a GLSL vertex shader attribute, * otherwise false, ie intended for fixed function vertex pointer */ @@ -47,10 +62,10 @@ public interface GLArrayData { * The index of the predefined array index, see list below, * or -1 in case of a shader attribute array. * - * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY - * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY - * @see javax.media.opengl.GL2#GL_COLOR_ARRAY - * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY + * @see GLPointerFunc#GL_VERTEX_ARRAY + * @see GLPointerFunc#GL_NORMAL_ARRAY + * @see GLPointerFunc#GL_COLOR_ARRAY + * @see GLPointerFunc#GL_TEXTURE_COORD_ARRAY */ public int getIndex(); @@ -61,6 +76,11 @@ public interface GLArrayData { /** * Set a new name for this array. + * <p> + * This clears the location, i.e. sets it to -1. + * </p> + * @see #setLocation(int) + * @see #setLocation(GL2ES2, int) */ public void setName(String newName); @@ -72,14 +92,37 @@ public interface GLArrayData { public int getLocation(); /** - * Sets the determined location of the shader attribute - * This is usually done within ShaderState. + * Sets the given location of the shader attribute * + * @return the given location * @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData) */ - public void setLocation(int v); + public int setLocation(int v); /** + * Retrieves the location of the shader attribute from the linked shader program. + * <p> + * No validation is performed within the implementation. + * </p> + * @param gl + * @param program + * @return ≥0 denotes a valid attribute location as found and used in the given shader program. + * <0 denotes an invalid location, i.e. not found or used in the given shader program. + */ + public int setLocation(GL2ES2 gl, int program); + + /** + * Binds the location of the shader attribute to the given location for the unlinked shader program. + * <p> + * No validation is performed within the implementation. + * </p> + * @param gl + * @param program + * @return the given location + */ + public int setLocation(GL2ES2 gl, int program, int location); + + /** * Determines whether the data is server side (VBO) and enabled, * or a client side array (false). */ diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java index 18a422670..60d0c58bf 100644 --- a/src/jogl/classes/javax/media/opengl/GLUniformData.java +++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java @@ -147,10 +147,26 @@ public class GLUniformData { public int getLocation() { return location; } /** - * Sets the determined location of the shader uniform. + * Sets the given location of the shader uniform. + * @return the given location */ - public GLUniformData setLocation(int location) { this.location=location; return this; } + public int setLocation(int location) { this.location=location; return location; } + /** + * Retrieves the location of the shader uniform from the linked shader program. + * <p> + * No validation is performed within the implementation. + * </p> + * @param gl + * @param program + * @return ≥0 denotes a valid uniform location as found and used in the given shader program. + * <0 denotes an invalid location, i.e. not found or used in the given shader program. + */ + public int setLocation(GL2ES2 gl, int program) { + location = gl.glGetUniformLocation(program, name); + return location; + } + public Object getObject() { return data; } diff --git a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java index 62ff3aa09..7cd7da53e 100644 --- a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java +++ b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java @@ -120,6 +120,7 @@ import javax.media.opengl.glu.GLU; import javax.media.opengl.glu.GLUquadric; import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.glsl.ShaderState; /** * GLUquadricImpl.java @@ -140,22 +141,26 @@ public class GLUquadricImpl implements GLUquadric { private boolean immModeSinkImmediate; public int normalType; public GL gl; + public ShaderState shaderState; + public int shaderProgram; public static final boolean USE_NORM = true; public static final boolean USE_TEXT = false; private ImmModeSink immModeSink=null; - public GLUquadricImpl(GL gl, boolean useGLSL) { + public GLUquadricImpl(GL gl, boolean useGLSL, ShaderState st, int shaderProgram) { this.gl=gl; this.useGLSL = useGLSL; - drawStyle = GLU.GLU_FILL; - orientation = GLU.GLU_OUTSIDE; - textureFlag = false; - normals = GLU.GLU_SMOOTH; - normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT; - immModeSinkImmediate=true; - immModeSinkEnabled=!gl.isGL2(); + this.drawStyle = GLU.GLU_FILL; + this.orientation = GLU.GLU_OUTSIDE; + this.textureFlag = false; + this.normals = GLU.GLU_SMOOTH; + this.normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT; + this.immModeSinkImmediate=true; + this.immModeSinkEnabled=!gl.isGL2(); + this.shaderState = st; + this.shaderProgram = shaderProgram; replaceImmModeSink(); } @@ -191,12 +196,21 @@ public class GLUquadricImpl implements GLUquadric { ImmModeSink res = immModeSink; if(useGLSL) { - immModeSink = ImmModeSink.createGLSL (32, - 3, GL.GL_FLOAT, // vertex - 0, GL.GL_FLOAT, // color - USE_NORM?3:0, normalType, // normal - USE_TEXT?2:0, GL.GL_FLOAT, // texCoords - GL.GL_STATIC_DRAW); + if(null != shaderState) { + immModeSink = ImmModeSink.createGLSL (32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType, // normal + USE_TEXT?2:0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW, shaderState); + } else { + immModeSink = ImmModeSink.createGLSL (32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType, // normal + USE_TEXT?2:0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW, shaderProgram); + } } else { immModeSink = ImmModeSink.createFixed(32, 3, GL.GL_FLOAT, // vertex diff --git a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java index a6314a216..1a4ca345b 100644 --- a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java @@ -31,9 +31,9 @@ package jogamp.opengl.util; import javax.media.opengl.*; /** - * Handles consistency of buffer data and array state. - * Implementations shall consider buffer types (VBO, ..), interleaved, etc. - * They also need to consider array state types, i.e. fixed function or GLSL. + * Handles consistency of buffer data and array state.<br/> + * Implementations shall consider buffer types (VBO, ..), interleaved, etc.<br/> + * They also need to consider array state types, i.e. fixed function or GLSL.<br/> */ public interface GLArrayHandler { diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java index 79bed90c9..3c468f358 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java @@ -44,8 +44,8 @@ import com.jogamp.opengl.util.glsl.ShaderState; * Used for 1:1 GLSL arrays, i.e. where the buffer data * represents this array only. */ -public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandler { - +public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandler { + public GLSLArrayHandler(GLArrayDataEditable ad) { super(ad); } @@ -60,8 +60,14 @@ public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandle public final void enableState(GL gl, boolean enable, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - + if( null != ext ) { + enableShaderState(glsl, enable, (ShaderState)ext); + } else { + enableSimple(glsl, enable); + } + } + + private final void enableShaderState(GL2ES2 glsl, boolean enable, ShaderState st) { if(enable) { /* * This would be the non optimized code path: @@ -108,5 +114,57 @@ public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandle st.disableVertexAttribArray(glsl, ad); } } + + private final void enableSimple(GL2ES2 glsl, boolean enable) { + final int location = ad.getLocation(); + if( 0 > location ) { + return; + } + if(enable) { + /* + * This would be the non optimized code path: + * + if(ad.isVBO()) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + if(!ad.isVBOWritten()) { + if(null!=buffer) { + glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + } + ad.setVBOWritten(true); + } + } + st.vertexAttribPointer(glsl, ad); + */ + final Buffer buffer = ad.getBuffer(); + if(ad.isVBO()) { + // bind and refresh the VBO / vertex-attr only if necessary + if(!ad.isVBOWritten()) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + if(null!=buffer) { + glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + } + ad.setVBOWritten(true); + glsl.glVertexAttribPointer(ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } else { + // didn't experience a performance hit on this query .. + // (using ShaderState's location query above to validate the location) + final int[] qi = new int[1]; + glsl.glGetVertexAttribiv(location, GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); + if(ad.getVBOName() != qi[0]) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + glsl.glVertexAttribPointer(ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } + } + } else if(null!=buffer) { + glsl.glVertexAttribPointer(ad); + } + + glsl.glEnableVertexAttribArray(location); + } else { + glsl.glDisableVertexAttribArray(location); + } + } } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java index c5beb7dd0..855406db3 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java @@ -53,9 +53,13 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat { public final void syncData(GL gl, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - - st.vertexAttribPointer(glsl, ad); + if( null != ext ) { + ((ShaderState)ext).vertexAttribPointer(glsl, ad); + } else { + if( 0 <= ad.getLocation() ) { + glsl.glVertexAttribPointer(ad); + } + } /** * Due to probable application VBO switching, this might not make any sense .. * @@ -75,13 +79,22 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat { public final void enableState(GL gl, boolean enable, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - - if(enable) { - st.enableVertexAttribArray(glsl, ad); + if( null != ext ) { + final ShaderState st = (ShaderState)ext; + if(enable) { + st.enableVertexAttribArray(glsl, ad); + } else { + st.disableVertexAttribArray(glsl, ad); + } } else { - st.disableVertexAttribArray(glsl, ad); + final int location = ad.getLocation(); + if( 0 <= location ) { + if(enable) { + glsl.glEnableVertexAttribArray(location); + } else { + glsl.glDisableVertexAttribArray(location); + } + } } } } - |