diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util')
4 files changed, 145 insertions, 116 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java index c735de468..20b032a41 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java @@ -155,9 +155,9 @@ public class ShaderCode { return res; } } - Set binFmts = ShaderUtil.getShaderBinaryFormats(gl); - for(Iterator iter=binFmts.iterator(); null==res && iter.hasNext(); ) { - int bFmt = ((Integer)(iter.next())).intValue(); + Set<Integer> binFmts = ShaderUtil.getShaderBinaryFormats(gl); + for(Iterator<Integer> iter=binFmts.iterator(); null==res && iter.hasNext(); ) { + int bFmt = iter.next().intValue(); String bFmtPath = getBinarySubPath(bFmt); if(null==bFmtPath) continue; binFileName = binRoot + '/' + bFmtPath + '/' + basename + "." + getFileSuffix(true, type); @@ -174,16 +174,8 @@ public class ShaderCode { /** * 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; } + public int id() { return id; } public int shaderType() { return shaderType; } public String shaderTypeStr() { return shaderTypeStr(shaderType); } @@ -239,7 +231,7 @@ public class ShaderCode { shaderSource=null; shaderBinaryFormat=-1; shaderType=-1; - id=null; + id=-1; } public boolean equals(Object obj) { @@ -250,7 +242,7 @@ public class ShaderCode { return false; } public int hashCode() { - return id.intValue(); + return id; } public String toString() { StringBuffer buf = new StringBuffer("ShaderCode [id="+id+", type="+shaderTypeStr()+", valid="+valid+", shader: "); @@ -359,12 +351,12 @@ public class ShaderCode { protected int shaderBinaryFormat = -1; protected IntBuffer shader = null; protected int shaderType = -1; - protected Integer id = null; + protected int id = -1; protected boolean valid=false; - private static synchronized Integer getNextID() { - return new Integer(nextID++); + private static synchronized int getNextID() { + return nextID++; } protected static int nextID = 1; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java index b6908c1a1..b622571e7 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java @@ -30,11 +30,12 @@ package com.jogamp.opengl.util.glsl; import javax.media.opengl.*; -import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.io.PrintStream; public class ShaderProgram { + public ShaderProgram() { id = getNextID(); } @@ -51,16 +52,8 @@ public class 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; } + public int id() { return id; } /** * Detaches all shader codes and deletes the program. @@ -88,15 +81,18 @@ public class ShaderProgram { * 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()); + useProgram(gl, false); + for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = iter.next(); + if(attachedShaderCode.remove(shaderCode)) { + ShaderUtil.detachShader(gl, shaderProgram, shaderCode.shader()); + } if(releaseShaderToo) { shaderCode.destroy(gl); } } - shaderMap.clear(); + allShaderCode.clear(); + attachedShaderCode.clear(); gl.glDeleteProgram(shaderProgram); shaderProgram=-1; } @@ -106,35 +102,78 @@ public class ShaderProgram { // /** - * 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. + * Adds a new shader to this program. + * + * <p>This command does not compile and attach the shader, + * use {@link #add(GL2ES2, ShaderCode)} for this purpose.</p> */ - public synchronized boolean add(ShaderCode shaderCode) { - if(shaderMap.containsKey(shaderCode.key())) return false; - shaderMap.put(shaderCode.key(), shaderCode); - return true; + public synchronized void add(ShaderCode shaderCode) throws GLException { + allShaderCode.add(shaderCode); } + public synchronized boolean contains(ShaderCode shaderCode) { + return allShaderCode.contains(shaderCode); + } + + /** + * Warning slow O(n) operation .. + * @param id + * @return + */ public synchronized ShaderCode getShader(int id) { - return (ShaderCode) shaderMap.get(new Integer(id)); + for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = iter.next(); + if(shaderCode.id() == id) { + return shaderCode; + } + } + return null; } // - // Program handling + // ShaderCode / Program handling // /** - * Replace a shader in a 'running' program. - * Refetches all previously bin/get attribute names - * and resets all attribute data as well + * Creates the empty GL program object using {@link GL2ES2#glCreateProgram()} + * + * @param gl + */ + public synchronized final void init(GL2ES2 gl) { + if(0>shaderProgram) { + shaderProgram = gl.glCreateProgram(); + } + } + + /** + * Adds a new shader to a this non running program. + * + * <p>Compiles and attaches the shader, if not done yet.</p> + * + * @return true if the shader was successfully added, false if compilation failed. + */ + public synchronized boolean add(GL2ES2 gl, ShaderCode shaderCode, PrintStream verboseOut) { + init(gl); + if( allShaderCode.add(shaderCode) ) { + if(!shaderCode.compile(gl, verboseOut)) { + return false; + } + if(attachedShaderCode.add(shaderCode)) { + ShaderUtil.attachShader(gl, shaderProgram, shaderCode.shader()); + } + } + return true; + } + + /** + * Replace a shader in a program and re-links the program. * * @param gl - * @param oldShaderID the to be replace Shader + * @param oldShader the to be replace Shader * @param newShader the new ShaderCode - * @param verboseOut the optional verbose outputstream - * @throws GLException is the program is not linked + * @param verboseOut the optional verbose output stream + * + * @return true if all steps are valid, shader compilation, attachment and linking; otherwise false. * * @see ShaderState#glEnableVertexAttribArray * @see ShaderState#glDisableVertexAttribArray @@ -145,47 +184,44 @@ public class ShaderProgram { * @see ShaderState#glResetAllVertexAttributes * @see ShaderState#glResetAllVertexAttributes */ - 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); + public synchronized boolean replaceShader(GL2ES2 gl, ShaderCode oldShader, ShaderCode newShader, PrintStream verboseOut) { + init(gl); + if(!newShader.compile(gl, verboseOut)) { return false; - } - if(oldShaderID>=0) { - ShaderCode oldShader = (ShaderCode) shaderMap.remove(new Integer(oldShaderID)); - if(null!=oldShader) { + } + + boolean shaderWasInUse = inUse(); + if(shaderWasInUse) { + useProgram(gl, false); + } + + if(null != oldShader && allShaderCode.remove(oldShader)) { + if(attachedShaderCode.remove(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(attachedShaderCode.add(newShader)) { + ShaderUtil.attachShader(gl, shaderProgram, newShader.shader()); } - - if(shaderWasInUse) { - glUseProgram(gl, true); + + gl.glLinkProgram(shaderProgram); + + programLinked = ShaderUtil.isProgramValid(gl, shaderProgram, System.err); + if ( programLinked && shaderWasInUse ) { + useProgram(gl, true); } - return true; + return programLinked; } /** - * Creates the empty GL program object using {@link GL2ES2#glCreateProgram()} - * - * @param gl - */ - public final void init(GL2ES2 gl) { - if(0>shaderProgram) { - shaderProgram = gl.glCreateProgram(); - } - } - - /** - * Compiles and links the shader code to the program. - * Within this process, all GL resources (shader and program objects) are created if necessary. + * Links the shader code to the program. + * + * <p>Compiles and attaches the shader code to the program if not done by yet</p> + * + * <p>Within this process, all GL resources (shader and program objects) are created if necessary.</p> * * @param gl * @param verboseOut @@ -194,18 +230,16 @@ public class ShaderProgram { * @see #init(GL2ES2) */ public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) { - if(programLinked) throw new GLException("Program is already linked"); + init(gl); - if(0>shaderProgram) { - shaderProgram = gl.glCreateProgram(); - } - - for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { - ShaderCode shaderCode = (ShaderCode) iter.next(); + for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) { + final ShaderCode shaderCode = iter.next(); if(!shaderCode.compile(gl, verboseOut)) { return false; } - ShaderUtil.attachShader(gl, shaderProgram, shaderCode.shader()); + if(attachedShaderCode.add(shaderCode)) { + ShaderUtil.attachShader(gl, shaderProgram, shaderCode.shader()); + } } // Link the program @@ -225,40 +259,37 @@ public class ShaderProgram { } public int hashCode() { - return id.intValue(); + return id; } 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()); + for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) { + buf.append(iter.next()); buf.append(" "); } buf.append("]"); return buf.toString(); } - protected synchronized void glUseProgram(GL2ES2 gl, boolean on) { + protected synchronized void useProgram(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; + protected HashSet<ShaderCode> allShaderCode = new HashSet<ShaderCode>(); + protected HashSet<ShaderCode> attachedShaderCode = new HashSet<ShaderCode>(); + protected int id = -1; - private static synchronized Integer getNextID() { - return new Integer(nextID++); + private static synchronized int getNextID() { + return nextID++; } protected static int nextID = 1; } 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 d3f224a2a..de77a1941 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -139,7 +139,7 @@ public class ShaderState { public synchronized void glUseProgram(GL2ES2 gl, boolean on) { if(null==shaderProgram) { throw new GLException("No program is attached"); } if(on) { - shaderProgram.glUseProgram(gl, true); + shaderProgram.useProgram(gl, true); // update the current ShaderState to the TLS .. gl.getContext().attachObject(ShaderState.class.getName(), this); if(resetAllShaderData) { @@ -148,7 +148,7 @@ public class ShaderState { glResetAllUniforms(gl); } } else { - shaderProgram.glUseProgram(gl, false); + shaderProgram.useProgram(gl, false); } } @@ -204,7 +204,7 @@ public class ShaderState { if(shaderProgram.linked()) { glUseProgram(gl, true); if(!prgInUse) { - shaderProgram.glUseProgram(gl, false); + shaderProgram.useProgram(gl, false); } } } @@ -249,7 +249,7 @@ public class ShaderState { if(null!=shaderProgram) { prgInUse = shaderProgram.inUse(); if(!prgInUse) { - shaderProgram.glUseProgram(gl, true); + shaderProgram.useProgram(gl, true); } } glReleaseAllVertexAttributes(gl); @@ -258,7 +258,7 @@ public class ShaderState { if(releaseProgramToo) { shaderProgram.release(gl, releaseShaderToo); } else if(!prgInUse) { - shaderProgram.glUseProgram(gl, false); + shaderProgram.useProgram(gl, false); } } } @@ -512,6 +512,9 @@ public class ShaderState { if(null==shaderProgram) throw new GLException("No program is attached"); if(0 > data.getLocation()) { glGetAttribLocation(gl, data); + } else { + // ensure data is the current bound one + vertexAttribMap2Data.put(data.getName(), data); } return glEnableVertexAttribArray(gl, data.getName(), data.getLocation()); } @@ -608,7 +611,11 @@ public class ShaderState { // if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); if(0 > data.getLocation()) { glGetAttribLocation(gl, data); - } + } /* else { + // Already achieved by glEnableVertexAttribArray(..) + // ensure data is the current bound one + vertexAttribMap2Data.put(data.getName(), data); + } */ if(0 <= data.getLocation()) { // only pass the data, if the attribute exists in the current shader if(DEBUG) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java index 3a5a24116..c81e1f961 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java @@ -51,7 +51,7 @@ public class ShaderUtil { public abstract boolean isProgramValid(GL gl, int programObj); public abstract boolean isProgramValid(GL gl, int programObj, PrintStream verboseOut); public abstract void createShader(GL gl, int type, IntBuffer shaders); - public abstract Set getShaderBinaryFormats(GL gl); + public abstract Set<Integer> getShaderBinaryFormats(GL gl); public abstract boolean isShaderCompilerAvailable(GL gl); public abstract void shaderSource(GL gl, int shader, java.lang.String[] source); public abstract void shaderSource(GL gl, IntBuffer shaders, java.lang.String[][] sources); @@ -74,7 +74,7 @@ public class ShaderUtil { public String getShaderInfoLog(GL _gl, int shaderObj) { GL2ES2 gl = _gl.getGL2ES2(); int[] infoLogLength=new int[1]; - gl.glGetShaderiv(shaderObj, gl.GL_INFO_LOG_LENGTH, infoLogLength, 0); + gl.glGetShaderiv(shaderObj, GL2ES2.GL_INFO_LOG_LENGTH, infoLogLength, 0); if(infoLogLength[0]==0) { return "(no info log)"; @@ -89,7 +89,7 @@ public class ShaderUtil { public String getProgramInfoLog(GL _gl, int programObj) { GL2ES2 gl = _gl.getGL2ES2(); int[] infoLogLength=new int[1]; - gl.glGetProgramiv(programObj, gl.GL_INFO_LOG_LENGTH, infoLogLength, 0); + gl.glGetProgramiv(programObj, GL2ES2.GL_INFO_LOG_LENGTH, infoLogLength, 0); if(infoLogLength[0]==0) { return "(no info log)"; @@ -143,14 +143,13 @@ public class ShaderUtil { public boolean isProgramValid(GL _gl, int programObj, PrintStream verboseOut) { GL2ES2 gl = _gl.getGL2ES2(); - int[] ires = new int[1]; if(!gl.glIsProgram(programObj)) { if(null!=verboseOut) { verboseOut.println("Program name invalid: "+programObj); } return false; } - if(!isProgramStatusValid(gl, programObj, gl.GL_LINK_STATUS)) { + if(!isProgramStatusValid(gl, programObj, GL2ES2.GL_LINK_STATUS)) { if(null!=verboseOut) { verboseOut.println("Program link failed: "+programObj+"\n\t"+ getProgramInfoLog(gl, programObj)); } @@ -159,7 +158,7 @@ public class ShaderUtil { if ( !gl.isGLES2() || isShaderCompilerAvailable(gl) ) { // failed on APX2500 (ES2.0, no compiler) for valid programs gl.glValidateProgram(programObj); - if(!isProgramStatusValid(gl, programObj, gl.GL_VALIDATE_STATUS)) { + if(!isProgramStatusValid(gl, programObj, GL2ES2.GL_VALIDATE_STATUS)) { if(null!=verboseOut) { verboseOut.println("Program validation failed: "+programObj+"\n\t"+ getProgramInfoLog(gl, programObj)); } @@ -177,15 +176,15 @@ public class ShaderUtil { } private Boolean shaderCompilerAvailable = null; - private Set shaderBinaryFormats = null; + private Set<Integer> shaderBinaryFormats = null; - public Set getShaderBinaryFormats(GL _gl) { + public Set<Integer> getShaderBinaryFormats(GL _gl) { GL2ES2 gl = _gl.getGL2ES2(); if(null==shaderBinaryFormats) { gl.getContext().validateCurrent(); int[] param = new int[1]; - shaderBinaryFormats = new HashSet(); + shaderBinaryFormats = new HashSet<Integer>(); if (gl.isGLES2()) { gl.glGetIntegerv(GL2ES2.GL_NUM_SHADER_BINARY_FORMATS, param, 0); @@ -207,7 +206,7 @@ public class ShaderUtil { GL2ES2 gl = _gl.getGL2ES2(); if(null==shaderCompilerAvailable) { gl.getContext().validateCurrent(); - Set bfs = getShaderBinaryFormats(gl); + Set<Integer> bfs = getShaderBinaryFormats(gl); if(gl.isGLES2()) { byte[] param = new byte[1]; gl.glGetBooleanv(GL2ES2.GL_SHADER_COMPILER, param, 0); @@ -366,7 +365,7 @@ public class ShaderUtil { verboseOut.println("createAndCompileShader: CompileShader failed, GL Error: 0x"+Integer.toHexString(err)); } - return isShaderStatusValid(gl, shader, gl.GL_COMPILE_STATUS, verboseOut) && err == GL.GL_NO_ERROR; + return isShaderStatusValid(gl, shader, GL2ES2.GL_COMPILE_STATUS, verboseOut) && err == GL.GL_NO_ERROR; } } @@ -411,7 +410,7 @@ public class ShaderUtil { getImpl(gl).createShader(gl, type, shaders); } - public static Set getShaderBinaryFormats(GL gl) { + public static Set<Integer> getShaderBinaryFormats(GL gl) { return getImpl(gl).getShaderBinaryFormats(gl); } |