0001: /*
0002: * $RCSfile: ShaderProgramRetained.java,v $
0003: *
0004: * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006: *
0007: * This code is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU General Public License version 2 only, as
0009: * published by the Free Software Foundation. Sun designates this
0010: * particular file as subject to the "Classpath" exception as provided
0011: * by Sun in the LICENSE file that accompanied this code.
0012: *
0013: * This code is distributed in the hope that it will be useful, but WITHOUT
0014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: * version 2 for more details (a copy is included in the LICENSE file that
0017: * accompanied this code).
0018: *
0019: * You should have received a copy of the GNU General Public License version
0020: * 2 along with this work; if not, write to the Free Software Foundation,
0021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022: *
0023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024: * CA 95054 USA or visit www.sun.com if you need additional information or
0025: * have any questions.
0026: *
0027: * $Revision: 1.7 $
0028: * $Date: 2008/02/28 20:17:30 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import java.util.*;
0035: import javax.vecmath.*;
0036:
0037: /**
0038: * The ShaderProgramRetained object is a component object of an AppearanceRetained
0039: * object that defines the shader properties used when programmable shader is
0040: * enabled. ShaderProgramRetained object is an abstract class. All shader program
0041: * objects must be created as either a GLSLShaderProgramRetained object or a
0042: * CgShaderProgramRetained object.
0043: */
0044: abstract class ShaderProgramRetained extends NodeComponentRetained {
0045:
0046: // Each element in the array corresponds to a unique renderer if shared
0047: // context or a unique canvas otherwise.
0048: protected ShaderProgramData shaderProgramData[];
0049:
0050: // Flag indicating whether an UNSUPPORTED_LANGUAGE_ERROR has
0051: // already been reported for this shader program object. It is
0052: // set in verifyShaderProgram and cleared in setLive or clearLive.
0053: // TODO KCR: Add code to clear this in setLive or clearLive
0054: private boolean unsupportedErrorReported = false;
0055:
0056: // Flag indicating whether a LINK_ERROR has occurred for this shader program
0057: // object. It is set in updateNative to indicate that the linkShaderProgram
0058: // operation failed. It is cleared in setLive or clearLive.
0059: // TODO KCR: Add code to clear this in setLive or clearLive
0060: private boolean linkErrorOccurred = false;
0061:
0062: // an array of shaders used by this shader program
0063: protected ShaderRetained[] shaders;
0064:
0065: // an array of vertex attribute names
0066: protected String[] vertexAttrNames;
0067:
0068: // an array of (uniform) shader attribute names
0069: protected String[] shaderAttrNames;
0070:
0071: // Set of ShaderAttribute objects for which we have already reported an error
0072: private HashSet shaderAttrErrorSet = null;
0073:
0074: // need to synchronize access from multiple rendering threads
0075: Object resourceLock = new Object();
0076:
0077: // Package-scope default constructor
0078: ShaderProgramRetained() {
0079: }
0080:
0081: /**
0082: * Sets the vertex attribute names array for this ShaderProgram
0083: * object. Each element in the array specifies the shader
0084: * attribute name that is bound to the corresponding numbered
0085: * vertex attribute within a GeometryArray object that uses this
0086: * shader program. Array element 0 specifies the name of
0087: * GeometryArray vertex attribute 0, array element 1 specifies the
0088: * name of GeometryArray vertex attribute 1, and so forth.
0089: * The array of names may be null or empty (0 length), but the
0090: * elements of the array must be non-null.
0091: *
0092: * @param vertexAttrNames array of vertex attribute names for this
0093: * shader program. A copy of this array is made.
0094: */
0095: void setVertexAttrNames(String[] vertexAttrNames) {
0096: if (vertexAttrNames == null) {
0097: this .vertexAttrNames = null;
0098: } else {
0099: this .vertexAttrNames = (String[]) vertexAttrNames.clone();
0100: }
0101: }
0102:
0103: /**
0104: * Retrieves the vertex attribute names array from this
0105: * ShaderProgram object.
0106: *
0107: * @return a copy of this ShaderProgram's array of vertex attribute names.
0108: */
0109: String[] getVertexAttrNames() {
0110:
0111: if (vertexAttrNames == null) {
0112: return null;
0113: }
0114:
0115: return (String[]) vertexAttrNames.clone();
0116:
0117: }
0118:
0119: /**
0120: * Sets the shader attribute names array for this ShaderProgram
0121: * object. Each element in the array specifies a shader
0122: * attribute name that may be set via a ShaderAttribute object.
0123: * Only those attributes whose names that appear in the shader
0124: * attribute names array can be set for a given shader program.
0125: * The array of names may be null or empty (0 length), but the
0126: * elements of the array must be non-null.
0127: *
0128: * @param shaderAttrNames array of shader attribute names for this
0129: * shader program. A copy of this array is made.
0130: */
0131: void setShaderAttrNames(String[] shaderAttrNames) {
0132: if (shaderAttrNames == null) {
0133: this .shaderAttrNames = null;
0134: } else {
0135: this .shaderAttrNames = (String[]) shaderAttrNames.clone();
0136: }
0137: }
0138:
0139: /**
0140: * Retrieves the shader attribute names array from this
0141: * ShaderProgram object.
0142: *
0143: * @return a copy of this ShaderProgram's array of shader attribute names.
0144: */
0145:
0146: String[] getShaderAttrNames() {
0147:
0148: if (shaderAttrNames == null) {
0149: return null;
0150: }
0151:
0152: return (String[]) shaderAttrNames.clone();
0153:
0154: }
0155:
0156: /**
0157: * Copies the specified array of shaders into this shader
0158: * program. This method makes a shallow copy of the array. The
0159: * array of shaders may be null or empty (0 length), but the
0160: * elements of the array must be non-null. The shading
0161: * language of each shader in the array must match the
0162: * subclass. Subclasses may impose additional restrictions.
0163: *
0164: * @param shaders array of Shader objects to be copied into this
0165: * ShaderProgram
0166: *
0167: * @exception CapabilityNotSetException if appropriate capability is
0168: * not set and this object is part of live or compiled scene graph
0169: *
0170: * @exception IllegalArgumentException if the shading language of
0171: * any shader in the shaders array doesn't match the type of the
0172: * subclass.
0173: */
0174: void setShaders(Shader[] shaders) {
0175:
0176: if (shaders == null) {
0177: this .shaders = null;
0178: return;
0179: }
0180:
0181: this .shaders = new ShaderRetained[shaders.length];
0182:
0183: // Copy vertex and fragment shader
0184: for (int i = 0; i < shaders.length; i++) {
0185: this .shaders[i] = (ShaderRetained) shaders[i].retained;
0186: }
0187:
0188: }
0189:
0190: /**
0191: * Retrieves the array of shaders from this shader program. A
0192: * shallow copy of the array is returned. The return value may
0193: * be null.
0194: *
0195: * @return a copy of this ShaderProgram's array of Shader objects
0196: *
0197: */
0198: Shader[] getShaders() {
0199:
0200: if (shaders == null) {
0201: return null;
0202: } else {
0203: Shader shads[] = new Shader[shaders.length];
0204: for (int i = 0; i < shaders.length; i++) {
0205: if (shaders[i] != null) {
0206: shads[i] = (Shader) shaders[i].source;
0207: } else {
0208: shads[i] = null;
0209: }
0210: }
0211: return shads;
0212: }
0213: }
0214:
0215: /**
0216: * Method to create the native shader.
0217: */
0218: abstract ShaderError createShader(Context ctx,
0219: ShaderRetained shader, ShaderId[] shaderIdArr);
0220:
0221: /**
0222: * Method to destroy the native shader.
0223: */
0224: abstract ShaderError destroyShader(Context ctx, ShaderId shaderId);
0225:
0226: /**
0227: * Method to compile the native shader.
0228: */
0229: abstract ShaderError compileShader(Context ctx, ShaderId shaderId,
0230: String source);
0231:
0232: /**
0233: * Method to create the native shader program.
0234: */
0235: abstract ShaderError createShaderProgram(Context ctx,
0236: ShaderProgramId[] shaderProgramIdArr);
0237:
0238: /**
0239: * Method to destroy the native shader program.
0240: */
0241: abstract ShaderError destroyShaderProgram(Context ctx,
0242: ShaderProgramId shaderProgramId);
0243:
0244: /**
0245: * Method to link the native shader program.
0246: */
0247: abstract ShaderError linkShaderProgram(Context ctx,
0248: ShaderProgramId shaderProgramId, ShaderId[] shaderIds);
0249:
0250: /**
0251: * Method to bind a vertex attribute name to the specified index.
0252: */
0253: abstract ShaderError bindVertexAttrName(Context ctx,
0254: ShaderProgramId shaderProgramId, String attrName,
0255: int attrIndex);
0256:
0257: /**
0258: * Method to lookup a list of (uniform) shader attribute names and return
0259: * information about the attributes.
0260: */
0261: abstract void lookupShaderAttrNames(Context ctx,
0262: ShaderProgramId shaderProgramId, String[] attrNames,
0263: AttrNameInfo[] attrNameInfoArr);
0264:
0265: /*
0266: * Method to lookup a list of vertex attribute names.
0267: */
0268: abstract void lookupVertexAttrNames(Context ctx,
0269: ShaderProgramId shaderProgramId, String[] attrNames,
0270: boolean[] errArr);
0271:
0272: /**
0273: * Method to use the native shader program.
0274: */
0275: abstract ShaderError enableShaderProgram(Context ctx,
0276: ShaderProgramId shaderProgramId);
0277:
0278: /**
0279: * Method to disable the native shader program.
0280: */
0281: abstract ShaderError disableShaderProgram(Context ctx);
0282:
0283: // ShaderAttributeValue methods
0284:
0285: abstract ShaderError setUniform1i(Context ctx,
0286: ShaderProgramId shaderProgramId,
0287: ShaderAttrLoc uniformLocation, int value);
0288:
0289: abstract ShaderError setUniform1f(Context ctx,
0290: ShaderProgramId shaderProgramId,
0291: ShaderAttrLoc uniformLocation, float value);
0292:
0293: abstract ShaderError setUniform2i(Context ctx,
0294: ShaderProgramId shaderProgramId,
0295: ShaderAttrLoc uniformLocation, int[] value);
0296:
0297: abstract ShaderError setUniform2f(Context ctx,
0298: ShaderProgramId shaderProgramId,
0299: ShaderAttrLoc uniformLocation, float[] value);
0300:
0301: abstract ShaderError setUniform3i(Context ctx,
0302: ShaderProgramId shaderProgramId,
0303: ShaderAttrLoc uniformLocation, int[] value);
0304:
0305: abstract ShaderError setUniform3f(Context ctx,
0306: ShaderProgramId shaderProgramId,
0307: ShaderAttrLoc uniformLocation, float[] value);
0308:
0309: abstract ShaderError setUniform4i(Context ctx,
0310: ShaderProgramId shaderProgramId,
0311: ShaderAttrLoc uniformLocation, int[] value);
0312:
0313: abstract ShaderError setUniform4f(Context ctx,
0314: ShaderProgramId shaderProgramId,
0315: ShaderAttrLoc uniformLocation, float[] value);
0316:
0317: abstract ShaderError setUniformMatrix3f(Context ctx,
0318: ShaderProgramId shaderProgramId,
0319: ShaderAttrLoc uniformLocation, float[] value);
0320:
0321: abstract ShaderError setUniformMatrix4f(Context ctx,
0322: ShaderProgramId shaderProgramId,
0323: ShaderAttrLoc uniformLocation, float[] value);
0324:
0325: // ShaderAttributeArray methods
0326:
0327: abstract ShaderError setUniform1iArray(Context ctx,
0328: ShaderProgramId shaderProgramId,
0329: ShaderAttrLoc uniformLocation, int numElements, int[] value);
0330:
0331: abstract ShaderError setUniform1fArray(Context ctx,
0332: ShaderProgramId shaderProgramId,
0333: ShaderAttrLoc uniformLocation, int numElements,
0334: float[] value);
0335:
0336: abstract ShaderError setUniform2iArray(Context ctx,
0337: ShaderProgramId shaderProgramId,
0338: ShaderAttrLoc uniformLocation, int numElements, int[] value);
0339:
0340: abstract ShaderError setUniform2fArray(Context ctx,
0341: ShaderProgramId shaderProgramId,
0342: ShaderAttrLoc uniformLocation, int numElements,
0343: float[] value);
0344:
0345: abstract ShaderError setUniform3iArray(Context ctx,
0346: ShaderProgramId shaderProgramId,
0347: ShaderAttrLoc uniformLocation, int numElements, int[] value);
0348:
0349: abstract ShaderError setUniform3fArray(Context ctx,
0350: ShaderProgramId shaderProgramId,
0351: ShaderAttrLoc uniformLocation, int numElements,
0352: float[] value);
0353:
0354: abstract ShaderError setUniform4iArray(Context ctx,
0355: ShaderProgramId shaderProgramId,
0356: ShaderAttrLoc uniformLocation, int numElements, int[] value);
0357:
0358: abstract ShaderError setUniform4fArray(Context ctx,
0359: ShaderProgramId shaderProgramId,
0360: ShaderAttrLoc uniformLocation, int numElements,
0361: float[] value);
0362:
0363: abstract ShaderError setUniformMatrix3fArray(Context ctx,
0364: ShaderProgramId shaderProgramId,
0365: ShaderAttrLoc uniformLocation, int numElements,
0366: float[] value);
0367:
0368: abstract ShaderError setUniformMatrix4fArray(Context ctx,
0369: ShaderProgramId shaderProgramId,
0370: ShaderAttrLoc uniformLocation, int numElements,
0371: float[] value);
0372:
0373: /**
0374: * Method to return a flag indicating whether this
0375: * ShaderProgram is supported on the specified Canvas.
0376: */
0377: abstract boolean isSupported(Canvas3D cv);
0378:
0379: void setLive(boolean backgroundGroup, int refCount) {
0380:
0381: // System.err.println("ShaderProgramRetained.setLive()");
0382:
0383: if (shaders != null) {
0384: for (int i = 0; i < shaders.length; i++) {
0385: shaders[i].setLive(backgroundGroup, refCount);
0386: }
0387: }
0388:
0389: super .doSetLive(backgroundGroup, refCount);
0390: super .markAsLive();
0391:
0392: }
0393:
0394: void clearLive(int refCount) {
0395:
0396: // System.err.println("ShaderProgramRetained.clearLive()");
0397:
0398: super .clearLive(refCount);
0399:
0400: if (shaders != null) {
0401: for (int i = 0; i < shaders.length; i++) {
0402: shaders[i].clearLive(refCount);
0403: }
0404: }
0405: }
0406:
0407: /**
0408: * Method to enable the native shader program.
0409: */
0410: private ShaderError enableShaderProgram(Canvas3D cv, int cvRdrIndex) {
0411: assert (cvRdrIndex >= 0);
0412: synchronized (resourceLock) {
0413: return enableShaderProgram(cv.ctx,
0414: shaderProgramData[cvRdrIndex].getShaderProgramId());
0415: }
0416:
0417: }
0418:
0419: /**
0420: * Method to disable the native shader program.
0421: */
0422: private ShaderError disableShaderProgram(Canvas3D cv) {
0423: return disableShaderProgram(cv.ctx);
0424: }
0425:
0426: /**
0427: * Initializes a mirror object.
0428: */
0429: synchronized void initMirrorObject() {
0430:
0431: // Create mirror copy of shaders
0432: if (this .shaders == null) {
0433: ((ShaderProgramRetained) mirror).shaders = null;
0434: } else {
0435: ((ShaderProgramRetained) mirror).shaders = new ShaderRetained[this .shaders.length];
0436: // Copy vertex and fragment shader
0437: for (int i = 0; i < this .shaders.length; i++) {
0438: ((ShaderProgramRetained) mirror).shaders[i] = (ShaderRetained) this .shaders[i].mirror;
0439: }
0440: }
0441: ((ShaderProgramRetained) mirror).shaderProgramData = null;
0442:
0443: // Create mirror copy of vertex attribute names
0444: if (this .vertexAttrNames == null) {
0445: ((ShaderProgramRetained) mirror).vertexAttrNames = null;
0446: } else {
0447: ((ShaderProgramRetained) mirror).vertexAttrNames = (String[]) this .vertexAttrNames
0448: .clone();
0449: }
0450:
0451: // Create mirror copy of shader attribute names
0452: if (this .shaderAttrNames == null) {
0453: ((ShaderProgramRetained) mirror).shaderAttrNames = null;
0454: } else {
0455: ((ShaderProgramRetained) mirror).shaderAttrNames = (String[]) this .shaderAttrNames
0456: .clone();
0457: }
0458:
0459: // Clear shader attribute error set
0460: ((ShaderProgramRetained) mirror).shaderAttrErrorSet = null;
0461: }
0462:
0463: /**
0464: * Update the "component" field of the mirror object with the given "value"
0465: */
0466: synchronized void updateMirrorObject(int component, Object value) {
0467:
0468: // ShaderProgram can't be modified once it is live.
0469: assert (false);
0470: System.err
0471: .println("ShaderProgramRetained : updateMirrorObject NOT IMPLEMENTED YET");
0472: }
0473:
0474: /**
0475: * Method to create a ShaderProgramData object for the specified
0476: * canvas/renderer if it doesn't already exist.
0477: *
0478: * Issue 378 : reset the ShaderProgramData object if the context
0479: * has been recreated for the particular canvas / renderer.
0480: */
0481: private void createShaderProgramData(int cvRdrIndex,
0482: long ctxTimeStamp) {
0483: // Create shaderProgram resources if it has not been done.
0484: synchronized (resourceLock) {
0485: if (shaderProgramData == null) {
0486: // We rely on Java to initial the array elements to null.
0487: shaderProgramData = new ShaderProgramData[cvRdrIndex + 1];
0488: } else if (shaderProgramData.length <= cvRdrIndex) {
0489: // We rely on Java to initial the array elements to null.
0490: ShaderProgramData[] tempSPData = new ShaderProgramData[cvRdrIndex + 1];
0491: System.arraycopy(shaderProgramData, 0, tempSPData, 0,
0492: shaderProgramData.length);
0493: shaderProgramData = tempSPData;
0494: }
0495:
0496: if (shaderProgramData[cvRdrIndex] == null) {
0497: shaderProgramData[cvRdrIndex] = new ShaderProgramData();
0498: } else if (shaderProgramData[cvRdrIndex].getCtxTimeStamp() != ctxTimeStamp) {
0499: // Issue 378 - reset the shader program data for this canvas / renderer
0500: // if the context has been recreated
0501: shaderProgramData[cvRdrIndex].reset();
0502: }
0503: shaderProgramData[cvRdrIndex].setCtxTimeStamp(ctxTimeStamp);
0504: }
0505: }
0506:
0507: /**
0508: * Method to create the native shader program. We must already have
0509: * called createShaderProgramData for this cvRdrIndex.
0510: */
0511: private ShaderError createShaderProgram(Canvas3D cv, int cvRdrIndex) {
0512: // Create shaderProgram resources if it has not been done.
0513: synchronized (resourceLock) {
0514: assert shaderProgramData[cvRdrIndex].getShaderProgramId() == null;
0515:
0516: ShaderProgramId[] spIdArr = new ShaderProgramId[1];
0517: ShaderError err = createShaderProgram(cv.ctx, spIdArr);
0518: if (err != null) {
0519: return err;
0520: }
0521: shaderProgramData[cvRdrIndex]
0522: .setShaderProgramId(spIdArr[0]);
0523: }
0524:
0525: return null;
0526: }
0527:
0528: /**
0529: * Method to link the native shader program.
0530: */
0531: private ShaderError linkShaderProgram(Canvas3D cv, int cvRdrIndex,
0532: ShaderRetained[] shaders) {
0533: synchronized (resourceLock) {
0534: ShaderId[] shaderIds = new ShaderId[shaders.length];
0535: for (int i = 0; i < shaders.length; i++) {
0536: synchronized (shaders[i]) {
0537: shaderIds[i] = shaders[i].shaderData[cvRdrIndex]
0538: .getShaderId();
0539: }
0540: }
0541: ShaderError err = linkShaderProgram(cv.ctx,
0542: shaderProgramData[cvRdrIndex].getShaderProgramId(),
0543: shaderIds);
0544: if (err != null) {
0545: return err;
0546: }
0547: shaderProgramData[cvRdrIndex].setLinked(true);
0548: }
0549:
0550: return null;
0551: }
0552:
0553: private ShaderError bindVertexAttrName(Canvas3D cv, int cvRdrIndex,
0554: String attrName, int attrIndex) {
0555: assert (attrName != null);
0556: synchronized (resourceLock) {
0557: ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex]
0558: .getShaderProgramId();
0559: // System.err.println("attrName = " + attrName);
0560: ShaderError err = bindVertexAttrName(cv.ctx,
0561: shaderProgramId, attrName, attrIndex);
0562: if (err != null) {
0563: return err;
0564: }
0565: }
0566: return null;
0567: }
0568:
0569: private void lookupVertexAttrNames(Canvas3D cv, int cvRdrIndex,
0570: String[] attrNames) {
0571: synchronized (resourceLock) {
0572: ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex]
0573: .getShaderProgramId();
0574:
0575: boolean[] errArr = new boolean[attrNames.length];
0576: lookupVertexAttrNames(cv.ctx, shaderProgramId, attrNames,
0577: errArr);
0578:
0579: for (int i = 0; i < attrNames.length; i++) {
0580: // Report non-fatal error if detected
0581: if (errArr[i]) {
0582: String errMsg = "Vertex Attribute name lookup failed: "
0583: + attrNames[i];
0584: ShaderError err = new ShaderError(
0585: ShaderError.VERTEX_ATTRIBUTE_LOOKUP_ERROR,
0586: errMsg);
0587: err.setShaderProgram((ShaderProgram) this .source);
0588: err.setCanvas3D(cv);
0589: notifyErrorListeners(cv, err);
0590: }
0591: }
0592: }
0593: }
0594:
0595: private void lookupShaderAttrNames(Canvas3D cv, int cvRdrIndex,
0596: String[] attrNames) {
0597: synchronized (resourceLock) {
0598: ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex]
0599: .getShaderProgramId();
0600:
0601: AttrNameInfo[] attrNameInfoArr = new AttrNameInfo[attrNames.length];
0602: lookupShaderAttrNames(cv.ctx, shaderProgramId, attrNames,
0603: attrNameInfoArr);
0604:
0605: for (int i = 0; i < attrNames.length; i++) {
0606: shaderProgramData[cvRdrIndex].setAttrNameInfo(
0607: attrNames[i], attrNameInfoArr[i]);
0608:
0609: // Report non-fatal error if location is invalid
0610: if (attrNameInfoArr[i].getLocation() == null) {
0611: String errMsg = "Attribute name lookup failed: "
0612: + attrNames[i];
0613: ShaderError err = new ShaderError(
0614: ShaderError.SHADER_ATTRIBUTE_LOOKUP_ERROR,
0615: errMsg);
0616: err.setShaderProgram((ShaderProgram) this .source);
0617: err.setCanvas3D(cv);
0618: notifyErrorListeners(cv, err);
0619: }
0620: }
0621: }
0622: }
0623:
0624: /**
0625: * Method to return the shaderProgram data for the specified canvas or renderer
0626: */
0627: private ShaderProgramData getShaderProgramData(int cvRdrIndex) {
0628: synchronized (resourceLock) {
0629: return shaderProgramData[cvRdrIndex];
0630: }
0631: }
0632:
0633: /**
0634: * Method to create the native shader. We must already have
0635: * called createShaderData for this cvRdrIndex.
0636: */
0637: private ShaderError createShader(Canvas3D cv, int cvRdrIndex,
0638: ShaderRetained shader) {
0639:
0640: // Create shaderProgram resources if it has not been done.
0641: synchronized (shader.resourceLock) {
0642: if (shader.shaderData[cvRdrIndex].getShaderId() != null) {
0643: // We have already created the shaderId for this Canvas.
0644: return null;
0645: }
0646:
0647: ShaderId[] shaderIdArr = new ShaderId[1];
0648: ShaderError err = createShader(cv.ctx, shader, shaderIdArr);
0649: if (err != null) {
0650: return err;
0651: }
0652: shader.shaderData[cvRdrIndex].setShaderId(shaderIdArr[0]);
0653: }
0654: return null;
0655: }
0656:
0657: /**
0658: * Method to compile the native shader.
0659: */
0660: private ShaderError compileShader(Canvas3D cv, int cvRdrIndex,
0661: ShaderRetained shader) {
0662:
0663: synchronized (shader.resourceLock) {
0664:
0665: if (shader.shaderData[cvRdrIndex].isCompiled()) {
0666: // We have already compiled the shaderId for this Canvas.
0667: return null;
0668: }
0669:
0670: String source = ((SourceCodeShaderRetained) shader)
0671: .getShaderSource();
0672: ShaderError err = compileShader(cv.ctx,
0673: shader.shaderData[cvRdrIndex].getShaderId(), source);
0674: if (err != null) {
0675: return err;
0676: }
0677: shader.shaderData[cvRdrIndex].setCompiled(true);
0678: }
0679:
0680: return null;
0681: }
0682:
0683: /**
0684: * Send a message to the notification thread, which will call the
0685: * shader error listeners.
0686: */
0687: void notifyErrorListeners(Canvas3D cv, ShaderError err) {
0688: J3dNotification notification = new J3dNotification();
0689: notification.type = J3dNotification.SHADER_ERROR;
0690: notification.universe = cv.view.universe;
0691: notification.args[0] = err;
0692: VirtualUniverse.mc.sendNotification(notification);
0693: }
0694:
0695: /**
0696: * This method checks whether this ShaderProgram is supported on
0697: * the specified Canvas. If it isn't supported, it will report a
0698: * ShaderError unless an error has already been reported for this
0699: * shader program.
0700: */
0701: private boolean verifyShaderProgramSupported(Canvas3D cv) {
0702: boolean supported = isSupported(cv);
0703: if (!supported && !unsupportedErrorReported) {
0704: String errorMsg = J3dI18N
0705: .getString("ShaderProgramRetained0");
0706: ShaderError err = new ShaderError(
0707: ShaderError.UNSUPPORTED_LANGUAGE_ERROR, errorMsg);
0708: err.setShaderProgram((ShaderProgram) this .source);
0709: err.setCanvas3D(cv);
0710: notifyErrorListeners(cv, err);
0711: unsupportedErrorReported = true;
0712: }
0713: return supported;
0714: }
0715:
0716: /**
0717: * Method to destroy the native shader.
0718: */
0719: void destroyShader(Canvas3D cv, int cvRdrIndex,
0720: ShaderRetained shader) {
0721: if (!verifyShaderProgramSupported(cv)) {
0722: return;
0723: }
0724:
0725: // Destroy shader resource if it exists
0726: synchronized (shader.resourceLock) {
0727: // Check whether an entry in the shaderData array has been allocated
0728: if (shader.shaderData == null
0729: || shader.shaderData.length <= cvRdrIndex
0730: || shader.shaderData[cvRdrIndex] == null) {
0731: return;
0732: }
0733:
0734: // Nothing to do if the shaderId is null
0735: if (shader.shaderData[cvRdrIndex].getShaderId() == null) {
0736: return;
0737: }
0738:
0739: // Destroy the native resource and set the ID to null for this canvas/renderer
0740: // Ignore any possible shader error, because there is no meaningful way to report it
0741: destroyShader(cv.ctx, shader.shaderData[cvRdrIndex]
0742: .getShaderId());
0743: shader.shaderData[cvRdrIndex].reset();
0744: }
0745: }
0746:
0747: /**
0748: * Method to destroy the native shader program.
0749: */
0750: void destroyShaderProgram(Canvas3D cv, int cvRdrIndex) {
0751: if (!verifyShaderProgramSupported(cv)) {
0752: return;
0753: }
0754:
0755: // Destroy shaderProgram resource if it exists
0756: synchronized (resourceLock) {
0757: assert (shaderProgramData != null
0758: && shaderProgramData.length > cvRdrIndex && shaderProgramData[cvRdrIndex] != null);
0759:
0760: // // Check whether an entry in the shaderProgramData array has been allocated
0761: // if (shaderProgramData == null ||
0762: // shaderProgramData.length <= cvRdrIndex ||
0763: // shaderProgramData[cvRdrIndex] == null) {
0764: // return;
0765: // }
0766:
0767: ShaderProgramId shaderProgramId = shaderProgramData[cvRdrIndex]
0768: .getShaderProgramId();
0769: // Nothing to do if the shaderProgramId is null
0770: if (shaderProgramId == null) {
0771: return;
0772: }
0773:
0774: // Destroy the native resource, set the ID to null for this canvas/renderer,
0775: // and clear the bit in the resourceCreationMask
0776: // Ignore any possible shader error, because there is no meaningful way to report it
0777: destroyShaderProgram(cv.ctx, shaderProgramId);
0778: // Reset this ShaderProgramData object.
0779: shaderProgramData[cvRdrIndex].reset();
0780: }
0781: }
0782:
0783: /**
0784: * updateNative is called while traversing the RenderBin to
0785: * update the shader program state
0786: */
0787: void updateNative(Canvas3D cv, boolean enable) {
0788: // System.err.println("ShaderProgramRetained.updateNative : ");
0789:
0790: final boolean useSharedCtx = cv.useSharedCtx
0791: && cv.screen.renderer.sharedCtx != null;
0792: int cvRdrIndex;
0793: long ctxTimeStamp;
0794:
0795: if (useSharedCtx) {
0796: cvRdrIndex = cv.screen.renderer.rendererId;
0797: ctxTimeStamp = cv.screen.renderer.sharedCtxTimeStamp;
0798: } else {
0799: cvRdrIndex = cv.canvasId;
0800: ctxTimeStamp = cv.ctxTimeStamp;
0801: }
0802:
0803: // Create ShaderProgramData object for this canvas/renderer if it doesn't already exist
0804: createShaderProgramData(cvRdrIndex, ctxTimeStamp);
0805:
0806: // Check whether this shader program type is supported for this canvas
0807: if (!verifyShaderProgramSupported(cv)) {
0808: return;
0809: }
0810:
0811: // Just disable shader program and return if enable parameter is set to false
0812: if (!enable) {
0813: // Given the current design, disableShaderProgram cannot return a non-null value,
0814: // so no need to check it
0815: disableShaderProgram(cv);
0816: return;
0817: }
0818:
0819: // Just disable shader program and return if array of shaders is empty,
0820: // or if a previous attempt to link resulted in an error
0821: if (shaders == null || shaders.length == 0 || linkErrorOccurred) {
0822: disableShaderProgram(cv);
0823: return;
0824: }
0825:
0826: boolean loadShaderProgram = false; // flag indicating whether to reload all shaderProgram states
0827: if (getShaderProgramData(cvRdrIndex).getShaderProgramId() == null) {
0828: loadShaderProgram = true;
0829: }
0830:
0831: //System.err.println(".... loadShaderProgram = " + loadShaderProgram);
0832: //System.err.println(".... resourceCreationMask= " + resourceCreationMask);
0833:
0834: ShaderError err = null;
0835: boolean errorOccurred = false;
0836: if (loadShaderProgram) {
0837: if (useSharedCtx) {
0838: // TODO : Need to test useSharedCtx case. ** Untested case **
0839: cv.makeCtxCurrent(cv.screen.renderer.sharedCtx);
0840: }
0841:
0842: // Create shader resources if not already done
0843: for (int i = 0; i < shaders.length; i++) {
0844: // Create ShaderProgramData object for this canvas/renderer if it doesn't already exist
0845: shaders[i].createShaderData(cvRdrIndex, ctxTimeStamp);
0846:
0847: if (shaders[i].compileErrorOccurred) {
0848: errorOccurred = true;
0849: } else {
0850: err = createShader(cv, cvRdrIndex, shaders[i]);
0851: if (err != null) {
0852: err
0853: .setShaderProgram((ShaderProgram) this .source);
0854: err.setShader((Shader) shaders[i].source);
0855: err.setCanvas3D(cv);
0856: notifyErrorListeners(cv, err);
0857: errorOccurred = true;
0858: } else {
0859: err = compileShader(cv, cvRdrIndex, shaders[i]);
0860: if (err != null) {
0861: err
0862: .setShaderProgram((ShaderProgram) this .source);
0863: err.setShader((Shader) shaders[i].source);
0864: err.setCanvas3D(cv);
0865: notifyErrorListeners(cv, err);
0866: destroyShader(cv, cvRdrIndex, shaders[i]);
0867: shaders[i].compileErrorOccurred = true;
0868: errorOccurred = true;
0869: }
0870: }
0871: }
0872: }
0873:
0874: // Create shader program
0875: if (!errorOccurred) {
0876: err = createShaderProgram(cv, cvRdrIndex);
0877: if (err != null) {
0878: err.setShaderProgram((ShaderProgram) this .source);
0879: err.setCanvas3D(cv);
0880: notifyErrorListeners(cv, err);
0881: errorOccurred = true;
0882: }
0883: }
0884:
0885: boolean linked = getShaderProgramData(cvRdrIndex)
0886: .isLinked();
0887: if (!linked) {
0888: // Bind vertex attribute names
0889: if (!errorOccurred) {
0890: if (vertexAttrNames != null) {
0891: // System.err.println("vertexAttrNames.length = " + vertexAttrNames.length);
0892: for (int i = 0; i < vertexAttrNames.length; i++) {
0893: err = bindVertexAttrName(cv, cvRdrIndex,
0894: vertexAttrNames[i], i);
0895: // Report non-fatal error, if one was detected
0896: if (err != null) {
0897: err
0898: .setShaderProgram((ShaderProgram) this .source);
0899: err.setCanvas3D(cv);
0900: notifyErrorListeners(cv, err);
0901: }
0902: }
0903: }
0904: }
0905:
0906: // Link shader program
0907: if (!errorOccurred) {
0908: err = linkShaderProgram(cv, cvRdrIndex, shaders);
0909: if (err != null) {
0910: err
0911: .setShaderProgram((ShaderProgram) this .source);
0912: err.setCanvas3D(cv);
0913: notifyErrorListeners(cv, err);
0914: destroyShaderProgram(cv, cvRdrIndex);
0915: linkErrorOccurred = true;
0916: errorOccurred = true;
0917: }
0918: }
0919:
0920: // lookup vertex attribute names
0921: if (!errorOccurred) {
0922: if (vertexAttrNames != null) {
0923: lookupVertexAttrNames(cv, cvRdrIndex,
0924: vertexAttrNames);
0925: }
0926: }
0927:
0928: // Lookup shader attribute names
0929: if (!errorOccurred) {
0930: if (shaderAttrNames != null) {
0931: // System.err.println("shaderAttrNames.length = " + shaderAttrNames.length);
0932: lookupShaderAttrNames(cv, cvRdrIndex,
0933: shaderAttrNames);
0934: }
0935: }
0936: }
0937:
0938: // Restore current context if we changed it to the shareCtx
0939: if (useSharedCtx) {
0940: cv.makeCtxCurrent(cv.ctx);
0941: }
0942:
0943: // If compilation or link error occured, disable shader program and return
0944: if (errorOccurred) {
0945: disableShaderProgram(cv);
0946: return;
0947: }
0948: }
0949:
0950: // Now we can enable the shader program
0951: enableShaderProgram(cv, cvRdrIndex);
0952: }
0953:
0954: /**
0955: * Update native value for ShaderAttributeValue class
0956: */
0957: ShaderError setUniformAttrValue(Context ctx,
0958: ShaderProgramId shaderProgramId, ShaderAttrLoc loc,
0959: ShaderAttributeValueRetained sav) {
0960:
0961: switch (sav.getClassType()) {
0962: case ShaderAttributeObjectRetained.TYPE_INTEGER:
0963: return setUniform1i(ctx, shaderProgramId, loc,
0964: ((int[]) sav.attrWrapper.getRef())[0]);
0965:
0966: case ShaderAttributeObjectRetained.TYPE_FLOAT:
0967: return setUniform1f(ctx, shaderProgramId, loc,
0968: ((float[]) sav.attrWrapper.getRef())[0]);
0969:
0970: case ShaderAttributeObjectRetained.TYPE_TUPLE2I:
0971: return setUniform2i(ctx, shaderProgramId, loc,
0972: (int[]) sav.attrWrapper.getRef());
0973:
0974: case ShaderAttributeObjectRetained.TYPE_TUPLE2F:
0975: return setUniform2f(ctx, shaderProgramId, loc,
0976: (float[]) sav.attrWrapper.getRef());
0977:
0978: case ShaderAttributeObjectRetained.TYPE_TUPLE3I:
0979: return setUniform3i(ctx, shaderProgramId, loc,
0980: (int[]) sav.attrWrapper.getRef());
0981:
0982: case ShaderAttributeObjectRetained.TYPE_TUPLE3F:
0983: return setUniform3f(ctx, shaderProgramId, loc,
0984: (float[]) sav.attrWrapper.getRef());
0985:
0986: case ShaderAttributeObjectRetained.TYPE_TUPLE4I:
0987: return setUniform4i(ctx, shaderProgramId, loc,
0988: (int[]) sav.attrWrapper.getRef());
0989:
0990: case ShaderAttributeObjectRetained.TYPE_TUPLE4F:
0991: return setUniform4f(ctx, shaderProgramId, loc,
0992: (float[]) sav.attrWrapper.getRef());
0993:
0994: case ShaderAttributeObjectRetained.TYPE_MATRIX3F:
0995: return setUniformMatrix3f(ctx, shaderProgramId, loc,
0996: (float[]) sav.attrWrapper.getRef());
0997:
0998: case ShaderAttributeObjectRetained.TYPE_MATRIX4F:
0999: return setUniformMatrix4f(ctx, shaderProgramId, loc,
1000: (float[]) sav.attrWrapper.getRef());
1001:
1002: default:
1003: // Should never get here
1004: assert false : "Unrecognized ShaderAttributeValue classType";
1005: return null;
1006: }
1007: }
1008:
1009: /**
1010: * Update native value for ShaderAttributeArray class
1011: */
1012: ShaderError setUniformAttrArray(Context ctx,
1013: ShaderProgramId shaderProgramId, ShaderAttrLoc loc,
1014: ShaderAttributeArrayRetained saa) {
1015:
1016: switch (saa.getClassType()) {
1017: case ShaderAttributeObjectRetained.TYPE_INTEGER:
1018: return setUniform1iArray(ctx, shaderProgramId, loc, saa
1019: .length(), ((int[]) saa.attrWrapper.getRef()));
1020:
1021: case ShaderAttributeObjectRetained.TYPE_FLOAT:
1022: return setUniform1fArray(ctx, shaderProgramId, loc, saa
1023: .length(), ((float[]) saa.attrWrapper.getRef()));
1024:
1025: case ShaderAttributeObjectRetained.TYPE_TUPLE2I:
1026: return setUniform2iArray(ctx, shaderProgramId, loc, saa
1027: .length(), (int[]) saa.attrWrapper.getRef());
1028:
1029: case ShaderAttributeObjectRetained.TYPE_TUPLE2F:
1030: return setUniform2fArray(ctx, shaderProgramId, loc, saa
1031: .length(), (float[]) saa.attrWrapper.getRef());
1032:
1033: case ShaderAttributeObjectRetained.TYPE_TUPLE3I:
1034: return setUniform3iArray(ctx, shaderProgramId, loc, saa
1035: .length(), (int[]) saa.attrWrapper.getRef());
1036:
1037: case ShaderAttributeObjectRetained.TYPE_TUPLE3F:
1038: return setUniform3fArray(ctx, shaderProgramId, loc, saa
1039: .length(), (float[]) saa.attrWrapper.getRef());
1040:
1041: case ShaderAttributeObjectRetained.TYPE_TUPLE4I:
1042: return setUniform4iArray(ctx, shaderProgramId, loc, saa
1043: .length(), (int[]) saa.attrWrapper.getRef());
1044:
1045: case ShaderAttributeObjectRetained.TYPE_TUPLE4F:
1046: return setUniform4fArray(ctx, shaderProgramId, loc, saa
1047: .length(), (float[]) saa.attrWrapper.getRef());
1048:
1049: case ShaderAttributeObjectRetained.TYPE_MATRIX3F:
1050: return setUniformMatrix3fArray(ctx, shaderProgramId, loc,
1051: saa.length(), (float[]) saa.attrWrapper.getRef());
1052:
1053: case ShaderAttributeObjectRetained.TYPE_MATRIX4F:
1054: return setUniformMatrix4fArray(ctx, shaderProgramId, loc,
1055: saa.length(), (float[]) saa.attrWrapper.getRef());
1056:
1057: default:
1058: // Should never get here
1059: assert false : "Unrecognized ShaderAttributeArray classType";
1060: return null;
1061: }
1062:
1063: }
1064:
1065: void setShaderAttributes(Canvas3D cv,
1066: ShaderAttributeSetRetained attributeSet) {
1067: final boolean useSharedCtx = cv.useSharedCtx
1068: && cv.screen.renderer.sharedCtx != null;
1069: final int cvRdrIndex = useSharedCtx ? cv.screen.renderer.rendererId
1070: : cv.canvasId;
1071: ShaderProgramData spData = getShaderProgramData(cvRdrIndex);
1072:
1073: // Just return if shader program wasn't linked successfully
1074: if (!spData.isLinked()) {
1075: return;
1076: }
1077:
1078: ShaderProgramId shaderProgramId = spData.getShaderProgramId();
1079:
1080: Iterator attrs = attributeSet.getAttrs().values().iterator();
1081: while (attrs.hasNext()) {
1082: ShaderError err = null;
1083: ShaderAttributeRetained saRetained = (ShaderAttributeRetained) attrs
1084: .next();
1085:
1086: // Lookup attribute info for the specified attrName; null means
1087: // that the name does not appear in the ShaderProgram, so we will
1088: // report an error.
1089: AttrNameInfo attrNameInfo = spData
1090: .getAttrNameInfo(saRetained.getAttributeName());
1091: if (attrNameInfo == null) {
1092: // System.err.println("ShaderProgramRetained : attrLocation (" + saRetained.getAttributeName() + ") is null.");
1093: String errMsg = "Attribute name not set in ShaderProgram: "
1094: + saRetained.getAttributeName(); // TODO: I18N
1095: err = new ShaderError(
1096: ShaderError.SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR,
1097: errMsg);
1098: } else {
1099: ShaderAttrLoc loc = attrNameInfo.getLocation();
1100: if (loc != null) {
1101: if (saRetained instanceof ShaderAttributeValueRetained) {
1102: ShaderAttributeValueRetained savRetained = (ShaderAttributeValueRetained) saRetained;
1103: if (attrNameInfo.isArray()
1104: || (savRetained.getClassType() != attrNameInfo
1105: .getType())) {
1106: String errMsg = "Attribute type mismatch: "
1107: + savRetained.getAttributeName(); // TODO: I18N
1108: err = new ShaderError(
1109: ShaderError.SHADER_ATTRIBUTE_TYPE_ERROR,
1110: errMsg);
1111: } else {
1112: err = setUniformAttrValue(cv.ctx,
1113: shaderProgramId, loc, savRetained);
1114: }
1115: } else if (saRetained instanceof ShaderAttributeArrayRetained) {
1116: ShaderAttributeArrayRetained saaRetained = (ShaderAttributeArrayRetained) saRetained;
1117: if (!attrNameInfo.isArray()
1118: || (saaRetained.getClassType() != attrNameInfo
1119: .getType())) {
1120: String errMsg = "Attribute type mismatch: "
1121: + saaRetained.getAttributeName(); // TODO: I18N
1122: err = new ShaderError(
1123: ShaderError.SHADER_ATTRIBUTE_TYPE_ERROR,
1124: errMsg);
1125: } else {
1126: err = setUniformAttrArray(cv.ctx,
1127: shaderProgramId, loc, saaRetained);
1128: }
1129: } else if (saRetained instanceof ShaderAttributeBindingRetained) {
1130: assert false;
1131: throw new RuntimeException("not implemented");
1132: } else {
1133: assert false;
1134: }
1135: }
1136: }
1137:
1138: if (err != null) {
1139: // Before reporting the ShaderAttribute error, check
1140: // whether it has already been reported for this ShaderProgram
1141: if (shaderAttrErrorSet == null) {
1142: shaderAttrErrorSet = new HashSet();
1143: }
1144: if (shaderAttrErrorSet.add(saRetained.source)) {
1145: err.setShaderProgram((ShaderProgram) this .source);
1146: err
1147: .setShaderAttributeSet((ShaderAttributeSet) attributeSet.source);
1148: err
1149: .setShaderAttribute((ShaderAttribute) saRetained.source);
1150: err.setCanvas3D(cv);
1151: notifyErrorListeners(cv, err);
1152: }
1153: }
1154: }
1155: }
1156:
1157: class ShaderProgramData extends Object {
1158:
1159: // issue 378 - time stamp of context creation for this Canvas
1160: private long ctxTimeStamp;
1161:
1162: // shaderProgramId use by native code.
1163: private ShaderProgramId shaderProgramId = null;
1164:
1165: // linked flag for native.
1166: private boolean linked = false;
1167:
1168: // A map of locations for ShaderAttributes.
1169: private HashMap attrNameInfoMap = new HashMap();
1170:
1171: /** ShaderProgramData Constructor */
1172: ShaderProgramData() {
1173: }
1174:
1175: void reset() {
1176: ctxTimeStamp = 0L;
1177: shaderProgramId = null;
1178: linked = false;
1179: attrNameInfoMap.clear();
1180: }
1181:
1182: long getCtxTimeStamp() {
1183: return ctxTimeStamp;
1184: }
1185:
1186: void setCtxTimeStamp(long ctxTimeStamp) {
1187: this .ctxTimeStamp = ctxTimeStamp;
1188: }
1189:
1190: void setShaderProgramId(ShaderProgramId shaderProgramId) {
1191: this .shaderProgramId = shaderProgramId;
1192: }
1193:
1194: ShaderProgramId getShaderProgramId() {
1195: return this .shaderProgramId;
1196: }
1197:
1198: void setLinked(boolean linked) {
1199: this .linked = linked;
1200: }
1201:
1202: boolean isLinked() {
1203: return linked;
1204: }
1205:
1206: void setAttrNameInfo(String shaderAttribute,
1207: AttrNameInfo attrNameInfo) {
1208: assert (shaderAttribute != null);
1209: attrNameInfoMap.put(shaderAttribute, attrNameInfo);
1210: }
1211:
1212: AttrNameInfo getAttrNameInfo(String shaderAttribute) {
1213: return (AttrNameInfo) attrNameInfoMap.get(shaderAttribute);
1214: }
1215:
1216: }
1217:
1218: // Data associated with an attribute name
1219: class AttrNameInfo {
1220: void setLocation(ShaderAttrLoc loc) {
1221: this .loc = loc;
1222: }
1223:
1224: ShaderAttrLoc getLocation() {
1225: return loc;
1226: }
1227:
1228: void setType(int type) {
1229: this .type = type;
1230: }
1231:
1232: int getType() {
1233: return type;
1234: }
1235:
1236: boolean isArray() {
1237: return isArray;
1238: }
1239:
1240: void setArray(boolean isArray) {
1241: this .isArray = isArray;
1242: }
1243:
1244: // Location of attribute name in linked shader program
1245: private ShaderAttrLoc loc;
1246:
1247: // boolean indicating whether the attribute is an array
1248: private boolean isArray;
1249:
1250: // type of shader attribute
1251: private int type;
1252: }
1253:
1254: }
|