aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/ShaderProgramRetained.java
diff options
context:
space:
mode:
authorHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
committerHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
commit7a2e20caac9db6f789a7b3fab344b9758af45335 (patch)
treeb5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/ShaderProgramRetained.java
parentf76ce302c4bb2a9f03bbee571ec5d05c29633023 (diff)
j3dcore: flatten the directory structure a bit
Signed-off-by: Harvey Harrison <[email protected]>
Diffstat (limited to 'src/javax/media/j3d/ShaderProgramRetained.java')
-rw-r--r--src/javax/media/j3d/ShaderProgramRetained.java1233
1 files changed, 1233 insertions, 0 deletions
diff --git a/src/javax/media/j3d/ShaderProgramRetained.java b/src/javax/media/j3d/ShaderProgramRetained.java
new file mode 100644
index 0000000..ec63b3a
--- /dev/null
+++ b/src/javax/media/j3d/ShaderProgramRetained.java
@@ -0,0 +1,1233 @@
+/*
+ * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package javax.media.j3d;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * The ShaderProgramRetained object is a component object of an AppearanceRetained
+ * object that defines the shader properties used when programmable shader is
+ * enabled. ShaderProgramRetained object is an abstract class. All shader program
+ * objects must be created as either a GLSLShaderProgramRetained object or a
+ * CgShaderProgramRetained object.
+ */
+abstract class ShaderProgramRetained extends NodeComponentRetained {
+
+ // Each element in the array corresponds to a unique renderer if shared
+ // context or a unique canvas otherwise.
+ protected ShaderProgramData shaderProgramData[];
+
+ // Flag indicating whether an UNSUPPORTED_LANGUAGE_ERROR has
+ // already been reported for this shader program object. It is
+ // set in verifyShaderProgram and cleared in setLive or clearLive.
+ // TODO KCR: Add code to clear this in setLive or clearLive
+ private boolean unsupportedErrorReported = false;
+
+ // Flag indicating whether a LINK_ERROR has occurred for this shader program
+ // object. It is set in updateNative to indicate that the linkShaderProgram
+ // operation failed. It is cleared in setLive or clearLive.
+ // TODO KCR: Add code to clear this in setLive or clearLive
+ private boolean linkErrorOccurred = false;
+
+ // an array of shaders used by this shader program
+ protected ShaderRetained[] shaders;
+
+ // an array of vertex attribute names
+ protected String[] vertexAttrNames;
+
+ // an array of (uniform) shader attribute names
+ protected String[] shaderAttrNames;
+
+// Set of ShaderAttribute objects for which we have already reported an error
+private HashSet<ShaderAttribute> shaderAttrErrorSet = null;
+
+ // need to synchronize access from multiple rendering threads
+ Object resourceLock = new Object();
+
+ // Package-scope default constructor
+ ShaderProgramRetained() {
+ }
+
+ /**
+ * Sets the vertex attribute names array for this ShaderProgram
+ * object. Each element in the array specifies the shader
+ * attribute name that is bound to the corresponding numbered
+ * vertex attribute within a GeometryArray object that uses this
+ * shader program. Array element 0 specifies the name of
+ * GeometryArray vertex attribute 0, array element 1 specifies the
+ * name of GeometryArray vertex attribute 1, and so forth.
+ * The array of names may be null or empty (0 length), but the
+ * elements of the array must be non-null.
+ *
+ * @param vertexAttrNames array of vertex attribute names for this
+ * shader program. A copy of this array is made.
+ */
+ void setVertexAttrNames(String[] vertexAttrNames) {
+ if (vertexAttrNames == null) {
+ this.vertexAttrNames = null;
+ }
+ else {
+ this.vertexAttrNames = vertexAttrNames.clone();
+ }
+ }
+
+
+ /**
+ * Retrieves the vertex attribute names array from this
+ * ShaderProgram object.
+ *
+ * @return a copy of this ShaderProgram's array of vertex attribute names.
+ */
+ String[] getVertexAttrNames() {
+
+ if (vertexAttrNames == null) {
+ return null;
+ }
+
+ return vertexAttrNames.clone();
+
+ }
+
+
+ /**
+ * Sets the shader attribute names array for this ShaderProgram
+ * object. Each element in the array specifies a shader
+ * attribute name that may be set via a ShaderAttribute object.
+ * Only those attributes whose names that appear in the shader
+ * attribute names array can be set for a given shader program.
+ * The array of names may be null or empty (0 length), but the
+ * elements of the array must be non-null.
+ *
+ * @param shaderAttrNames array of shader attribute names for this
+ * shader program. A copy of this array is made.
+ */
+ void setShaderAttrNames(String[] shaderAttrNames) {
+ if (shaderAttrNames == null) {
+ this.shaderAttrNames = null;
+ }
+ else {
+ this.shaderAttrNames = shaderAttrNames.clone();
+ }
+ }
+
+
+ /**
+ * Retrieves the shader attribute names array from this
+ * ShaderProgram object.
+ *
+ * @return a copy of this ShaderProgram's array of shader attribute names.
+ */
+
+ String[] getShaderAttrNames() {
+
+ if (shaderAttrNames == null) {
+ return null;
+ }
+
+ return shaderAttrNames.clone();
+
+ }
+
+
+
+ /**
+ * Copies the specified array of shaders into this shader
+ * program. This method makes a shallow copy of the array. The
+ * array of shaders may be null or empty (0 length), but the
+ * elements of the array must be non-null. The shading
+ * language of each shader in the array must match the
+ * subclass. Subclasses may impose additional restrictions.
+ *
+ * @param shaders array of Shader objects to be copied into this
+ * ShaderProgram
+ *
+ * @exception CapabilityNotSetException if appropriate capability is
+ * not set and this object is part of live or compiled scene graph
+ *
+ * @exception IllegalArgumentException if the shading language of
+ * any shader in the shaders array doesn't match the type of the
+ * subclass.
+ */
+ void setShaders(Shader[] shaders) {
+
+ if (shaders == null) {
+ this.shaders = null;
+ return;
+ }
+
+ this.shaders = new ShaderRetained[shaders.length];
+
+ // Copy vertex and fragment shader
+ for (int i = 0; i < shaders.length; i++) {
+ this.shaders[i] = (ShaderRetained)shaders[i].retained;
+ }
+
+ }
+
+ /**
+ * Retrieves the array of shaders from this shader program. A
+ * shallow copy of the array is returned. The return value may
+ * be null.
+ *
+ * @return a copy of this ShaderProgram's array of Shader objects
+ *
+ */
+ Shader[] getShaders() {
+
+ if (shaders == null) {
+ return null;
+ } else {
+ Shader shads[] =
+ new Shader[shaders.length];
+ for (int i = 0; i < shaders.length; i++) {
+ if (shaders[i] != null) {
+ shads[i] = (Shader) shaders[i].source;
+ } else {
+ shads[i] = null;
+ }
+ }
+ return shads;
+ }
+ }
+
+ /**
+ * Method to create the native shader.
+ */
+ abstract ShaderError createShader(Context ctx, ShaderRetained shader, ShaderId[] shaderIdArr);
+
+ /**
+ * Method to destroy the native shader.
+ */
+ abstract ShaderError destroyShader(Context ctx, ShaderId shaderId);
+
+ /**
+ * Method to compile the native shader.
+ */
+ abstract ShaderError compileShader(Context ctx, ShaderId shaderId, String source);
+
+ /**
+ * Method to create the native shader program.
+ */
+ abstract ShaderError createShaderProgram(Context ctx, ShaderProgramId[] shaderProgramIdArr);
+
+ /**
+ * Method to destroy the native shader program.
+ */
+ abstract ShaderError destroyShaderProgram(Context ctx, ShaderProgramId shaderProgramId);
+
+ /**
+ * Method to link the native shader program.
+ */
+ abstract ShaderError linkShaderProgram(Context ctx, ShaderProgramId shaderProgramId, ShaderId[] shaderIds);
+
+ /**
+ * Method to bind a vertex attribute name to the specified index.
+ */
+ abstract ShaderError bindVertexAttrName(Context ctx, ShaderProgramId shaderProgramId, String attrName, int attrIndex);
+
+ /**
+ * Method to lookup a list of (uniform) shader attribute names and return
+ * information about the attributes.
+ */
+ abstract void lookupShaderAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, AttrNameInfo[] attrNameInfoArr);
+
+ /*
+ * Method to lookup a list of vertex attribute names.
+ */
+ abstract void lookupVertexAttrNames(Context ctx, ShaderProgramId shaderProgramId, String[] attrNames, boolean[] errArr);
+
+ /**
+ * Method to use the native shader program.
+ */
+ abstract ShaderError enableShaderProgram(Context ctx, ShaderProgramId shaderProgramId);
+
+ /**
+ * Method to disable the native shader program.
+ */
+ abstract ShaderError disableShaderProgram(Context ctx);
+
+ // ShaderAttributeValue methods
+
+ abstract ShaderError setUniform1i(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int value);
+
+ abstract ShaderError setUniform1f(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ float value);
+
+ abstract ShaderError setUniform2i(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int[] value);
+
+ abstract ShaderError setUniform2f(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ float[] value);
+
+ abstract ShaderError setUniform3i(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int[] value);
+
+ abstract ShaderError setUniform3f(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ float[] value);
+
+ abstract ShaderError setUniform4i(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int[] value);
+
+ abstract ShaderError setUniform4f(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ float[] value);
+
+ abstract ShaderError setUniformMatrix3f(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ float[] value);
+
+ abstract ShaderError setUniformMatrix4f(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ float[] value);
+
+
+ // ShaderAttributeArray methods
+
+ abstract ShaderError setUniform1iArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ int[] value);
+
+ abstract ShaderError setUniform1fArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ float[] value);
+
+ abstract ShaderError setUniform2iArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ int[] value);
+
+ abstract ShaderError setUniform2fArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ float[] value);
+
+ abstract ShaderError setUniform3iArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ int[] value);
+
+ abstract ShaderError setUniform3fArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ float[] value);
+
+ abstract ShaderError setUniform4iArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ int[] value);
+
+ abstract ShaderError setUniform4fArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ float[] value);
+
+ abstract ShaderError setUniformMatrix3fArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ float[] value);
+
+ abstract ShaderError setUniformMatrix4fArray(Context ctx,
+ ShaderProgramId shaderProgramId,
+ ShaderAttrLoc uniformLocation,
+ int numElements,
+ float[] value);
+
+
+ /**
+ * Method to return a flag indicating whether this
+ * ShaderProgram is supported on the specified Canvas.
+ */
+ abstract boolean isSupported(Canvas3D cv);
+
+
+ @Override
+ void setLive(boolean backgroundGroup, int refCount) {
+
+ // System.err.println("ShaderProgramRetained.setLive()");
+
+ if (shaders != null) {
+ for (int i = 0; i < shaders.length; i++){
+ shaders[i].setLive(backgroundGroup, refCount);
+ }
+ }
+
+ super.doSetLive(backgroundGroup, refCount);
+ super.markAsLive();
+
+ }
+
+ @Override
+ void clearLive(int refCount) {
+
+ // System.err.println("ShaderProgramRetained.clearLive()");
+
+ super.clearLive(refCount);
+
+ if (shaders != null) {
+ for (int i = 0; i < shaders.length; i++) {
+ shaders[i].clearLive(refCount);
+ }
+ }
+ }
+
+ /**
+ * Method to enable the native shader program.
+ */
+ private ShaderError enableShaderProgram(Canvas3D cv, int cvRdrIndex) {
+ assert(cvRdrIndex >= 0);
+ synchronized(resourceLock) {
+ return enableShaderProgram(cv.ctx,
+ shaderProgramData[cvRdrIndex].getShaderProgramId());
+ }
+
+ }
+
+ /**
+ * Method to disable the native shader program.
+ */
+ private ShaderError disableShaderProgram(Canvas3D cv) {
+ return disableShaderProgram(cv.ctx);
+ }
+
+ /**
+ * Initializes a mirror object.
+ */
+ @Override
+ synchronized void initMirrorObject() {
+
+ // Create mirror copy of shaders
+ if (this.shaders == null) {
+ ((ShaderProgramRetained)mirror).shaders = null;
+ }
+ else {
+ ((ShaderProgramRetained)mirror).shaders = new ShaderRetained[this.shaders.length];
+ // Copy vertex and fragment shader
+ for (int i = 0; i < this.shaders.length; i++) {
+ ((ShaderProgramRetained)mirror).shaders[i] =
+ (ShaderRetained)this.shaders[i].mirror;
+ }
+ }
+ ((ShaderProgramRetained)mirror).shaderProgramData = null;
+
+ // Create mirror copy of vertex attribute names
+ if (this.vertexAttrNames == null) {
+ ((ShaderProgramRetained)mirror).vertexAttrNames = null;
+ }
+ else {
+ ((ShaderProgramRetained)mirror).vertexAttrNames = this.vertexAttrNames.clone();
+ }
+
+ // Create mirror copy of shader attribute names
+ if (this.shaderAttrNames == null) {
+ ((ShaderProgramRetained)mirror).shaderAttrNames = null;
+ }
+ else {
+ ((ShaderProgramRetained)mirror).shaderAttrNames = this.shaderAttrNames.clone();
+ }
+
+ // Clear shader attribute error set
+ ((ShaderProgramRetained)mirror).shaderAttrErrorSet = null;
+ }
+
+ /**
+ * Update the "component" field of the mirror object with the given "value"
+ */
+ @Override
+ synchronized void updateMirrorObject(int component, Object value) {
+
+ // ShaderProgram can't be modified once it is live.
+ assert(false);
+ System.err.println("ShaderProgramRetained : updateMirrorObject NOT IMPLEMENTED YET");
+ }
+
+ /**
+ * Method to create a ShaderProgramData object for the specified
+ * canvas/renderer if it doesn't already exist.
+ *
+ * Issue 378 : reset the ShaderProgramData object if the context
+ * has been recreated for the particular canvas / renderer.
+ */
+ private void createShaderProgramData(int cvRdrIndex, long ctxTimeStamp) {
+ // Create shaderProgram resources if it has not been done.
+ synchronized(resourceLock) {
+ if(shaderProgramData == null) {
+ // We rely on Java to initial the array elements to null.
+ shaderProgramData = new ShaderProgramData[cvRdrIndex+1];
+ }
+ else if(shaderProgramData.length <= cvRdrIndex) {
+ // We rely on Java to initial the array elements to null.
+ ShaderProgramData[] tempSPData = new ShaderProgramData[cvRdrIndex+1];
+ System.arraycopy(shaderProgramData, 0,
+ tempSPData, 0,
+ shaderProgramData.length);
+ shaderProgramData = tempSPData;
+ }
+
+ if(shaderProgramData[cvRdrIndex] == null) {
+ shaderProgramData[cvRdrIndex] = new ShaderProgramData();
+ } else if (shaderProgramData[cvRdrIndex].getCtxTimeStamp() != ctxTimeStamp) {
+ // Issue 378 - reset the shader program data for this canvas / renderer
+ // if the context has been recreated
+ shaderProgramData[cvRdrIndex].reset();
+ }
+ shaderProgramData[cvRdrIndex].setCtxTimeStamp(ctxTimeStamp);
+ }
+ }
+
+ /**
+ * Method to create the native shader program. We must already have
+ * called createShaderProgramData for this cvRdrIndex.
+ */
+ private ShaderError createShaderProgram(Canvas3D cv, int cvRdrIndex) {
+ // Create shaderProgram resources if it has not been done.
+ synchronized(resourceLock) {
+ assert shaderProgramData[cvRdrIndex].getShaderProgramId() == null;
+
+ ShaderProgramId[] spIdArr = new ShaderProgramId[1];
+ ShaderError err = createShaderProgram(cv.ctx, spIdArr);
+ if(err != null) {
+ return err;
+ }
+ shaderProgramData[cvRdrIndex].setShaderProgramId(spIdArr[0]);
+ }
+
+ return null;
+ }
+
+ /**
+ * Method to link the native shader program.
+ */
+ private ShaderError linkShaderProgram(Canvas3D cv, int cvRdrIndex,
+ ShaderRetained[] shaders) {
+ synchronized(resourceLock) {
+ ShaderId[] shaderIds = new ShaderId[shaders.length];
+ for(int i=0; i<shaders.length; i++) {
+ synchronized(shaders[i]) {
+ shaderIds[i] = shaders[i].shaderData[cvRdrIndex].getShaderId();
+ }
+ }
+ ShaderError err =
+ linkShaderProgram(cv.ctx,
+ shaderProgramData[cvRdrIndex].getShaderProgramId(),
+ shaderIds);
+ if(err != null) {
+ return err;
+ }
+ shaderProgramData[cvRdrIndex].setLinked(true);
+ }
+
+ return null;
+ }
+
+
+ private ShaderError bindVertexAttrName(Canvas3D cv, int cvRdrIndex, String attrName, int attrIndex) {
+ assert(attrName != null);
+ synchronized(resourceLock) {
+ ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId();
+// System.err.println("attrName = " + attrName);
+ ShaderError err = bindVertexAttrName(cv.ctx, shaderProgramId, attrName, attrIndex);
+ if (err != null) {
+ return err;
+ }
+ }
+ return null;
+ }
+
+ private void lookupVertexAttrNames(Canvas3D cv, int cvRdrIndex, String[] attrNames) {
+ synchronized(resourceLock) {
+ ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId();
+
+ boolean[] errArr = new boolean[attrNames.length];
+ lookupVertexAttrNames(cv.ctx, shaderProgramId, attrNames, errArr);
+
+ for (int i = 0; i < attrNames.length; i++) {
+ // Report non-fatal error if detected
+ if (errArr[i]) {
+ String errMsg = "Vertex Attribute name lookup failed: " + attrNames[i];
+ ShaderError err = new ShaderError(ShaderError.VERTEX_ATTRIBUTE_LOOKUP_ERROR, errMsg);
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ }
+ }
+ }
+ }
+
+
+ private void lookupShaderAttrNames(Canvas3D cv, int cvRdrIndex, String[] attrNames) {
+ synchronized(resourceLock) {
+ ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId();
+
+ AttrNameInfo[] attrNameInfoArr = new AttrNameInfo[attrNames.length];
+ lookupShaderAttrNames(cv.ctx, shaderProgramId, attrNames, attrNameInfoArr);
+
+ for (int i = 0; i < attrNames.length; i++) {
+ shaderProgramData[cvRdrIndex].setAttrNameInfo(attrNames[i], attrNameInfoArr[i]);
+
+ // Report non-fatal error if location is invalid
+ if (attrNameInfoArr[i].getLocation() == null) {
+ String errMsg = "Attribute name lookup failed: " + attrNames[i];
+ ShaderError err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_LOOKUP_ERROR, errMsg);
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Method to return the shaderProgram data for the specified canvas or renderer
+ */
+ private ShaderProgramData getShaderProgramData(int cvRdrIndex) {
+ synchronized(resourceLock) {
+ return shaderProgramData[cvRdrIndex];
+ }
+ }
+
+ /**
+ * Method to create the native shader. We must already have
+ * called createShaderData for this cvRdrIndex.
+ */
+ private ShaderError createShader(Canvas3D cv, int cvRdrIndex, ShaderRetained shader) {
+
+ // Create shaderProgram resources if it has not been done.
+ synchronized(shader.resourceLock) {
+ if (shader.shaderData[cvRdrIndex].getShaderId() != null) {
+ // We have already created the shaderId for this Canvas.
+ return null;
+ }
+
+ ShaderId[] shaderIdArr = new ShaderId[1];
+ ShaderError err = createShader(cv.ctx, shader, shaderIdArr);
+ if(err != null) {
+ return err;
+ }
+ shader.shaderData[cvRdrIndex].setShaderId(shaderIdArr[0]);
+ }
+ return null;
+ }
+
+ /**
+ * Method to compile the native shader.
+ */
+ private ShaderError compileShader(Canvas3D cv, int cvRdrIndex, ShaderRetained shader) {
+
+ synchronized(shader.resourceLock) {
+
+ if (shader.shaderData[cvRdrIndex].isCompiled()) {
+ // We have already compiled the shaderId for this Canvas.
+ return null;
+ }
+
+ String source = ((SourceCodeShaderRetained)shader).getShaderSource();
+ ShaderError err = compileShader(cv.ctx, shader.shaderData[cvRdrIndex].getShaderId(), source);
+ if(err != null) {
+ return err;
+ }
+ shader.shaderData[cvRdrIndex].setCompiled(true);
+ }
+
+ return null;
+ }
+
+ /**
+ * Send a message to the notification thread, which will call the
+ * shader error listeners.
+ */
+ void notifyErrorListeners(Canvas3D cv, ShaderError err) {
+ J3dNotification notification = new J3dNotification();
+ notification.type = J3dNotification.SHADER_ERROR;
+ notification.universe = cv.view.universe;
+ notification.args[0] = err;
+ VirtualUniverse.mc.sendNotification(notification);
+ }
+
+
+ /**
+ * This method checks whether this ShaderProgram is supported on
+ * the specified Canvas. If it isn't supported, it will report a
+ * ShaderError unless an error has already been reported for this
+ * shader program.
+ */
+ private boolean verifyShaderProgramSupported(Canvas3D cv) {
+ boolean supported = isSupported(cv);
+ if (!supported && !unsupportedErrorReported) {
+ String errorMsg = J3dI18N.getString("ShaderProgramRetained0");
+ ShaderError err = new ShaderError(ShaderError.UNSUPPORTED_LANGUAGE_ERROR, errorMsg);
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ unsupportedErrorReported = true;
+ }
+ return supported;
+ }
+
+ /**
+ * Method to destroy the native shader.
+ */
+ void destroyShader(Canvas3D cv, int cvRdrIndex, ShaderRetained shader) {
+ if (!verifyShaderProgramSupported(cv)) {
+ return;
+ }
+
+ // Destroy shader resource if it exists
+ synchronized(shader.resourceLock) {
+ // Check whether an entry in the shaderData array has been allocated
+ if (shader.shaderData == null ||
+ shader.shaderData.length <= cvRdrIndex ||
+ shader.shaderData[cvRdrIndex] == null) {
+ return;
+ }
+
+ // Nothing to do if the shaderId is null
+ if (shader.shaderData[cvRdrIndex].getShaderId() == null) {
+ return;
+ }
+
+ // Destroy the native resource and set the ID to null for this canvas/renderer
+ // Ignore any possible shader error, because there is no meaningful way to report it
+ destroyShader(cv.ctx, shader.shaderData[cvRdrIndex].getShaderId());
+ shader.shaderData[cvRdrIndex].reset();
+ }
+ }
+
+
+ /**
+ * Method to destroy the native shader program.
+ */
+ void destroyShaderProgram(Canvas3D cv, int cvRdrIndex) {
+ if (!verifyShaderProgramSupported(cv)) {
+ return;
+ }
+
+ // Destroy shaderProgram resource if it exists
+ synchronized(resourceLock) {
+ assert(shaderProgramData != null &&
+ shaderProgramData.length > cvRdrIndex &&
+ shaderProgramData[cvRdrIndex] != null);
+
+// // Check whether an entry in the shaderProgramData array has been allocated
+// if (shaderProgramData == null ||
+// shaderProgramData.length <= cvRdrIndex ||
+// shaderProgramData[cvRdrIndex] == null) {
+// return;
+// }
+
+ ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId();
+ // Nothing to do if the shaderProgramId is null
+ if (shaderProgramId == null) {
+ return;
+ }
+
+ // Destroy the native resource, set the ID to null for this canvas/renderer,
+ // and clear the bit in the resourceCreationMask
+ // Ignore any possible shader error, because there is no meaningful way to report it
+ destroyShaderProgram(cv.ctx, shaderProgramId);
+ // Reset this ShaderProgramData object.
+ shaderProgramData[cvRdrIndex].reset();
+ }
+ }
+
+
+ /**
+ * updateNative is called while traversing the RenderBin to
+ * update the shader program state
+ */
+ void updateNative(Canvas3D cv, boolean enable) {
+ // System.err.println("ShaderProgramRetained.updateNative : ");
+
+ final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != null;
+ int cvRdrIndex;
+ long ctxTimeStamp;
+
+ if (useSharedCtx) {
+ cvRdrIndex = cv.screen.renderer.rendererId;
+ ctxTimeStamp = cv.screen.renderer.sharedCtxTimeStamp;
+ } else {
+ cvRdrIndex = cv.canvasId;
+ ctxTimeStamp = cv.ctxTimeStamp;
+ }
+
+ // Create ShaderProgramData object for this canvas/renderer if it doesn't already exist
+ createShaderProgramData(cvRdrIndex, ctxTimeStamp);
+
+ // Check whether this shader program type is supported for this canvas
+ if (!verifyShaderProgramSupported(cv)) {
+ return;
+ }
+
+ // Just disable shader program and return if enable parameter is set to false
+ if (!enable) {
+ // Given the current design, disableShaderProgram cannot return a non-null value,
+ // so no need to check it
+ disableShaderProgram(cv);
+ return;
+ }
+
+ // Just disable shader program and return if array of shaders is empty,
+ // or if a previous attempt to link resulted in an error
+ if (shaders == null || shaders.length == 0 || linkErrorOccurred) {
+ disableShaderProgram(cv);
+ return;
+ }
+
+ boolean loadShaderProgram = false; // flag indicating whether to reload all shaderProgram states
+ if (getShaderProgramData(cvRdrIndex).getShaderProgramId() == null) {
+ loadShaderProgram = true;
+ }
+
+ //System.err.println(".... loadShaderProgram = " + loadShaderProgram);
+ //System.err.println(".... resourceCreationMask= " + resourceCreationMask);
+
+ ShaderError err = null;
+ boolean errorOccurred = false;
+ if (loadShaderProgram) {
+ if (useSharedCtx) {
+ // TODO : Need to test useSharedCtx case. ** Untested case **
+ cv.makeCtxCurrent(cv.screen.renderer.sharedCtx);
+ }
+
+ // Create shader resources if not already done
+ for(int i=0; i < shaders.length; i++) {
+ // Create ShaderProgramData object for this canvas/renderer if it doesn't already exist
+ shaders[i].createShaderData(cvRdrIndex, ctxTimeStamp);
+
+ if (shaders[i].compileErrorOccurred) {
+ errorOccurred = true;
+ }
+ else {
+ err = createShader(cv, cvRdrIndex, shaders[i]);
+ if (err != null) {
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setShader((Shader)shaders[i].source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ errorOccurred = true;
+ }
+ else {
+ err = compileShader(cv, cvRdrIndex, shaders[i]);
+ if (err != null) {
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setShader((Shader)shaders[i].source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ destroyShader(cv, cvRdrIndex, shaders[i]);
+ shaders[i].compileErrorOccurred = true;
+ errorOccurred = true;
+ }
+ }
+ }
+ }
+
+ // Create shader program
+ if (!errorOccurred) {
+ err = createShaderProgram(cv, cvRdrIndex);
+ if (err != null) {
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ errorOccurred = true;
+ }
+ }
+
+ boolean linked = getShaderProgramData(cvRdrIndex).isLinked();
+ if (!linked) {
+ // Bind vertex attribute names
+ if (!errorOccurred) {
+ if (vertexAttrNames != null) {
+// System.err.println("vertexAttrNames.length = " + vertexAttrNames.length);
+ for (int i = 0; i < vertexAttrNames.length; i++) {
+ err = bindVertexAttrName(cv, cvRdrIndex, vertexAttrNames[i], i);
+ // Report non-fatal error, if one was detected
+ if (err != null) {
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ }
+ }
+ }
+ }
+
+ // Link shader program
+ if (!errorOccurred) {
+ err = linkShaderProgram(cv, cvRdrIndex, shaders);
+ if (err != null) {
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ destroyShaderProgram(cv, cvRdrIndex);
+ linkErrorOccurred = true;
+ errorOccurred = true;
+ }
+ }
+
+ // lookup vertex attribute names
+ if (!errorOccurred) {
+ if (vertexAttrNames != null) {
+ lookupVertexAttrNames(cv, cvRdrIndex, vertexAttrNames);
+ }
+ }
+
+ // Lookup shader attribute names
+ if (!errorOccurred) {
+ if (shaderAttrNames != null) {
+// System.err.println("shaderAttrNames.length = " + shaderAttrNames.length);
+ lookupShaderAttrNames(cv, cvRdrIndex, shaderAttrNames);
+ }
+ }
+ }
+
+ // Restore current context if we changed it to the shareCtx
+ if (useSharedCtx) {
+ cv.makeCtxCurrent(cv.ctx);
+ }
+
+ // If compilation or link error occured, disable shader program and return
+ if (errorOccurred) {
+ disableShaderProgram(cv);
+ return;
+ }
+ }
+
+ // Now we can enable the shader program
+ enableShaderProgram(cv, cvRdrIndex);
+ }
+
+ /**
+ * Update native value for ShaderAttributeValue class
+ */
+ ShaderError setUniformAttrValue(Context ctx, ShaderProgramId shaderProgramId,
+ ShaderAttrLoc loc, ShaderAttributeValueRetained sav) {
+
+ switch (sav.getClassType()) {
+ case ShaderAttributeObjectRetained.TYPE_INTEGER:
+ return setUniform1i(ctx, shaderProgramId, loc,
+ ((int[])sav.attrWrapper.getRef())[0]);
+
+ case ShaderAttributeObjectRetained.TYPE_FLOAT:
+ return setUniform1f(ctx, shaderProgramId, loc,
+ ((float[])sav.attrWrapper.getRef())[0]);
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE2I:
+ return setUniform2i(ctx, shaderProgramId, loc,
+ (int[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE2F:
+ return setUniform2f(ctx, shaderProgramId, loc,
+ (float[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE3I:
+ return setUniform3i(ctx, shaderProgramId, loc,
+ (int[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE3F:
+ return setUniform3f(ctx, shaderProgramId, loc,
+ (float[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE4I:
+ return setUniform4i(ctx, shaderProgramId, loc,
+ (int[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE4F:
+ return setUniform4f(ctx, shaderProgramId, loc,
+ (float[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_MATRIX3F:
+ return setUniformMatrix3f(ctx, shaderProgramId, loc,
+ (float[])sav.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_MATRIX4F:
+ return setUniformMatrix4f(ctx, shaderProgramId, loc,
+ (float[])sav.attrWrapper.getRef());
+
+ default:
+ // Should never get here
+ assert false : "Unrecognized ShaderAttributeValue classType";
+ return null;
+ }
+ }
+
+ /**
+ * Update native value for ShaderAttributeArray class
+ */
+ ShaderError setUniformAttrArray(Context ctx, ShaderProgramId shaderProgramId,
+ ShaderAttrLoc loc, ShaderAttributeArrayRetained saa) {
+
+ switch (saa.getClassType()) {
+ case ShaderAttributeObjectRetained.TYPE_INTEGER:
+ return setUniform1iArray(ctx, shaderProgramId, loc, saa.length(),
+ ((int[])saa.attrWrapper.getRef()));
+
+ case ShaderAttributeObjectRetained.TYPE_FLOAT:
+ return setUniform1fArray(ctx, shaderProgramId, loc, saa.length(),
+ ((float[])saa.attrWrapper.getRef()));
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE2I:
+ return setUniform2iArray(ctx, shaderProgramId, loc, saa.length(),
+ (int[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE2F:
+ return setUniform2fArray(ctx, shaderProgramId, loc, saa.length(),
+ (float[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE3I:
+ return setUniform3iArray(ctx, shaderProgramId, loc, saa.length(),
+ (int[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE3F:
+ return setUniform3fArray(ctx, shaderProgramId, loc, saa.length(),
+ (float[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE4I:
+ return setUniform4iArray(ctx, shaderProgramId, loc, saa.length(),
+ (int[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_TUPLE4F:
+ return setUniform4fArray(ctx, shaderProgramId, loc, saa.length(),
+ (float[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_MATRIX3F:
+ return setUniformMatrix3fArray(ctx, shaderProgramId, loc, saa.length(),
+ (float[])saa.attrWrapper.getRef());
+
+ case ShaderAttributeObjectRetained.TYPE_MATRIX4F:
+ return setUniformMatrix4fArray(ctx, shaderProgramId, loc, saa.length(),
+ (float[])saa.attrWrapper.getRef());
+
+ default:
+ // Should never get here
+ assert false : "Unrecognized ShaderAttributeArray classType";
+ return null;
+ }
+
+ }
+
+
+ void setShaderAttributes(Canvas3D cv, ShaderAttributeSetRetained attributeSet) {
+ final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != null;
+ final int cvRdrIndex = useSharedCtx ? cv.screen.renderer.rendererId : cv.canvasId;
+ ShaderProgramData spData = getShaderProgramData(cvRdrIndex);
+
+ // Just return if shader program wasn't linked successfully
+ if (!spData.isLinked()) {
+ return;
+ }
+
+ ShaderProgramId shaderProgramId = spData.getShaderProgramId();
+
+ Iterator<ShaderAttributeRetained> attrs = attributeSet.getAttrs().values().iterator();
+ while (attrs.hasNext()) {
+ ShaderError err = null;
+ ShaderAttributeRetained saRetained = attrs.next();
+
+ // Lookup attribute info for the specified attrName; null means
+ // that the name does not appear in the ShaderProgram, so we will
+ // report an error.
+ AttrNameInfo attrNameInfo = spData.getAttrNameInfo(saRetained.getAttributeName());
+ if(attrNameInfo == null) {
+// System.err.println("ShaderProgramRetained : attrLocation (" + saRetained.getAttributeName() + ") is null.");
+ String errMsg = "Attribute name not set in ShaderProgram: " + saRetained.getAttributeName(); // TODO: I18N
+ err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR, errMsg);
+ } else {
+ ShaderAttrLoc loc = attrNameInfo.getLocation();
+ if (loc != null) {
+ if (saRetained instanceof ShaderAttributeValueRetained) {
+ ShaderAttributeValueRetained savRetained = (ShaderAttributeValueRetained)saRetained;
+ if (attrNameInfo.isArray() ||
+ (savRetained.getClassType() != attrNameInfo.getType())) {
+ String errMsg = "Attribute type mismatch: " + savRetained.getAttributeName(); // TODO: I18N
+ err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_TYPE_ERROR, errMsg);
+ }
+ else {
+ err = setUniformAttrValue(cv.ctx, shaderProgramId, loc, savRetained);
+ }
+ } else if (saRetained instanceof ShaderAttributeArrayRetained) {
+ ShaderAttributeArrayRetained saaRetained = (ShaderAttributeArrayRetained)saRetained;
+ if (!attrNameInfo.isArray() ||
+ (saaRetained.getClassType() != attrNameInfo.getType())) {
+ String errMsg = "Attribute type mismatch: " + saaRetained.getAttributeName(); // TODO: I18N
+ err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_TYPE_ERROR, errMsg);
+ }
+ else {
+ err = setUniformAttrArray(cv.ctx, shaderProgramId, loc, saaRetained);
+ }
+ } else if (saRetained instanceof ShaderAttributeBindingRetained) {
+ assert false;
+ throw new RuntimeException("not implemented");
+ } else {
+ assert false;
+ }
+ }
+ }
+
+ if (err != null) {
+ // Before reporting the ShaderAttribute error, check
+ // whether it has already been reported for this ShaderProgram
+ if (shaderAttrErrorSet == null) {
+ shaderAttrErrorSet = new HashSet<ShaderAttribute>();
+ }
+ if (shaderAttrErrorSet.add((ShaderAttribute) saRetained.source)) {
+ err.setShaderProgram((ShaderProgram)this.source);
+ err.setShaderAttributeSet((ShaderAttributeSet)attributeSet.source);
+ err.setShaderAttribute((ShaderAttribute)saRetained.source);
+ err.setCanvas3D(cv);
+ notifyErrorListeners(cv, err);
+ }
+ }
+ }
+ }
+
+ class ShaderProgramData extends Object {
+
+ // issue 378 - time stamp of context creation for this Canvas
+ private long ctxTimeStamp;
+
+ // shaderProgramId use by native code.
+ private ShaderProgramId shaderProgramId = null;
+
+ // linked flag for native.
+ private boolean linked = false;
+
+ // A map of locations for ShaderAttributes.
+private HashMap<String, AttrNameInfo> attrNameInfoMap = new HashMap<String, AttrNameInfo>();
+
+ /** ShaderProgramData Constructor */
+ ShaderProgramData() {
+ }
+
+ void reset() {
+ ctxTimeStamp = 0L;
+ shaderProgramId = null;
+ linked = false;
+ attrNameInfoMap.clear();
+ }
+
+ long getCtxTimeStamp() {
+ return ctxTimeStamp;
+ }
+
+ void setCtxTimeStamp(long ctxTimeStamp) {
+ this.ctxTimeStamp = ctxTimeStamp;
+ }
+
+ void setShaderProgramId(ShaderProgramId shaderProgramId) {
+ this.shaderProgramId = shaderProgramId;
+ }
+
+ ShaderProgramId getShaderProgramId() {
+ return this.shaderProgramId;
+ }
+
+ void setLinked(boolean linked) {
+ this.linked = linked;
+ }
+
+ boolean isLinked() {
+ return linked;
+ }
+
+void setAttrNameInfo(String shaderAttribute, AttrNameInfo attrNameInfo) {
+ assert (shaderAttribute != null);
+ attrNameInfoMap.put(shaderAttribute, attrNameInfo);
+}
+
+AttrNameInfo getAttrNameInfo(String shaderAttribute) {
+ return attrNameInfoMap.get(shaderAttribute);
+}
+
+ }
+
+ // Data associated with an attribute name
+ class AttrNameInfo {
+ void setLocation(ShaderAttrLoc loc) {
+ this.loc = loc;
+ }
+
+ ShaderAttrLoc getLocation() {
+ return loc;
+ }
+
+ void setType(int type) {
+ this.type = type;
+ }
+
+ int getType() {
+ return type;
+ }
+
+ boolean isArray() {
+ return isArray;
+ }
+
+ void setArray(boolean isArray) {
+ this.isArray = isArray;
+ }
+
+ // Location of attribute name in linked shader program
+ private ShaderAttrLoc loc;
+
+ // boolean indicating whether the attribute is an array
+ private boolean isArray;
+
+ // type of shader attribute
+ private int type;
+ }
+
+}