summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-04-22 14:29:12 +0200
committerSven Gothel <[email protected]>2011-04-22 14:29:12 +0200
commit54f58c0cb990eb2b4fc8c3be785cc47bde575f37 (patch)
tree20a3d4b0a4b4d6aceab9a8f65a8b05560ae3d8b3 /src
parentc1688186ece849002650bdb667a71bbcc628a684 (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')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java674
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp17
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp21
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp17
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java197
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java395
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java346
7 files changed, 1446 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;
}
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");
+ }
+}