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 | |
parent | c1688186ece849002650bdb667a71bbcc628a684 (diff) |
ShaderState: Validated impl./state-handling / Added comments
Capable of glBinAttribLocation(..)
Proper state check (has program, linked program, ..) for attrib/uniform methods.
8 files changed, 1454 insertions, 225 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 48ab0ae6a..4bb0ee028 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -73,7 +73,8 @@ function jrun() { #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GraphicsConfiguration" #D_ARGS="-Djogl.debug.GLCanvas" #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock" - D_ARGS="-Djogl.debug.graph.curve" + #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode" + #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLState" #X_ARGS="-Dsun.java2d.noddraw=true -Dsun.java2d.opengl=true" #X_ARGS="-verbose:jni" @@ -120,8 +121,6 @@ function testawtmt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestTransformFeedbackVaryingsBug407NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestRemoteWindow01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestRemoteGLWindows01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.gears.newt.TestGearsNEWT $* @@ -197,10 +196,15 @@ function testawtmt() { #testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestTransformFeedbackVaryingsBug407NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState01NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $* + #testnoawt com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01 $* #testnoawt com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT01 $* +#testnoawt com.jogamp.opengl.test.junit.graph.demos.ui.UINewtDemo01 $* #testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo01 $* -testnoawt com.jogamp.opengl.test.junit.graph.demos.ui.UINewtDemo01 $* #testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo02 $* #testnoawt com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo01 $* #testnoawt com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo02 $* 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; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp new file mode 100644 index 000000000..a41960ab8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp @@ -0,0 +1,17 @@ +// Copyright 2010 JogAmp Community. All rights reserved. + +#ifdef GL_ES + #define MEDIUMP mediump + #define HIGHP highp +#else + #define MEDIUMP + #define HIGHP +#endif + +varying HIGHP vec4 frontColor; + +void main (void) +{ + gl_FragColor = frontColor; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp new file mode 100644 index 000000000..a785b086c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp @@ -0,0 +1,21 @@ +// Copyright 2010 JogAmp Community. All rights reserved. + +#ifdef GL_ES + #define MEDIUMP mediump + #define HIGHP highp +#else + #define MEDIUMP + #define HIGHP +#endif + +uniform MEDIUMP mat4 mgl_PMVMatrix[2]; +attribute HIGHP vec4 mgl_Vertex; +attribute HIGHP vec4 mgl_Color; +varying HIGHP vec4 frontColor; + +void main(void) +{ + frontColor=mgl_Color; + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp new file mode 100644 index 000000000..7c8bd56f1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp @@ -0,0 +1,17 @@ +// Copyright 2010 JogAmp Community. All rights reserved. + +#ifdef GL_ES + #define MEDIUMP mediump + #define HIGHP highp +#else + #define MEDIUMP + #define HIGHP +#endif + +varying HIGHP vec4 frontColor; + +void main (void) +{ + gl_FragColor = frontColor.bgra; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java new file mode 100644 index 000000000..de6b91242 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java @@ -0,0 +1,197 @@ +/** + * 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.test.junit.jogl.glsl; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.glsl.ShaderState; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; + +public class GLSLMiscHelper { + public static GLWindow createWindow() { + GLProfile glp = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities caps = new GLCapabilities(glp); + GLWindow window = GLWindow.create(caps); + window.setSize(800, 600); + window.setVisible(true); + Assert.assertTrue(window.isNativeValid()); + window.display(); + Assert.assertTrue(window.isRealized()); + Assert.assertTrue(window.getContext().isCreated()); + return window; + } + + public static void validateGLArrayDataServerState(GL2ES2 gl, GLArrayDataServer data) { + int[] qi = new int[1]; + gl.glGetVertexAttribiv(data.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_ENABLED, qi, 0); + Assert.assertEquals(data.enabled()?GL.GL_TRUE:GL.GL_FALSE, qi[0]); + gl.glGetVertexAttribiv(data.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); + Assert.assertEquals(data.getVBOName(), qi[0]); + Assert.assertEquals(data.getByteSize(), gl.glGetBufferSize(data.getVBOName())); + } + + public static void pause(long ms) throws InterruptedException { + long t0 = System.currentTimeMillis(); + while( System.currentTimeMillis() - t0 < ms) { + Thread.sleep(ms); + } + } + + public static void displayVCArrays(GLWindow window, GL2ES2 gl, boolean preEnable, GLArrayDataServer vertices, GLArrayDataServer colors, boolean postDisable, int num, long postDelay) throws InterruptedException { + System.err.println("screen #"+num); + if(preEnable) { + vertices.enableBuffer(gl, true); + Assert.assertEquals(vertices.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); + colors.enableBuffer(gl, true); + Assert.assertEquals(colors.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); + } + Assert.assertTrue(vertices.enabled()); + Assert.assertTrue(colors.enabled()); + + validateGLArrayDataServerState(gl, vertices); + validateGLArrayDataServerState(gl, colors); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + if(postDisable) { + vertices.enableBuffer(gl, false); + colors.enableBuffer(gl, false); + Assert.assertTrue(!vertices.enabled()); + Assert.assertTrue(!colors.enabled()); + } + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + window.swapBuffers(); + if(postDelay>0) { pause(postDelay); } + } + + public static void displayVCArraysNoChecks(GLWindow window, GL2ES2 gl, boolean preEnable, GLArrayDataServer vertices, GLArrayDataServer colors, boolean postDisable) throws InterruptedException { + if(preEnable) { + vertices.enableBuffer(gl, true); + colors.enableBuffer(gl, true); + } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + if(postDisable) { + vertices.enableBuffer(gl, false); + colors.enableBuffer(gl, false); + } + window.swapBuffers(); + } + + public static GLArrayDataServer createRSVertices0(GL2ES2 gl, ShaderState st, int location) { + // Allocate Vertex Array0 + GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL(st, "mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + if(0<=location) { + st.glBindAttribLocation(gl, location, vertices0); + } + Assert.assertTrue(vertices0.isVBO()); + Assert.assertTrue(vertices0.isVertexAttribute()); + Assert.assertTrue(!vertices0.isVBOWritten()); + Assert.assertTrue(!vertices0.sealed()); + vertices0.putf(-2); vertices0.putf(2); vertices0.putf(0); + vertices0.putf(2); vertices0.putf(2); vertices0.putf(0); + vertices0.putf(-2); vertices0.putf(-2); vertices0.putf(0); + vertices0.putf(2); vertices0.putf(-2); vertices0.putf(0); + vertices0.seal(gl, true); + Assert.assertTrue(vertices0.isVBOWritten()); + Assert.assertTrue(vertices0.sealed()); + Assert.assertEquals(4, vertices0.getElementNumber()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(vertices0, st.getAttribute("mgl_Vertex")); + Assert.assertEquals(vertices0.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); + validateGLArrayDataServerState(gl, vertices0); + return vertices0; + } + + public static GLArrayDataServer createRSVertices1(GL2ES2 gl, ShaderState st) { + GLArrayDataServer vertices1 = GLArrayDataServer.createGLSL(st, "mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + Assert.assertTrue(vertices1.isVBO()); + Assert.assertTrue(vertices1.isVertexAttribute()); + Assert.assertTrue(!vertices1.isVBOWritten()); + Assert.assertTrue(!vertices1.sealed()); + vertices1.putf(-2); vertices1.putf(1); vertices1.putf(0); + vertices1.putf(2); vertices1.putf(1); vertices1.putf(0); + vertices1.putf(-2); vertices1.putf(-1); vertices1.putf(0); + vertices1.putf(2); vertices1.putf(-1); vertices1.putf(0); + vertices1.seal(gl, true); + Assert.assertTrue(vertices1.isVBOWritten()); + Assert.assertTrue(vertices1.sealed()); + Assert.assertEquals(4, vertices1.getElementNumber()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(vertices1, st.getAttribute("mgl_Vertex")); + Assert.assertEquals(vertices1.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); + validateGLArrayDataServerState(gl, vertices1); + return vertices1; + } + + public static GLArrayDataServer createRSColors0(GL2ES2 gl, ShaderState st, int location) { + GLArrayDataServer colors0 = GLArrayDataServer.createGLSL(st, "mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + if(0<=location) { + st.glBindAttribLocation(gl, location, colors0); + } + colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.seal(gl, true); + Assert.assertTrue(colors0.isVBO()); + Assert.assertTrue(colors0.isVertexAttribute()); + Assert.assertTrue(colors0.isVBOWritten()); + Assert.assertTrue(colors0.sealed()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(colors0, st.getAttribute("mgl_Color")); + Assert.assertEquals(colors0.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); + validateGLArrayDataServerState(gl, colors0); + return colors0; + } + + public static GLArrayDataServer createRSColors1(GL2ES2 gl, ShaderState st) { + // Allocate Color Array1 + GLArrayDataServer colors1 = GLArrayDataServer.createGLSL(st, "mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1); + colors1.putf(0); colors1.putf(1); colors1.putf(0); colors1.putf(1); + colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1); + colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1); + colors1.seal(gl, true); + Assert.assertTrue(colors1.isVBO()); + Assert.assertTrue(colors1.isVertexAttribute()); + Assert.assertTrue(colors1.isVBOWritten()); + Assert.assertTrue(colors1.sealed()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(colors1, st.getAttribute("mgl_Color")); + Assert.assertEquals(colors1.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); + validateGLArrayDataServerState(gl, colors1); + return colors1; + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java new file mode 100644 index 000000000..09e6f4e8c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java @@ -0,0 +1,395 @@ +/** + * 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.test.junit.jogl.glsl; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquare0; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLUniformData; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Testing different vertex attribute (VA) data sets on one shader + * and shader state in general. + */ +public class TestGLSLShaderState01NEWT extends UITestCase { + static long durationPerTest = 10; // ms + static int frames_perftest = 5000; // frames + static int frames_warmup = 100; // frames + + static final int vertices0_loc = 1; + static final int colors0_loc = 2; + + @Test + public void testShaderState01Validation() throws InterruptedException { + // preset .. + GLWindow window = GLSLMiscHelper.createWindow(); + GLContext context = window.getContext(); + context.setSynchronized(true); + context.makeCurrent(); + GL2ES2 gl = context.getGL().getGL2ES2(); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // test code .. + ShaderState st = new ShaderState(); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + Assert.assertTrue(0>sp.program()); + sp.init(gl); + Assert.assertTrue(0<=sp.program()); + Assert.assertTrue(!sp.inUse()); + Assert.assertTrue(!sp.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + st.attachShaderProgram(gl, sp); + + // Allocate Vertex Array0 + GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, st, vertices0_loc); + System.err.println("vertices0: " + vertices0); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(vertices0_loc, vertices0.getLocation()); + + // Allocate Color Array0 + GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, st, colors0_loc); + System.err.println("colors0: " + colors0); + colors0.enableBuffer(gl, false); + Assert.assertEquals(colors0_loc, colors0.getLocation()); + + Assert.assertTrue(sp.link(gl, System.err)); + Assert.assertTrue(sp.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + Assert.assertEquals(vertices0_loc, vertices0.getLocation()); + Assert.assertEquals(vertices0_loc, st.glGetAttribLocation(gl, vertices0.getName())); + Assert.assertEquals(vertices0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), vertices0.getName())); + + Assert.assertEquals(colors0_loc, colors0.getLocation()); + Assert.assertEquals(colors0_loc, st.glGetAttribLocation(gl, colors0.getName())); + Assert.assertEquals(colors0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), colors0.getName())); + + Assert.assertEquals(null, ShaderState.getShaderState(gl)); + st.glUseProgram(gl, true); + Assert.assertTrue(sp.inUse()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(st, ShaderState.getShaderState(gl)); + + // setup mgl_PMVMatrix + PMVMatrix pmvMatrix = new PMVMatrix(); + GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + st.glUniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(pmvMatrixUniform, st.getUniform("mgl_PMVMatrix")); + + // Allocate Vertex Array1 + GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl, st); + System.err.println("vertices1: " + vertices1); + vertices1.enableBuffer(gl, false); + + // Allocate Color Array1 + GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl, st); + System.err.println("colors1: " + colors1); + colors1.enableBuffer(gl, false); + + // misc GL setup + gl.glClearColor(0, 0, 0, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, (float) window.getWidth() / (float) window.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + st.glUniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // display #1 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 1, durationPerTest); + + // display #2 #1 vertices1 / colors1 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices1, colors1, true, 2, durationPerTest); + + // display #3 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 3, durationPerTest); + + // cleanup + vertices1.destroy(gl); + vertices0.destroy(gl); + colors0.destroy(gl); + colors1.destroy(gl); + st.glUseProgram(gl, false); + sp.release(gl, true); + context.release(); + window.destroy(); + } + + @Test + public void testShaderState00PerformanceSingleKeepEnabled() throws InterruptedException { + testShaderState00PerformanceSingle(false); + } + @Test + public void testShaderState00PerformanceSingleToggleEnable() throws InterruptedException { + testShaderState00PerformanceSingle(true); + } + + void testShaderState00PerformanceSingle(boolean toggleEnable) throws InterruptedException { + // preset .. + GLWindow window = GLSLMiscHelper.createWindow(); + GLContext context = window.getContext(); + context.setSynchronized(true); + context.makeCurrent(); + GL2ES2 gl = context.getGL().getGL2ES2(); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // test code .. + ShaderState st = new ShaderState(); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + sp.init(gl); + Assert.assertTrue(sp.link(gl, System.err)); + + st.attachShaderProgram(gl, sp); + st.glUseProgram(gl, true); + + // setup mgl_PMVMatrix + PMVMatrix pmvMatrix = new PMVMatrix(); + GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.glUniform(gl, pmvMatrixUniform); + + // Allocate Vertex Array0 + GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, st, -1); + vertices0.enableBuffer(gl, toggleEnable ? false : true); + + // Allocate Color Array0 + GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, st, -1); + colors0.enableBuffer(gl, toggleEnable ? false : true); + + // misc GL setup + gl.glClearColor(0, 0, 0, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, (float) window.getWidth() / (float) window.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + st.glUniform(gl, pmvMatrixUniform); + + long t0 = System.currentTimeMillis(); + int frames; + + // validation .. + GLSLMiscHelper.displayVCArrays(window, gl, toggleEnable, vertices0, colors0, toggleEnable, 1, 0); + + // warmup .. + for(frames=0; frames<frames_warmup; frames++) { + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, toggleEnable, vertices0, colors0, toggleEnable); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, toggleEnable, vertices0, colors0, toggleEnable); + } + // measure .. + for(frames=0; frames<frames_perftest; frames++) { + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, toggleEnable, vertices0, colors0, toggleEnable); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, toggleEnable, vertices0, colors0, toggleEnable); + } + final long t1 = System.currentTimeMillis(); + final long dt = t1 - t0; + final double fps = ( frames * 1000.0 ) / (double) dt; + final String fpsS = String.valueOf(fps); + final int fpsSp = fpsS.indexOf('.'); + System.err.println("testShaderState00PerformanceSingle toggleEnable "+toggleEnable+": "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f"); + + // cleanup + st.glUseProgram(gl, false); + sp.release(gl, true); + vertices0.destroy(gl); + colors0.destroy(gl); + context.release(); + window.destroy(); + } + + @Test + public void testShaderState01PerformanceDouble() throws InterruptedException { + // preset .. + GLWindow window = GLSLMiscHelper.createWindow(); + GLContext context = window.getContext(); + context.setSynchronized(true); + context.makeCurrent(); + GL2ES2 gl = context.getGL().getGL2ES2(); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // test code .. + ShaderState st = new ShaderState(); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + sp.init(gl); + Assert.assertTrue(sp.link(gl, System.err)); + + st.attachShaderProgram(gl, sp); + st.glUseProgram(gl, true); + + // setup mgl_PMVMatrix + PMVMatrix pmvMatrix = new PMVMatrix(); + GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.glUniform(gl, pmvMatrixUniform); + + // Allocate Vertex Array0 + GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, st, -1); + vertices0.enableBuffer(gl, false); + + // Allocate Vertex Array1 + GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl, st); + vertices1.enableBuffer(gl, false); + + // Allocate Color Array0 + GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, st, -1); + colors0.enableBuffer(gl, false); + + // Allocate Color Array1 + GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl, st); + colors1.enableBuffer(gl, false); + + // misc GL setup + gl.glClearColor(0, 0, 0, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, (float) window.getWidth() / (float) window.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + st.glUniform(gl, pmvMatrixUniform); + + // validation .. + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 1, 0); + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices1, colors1, true, 2, 0); + + long t0 = System.currentTimeMillis(); + int frames; + // warmup .. + for(frames=0; frames<frames_warmup; frames++) { + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices0, colors0, true); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices1, colors1, true); + } + // measure .. + for(frames=0; frames<frames_perftest; frames++) { + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices0, colors0, true); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices1, colors1, true); + } + final long t1 = System.currentTimeMillis(); + final long dt = t1 - t0; + final double fps = ( frames * 1000.0 ) / (double) dt; + final String fpsS = String.valueOf(fps); + final int fpsSp = fpsS.indexOf('.'); + System.err.println("testShaderState01PerformanceDouble: "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f"); + + // cleanup + st.glUseProgram(gl, false); + sp.release(gl, true); + vertices1.destroy(gl); + vertices0.destroy(gl); + colors0.destroy(gl); + colors1.destroy(gl); + context.release(); + window.destroy(); + } + + public static void main(String args[]) throws IOException { + System.err.println("main - start"); + boolean wait = false; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } + if(args[i].equals("-wait")) { + wait = true; + } + } + if(wait) { + while(-1 == System.in.read()) ; + TestGLSLShaderState01NEWT tst = new TestGLSLShaderState01NEWT(); + try { + tst.testShaderState01PerformanceDouble(); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + String tstname = TestGLSLShaderState01NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + System.err.println("main - end"); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java new file mode 100644 index 000000000..7f41dbf30 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java @@ -0,0 +1,346 @@ +/** + * 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.test.junit.jogl.glsl; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquare0; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLUniformData; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Testing different vertex attribute (VA) data sets on one shader + * and shader state in general. + */ +public class TestGLSLShaderState02NEWT extends UITestCase { + static long durationPerTest = 10; // ms + static int frames_perftest = 5000; // frames + static int frames_warmup = 100; // frames + + static final int vertices0_loc = 1; + static final int colors0_loc = 2; + + @Test + public void testShaderState01Validation() throws InterruptedException { + // preset .. + GLWindow window = GLSLMiscHelper.createWindow(); + GLContext context = window.getContext(); + context.setSynchronized(true); + context.makeCurrent(); + GL2ES2 gl = context.getGL().getGL2ES2(); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // test code .. + ShaderState st = new ShaderState(); + + ShaderCode rsVp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader2"); + + ShaderProgram sp1 = new ShaderProgram(); + sp1.add(rsVp0); + sp1.add(rsFp1); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertTrue(0>sp1.program()); + sp1.init(gl); + Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(!sp1.inUse()); + Assert.assertTrue(!sp1.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertTrue(sp1.link(gl, System.err)); + Assert.assertTrue(sp1.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + ShaderProgram sp0 = new ShaderProgram(); + sp0.add(rsVp0); + sp0.add(rsFp0); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + Assert.assertTrue(0>sp0.program()); + sp0.init(gl); + Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(!sp0.inUse()); + Assert.assertTrue(!sp0.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + st.attachShaderProgram(gl, sp0); + + // Allocate Vertex Array0 + GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, st, vertices0_loc); + System.err.println("vertices0: " + vertices0); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(vertices0_loc, vertices0.getLocation()); + + // Allocate Color Array0 + GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, st, colors0_loc); + System.err.println("colors0: " + colors0); + colors0.enableBuffer(gl, false); + Assert.assertEquals(colors0_loc, colors0.getLocation()); + + Assert.assertTrue(sp0.link(gl, System.err)); + Assert.assertTrue(sp0.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + Assert.assertEquals(vertices0_loc, vertices0.getLocation()); + Assert.assertEquals(vertices0_loc, st.glGetAttribLocation(gl, vertices0.getName())); + Assert.assertEquals(vertices0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), vertices0.getName())); + + Assert.assertEquals(colors0_loc, colors0.getLocation()); + Assert.assertEquals(colors0_loc, st.glGetAttribLocation(gl, colors0.getName())); + Assert.assertEquals(colors0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), colors0.getName())); + + Assert.assertEquals(null, ShaderState.getShaderState(gl)); + st.glUseProgram(gl, true); + Assert.assertTrue(sp0.inUse()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(st, ShaderState.getShaderState(gl)); + + // setup mgl_PMVMatrix + PMVMatrix pmvMatrix = new PMVMatrix(); + GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + st.glUniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertEquals(pmvMatrixUniform, st.getUniform("mgl_PMVMatrix")); + + // Allocate Vertex Array1 + GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl, st); + System.err.println("vertices1: " + vertices1); + vertices1.enableBuffer(gl, false); + + // Allocate Color Array1 + GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl, st); + System.err.println("colors1: " + colors1); + colors1.enableBuffer(gl, false); + + // misc GL setup + gl.glClearColor(0, 0, 0, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, (float) window.getWidth() / (float) window.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + st.glUniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // display #1 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 1, durationPerTest); + + // display #2 #1 vertices1 / colors1 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices1, colors1, true, 2, durationPerTest); + + // display #3 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 3, durationPerTest); + + // SP1 + // both are currently not attached to ShaderState, hence we have to reset their location as well + vertices0.setLocation(-1); + colors0.setLocation(-1); + + st.attachShaderProgram(gl, sp1); + + // display #1 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 10, durationPerTest); + + // display #2 #1 vertices1 / colors1 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices1, colors1, true, 20, durationPerTest); + + // display #3 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 30, durationPerTest); + + // cleanup + vertices1.destroy(gl); + vertices0.destroy(gl); + colors0.destroy(gl); + colors1.destroy(gl); + st.glUseProgram(gl, false); + sp0.release(gl, true); + context.release(); + window.destroy(); + } + + @Test + public void testShaderState01PerformanceDouble() throws InterruptedException { + // preset .. + GLWindow window = GLSLMiscHelper.createWindow(); + GLContext context = window.getContext(); + context.setSynchronized(true); + context.makeCurrent(); + GL2ES2 gl = context.getGL().getGL2ES2(); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // test code .. + ShaderState st = new ShaderState(); + + ShaderCode rsVp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader"); + ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RedSquare0.class, + "shader", "shader/bin", "RedSquareShader2"); + + ShaderProgram sp1 = new ShaderProgram(); + sp1.add(rsVp0); + sp1.add(rsFp1); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + Assert.assertTrue(0>sp1.program()); + sp1.init(gl); + Assert.assertTrue(sp1.link(gl, System.err)); + + ShaderProgram sp0 = new ShaderProgram(); + sp0.add(rsVp0); + sp0.add(rsFp0); + + sp0.init(gl); + Assert.assertTrue(sp0.link(gl, System.err)); + + st.attachShaderProgram(gl, sp0); + st.glUseProgram(gl, true); + + // setup mgl_PMVMatrix + PMVMatrix pmvMatrix = new PMVMatrix(); + GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.glUniform(gl, pmvMatrixUniform); + + // Allocate Vertex Array0 + GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, st, -1); + vertices0.enableBuffer(gl, false); + + // Allocate Vertex Array1 + GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl, st); + vertices1.enableBuffer(gl, false); + + // Allocate Color Array0 + GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, st, -1); + colors0.enableBuffer(gl, false); + + // Allocate Color Array1 + GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl, st); + colors1.enableBuffer(gl, false); + + // misc GL setup + gl.glClearColor(0, 0, 0, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, (float) window.getWidth() / (float) window.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + st.glUniform(gl, pmvMatrixUniform); + + // validation .. + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices0, colors0, true, 1, 0); + GLSLMiscHelper.displayVCArrays(window, gl, true, vertices1, colors1, true, 2, 0); + + long t0 = System.currentTimeMillis(); + int frames; + // warmup .. + for(frames=0; frames<frames_warmup; frames++) { + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices0, colors0, true); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices1, colors1, true); + } + // measure .. + for(frames=0; frames<frames_perftest; frames+=2) { + // SP0 + vertices0.setLocation(-1); + colors0.setLocation(-1); + st.attachShaderProgram(gl, sp0); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices0, colors0, true); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices1, colors1, true); + // SP1 + vertices0.setLocation(-1); + colors0.setLocation(-1); + st.attachShaderProgram(gl, sp1); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices0, colors0, true); + GLSLMiscHelper.displayVCArraysNoChecks(window, gl, true, vertices1, colors1, true); + } + + final long t1 = System.currentTimeMillis(); + final long dt = t1 - t0; + final double fps = ( frames * 1000.0 ) / (double) dt; + final String fpsS = String.valueOf(fps); + final int fpsSp = fpsS.indexOf('.'); + System.err.println("testShaderState01PerformanceDouble: "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f"); + + // cleanup + st.glUseProgram(gl, false); + sp0.release(gl, true); + vertices1.destroy(gl); + vertices0.destroy(gl); + colors0.destroy(gl); + colors1.destroy(gl); + context.release(); + window.destroy(); + } + + public static void main(String args[]) throws IOException { + System.err.println("main - start"); + boolean wait = false; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } + if(args[i].equals("-wait")) { + wait = true; + } + } + if(wait) { + while(-1 == System.in.read()) ; + } + String tstname = TestGLSLShaderState02NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + System.err.println("main - end"); + } +} |