001: /*
002: * $RCSfile: ShaderAppearanceRetained.java,v $
003: *
004: * Copyright 2004-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.10 $
028: * $Date: 2008/02/28 20:17:29 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.Vector;
035: import java.util.BitSet;
036: import java.util.ArrayList;
037:
038: /**
039: * The Appearance object defines all rendering state that can be set
040: * as a component object of a Shape3D node.
041: */
042: class ShaderAppearanceRetained extends AppearanceRetained {
043:
044: // Issue 485 - these values must start after the last value in Appearance
045: static final int SHADER_PROGRAM = 0x0800;
046: static final int SHADER_ATTRIBUTE_SET = 0x1000;
047:
048: //
049: // State variables: these should all be initialized to approproate
050: // Java 3D defaults.
051: //
052:
053: protected ShaderProgramRetained shaderProgram = null;
054: protected ShaderAttributeSetRetained shaderAttributeSet = null;
055: protected boolean isMirror = false; // For Debugging.
056:
057: /**
058: * Set the shader program object to the specified object.
059: * @param shaderProgram object that specifies the desired shader program
060: * and shader program attributes.
061: */
062: void setShaderProgram(ShaderProgram sp) {
063: synchronized (liveStateLock) {
064: if (source.isLive()) {
065: // System.err.println("**** ShaderAppearceRetained.setShaderProgram()");
066:
067: if (this .shaderProgram != null) {
068: this .shaderProgram.clearLive(refCount);
069: this .shaderProgram.removeMirrorUsers(this );
070: }
071:
072: if (sp != null) {
073: ((ShaderProgramRetained) sp.retained).setLive(
074: inBackgroundGroup, refCount);
075: ((ShaderProgramRetained) sp.retained)
076: .copyMirrorUsers(this );
077: }
078:
079: sendMessage(
080: SHADER_PROGRAM,
081: (sp != null ? ((ShaderProgramRetained) sp.retained).mirror
082: : null));
083:
084: }
085:
086: if (sp == null) {
087: this .shaderProgram = null;
088: } else {
089: this .shaderProgram = (ShaderProgramRetained) sp.retained;
090: }
091: }
092: }
093:
094: /**
095: * Retrieves the current shader program object.
096: * @return current shader program object
097: */
098: ShaderProgram getShaderProgram() {
099: return (shaderProgram == null ? null
100: : (ShaderProgram) shaderProgram.source);
101: }
102:
103: /**
104: * Sets the ShaderAttributeSet object to the specified object. Setting it to
105: * null is equivalent to specifying an empty set of attributes.
106: *
107: * @param shaderAttributeSet object that specifies the desired shader attributes
108: */
109: void setShaderAttributeSet(ShaderAttributeSet sas) {
110: synchronized (liveStateLock) {
111: if (source.isLive()) {
112: // System.err.println("**** ShaderAppearceRetained.setShaderAttributeSet()");
113:
114: if (this .shaderAttributeSet != null) {
115: this .shaderAttributeSet.clearLive(refCount);
116: this .shaderAttributeSet.removeMirrorUsers(this );
117: }
118:
119: if (sas != null) {
120: ((ShaderAttributeSetRetained) sas.retained)
121: .setLive(inBackgroundGroup, refCount);
122: ((ShaderAttributeSetRetained) sas.retained)
123: .copyMirrorUsers(this );
124: }
125:
126: // System.err.println(" -- testing needed!");
127: sendMessage(
128: SHADER_ATTRIBUTE_SET,
129: (sas != null ? ((ShaderAttributeSetRetained) sas.retained).mirror
130: : null));
131:
132: }
133:
134: if (sas == null) {
135: this .shaderAttributeSet = null;
136: } else {
137: this .shaderAttributeSet = (ShaderAttributeSetRetained) sas.retained;
138: }
139: }
140: }
141:
142: /**
143: * Retrieves the current ShaderAttributeSet object.
144: * @return current ShaderAttributeSet object
145: */
146: ShaderAttributeSet getShaderAttributeSet() {
147: return (shaderAttributeSet == null ? null
148: : (ShaderAttributeSet) shaderAttributeSet.source);
149:
150: }
151:
152: public boolean equals(Object obj) {
153: return ((obj instanceof ShaderAppearanceRetained) && equals((ShaderAppearanceRetained) obj));
154: }
155:
156: boolean equals(ShaderAppearanceRetained sApp) {
157: boolean flag;
158: flag = (sApp == this );
159:
160: // If the reference is the same, we can stop check.
161: if (flag)
162: return flag;
163:
164: // Check each member's reference for equal.
165: flag = ((sApp != null) && (shaderProgram == sApp.shaderProgram) && (shaderAttributeSet == sApp.shaderAttributeSet));
166:
167: if (!flag)
168: return flag;
169:
170: return super .equals(sApp);
171:
172: }
173:
174: synchronized void createMirrorObject() {
175: // System.err.println("ShaderAppearanceRetained : createMirrorObject()");
176:
177: if (mirror == null) {
178: // we can't check isStatic() since it sub-NodeComponent
179: // create a new one, we should create a
180: // new AppearanceRetained() even though isStatic() = true.
181: // For simplicity, always create a retained side.
182: mirror = new ShaderAppearanceRetained();
183: ((ShaderAppearanceRetained) mirror).isMirror = true; // For Debugging.
184: }
185: initMirrorObject();
186: }
187:
188: /**
189: * This routine updates the mirror appearance for this appearance.
190: * It also calls the update method for each node component if it
191: * is not null.
192: */
193: synchronized void initMirrorObject() {
194: // System.err.println("ShaderAppearanceRetained : initMirrorObject()");
195:
196: super .initMirrorObject();
197:
198: ShaderAppearanceRetained mirrorApp = (ShaderAppearanceRetained) mirror;
199:
200: if (shaderProgram != null) {
201: mirrorApp.shaderProgram = (ShaderProgramRetained) shaderProgram.mirror;
202: } else {
203: mirrorApp.shaderProgram = null;
204: }
205:
206: if (shaderAttributeSet != null) {
207: mirrorApp.shaderAttributeSet = (ShaderAttributeSetRetained) shaderAttributeSet.mirror;
208: } else {
209: // System.err.println("shaderAttributeSet is null");
210: mirrorApp.shaderAttributeSet = null;
211: }
212:
213: }
214:
215: /**
216: * Update the "component" field of the mirror object with the
217: * given "value"
218: */
219: synchronized void updateMirrorObject(int component, Object value) {
220:
221: // System.err.println("ShaderAppearanceRetained : updateMirrorObject(): " +
222: // "this = " + this + " component = " + component + " value = " + value);
223: super .updateMirrorObject(component, value);
224: ShaderAppearanceRetained mirrorApp = (ShaderAppearanceRetained) mirror;
225: if ((component & SHADER_PROGRAM) != 0) {
226: mirrorApp.shaderProgram = (ShaderProgramRetained) value;
227: } else if ((component & SHADER_ATTRIBUTE_SET) != 0) {
228: mirrorApp.shaderAttributeSet = (ShaderAttributeSetRetained) value;
229: }
230:
231: }
232:
233: /**
234: * This method calls the setLive method of all appearance bundle
235: * objects.
236: */
237: void doSetLive(boolean backgroundGroup, int refCount) {
238: // System.err.println("ShaderAppearceRetained.doSetLive()");
239:
240: if (shaderProgram != null) {
241: shaderProgram.setLive(backgroundGroup, refCount);
242: }
243:
244: if (shaderAttributeSet != null) {
245: shaderAttributeSet.setLive(backgroundGroup, refCount);
246: }
247:
248: // Increment the reference count and initialize the appearance
249: // mirror object
250: super .doSetLive(backgroundGroup, refCount);
251: }
252:
253: /**
254: * This clearLive routine first calls the superclass's method, then
255: * it removes itself to the list of lights
256: */
257: void clearLive(int refCount) {
258: super .clearLive(refCount);
259:
260: if (shaderProgram != null) {
261: shaderProgram.clearLive(refCount);
262: }
263:
264: if (shaderAttributeSet != null) {
265: shaderAttributeSet.clearLive(refCount);
266: }
267: }
268:
269: synchronized void addAMirrorUser(Shape3DRetained shape) {
270:
271: super .addAMirrorUser(shape);
272: if (shaderProgram != null)
273: shaderProgram.addAMirrorUser(shape);
274: if (shaderAttributeSet != null)
275: shaderAttributeSet.addAMirrorUser(shape);
276: }
277:
278: synchronized void removeAMirrorUser(Shape3DRetained shape) {
279:
280: super .removeAMirrorUser(shape);
281: if (shaderProgram != null)
282: shaderProgram.removeAMirrorUser(shape);
283: if (shaderAttributeSet != null)
284: shaderAttributeSet.removeAMirrorUser(shape);
285: }
286:
287: final void sendMessage(int attrMask, Object attr) {
288: ArrayList univList = new ArrayList();
289: ArrayList gaList = Shape3DRetained.getGeomAtomsList(
290: mirror.users, univList);
291: // Send to rendering attribute structure, regardless of
292: // whether there are users or not (alternate appearance case ..)
293: J3dMessage createMessage = new J3dMessage();
294: createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
295: createMessage.type = J3dMessage.SHADER_APPEARANCE_CHANGED;
296: createMessage.universe = null;
297: createMessage.args[0] = this ;
298: createMessage.args[1] = new Integer(attrMask);
299: createMessage.args[2] = attr;
300: createMessage.args[3] = new Integer(changedFrequent);
301:
302: VirtualUniverse.mc.processMessage(createMessage);
303:
304: //System.err.println("univList.size is " + univList.size());
305: for (int i = 0; i < univList.size(); i++) {
306: createMessage = new J3dMessage();
307: createMessage.threads = J3dThread.UPDATE_RENDER;
308: createMessage.type = J3dMessage.SHADER_APPEARANCE_CHANGED;
309:
310: createMessage.universe = (VirtualUniverse) univList.get(i);
311: createMessage.args[0] = this ;
312: createMessage.args[1] = new Integer(attrMask);
313: createMessage.args[2] = attr;
314:
315: ArrayList gL = (ArrayList) gaList.get(i);
316: GeometryAtom[] gaArr = new GeometryAtom[gL.size()];
317: gL.toArray(gaArr);
318: createMessage.args[3] = gaArr;
319:
320: VirtualUniverse.mc.processMessage(createMessage);
321: }
322: }
323:
324: boolean isStatic() {
325: if (!super .isStatic()) {
326: return false;
327: }
328:
329: boolean flag = source.capabilityBitsEmpty()
330: && ((shaderProgram == null) || shaderProgram.source
331: .capabilityBitsEmpty())
332: && ((shaderAttributeSet == null) || shaderAttributeSet.source
333: .capabilityBitsEmpty());
334:
335: return flag;
336: }
337:
338: // Issue 209 - implement the compile method
339: // Simply pass along to the NodeComponents
340: void compile(CompileState compState) {
341: super .compile(compState);
342:
343: if (shaderProgram != null) {
344: shaderProgram.compile(compState);
345: }
346:
347: if (shaderAttributeSet != null) {
348: shaderAttributeSet.compile(compState);
349: }
350: }
351:
352: boolean isOpaque(int geoType) {
353:
354: if (!super .isOpaque(geoType)) {
355: return false;
356: }
357:
358: // TODO: IMPLEMENT THIS
359: // TODO: How do we determine whether a ShaderAppearance is opaque???
360: return true;
361: }
362:
363: void handleFrequencyChange(int bit) {
364: // System.err.println("ShaderAppearanceRetained : handleFrequencyChange()");
365: super .handleFrequencyChange(bit);
366:
367: int mask = 0;
368: if (bit == ShaderAppearance.ALLOW_SHADER_PROGRAM_WRITE)
369: mask = SHADER_PROGRAM;
370: else if (bit == ShaderAppearance.ALLOW_SHADER_ATTRIBUTE_SET_WRITE)
371: mask = SHADER_ATTRIBUTE_SET;
372:
373: if (mask != 0)
374: setFrequencyChangeMask(bit, mask);
375: }
376: }
|