001: /*
002: * $RCSfile: ShaderAttributeSetRetained.java,v $
003: *
004: * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.9 $
028: * $Date: 2008/02/28 20:17:29 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.Iterator;
035: import java.util.Map;
036: import java.util.HashMap;
037: import java.util.ArrayList;
038: import javax.vecmath.*;
039:
040: /**
041: * The ShaderAttributeSet object provides uniform attributes to shader
042: * programs.
043: */
044:
045: class ShaderAttributeSetRetained extends NodeComponentRetained {
046:
047: private Map attrs = new HashMap();
048:
049: // Lock used for synchronization of live state
050: Object liveStateLock = new Object();
051:
052: /**
053: * Constructs an empty ShaderAttributeSetretained object. The attributes set
054: * is initially empty.
055: */
056: ShaderAttributeSetRetained() {
057: }
058:
059: //
060: // Methods for dealing with the (name, value) pairs for explicit
061: // attributes
062: //
063:
064: /**
065: * Adds the specified shader attribute to the attributes set.
066: * The newly specified attribute replaces an attribute with the
067: * same name, if one already exists in the attributes set.
068: *
069: * @param attr the shader attribute to be added to the set
070: *
071: */
072: void put(ShaderAttribute attr) {
073: synchronized (liveStateLock) {
074: // System.err.println("ShaderAttributeSetRetained : put()");
075: ShaderAttributeRetained sAttr = (ShaderAttributeRetained) attr.retained;
076: // System.err.println("attr is " + attr );
077: // System.err.println("attrName is " + sAttr.attrName + " attr.Retained is "+ sAttr );
078: assert (sAttr != null);
079: attrs.put(sAttr.attrName, sAttr);
080:
081: if (source.isLive()) {
082: sAttr.setLive(inBackgroundGroup, refCount);
083: sAttr.copyMirrorUsers(this );
084:
085: sendMessage(ShaderConstants.ATTRIBUTE_SET_PUT,
086: sAttr.mirror);
087: }
088: }
089: }
090:
091: /**
092: * Retrieves the shader attribute with the specified
093: * <code>attrName</code> from the attributes set. If attrName does
094: * not exist in the attributes set, null is returned.
095: *
096: * @param attrName the name of the shader attribute to be retrieved
097: *
098: * @exception CapabilityNotSetException if appropriate capability is
099: * not set and this object is part of live or compiled scene graph
100: */
101: ShaderAttribute get(String attrName) {
102: return (ShaderAttribute) ((ShaderAttributeRetained) attrs
103: .get(attrName)).source;
104: }
105:
106: /**
107: * Removes the shader attribute with the specified
108: * <code>attrName</code> from the attributes set. If attrName does
109: * not exist in the attributes set then nothing happens.
110: *
111: * @param attrName the name of the shader attribute to be removed
112: */
113: void remove(String attrName) {
114: synchronized (liveStateLock) {
115: ShaderAttributeRetained sAttr = (ShaderAttributeRetained) attrs
116: .get(attrName);
117: attrs.remove(attrName);
118: if (source.isLive()) {
119: sAttr.clearLive(refCount);
120: sAttr.removeMirrorUsers(this );
121:
122: sendMessage(ShaderConstants.ATTRIBUTE_SET_REMOVE,
123: attrName);
124: }
125: }
126: }
127:
128: /**
129: * Removes the specified shader attribute from the attributes
130: * set. If the attribute does not exist in the attributes set then
131: * nothing happens. Note that this method will <i>not</i> remove a
132: * shader object other than the one specified, even if it has the
133: * same name as the specified attribute. Applications that wish to
134: * remove an attribute by name should use
135: * <code>removeAttribute(String)</code>.
136: *
137: * @param attr the shader attribute to be removed
138: */
139: void remove(ShaderAttribute attr) {
140: synchronized (liveStateLock) {
141: String attrName = attr.getAttributeName();
142: if (attrs.get(attrName) == attr) {
143: attrs.remove(attrName);
144: if (source.isLive()) {
145: ((ShaderAttributeRetained) attr.retained)
146: .clearLive(refCount);
147: ((ShaderAttributeRetained) attr.retained)
148: .removeMirrorUsers(this );
149:
150: sendMessage(ShaderConstants.ATTRIBUTE_SET_REMOVE,
151: attrName);
152: }
153: }
154: }
155: }
156:
157: /**
158: * Removes all shader attributes from the attributes set. The
159: * attributes set will be empty following this call.
160: *
161: */
162: void clear() {
163: synchronized (liveStateLock) {
164: attrs.clear();
165: if (source.isLive()) {
166: ShaderAttributeRetained[] sAttrs = new ShaderAttributeRetained[attrs
167: .size()];
168: sAttrs = (ShaderAttributeRetained[]) attrs.values()
169: .toArray(sAttrs);
170: for (int i = 0; i < sAttrs.length; i++) {
171: sAttrs[i].clearLive(refCount);
172: sAttrs[i].removeMirrorUsers(this );
173: }
174: sendMessage(ShaderConstants.ATTRIBUTE_SET_CLEAR, null);
175: }
176: }
177: }
178:
179: /**
180: * Returns a shallow copy of the attributes set.
181: *
182: * @return a shallow copy of the attributes set
183: *
184: */
185: ShaderAttribute[] getAll() {
186:
187: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
188: .size()];
189: ShaderAttribute[] sAttrs = new ShaderAttribute[sAttrsRetained.length];
190: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
191: .toArray(sAttrsRetained);
192: for (int i = 0; i < sAttrsRetained.length; i++) {
193: sAttrs[i] = (ShaderAttribute) sAttrsRetained[i].source;
194: }
195:
196: return sAttrs;
197: }
198:
199: /**
200: * Returns the number of elements in the attributes set.
201: *
202: * @return the number of elements in the attributes set
203: *
204: */
205: int size() {
206: return attrs.size();
207: }
208:
209: void updateNative(Canvas3D cv, ShaderProgramRetained shaderProgram) {
210: shaderProgram.setShaderAttributes(cv, this );
211: }
212:
213: Map getAttrs() {
214: return attrs;
215: }
216:
217: void setLive(boolean backgroundGroup, int refCount) {
218:
219: // System.err.println("ShaderAttributeSetRetained.setLive()");
220: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
221: .size()];
222: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
223: .toArray(sAttrsRetained);
224: for (int i = 0; i < sAttrsRetained.length; i++) {
225: sAttrsRetained[i].setLive(backgroundGroup, refCount);
226: }
227:
228: super .doSetLive(backgroundGroup, refCount);
229: super .markAsLive();
230: }
231:
232: synchronized void addAMirrorUser(Shape3DRetained shape) {
233:
234: super .addAMirrorUser(shape);
235:
236: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
237: .size()];
238: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
239: .toArray(sAttrsRetained);
240: for (int i = 0; i < sAttrsRetained.length; i++) {
241: sAttrsRetained[i].addAMirrorUser(shape);
242: }
243: }
244:
245: synchronized void removeAMirrorUser(Shape3DRetained shape) {
246: super .removeAMirrorUser(shape);
247:
248: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
249: .size()];
250: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
251: .toArray(sAttrsRetained);
252: for (int i = 0; i < sAttrsRetained.length; i++) {
253: sAttrsRetained[i].removeAMirrorUser(shape);
254: }
255: }
256:
257: synchronized void removeMirrorUsers(NodeComponentRetained node) {
258: super .removeMirrorUsers(node);
259:
260: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
261: .size()];
262: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
263: .toArray(sAttrsRetained);
264: for (int i = 0; i < sAttrsRetained.length; i++) {
265: sAttrsRetained[i].removeMirrorUsers(node);
266: }
267: }
268:
269: synchronized void copyMirrorUsers(NodeComponentRetained node) {
270: super .copyMirrorUsers(node);
271:
272: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
273: .size()];
274: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
275: .toArray(sAttrsRetained);
276: for (int i = 0; i < sAttrsRetained.length; i++) {
277: sAttrsRetained[i].copyMirrorUsers(node);
278: }
279: }
280:
281: void clearLive(int refCount) {
282: // System.err.println("ShaderAttributeSetRetained.clearLive()");
283:
284: super .clearLive(refCount);
285:
286: ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs
287: .size()];
288: sAttrsRetained = (ShaderAttributeRetained[]) attrs.values()
289: .toArray(sAttrsRetained);
290: for (int i = 0; i < sAttrsRetained.length; i++) {
291: sAttrsRetained[i].clearLive(refCount);
292: }
293: }
294:
295: synchronized void createMirrorObject() {
296: // System.err.println("ShaderAttributeSetRetained : createMirrorObject");
297: // This method should only call by setLive().
298: if (mirror == null) {
299: ShaderAttributeSetRetained mirrorSAS = new ShaderAttributeSetRetained();
300: mirror = mirrorSAS;
301: mirror.source = source;
302:
303: }
304: initMirrorObject();
305: }
306:
307: void initMirrorObject() {
308:
309: ShaderAttributeRetained[] sAttrs = new ShaderAttributeRetained[attrs
310: .size()];
311: sAttrs = (ShaderAttributeRetained[]) attrs.values().toArray(
312: sAttrs);
313: // Need to copy the mirror attrs
314: for (int i = 0; i < sAttrs.length; i++) {
315: ShaderAttributeRetained mirrorSA = (ShaderAttributeRetained) sAttrs[i].mirror;
316: assert (mirrorSA != null);
317: ((ShaderAttributeSetRetained) mirror).attrs.put(
318: mirrorSA.attrName, mirrorSA);
319: }
320: }
321:
322: /**
323: * Update the "component" field of the mirror object with the given "value"
324: */
325: synchronized void updateMirrorObject(int component, Object value) {
326:
327: // System.err.println("ShaderAttributeSetRetained : updateMirrorObject");
328:
329: ShaderAttributeSetRetained mirrorSAS = (ShaderAttributeSetRetained) mirror;
330:
331: if ((component & ShaderConstants.ATTRIBUTE_SET_PUT) != 0) {
332: // System.err.println(" -- ATTRIBUTE_SET_PUT");
333: ShaderAttributeRetained mirrorSA = (ShaderAttributeRetained) value;
334: assert (mirrorSA != null);
335: ((ShaderAttributeSetRetained) mirror).attrs.put(
336: mirrorSA.attrName, mirrorSA);
337: } else if ((component & ShaderConstants.ATTRIBUTE_SET_REMOVE) != 0) {
338: // System.err.println(" -- ATTRIBUTE_SET_REMOVE");
339: ((ShaderAttributeSetRetained) mirror).attrs
340: .remove((String) value);
341: } else if ((component & ShaderConstants.ATTRIBUTE_SET_CLEAR) != 0) {
342: // System.err.println(" -- ATTRIBUTE_SET_CLEAR");
343: ((ShaderAttributeSetRetained) mirror).attrs.clear();
344: } else {
345: assert (false);
346: }
347: }
348:
349: final void sendMessage(int attrMask, Object attr) {
350:
351: ArrayList univList = new ArrayList();
352: ArrayList gaList = Shape3DRetained.getGeomAtomsList(
353: mirror.users, univList);
354:
355: // Send to rendering attribute structure, regardless of
356: // whether there are users or not (alternate appearance case ..)
357: J3dMessage createMessage = new J3dMessage();
358: createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
359: createMessage.type = J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED;
360: createMessage.universe = null;
361: createMessage.args[0] = this ;
362: createMessage.args[1] = new Integer(attrMask);
363: createMessage.args[2] = attr;
364: // System.err.println("changedFreqent1 = "+changedFrequent);
365: createMessage.args[3] = new Integer(changedFrequent);
366: VirtualUniverse.mc.processMessage(createMessage);
367:
368: // System.err.println("univList.size is " + univList.size());
369: for (int i = 0; i < univList.size(); i++) {
370: createMessage = new J3dMessage();
371: createMessage.threads = J3dThread.UPDATE_RENDER;
372: createMessage.type = J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED;
373:
374: createMessage.universe = (VirtualUniverse) univList.get(i);
375: createMessage.args[0] = this ;
376: createMessage.args[1] = new Integer(attrMask);
377: createMessage.args[2] = attr;
378:
379: ArrayList gL = (ArrayList) gaList.get(i);
380: GeometryAtom[] gaArr = new GeometryAtom[gL.size()];
381: gL.toArray(gaArr);
382: createMessage.args[3] = gaArr;
383:
384: VirtualUniverse.mc.processMessage(createMessage);
385: }
386:
387: }
388:
389: // Issue 320 : Override base class method so we can force changedFrequent
390: // to be set whenever the capability is writable, regardless of whether
391: // it is frequently writable. We must do this because the ShaderBin doesn't
392: // support updating shader attributes when changedFrequent is 0.
393: void setFrequencyChangeMask(int bit, int mask) {
394: if (source.getCapability(bit)) {
395: changedFrequent |= mask;
396: } else if (!source.isLive()) {
397: // Record the freq->infreq change only for non-live node components
398: changedFrequent &= ~mask;
399: }
400: }
401:
402: void handleFrequencyChange(int bit) {
403: if (bit == ShaderAttributeSet.ALLOW_ATTRIBUTES_WRITE) {
404: setFrequencyChangeMask(bit, 0x1);
405: }
406: }
407:
408: }
|