diff options
author | Sven Gothel <[email protected]> | 2011-04-22 14:29:12 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-04-22 14:29:12 +0200 |
commit | 54f58c0cb990eb2b4fc8c3be785cc47bde575f37 (patch) | |
tree | 20a3d4b0a4b4d6aceab9a8f65a8b05560ae3d8b3 /src/jogl/classes/com/jogamp/opengl | |
parent | c1688186ece849002650bdb667a71bbcc628a684 (diff) |
ShaderState: Validated impl./state-handling / Added comments
Capable of glBinAttribLocation(..)
Proper state check (has program, linked program, ..) for attrib/uniform methods.
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java | 674 |
1 files changed, 453 insertions, 221 deletions
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 57ae6cfda..fe695ecb3 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -28,13 +28,22 @@ package com.jogamp.opengl.util.glsl; -import javax.media.opengl.*; -import jogamp.opengl.Debug; - +import java.security.AccessController; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.security.*; + +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; + +import jogamp.opengl.Debug; + +import com.jogamp.common.util.IntObjectHashMap; +import com.jogamp.opengl.util.GLArrayDataEditable; public class ShaderState { public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true, AccessController.getContext()); @@ -47,41 +56,106 @@ public class ShaderState { public void setVerbose(boolean v) { verbose=v; } /** - * Fetches the current shader state from the thread local storage (TLS) + * Fetches the current shader state from this thread (TLS) current GLContext * * @see com.jogamp.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrent() + * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() */ - public static synchronized ShaderState getCurrent() { - GLContext current = GLContext.getCurrent(); - if(null==current) { - throw new GLException("No context is current on this thread"); - } - return (ShaderState) current.getAttachedObject(ShaderState.class.getName()); + public static synchronized ShaderState getCurrentShaderState() { + return getShaderState(GLContext.getCurrentGL()); + } + + /** + * Fetches the shader state from the GL object's GLContext + * + * @param gl the GL object referencing the GLContext + * + * @see com.jogamp.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() + */ + public static synchronized ShaderState getShaderState(GL gl) { + return (ShaderState) gl.getContext().getAttachedObject(ShaderState.class.getName()); + } + + /** + * Returns the attached user object for the given name to this ShaderState. + */ + public final Object getAttachedObject(String name) { + return attachedObjectsByString.get(name); + } + + /** + * Attach user object for the given name to this ShaderState. + * Returns the previously set object or null. + * + * @return the previous mapped object or null if none + */ + public final Object attachObject(String name, Object obj) { + return attachedObjectsByString.put(name, obj); + } + + /** + * @param name name of the mapped object to detach + * + * @return the previous mapped object or null if none + */ + public final Object detachObject(String name) { + return attachedObjectsByString.remove(name); + } + + /** + * Returns the attached user object for the given name to this ShaderState. + */ + public final Object getAttachedObject(int name) { + return attachedObjectsByInt.get(name); + } + + /** + * Attach user object for the given name to this ShaderState. + * Returns the previously set object or null. + */ + public final Object attachObject(int name, Object obj) { + return attachedObjectsByInt.put(name, obj); } + public final Object detachObject(int name) { + return attachedObjectsByInt.remove(name); + } + /** * 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 + * @throws GLException if no program is not linked + * * @see com.jogamp.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrent() + * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() */ public synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(null==shaderProgram) { throw new GLException("No program is attached"); } if(on) { - if(null!=shaderProgram) { - shaderProgram.glUseProgram(gl, true); - } else { - throw new GLException("No program is attached"); - } + shaderProgram.glUseProgram(gl, true); // update the current ShaderState to the TLS .. - gl.getContext().putAttachedObject(ShaderState.class.getName(), this); - } else if(null!=shaderProgram) { + gl.getContext().attachObject(ShaderState.class.getName(), this); + if(resetAllShaderData) { + resetAllShaderData = false; + glResetAllVertexAttributes(gl); + glResetAllUniforms(gl); + } + } else { shaderProgram.glUseProgram(gl, false); } } + public synchronized void glUseProgram(GL2ES2 gl, ShaderProgram prog, boolean on) { + + } + public boolean linked() { return (null!=shaderProgram)?shaderProgram.linked():false; } @@ -118,7 +192,8 @@ public class ShaderState { return; } prgInUse = shaderProgram.inUse(); - shaderProgram.glUseProgram(gl, false); + glUseProgram(gl, false); + resetAllShaderData = true; } // register new one @@ -126,11 +201,11 @@ public class ShaderState { if(null!=shaderProgram) { // reinstall all data .. - shaderProgram.glUseProgram(gl, true); - glResetAllVertexAttributes(gl); - glResetAllUniforms(gl); - if(!prgInUse) { - shaderProgram.glUseProgram(gl, false); + if(shaderProgram.linked()) { + glUseProgram(gl, true); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } } } if(DEBUG) { @@ -149,6 +224,8 @@ public class ShaderState { */ public synchronized void destroy(GL2ES2 gl) { release(gl, true, true); + attachedObjectsByString.clear(); + attachedObjectsByInt.clear(); } /** @@ -191,193 +268,358 @@ public class ShaderState { // /** - * Binds an attribute to the shader. - * This must be done before the program is linked ! - * n name - 1 idx, where name is a uniq key + * Gets the cached location of a shader attribute. + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + * + * @see #glBindAttribLocation(GL2ES2, int, String) + * @see #glBindAttribLocation(GL2ES2, int, GLArrayData) + * @see #glGetAttribLocation(GL2ES2, String) + * @see GL2ES2#glGetAttribLocation(int, String) + */ + public int getAttribLocation(String name) { + Integer idx = (Integer) attribMap2Location.get(name); + return (null!=idx)?idx.intValue():-1; + } + + /** + * Get the previous cached vertex attribute data. + * + * @return the GLArrayData object, null if not previously set. * - * @throws GLException is the program is already linked + * @see #bindAttribute(GLArrayData) * - * @see #glBindAttribLocation - * @see javax.media.opengl.GL2ES2#glBindAttribLocation - * @see #glGetAttribLocation - * @see javax.media.opengl.GL2ES2#glGetAttribLocation - * @see #getAttribLocation + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes * @see ShaderProgram#glReplaceShader */ - public void glBindAttribLocation(GL2ES2 gl, int index, String name) { - if(null==shaderProgram) throw new GLException("No program is attached"); - if(shaderProgram.linked()) throw new GLException("Program is already linked"); - Integer idx = new Integer(index); - if(!attribMap2Idx.containsKey(name)) { - attribMap2Idx.put(name, idx); - gl.glBindAttribLocation(shaderProgram.program(), index, name); + public GLArrayData getAttribute(String name) { + return (GLArrayData) vertexAttribMap2Data.get(name); + } + + /** + * Bind the {@link GLArrayData} to this ShaderState. + * If an attribute location is cached (ie {@link #glBindAttribLocation(GL2ES2, int, String)}) + * it is promoted to the {@link GLArrayData} instance. + * To bind a {@link GLArrayData} with a given location + * {@link #glBindAttribLocation(GL2ES2, int, GLArrayData)} shall be used. + * + * @param data the {@link GLArrayData} to be processed + * @see #glBindAttribLocation(GL2ES2, int, String) + * @see #getAttribute(String) + */ + public void bindAttribute(GLArrayData data) { + final int location = getAttribLocation(data.getName()); + if(0<=location) { + data.setLocation(location); } + vertexAttribMap2Data.put(data.getName(), data); + } + + /** + * Binds a shader attribute to a location. + * Multiple names can be bound to one location. + * The value will be cached and can be retrieved via {@link #getAttribLocation(String)} + * before or after linking. + * + * @throws GLException if no program is attached + * @throws GLException if the program is already linked + * + * @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String) + * @see #glGetAttribLocation(GL2ES2, String) + * @see #getAttribLocation(String) + */ + public void glBindAttribLocation(GL2ES2 gl, int location, String name) { + if(null==shaderProgram) throw new GLException("No program is attached"); + if(shaderProgram.linked()) throw new GLException("Program is already linked"); + final Integer loc = new Integer(location); + attribMap2Location.put(name, loc); + gl.glBindAttribLocation(shaderProgram.program(), location, name); } /** - * Gets the index of a shader attribute. - * This must be done after the program is linked ! + * Binds a shader {@link GLArrayData} attribute to a location. + * Multiple names can be bound to one location. + * The value will be cached and can be retrieved via {@link #getAttribLocation(String)} + * and {@link #getAttribute(String)}before or after linking. + * The {@link GLArrayData}'s location will be set as well. + * + * @throws GLException if no program is attached + * @throws GLException if the program is already linked + * + * @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String) + * @see #glGetAttribLocation(GL2ES2, String) + * @see #getAttribLocation(String) + * @see #getAttribute(String) + */ + public void glBindAttribLocation(GL2ES2 gl, int location, GLArrayData data) { + glBindAttribLocation(gl, location, data.getName()); + data.setLocation(location); + vertexAttribMap2Data.put(data.getName(), data); + } + + /** + * Gets the location of a shader attribute, + * either the cached value {@link #getAttribLocation(String)} if valid or + * the retrieved one {@link GL2ES2#glGetAttribLocation(int, String)}. + * In the latter case the value will be cached. * * @return -1 if there is no such attribute available, * otherwise >= 0 - * @throws GLException is the program is not linked + * @throws GLException if no program is attached + * @throws GLException if the program is not linked and no location was cached. * - * @see #glBindAttribLocation - * @see javax.media.opengl.GL2ES2#glBindAttribLocation - * @see #glGetAttribLocation - * @see javax.media.opengl.GL2ES2#glGetAttribLocation - * @see #getAttribLocation - * @see ShaderProgram#glReplaceShader + * @see #getAttribLocation(String) + * @see #glBindAttribLocation(GL2ES2, int, GLArrayData) + * @see #glBindAttribLocation(GL2ES2, int, String) + * @see GL2ES2#glGetAttribLocation(int, String) */ public int glGetAttribLocation(GL2ES2 gl, String name) { - if(!shaderProgram.linked()) throw new GLException("Program is not linked"); - int index = getAttribLocation(name); - if(0>index) { - index = gl.glGetAttribLocation(shaderProgram.program(), name); - if(0<=index) { - Integer idx = new Integer(index); - attribMap2Idx.put(name, idx); + if(null==shaderProgram) throw new GLException("No program is attached"); + int location = getAttribLocation(name); + if(0>location) { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + location = gl.glGetAttribLocation(shaderProgram.program(), name); + if(0<=location) { + Integer idx = new Integer(location); + attribMap2Location.put(name, idx); if(DEBUG) { - System.err.println("Info: glGetAttribLocation: "+name+", loc: "+index); + System.err.println("Info: glGetAttribLocation: "+name+", loc: "+location); } } else if(verbose) { - Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", index: "+index); + Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", loc: "+location); tX.printStackTrace(); } } - return index; + return location; } - protected int getAttribLocation(String name) { - Integer idx = (Integer) attribMap2Idx.get(name); - return (null!=idx)?idx.intValue():-1; + /** + * Gets the location of a shader attribute, + * either the cached value {@link #getAttribLocation(String)} if valid or + * the retrieved one {@link GL2ES2#glGetAttribLocation(int, String)}. + * In the latter case the value will be cached. + * The {@link GLArrayData}'s location will be set as well. + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + * + * @throws GLException if no program is attached + * @throws GLException if the program is not linked and no location was cached. + * + * @see #getAttribLocation(String) + * @see #glBindAttribLocation(GL2ES2, int, GLArrayData) + * @see #glBindAttribLocation(GL2ES2, int, String) + * @see GL2ES2#glGetAttribLocation(int, String) + * @see #getAttribute(String) + */ + public int glGetAttribLocation(GL2ES2 gl, GLArrayData data) { + int location = glGetAttribLocation(gl, data.getName()); + data.setLocation(location); + vertexAttribMap2Data.put(data.getName(), data); + return location; } - - + // // Enabled Vertex Arrays and its data // /** - * Enable a vertex attribute array + * @return true if the named attribute is enable + */ + public final boolean isVertexAttribArrayEnabled(String name) { + return enabledVertexAttribArraySet.contains(name); + } + + /** + * @return true if the {@link GLArrayData} attribute is enable + */ + public final boolean isVertexAttribArrayEnabled(GLArrayData data) { + return isVertexAttribArrayEnabled(data.getName()); + } + + private boolean glEnableVertexAttribArray(GL2ES2 gl, String name, int location) { + enabledVertexAttribArraySet.add(name); + if(0>location) { + location = glGetAttribLocation(gl, name); + if(0>location) { + if(verbose) { + Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + } + if(DEBUG) { + System.err.println("Info: glEnableVertexAttribArray: "+name+", loc: "+location); + } + gl.glEnableVertexAttribArray(location); + return true; + } + + /** + * Enables a vertex attribute array. + * + * This method retrieves the the location via {@link #glGetAttribLocation(GL2ES2, GLArrayData)} + * hence {@link #glEnableVertexAttribArray(GL2ES2, GLArrayData)} shall be preferred. * * Even if the attribute is not found in the current shader, - * it is stored in this state. + * it is marked enabled in this state. * * @return false, if the name is not found, otherwise true * - * @throws GLException if the program is not in use - * + * @throws GLException if no program is attached + * @throws GLException if the program is not linked and no location was cached. + * * @see #glEnableVertexAttribArray * @see #glDisableVertexAttribArray * @see #glVertexAttribPointer * @see #getVertexAttribPointer - * @see #glReleaseAllVertexAttributes - * @see #glResetAllVertexAttributes - * @see ShaderProgram#glReplaceShader */ public boolean glEnableVertexAttribArray(GL2ES2 gl, String name) { - if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - enabledVertexAttribArraySet.add(name); - int index = glGetAttribLocation(gl, name); - if(0>index) { - if(verbose) { - Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name); - tX.printStackTrace(); - } - return false; - } - if(DEBUG) { - System.err.println("Info: glEnableVertexAttribArray: "+name+", loc: "+index); - } - gl.glEnableVertexAttribArray(index); - return true; - } - - public boolean isVertexAttribArrayEnabled(String name) { - if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - return enabledVertexAttribArraySet.contains(name); + return glEnableVertexAttribArray(gl, name, -1); } + /** - * Disables a vertex attribute array + * Enables a vertex attribute array, usually invoked by {@link GLArrayDataEditable#enableBuffer(GL, boolean)}. * + * This method uses the {@link GLArrayData}'s location if set + * and is the preferred alternative to {@link #glEnableVertexAttribArray(GL2ES2, String)}. + * If data location is unset it will be retrieved via {@link #glGetAttribLocation(GL2ES2, GLArrayData)} set + * and cached in this state. + * * Even if the attribute is not found in the current shader, - * it is removed from this state. + * it is marked enabled in this state. * * @return false, if the name is not found, otherwise true * - * @throws GLException if the program is not in use + * @throws GLException if no program is attached + * @throws GLException if the program is not linked and no location was cached. * * @see #glEnableVertexAttribArray * @see #glDisableVertexAttribArray * @see #glVertexAttribPointer * @see #getVertexAttribPointer - * @see #glReleaseAllVertexAttributes - * @see #glResetAllVertexAttributes - * @see ShaderProgram#glReplaceShader + * @see GLArrayDataEditable#enableBuffer(GL, boolean) */ - public boolean glDisableVertexAttribArray(GL2ES2 gl, String name) { - if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + public boolean glEnableVertexAttribArray(GL2ES2 gl, GLArrayData data) { + if(null==shaderProgram) throw new GLException("No program is attached"); + if(0 > data.getLocation()) { + glGetAttribLocation(gl, data); + } + return glEnableVertexAttribArray(gl, data.getName(), data.getLocation()); + } + + private boolean glDisableVertexAttribArray(GL2ES2 gl, String name, int location) { enabledVertexAttribArraySet.remove(name); - int index = glGetAttribLocation(gl, name); - if(0>index) { - if(verbose) { - Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name); - tX.printStackTrace(); + if(0>location) { + location = glGetAttribLocation(gl, name); + if(0>location) { + if(verbose) { + Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; } - return false; } if(DEBUG) { System.err.println("Info: glDisableVertexAttribArray: "+name); } - gl.glDisableVertexAttribArray(index); + gl.glDisableVertexAttribArray(location); return true; } - + /** - * Set the vertex attribute data. - * Enable the attribute, if it is not enabled yet. + * Disables a vertex attribute array * + * This method retrieves the the location via {@link #glGetAttribLocation(GL2ES2, GLArrayData)} + * hence {@link #glDisableVertexAttribArray(GL2ES2, GLArrayData)} shall be preferred. + * * Even if the attribute is not found in the current shader, - * it is stored in this state. + * it is removed from this state enabled list. * - * @param data the GLArrayData's name must match the attributes one, - * it's index will be set with the attribute's location, - * if found. + * @return false, if the name is not found, otherwise true + * + * @throws GLException if no program is attached + * @throws GLException if the program is not linked and no location was cached. + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + */ + public boolean glDisableVertexAttribArray(GL2ES2 gl, String name) { + return glDisableVertexAttribArray(gl, name, -1); + } + + /** + * Disables a vertex attribute array + * + * This method uses the {@link GLArrayData}'s location if set + * and is the preferred alternative to {@link #glDisableVertexAttribArray(GL2ES2, String)}. + * If data location is unset it will be retrieved via {@link #glGetAttribLocation(GL2ES2, GLArrayData)} set + * and cached in this state. + * + * Even if the attribute is not found in the current shader, + * it is removed from this state enabled list. * * @return false, if the name is not found, otherwise true * + * @throws GLException if no program is attached + * @throws GLException if the program is not linked and no location was cached. + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + */ + public boolean glDisableVertexAttribArray(GL2ES2 gl, GLArrayData data) { + if(null==shaderProgram) throw new GLException("No program is attached"); + if(0 > data.getLocation()) { + glGetAttribLocation(gl, data); + } + return glDisableVertexAttribArray(gl, data.getName(), data.getLocation()); + } + + /** + * Set the {@link GLArrayData} vertex attribute data. + * + * This method uses the {@link GLArrayData}'s location if set. + * If data location is unset it will be retrieved via {@link #glGetAttribLocation(GL2ES2, GLArrayData)}, set + * and cached in this state. + * + * Enables the attribute via {@link #glEnableVertexAttribArray(GL2ES2, GLArrayData)} , if it is not enabled yet. + * + * @return false, if the location could not be determined, otherwise true + * * @throws GLException if the program is not in use * * @see #glEnableVertexAttribArray * @see #glDisableVertexAttribArray * @see #glVertexAttribPointer * @see #getVertexAttribPointer - * @see #glReleaseAllVertexAttributes - * @see #glResetAllVertexAttributes - * @see ShaderProgram#glReplaceShader */ public boolean glVertexAttribPointer(GL2ES2 gl, GLArrayData data) { - if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + if(null==shaderProgram) throw new GLException("No program is attached"); + // if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + if(0 > data.getLocation()) { + glGetAttribLocation(gl, data); + } if(!enabledVertexAttribArraySet.contains(data.getName())) { - if(!glEnableVertexAttribArray(gl, data.getName())) { + if(!glEnableVertexAttribArray(gl, data)) { if(verbose) { Throwable tX = new Throwable("Info: glVertexAttribPointer: couldn't enable: "+data); tX.printStackTrace(); } } } - int index = getAttribLocation(data.getName()); - if(0>index) { - if(verbose) { - Throwable tX = new Throwable("Info: glVertexAttribPointer failed, no index for: "+data); - tX.printStackTrace(); - } - } - data.setLocation(index); - vertexAttribMap2Data.put(data.getName(), data); - if(0<=index) { + if(0 <= data.getLocation()) { // only pass the data, if the attribute exists in the current shader if(DEBUG) { System.err.println("Info: glVertexAttribPointer: "+data); @@ -389,23 +631,6 @@ public class ShaderState { } /** - * Get the vertex attribute data, previously set. - * - * @return the GLArrayData object, null if not previously set. - * - * @see #glEnableVertexAttribArray - * @see #glDisableVertexAttribArray - * @see #glVertexAttribPointer - * @see #getVertexAttribPointer - * @see #glReleaseAllVertexAttributes - * @see #glResetAllVertexAttributes - * @see ShaderProgram#glReplaceShader - */ - public GLArrayData getVertexAttribPointer(String name) { - return (GLArrayData) vertexAttribMap2Data.get(name); - } - - /** * Releases all mapped vertex attribute data, * disables all enabled attributes and loses all indices * @@ -423,8 +648,8 @@ public class ShaderState { public void glReleaseAllVertexAttributes(GL2ES2 gl) { if(null!=shaderProgram) { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - for(Iterator iter = vertexAttribMap2Data.keySet().iterator(); iter.hasNext(); ) { - if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + for(Iterator<GLArrayData> iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, iter.next())) { throw new GLException("Internal Error: mapped vertex attribute couldn't be disabled"); } } @@ -436,7 +661,7 @@ public class ShaderState { } vertexAttribMap2Data.clear(); enabledVertexAttribArraySet.clear(); - attribMap2Idx.clear(); + attribMap2Location.clear(); } /** @@ -474,51 +699,40 @@ public class ShaderState { } /** - * Reset all previously enabled mapped vertex attribute data, - * incl enabling them + * Reset all previously enabled mapped vertex attribute data. + * + * Attribute data is bound to the GL state<br> + * Attribute location is bound to the program<br> + * + * However, since binding an attribute to a location via {@link #glBindAttribLocation(GL2ES2, int, GLArrayData)} + * <i>must</i> happen before linking <b>and</b> we try to promote the attributes to the new program, + * we have to gather the probably new location etc. * * @throws GLException is the program is not in use * - * @see #glEnableVertexAttribArray - * @see #glDisableVertexAttribArray - * @see #glVertexAttribPointer - * @see #getVertexAttribPointer - * @see #glReleaseAllVertexAttributes - * @see #glResetAllVertexAttributes - * @see ShaderProgram#glReplaceShader + * @see #attachShaderProgram(GL2ES2, ShaderProgram) */ public void glResetAllVertexAttributes(GL2ES2 gl) { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - attribMap2Idx.clear(); - - /** - * - for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { - glEnableVertexAttribArray(gl, (String) iter.next()); - } - for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { - GLArrayData data = (GLArrayData) iter.next(); - - ... - } */ - - for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + attribMap2Location.clear(); + + for(Iterator<GLArrayData> iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + GLArrayData data = iter.next(); + // get new location .. - String name = (String) iter.next(); + String name = data.getName(); int loc = glGetAttribLocation(gl, name); - - // get & update data .. - GLArrayData data = getVertexAttribPointer(name); data.setLocation(loc); - vertexAttribMap2Data.put(name, data); if(0>loc) { // not used in shader continue; } - - // enable attrib, VBO and pass location/data - gl.glEnableVertexAttribArray(loc); + + if(enabledVertexAttribArraySet.contains(name)) { + // enable attrib, VBO and pass location/data + gl.glEnableVertexAttribArray(loc); + } if( data.isVBO() ) { gl.glBindBuffer(GL.GL_ARRAY_BUFFER, data.getVBOName()); @@ -548,22 +762,22 @@ public class ShaderState { */ protected int glGetUniformLocation(GL2ES2 gl, String name) { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - int index = getUniformLocation(name); - if(0>index) { - index = gl.glGetUniformLocation(shaderProgram.program(), name); - if(0<=index) { - Integer idx = new Integer(index); - uniformMap2Idx.put(name, idx); + int location = getUniformLocation(name); + if(0>location) { + location = gl.glGetUniformLocation(shaderProgram.program(), name); + if(0<=location) { + Integer idx = new Integer(location); + uniformMap2Location.put(name, idx); } else if(verbose) { - Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+index); + Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+location); tX.printStackTrace(); } } - return index; + return location; } protected int getUniformLocation(String name) { - Integer idx = (Integer) uniformMap2Idx.get(name); + Integer idx = (Integer) uniformMap2Location.get(name); return (null!=idx)?idx.intValue():-1; } @@ -608,7 +822,7 @@ public class ShaderState { * @return the GLUniformData object, null if not previously set. */ public GLUniformData getUniform(String name) { - return (GLUniformData) uniformMap2Data.get(name); + return uniformMap2Data.get(name); } /** @@ -619,58 +833,76 @@ public class ShaderState { */ public void glReleaseAllUniforms(GL2ES2 gl) { uniformMap2Data.clear(); - uniformMap2Idx.clear(); + uniformMap2Location.clear(); } /** * Reset all previously mapped uniform data + * + * Uniform data and location is bound to the program, + * hence both are updated here * * @throws GLException is the program is not in use + * + * @see #attachShaderProgram(GL2ES2, ShaderProgram) */ public void glResetAllUniforms(GL2ES2 gl) { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - uniformMap2Idx.clear(); - for(Iterator iter = uniformMap2Data.values().iterator(); iter.hasNext(); ) { - glUniform(gl, (GLUniformData) iter.next()); + uniformMap2Location.clear(); + for(Iterator<GLUniformData> iter = uniformMap2Data.values().iterator(); iter.hasNext(); ) { + glUniform(gl, iter.next()); } } - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("ShaderState["); - buf.append(shaderProgram.toString()); - buf.append(",EnabledStates: ["); + public StringBuilder toString(StringBuilder sb) { + if(null==sb) { + sb = new StringBuilder(); + } + + sb.append("ShaderState["); + sb.append(shaderProgram.toString()); + sb.append(",EnabledStates: ["); for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { - buf.append("\n "); - buf.append((String)iter.next()); + sb.append("\n "); + sb.append((String)iter.next()); } - buf.append("], ["); - for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { - GLArrayData data = (GLArrayData) iter.next(); + sb.append("], ["); + for(Iterator<GLArrayData> iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + GLArrayData data = iter.next(); if(data.getLocation()>=0) { - buf.append("\n "); - buf.append(data); + sb.append("\n "); + sb.append(data); } } - buf.append("], ["); - for(Iterator iter=uniformMap2Data.values().iterator(); iter.hasNext(); ) { - GLUniformData data = (GLUniformData) iter.next(); + sb.append("], ["); + for(Iterator<GLUniformData> iter=uniformMap2Data.values().iterator(); iter.hasNext(); ) { + GLUniformData data = iter.next(); if(data.getLocation()>=0) { - buf.append("\n "); - buf.append(data); + sb.append("\n "); + sb.append(data); } } - buf.append("]"); - return buf.toString(); + sb.append("]"); + return sb; } - + + @Override + public String toString() { + return toString(null).toString(); + } + protected boolean verbose = false; protected ShaderProgram shaderProgram=null; - protected HashMap attribMap2Idx = new HashMap(); - protected HashSet enabledVertexAttribArraySet = new HashSet(); - protected HashMap vertexAttribMap2Data = new HashMap(); - protected HashMap uniformMap2Idx = new HashMap(); - protected HashMap uniformMap2Data = new HashMap(); - + + protected HashSet<String> enabledVertexAttribArraySet = new HashSet<String>(); + protected HashMap<String, Integer> attribMap2Location = new HashMap<String, Integer>(); + protected HashMap<String, GLArrayData> vertexAttribMap2Data = new HashMap<String, GLArrayData>(); + + protected HashMap<String, Integer> uniformMap2Location = new HashMap<String, Integer>(); + protected HashMap<String, GLUniformData> uniformMap2Data = new HashMap<String, GLUniformData>(); + + private HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>(); + private IntObjectHashMap attachedObjectsByInt = new IntObjectHashMap(); + private boolean resetAllShaderData = false; } |