aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2009-06-15 22:57:38 +0000
committerKenneth Russel <[email protected]>2009-06-15 22:57:38 +0000
commita959c53b7ac91e489bf0959391e892790b9ff248 (patch)
tree4664742a4f9f6daa694364292e376ad2e6ee97d1 /src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java
parent506b634b780dcd23aa61015c2ceba3e687196abf (diff)
Copied JOGL_2_SANDBOX r1957 on to trunk; JOGL_2_SANDBOX branch is now closed
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1959 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java')
-rw-r--r--src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java
new file mode 100644
index 000000000..c06eae383
--- /dev/null
+++ b/src/jogl/classes/com/sun/opengl/util/glsl/ShaderProgram.java
@@ -0,0 +1,212 @@
+
+package com.sun.opengl.util.glsl;
+
+import javax.media.opengl.*;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.nio.*;
+import java.io.PrintStream;
+
+public class ShaderProgram {
+ public ShaderProgram() {
+ id = getNextID();
+ }
+
+ public boolean linked() {
+ return programLinked;
+ }
+
+ public boolean inUse() {
+ return programInUse;
+ }
+
+ public int program() { return shaderProgram; }
+
+ /**
+ * returns the uniq shader id as an integer
+ * @see #key()
+ */
+ public int id() { return id.intValue(); }
+
+ /**
+ * returns the uniq shader id as an Integer
+ *
+ * @see #id()
+ */
+ public Integer key() { return id; }
+
+ /**
+ * Detaches all shader codes and deletes the program.
+ * Destroys the shader codes as well.
+ * Calls release(gl, true)
+ *
+ * @see #release(GL2ES2, boolean)
+ */
+ public synchronized void destroy(GL2ES2 gl) {
+ release(gl, true);
+ }
+
+ /**
+ * Detaches all shader codes and deletes the program.
+ * Calls release(gl, false)
+ *
+ * @see #release(GL2ES2, boolean)
+ */
+ public synchronized void release(GL2ES2 gl) {
+ release(gl, false);
+ }
+
+ /**
+ * Detaches all shader codes and deletes the program.
+ * If releaseShaderToo is true, destroys the shader codes as well.
+ */
+ public synchronized void release(GL2ES2 gl, boolean releaseShaderToo) {
+ glUseProgram(gl, false);
+ for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) {
+ ShaderCode shaderCode = (ShaderCode) iter.next();
+ ShaderUtil.detachShader(gl, shaderProgram, shaderCode.shader());
+ if(releaseShaderToo) {
+ shaderCode.destroy(gl);
+ }
+ }
+ shaderMap.clear();
+ gl.glDeleteProgram(shaderProgram);
+ shaderProgram=-1;
+ }
+
+ //
+ // ShaderCode handling
+ //
+
+ /**
+ * Adds a new shader to a this non running program.
+ *
+ * @return false if the program is in use, or the shader already exist,
+ * otherwise true.
+ */
+ public synchronized boolean add(ShaderCode shaderCode) {
+ if(shaderMap.containsKey(shaderCode.key())) return false;
+ shaderMap.put(shaderCode.key(), shaderCode);
+ return true;
+ }
+
+ public synchronized ShaderCode getShader(int id) {
+ return (ShaderCode) shaderMap.get(new Integer(id));
+ }
+
+ //
+ // Program handling
+ //
+
+ /**
+ * Replace a shader in a 'running' program.
+ * Refetches all previously bin/get attribute names
+ * and resets all attribute data as well
+ *
+ * @see getAttribLocation
+ * @param gl
+ * @param oldShaderID the to be replace Shader
+ * @param newShader the new ShaderCode
+ * @param verboseOut the optional verbose outputstream
+ * @throws GLException is the program is not linked
+ *
+ * @see #glRefetchAttribLocations
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public synchronized boolean glReplaceShader(GL2ES2 gl, int oldShaderID, ShaderCode newShader, PrintStream verboseOut) {
+ if(!programLinked) throw new GLException("Program is not linked");
+ boolean shaderWasInUse = programInUse;
+ glUseProgram(gl, false);
+ if(!newShader.compile(gl, verboseOut)) {
+ return false;
+ }
+ if(oldShaderID>=0) {
+ ShaderCode oldShader = (ShaderCode) shaderMap.remove(new Integer(oldShaderID));
+ if(null!=oldShader) {
+ ShaderUtil.detachShader(gl, shaderProgram, oldShader.shader());
+ }
+ }
+ add(newShader);
+
+ ShaderUtil.attachShader(gl, shaderProgram, newShader.shader());
+ gl.glLinkProgram(shaderProgram);
+ if ( ! ShaderUtil.isProgramValid(gl, shaderProgram, System.err) ) {
+ return false;
+ }
+
+ if(shaderWasInUse) {
+ glUseProgram(gl, true);
+ }
+ return true;
+ }
+
+ public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) {
+ if(programLinked) throw new GLException("Program is already linked");
+
+ if(0>shaderProgram) {
+ shaderProgram = gl.glCreateProgram();
+ }
+
+ for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) {
+ ShaderCode shaderCode = (ShaderCode) iter.next();
+ if(!shaderCode.compile(gl, verboseOut)) {
+ return false;
+ }
+ ShaderUtil.attachShader(gl, shaderProgram, shaderCode.shader());
+ }
+
+ // Link the program
+ gl.glLinkProgram(shaderProgram);
+
+ programLinked = ShaderUtil.isProgramValid(gl, shaderProgram, System.err);
+
+ return programLinked;
+ }
+
+ public boolean equals(Object obj) {
+ if(this==obj) return true;
+ if(obj instanceof ShaderCode) {
+ return id()==((ShaderCode)obj).id();
+ }
+ return false;
+ }
+ public int hashCode() {
+ return id.intValue();
+ }
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("ShaderProgram[id="+id);
+ buf.append(", linked="+programLinked+", inUse="+programInUse+", program: "+shaderProgram+", [");
+ for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) {
+ buf.append((ShaderCode) iter.next());
+ buf.append(" ");
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ protected synchronized void glUseProgram(GL2ES2 gl, boolean on) {
+ if(!programLinked) throw new GLException("Program is not linked");
+ if(programInUse==on) return;
+ gl.glUseProgram(on?shaderProgram:0);
+ programInUse = on;
+
+ //Throwable tX = new Throwable("Info: ShaderProgram.glUseProgram: "+on);
+ //tX.printStackTrace();
+
+ }
+
+ protected boolean programLinked = false;
+ protected boolean programInUse = false;
+ protected int shaderProgram=-1;
+ protected HashMap shaderMap = new HashMap();
+ protected Integer id = null;
+
+ private static synchronized Integer getNextID() {
+ return new Integer(nextID++);
+ }
+ protected static int nextID = 1;
+}
+