aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/sun/opengl/util/glsl/ShaderCode.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/ShaderCode.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/ShaderCode.java')
-rw-r--r--src/jogl/classes/com/sun/opengl/util/glsl/ShaderCode.java367
1 files changed, 367 insertions, 0 deletions
diff --git a/src/jogl/classes/com/sun/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/sun/opengl/util/glsl/ShaderCode.java
new file mode 100644
index 000000000..6e7512e6a
--- /dev/null
+++ b/src/jogl/classes/com/sun/opengl/util/glsl/ShaderCode.java
@@ -0,0 +1,367 @@
+
+package com.sun.opengl.util.glsl;
+
+import javax.media.opengl.*;
+import com.sun.opengl.util.*;
+
+import java.util.*;
+import java.nio.*;
+import java.io.*;
+import java.net.*;
+
+public class ShaderCode {
+ public static final String SUFFIX_VERTEX_SOURCE = "vp" ;
+ public static final String SUFFIX_VERTEX_BINARY = "bvp" ;
+ public static final String SUFFIX_FRAGMENT_SOURCE = "fp" ;
+ public static final String SUFFIX_FRAGMENT_BINARY = "bfp" ;
+
+ public static final String SUB_PATH_NVIDIA = "nvidia" ;
+
+ public ShaderCode(int type, int number, String[][] source) {
+ switch (type) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ break;
+ default:
+ throw new GLException("Unknown shader type: "+type);
+ }
+ shaderSource = source;
+ shaderBinaryFormat = -1;
+ shaderBinary = null;
+ shaderType = type;
+ shader = BufferUtil.newIntBuffer(number);
+ id = getNextID();
+ }
+
+ public ShaderCode(int type, int number, int binFormat, Buffer binary) {
+ switch (type) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ break;
+ default:
+ throw new GLException("Unknown shader type: "+type);
+ }
+ shaderSource = null;
+ shaderBinaryFormat = binFormat;
+ shaderBinary = binary;
+ shaderType = type;
+ shader = BufferUtil.newIntBuffer(number);
+ id = getNextID();
+ }
+
+ public static ShaderCode create(GL2ES2 gl, int type, int number, Class context, String[] sourceFiles) {
+ if(!ShaderUtil.isShaderCompilerAvailable(gl)) return null;
+
+ String[][] shaderSources = null;
+ if(null!=sourceFiles) {
+ shaderSources = new String[sourceFiles.length][1];
+ for(int i=0; null!=shaderSources && i<sourceFiles.length; i++) {
+ shaderSources[i][0] = readShaderSource(context, sourceFiles[i]);
+ if(null == shaderSources[i][0]) {
+ shaderSources = null;
+ }
+ }
+ }
+ if(null==shaderSources) {
+ return null;
+ }
+ return new ShaderCode(type, number, shaderSources);
+ }
+
+ public static ShaderCode create(int type, int number, Class context, int binFormat, String binaryFile) {
+ ByteBuffer shaderBinary = null;
+ if(null!=binaryFile && 0<=binFormat) {
+ shaderBinary = readShaderBinary(context, binaryFile);
+ if(null == shaderBinary) {
+ binFormat = -1;
+ }
+ }
+ if(null==shaderBinary) {
+ return null;
+ }
+ return new ShaderCode(type, number, binFormat, shaderBinary);
+ }
+
+ public static String getFileSuffix(boolean binary, int type) {
+ switch (type) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE;
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE;
+ default:
+ throw new GLException("illegal shader type: "+type);
+ }
+ }
+
+ public static String getBinarySubPath(int binFormat) {
+ switch (binFormat) {
+ case GLES2.GL_NVIDIA_PLATFORM_BINARY_NV:
+ return SUB_PATH_NVIDIA;
+ default:
+ throw new GLException("unsupported binary format: "+binFormat);
+ }
+ }
+
+ public static ShaderCode create(GL2ES2 gl, int type, int number, Class context,
+ String srcRoot, String binRoot, String basename) {
+ ShaderCode res = null;
+ String srcFileName = null;
+ String binFileName = null;
+
+ if(ShaderUtil.isShaderCompilerAvailable(gl)) {
+ String srcPath[] = new String[1];
+ srcFileName = srcRoot + '/' + basename + "." + getFileSuffix(false, type);
+ srcPath[0] = srcFileName;
+ res = create(gl, type, number, context, srcPath);
+ if(null!=res) {
+ return res;
+ }
+ }
+ Set binFmts = ShaderUtil.getShaderBinaryFormats(gl);
+ for(Iterator iter=binFmts.iterator(); null==res && iter.hasNext(); ) {
+ int bFmt = ((Integer)(iter.next())).intValue();
+ String bFmtPath = getBinarySubPath(bFmt);
+ if(null==bFmtPath) continue;
+ binFileName = binRoot + '/' + bFmtPath + '/' + basename + "." + getFileSuffix(true, type);
+ res = create(type, number, context, bFmt, binFileName);
+ }
+
+ if(null==res) {
+ throw new GLException("No shader code found (source nor binary) for src: "+srcFileName+
+ ", bin: "+binFileName);
+ }
+
+ return res;
+ }
+
+ public static boolean createAndLoadShader(GL2ES2 gl, IntBuffer shader, int shaderType,
+ int binFormat, java.nio.Buffer bin,
+ PrintStream verboseOut)
+ {
+ int err = gl.glGetError(); // flush previous errors ..
+ if(err!=GL.GL_NO_ERROR && null!=verboseOut) {
+ verboseOut.println("createAndLoadShader: Pre GL Error: 0x"+Integer.toHexString(err));
+ }
+
+ ShaderUtil.createShader(gl, shaderType, shader);
+ err = gl.glGetError();
+ if(err!=GL.GL_NO_ERROR) {
+ throw new GLException("createAndLoadShader: CreateShader failed, GL Error: 0x"+Integer.toHexString(err));
+ }
+
+
+ ShaderUtil.shaderBinary(gl, shader, binFormat, bin);
+
+ err = gl.glGetError();
+ if(err!=GL.GL_NO_ERROR && null!=verboseOut) {
+ verboseOut.println("createAndLoadShader: ShaderBinary failed, GL Error: 0x"+Integer.toHexString(err));
+ }
+ return err == GL.GL_NO_ERROR;
+ }
+
+ public static boolean createAndCompileShader(GL2ES2 gl, IntBuffer shader, int shaderType,
+ java.lang.String[][] sources,
+ PrintStream verboseOut)
+ {
+ int err = gl.glGetError(); // flush previous errors ..
+ if(err!=GL.GL_NO_ERROR && null!=verboseOut) {
+ verboseOut.println("createAndCompileShader: Pre GL Error: 0x"+Integer.toHexString(err));
+ }
+
+ ShaderUtil.createShader(gl, shaderType, shader);
+ err = gl.glGetError();
+ if(err!=GL.GL_NO_ERROR) {
+ throw new GLException("createAndCompileShader: CreateShader failed, GL Error: 0x"+Integer.toHexString(err));
+ }
+
+ ShaderUtil.shaderSource(gl, shader, sources);
+ err = gl.glGetError();
+ if(err!=GL.GL_NO_ERROR) {
+ throw new GLException("createAndCompileShader: ShaderSource failed, GL Error: 0x"+Integer.toHexString(err));
+ }
+
+ ShaderUtil.compileShader(gl, shader);
+ err = gl.glGetError();
+ if(err!=GL.GL_NO_ERROR && null!=verboseOut) {
+ verboseOut.println("createAndCompileShader: CompileShader failed, GL Error: 0x"+Integer.toHexString(err));
+ }
+
+ return ShaderUtil.isShaderStatusValid(gl, shader, gl.GL_COMPILE_STATUS, verboseOut) && err == GL.GL_NO_ERROR;
+ }
+
+ /**
+ * 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 shaderType() { return shaderType; }
+ public String shaderTypeStr() { return shaderTypeStr(shaderType); }
+
+ public static String shaderTypeStr(int type) {
+ switch (type) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ return "VERTEX_SHADER";
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ return "FRAGMENT_SHADER";
+ }
+ return "UNKNOWN_SHADER";
+ }
+
+ public int shaderBinaryFormat() { return shaderBinaryFormat; }
+ public Buffer shaderBinary() { return shaderBinary; }
+ public String[][] shaderSource() { return shaderSource; }
+
+ public boolean isValid() { return valid; }
+
+ public IntBuffer shader() { return shader; }
+
+ public boolean compile(GL2ES2 gl) {
+ return compile(gl, null);
+ }
+ public boolean compile(GL2ES2 gl, PrintStream verboseOut) {
+ if(isValid()) return true;
+
+ // Create & Compile the vertex/fragment shader objects
+ if(null!=shaderSource) {
+ valid=createAndCompileShader(gl, shader, shaderType,
+ shaderSource, verboseOut);
+ } else if(null!=shaderBinary) {
+ valid=createAndLoadShader(gl, shader, shaderType,
+ shaderBinaryFormat, shaderBinary, verboseOut);
+ } else {
+ throw new GLException("no code (source or binary)");
+ }
+ return valid;
+ }
+
+ public void destroy(GL2ES2 gl) {
+ if(isValid()) {
+ if(null!=gl) {
+ ShaderUtil.deleteShader(gl, shader());
+ }
+ valid=false;
+ }
+ if(null!=shaderBinary) {
+ shaderBinary.clear();
+ shaderBinary=null;
+ }
+ shaderSource=null;
+ shaderBinaryFormat=-1;
+ shaderType=-1;
+ id=null;
+ }
+
+ 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("ShaderCode [id="+id+", type="+shaderTypeStr()+", valid="+valid+", shader: ");
+ for(int i=0; i<shader.remaining(); i++) {
+ buf.append(" "+shader.get(i));
+ }
+ if(null!=shaderSource) {
+ buf.append(", source]");
+ } else if(null!=shaderBinary) {
+ buf.append(", binary "+shaderBinary+"]");
+ }
+ return buf.toString();
+ }
+
+ public static void readShaderSource(ClassLoader context, String path, URL url, StringBuffer result) {
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ if (line.startsWith("#include ")) {
+ String includeFile = line.substring(9).trim();
+ // Try relative path first
+ String next = Locator.getRelativeOf(path, includeFile);
+ URL nextURL = Locator.getResource(next, context);
+ if (nextURL == null) {
+ // Try absolute path
+ next = includeFile;
+ nextURL = Locator.getResource(next, context);
+ }
+ if (nextURL == null) {
+ // Fail
+ throw new FileNotFoundException("Can't find include file " + includeFile);
+ }
+ readShaderSource(context, next, nextURL, result);
+ } else {
+ result.append(line + "\n");
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String readShaderSource(Class context, String path) {
+ ClassLoader contextCL = (null!=context)?context.getClassLoader():null;
+ URL url = Locator.getResource(path, contextCL);
+ if (url == null && null!=context) {
+ // Try again by scoping the path within the class's package
+ String className = context.getName().replace('.', '/');
+ int lastSlash = className.lastIndexOf('/');
+ if (lastSlash >= 0) {
+ String tmpPath = className.substring(0, lastSlash + 1) + path;
+ url = Locator.getResource(tmpPath, contextCL);
+ if (url != null) {
+ path = tmpPath;
+ }
+ }
+ }
+ if (url == null) {
+ return null;
+ }
+ StringBuffer result = new StringBuffer();
+ readShaderSource(contextCL, path, url, result);
+ return result.toString();
+ }
+
+ public static ByteBuffer readShaderBinary(Class context, String path) {
+ try {
+ URL url = Locator.getResource(context, path);
+ if (url == null) {
+ return null;
+ }
+ return StreamUtil.readAll2Buffer(new BufferedInputStream(url.openStream()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ protected String[][] shaderSource = null;
+ protected Buffer shaderBinary = null;
+ protected int shaderBinaryFormat = -1;
+ protected IntBuffer shader = null;
+ protected int shaderType = -1;
+ protected Integer id = null;
+
+ protected boolean valid=false;
+
+ private static synchronized Integer getNextID() {
+ return new Integer(nextID++);
+ }
+ protected static int nextID = 1;
+}
+