001: /*
002: * $RCSfile: TextureUnitStateRetained.java,v $
003: *
004: * Copyright 1999-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:32 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.Color4f;
035: import java.util.ArrayList;
036:
037: class TextureUnitStateRetained extends NodeComponentRetained {
038:
039: static final int TEXTURE_CHANGED = 0x0001;
040: static final int TEXTURE_ATTRS_CHANGED = 0x0002;
041: static final int TEXCOORD_GEN_CHANGED = 0x0004;
042: static final int ALL_STATE_CHANGED = 0x0008;
043:
044: TextureRetained texture = null;
045: TextureAttributesRetained texAttrs = null;
046: TexCoordGenerationRetained texGen = null;
047:
048: /**
049: * An abstract method to validate the texture unit state component
050: */
051: final void setTextureUnitStateComponent(NodeComponent comp,
052: NodeComponentRetained this Comp, int messageOp) {
053: if (source.isLive()) {
054:
055: if ((comp == null && this Comp == null)
056: || (comp != null && comp.retained == this Comp))
057: return;
058:
059: if (this Comp != null) {
060: this Comp.clearLive(refCount);
061: this Comp.removeMirrorUsers(this );
062: }
063:
064: if (comp != null) {
065: ((NodeComponentRetained) comp.retained).setLive(
066: inBackgroundGroup, refCount);
067: // If texture unit is live, then copy all the users of this
068: // texture unit state as users of this texture component
069: ((NodeComponentRetained) comp.retained)
070: .copyMirrorUsers(this );
071: }
072:
073: if (messageOp != -1) {
074: sendMessage(
075: messageOp,
076: (comp == null ? null
077: : ((NodeComponentRetained) comp.retained).mirror));
078: }
079:
080: }
081: }
082:
083: final void initTextureUnitState(Texture texture,
084: TextureAttributes texAttrs, TexCoordGeneration texGen) {
085:
086: initTexture(texture);
087: initTextureAttributes(texAttrs);
088: initTexCoordGeneration(texGen);
089: }
090:
091: final void setTextureUnitState(Texture texture,
092: TextureAttributes texAttrs, TexCoordGeneration texGen) {
093:
094: setTextureUnitStateComponent(texture, this .texture, -1);
095: setTextureUnitStateComponent(texAttrs, this .texAttrs, -1);
096: setTextureUnitStateComponent(texGen, this .texGen, -1);
097:
098: // send all changes to the target threads in one
099: // message to avoid modifying the renderBin repeatedly
100:
101: Object args[] = new Object[3];
102: args[0] = (texture == null ? null
103: : ((TextureRetained) texture.retained).mirror);
104: args[1] = (texAttrs == null ? null
105: : ((TextureAttributesRetained) texAttrs.retained).mirror);
106: args[2] = (texGen == null ? null
107: : ((TexCoordGenerationRetained) texGen.retained).mirror);
108:
109: sendMessage(ALL_STATE_CHANGED, args);
110:
111: initTextureUnitState(texture, texAttrs, texGen);
112: }
113:
114: final void initTexture(Texture texture) {
115: if (texture == null)
116: this .texture = null;
117: else
118: this .texture = (TextureRetained) texture.retained;
119: }
120:
121: final void setTexture(Texture texture) {
122: setTextureUnitStateComponent(texture, this .texture,
123: TEXTURE_CHANGED);
124: initTexture(texture);
125: }
126:
127: final void initTextureAttributes(TextureAttributes texAttrs) {
128: if (texAttrs == null)
129: this .texAttrs = null;
130: else
131: this .texAttrs = (TextureAttributesRetained) texAttrs.retained;
132: }
133:
134: final void setTextureAttributes(TextureAttributes texAttrs) {
135: setTextureUnitStateComponent(texAttrs, this .texAttrs,
136: TEXTURE_ATTRS_CHANGED);
137: initTextureAttributes(texAttrs);
138: }
139:
140: final void initTexCoordGeneration(TexCoordGeneration texGen) {
141: if (texGen == null)
142: this .texGen = null;
143: else
144: this .texGen = (TexCoordGenerationRetained) texGen.retained;
145: }
146:
147: final void setTexCoordGeneration(TexCoordGeneration texGen) {
148: setTextureUnitStateComponent(texGen, this .texGen,
149: TEXCOORD_GEN_CHANGED);
150: initTexCoordGeneration(texGen);
151: }
152:
153: Texture getTexture() {
154: return (texture == null ? null : (Texture) texture.source);
155: }
156:
157: TextureAttributes getTextureAttributes() {
158: return (texAttrs == null ? null
159: : (TextureAttributes) texAttrs.source);
160: }
161:
162: TexCoordGeneration getTexCoordGeneration() {
163: return (texGen == null ? null
164: : (TexCoordGeneration) texGen.source);
165: }
166:
167: void updateNative(int unitIndex, Canvas3D cv, boolean reload,
168: boolean simulate) {
169:
170: //System.err.println("TextureUnitState/updateNative: unitIndex= " + unitIndex + " reload= " + reload + " simulate= " + simulate);
171:
172: // unitIndex can be -1 for the single texture case, so
173: // can't use unitIndex to index into the cv.texUnitState;
174: // in this case, use index 0
175:
176: int index = unitIndex;
177:
178: if (index < 0)
179: index = 0;
180:
181: boolean dirty = ((cv.canvasDirty & (Canvas3D.TEXTUREATTRIBUTES_DIRTY | Canvas3D.TEXTUREBIN_DIRTY)) != 0);
182:
183: if (this .texture == null) {
184: // if texture is null, then texture mapped is
185: // disabled for this texture unit; and no more
186: // state update is needed
187:
188: //System.err.println("texture is null");
189:
190: if (cv.texUnitState[index].texture != null) {
191: cv.resetTexture(cv.ctx, unitIndex);
192: cv.texUnitState[index].texture = null;
193: }
194: cv.canvasDirty &= ~Canvas3D.TEXTUREATTRIBUTES_DIRTY;
195: return;
196: } else {
197:
198: Pipeline.getPipeline().updateTextureUnitState(cv.ctx,
199: unitIndex, true);
200: }
201:
202: // reload is needed in a multi-texture case to bind the
203: // texture parameters to the texture unit state
204:
205: if (reload || dirty
206: || cv.texUnitState[index].texture != this .texture) {
207:
208: // texture cannot be null at this point because it is
209: // already checked above
210: this .texture.updateNative(cv);
211:
212: cv.texUnitState[index].texture = this .texture;
213:
214: }
215:
216: if (this .texAttrs == null) {
217: if (reload || dirty
218: || cv.texUnitState[index].texAttrs != null) {
219: cv.resetTextureAttributes(cv.ctx);
220: if (VirtualUniverse.mc.isD3D()
221: && (texGen != null)
222: && ((texGen.genMode == TexCoordGeneration.EYE_LINEAR) || ((texGen.genMode == TexCoordGeneration.SPHERE_MAP)))) {
223: // We need to reload tex since eye linear
224: // and sphere map in D3D will change the
225: // texture transform matrix also.
226: dirty = true;
227: }
228: cv.setBlendFunc(cv.ctx,
229: TransparencyAttributes.BLEND_ONE,
230: TransparencyAttributes.BLEND_ZERO);
231: cv.texUnitState[index].texAttrs = null;
232: }
233: } else {
234:
235: TextureAttributesRetained mTexAttrs;
236: if (this .texAttrs.mirror == null) {
237: mTexAttrs = this .texAttrs;
238: } else {
239: mTexAttrs = (TextureAttributesRetained) this .texAttrs.mirror;
240: }
241:
242: if (mTexAttrs.mirrorCompDirty) {
243: // This happen when canvas reference is same as
244: // texUnitState.texAttrs and we update the later without
245: // notify cache.
246: cv.texUnitState[index].texAttrs = null;
247: mTexAttrs.mirrorCompDirty = false;
248: }
249:
250: if (reload || dirty
251: || cv.texUnitState[index].texAttrs != mTexAttrs) {
252: this .texAttrs
253: .updateNative(cv, simulate, texture.format);
254: if (VirtualUniverse.mc.isD3D()
255: && (texGen != null)
256: && ((texGen.genMode == TexCoordGeneration.EYE_LINEAR) || ((texGen.genMode == TexCoordGeneration.SPHERE_MAP)))) {
257: dirty = true;
258: }
259: cv.texUnitState[index].texAttrs = mTexAttrs;
260: }
261: }
262:
263: if (this .texGen == null) {
264: if (reload || dirty
265: || cv.texUnitState[index].texGen != null) {
266: cv.resetTexCoordGeneration(cv.ctx);
267: cv.texUnitState[index].texGen = null;
268: }
269: } else {
270: TexCoordGenerationRetained mTexGen;
271:
272: if (this .texGen.mirror == null) {
273: mTexGen = this .texGen;
274: } else {
275: mTexGen = (TexCoordGenerationRetained) this .texGen.mirror;
276: }
277:
278: if (mTexGen.mirrorCompDirty) {
279: // This happen when canvas reference is same as
280: // texUnitState.texGen and we update the later without
281: // notify cache.
282: cv.texUnitState[index].texGen = null;
283: mTexGen.mirrorCompDirty = false;
284: }
285:
286: if (reload || dirty
287: || cv.texUnitState[index].texGen != mTexGen) {
288: this .texGen.updateNative(cv);
289: cv.texUnitState[index].texGen = mTexGen;
290: }
291: }
292: cv.canvasDirty &= ~Canvas3D.TEXTUREATTRIBUTES_DIRTY;
293: }
294:
295: /**
296: * Creates and initializes a mirror object, point the mirror object
297: * to the retained object if the object is not editable
298: */
299: synchronized void createMirrorObject() {
300:
301: if (mirror == null) {
302: TextureUnitStateRetained mirrorTus = new TextureUnitStateRetained();
303: mirror = mirrorTus;
304: }
305: mirror.source = source;
306: initMirrorObject();
307:
308: }
309:
310: synchronized void initMirrorObject() {
311:
312: TextureUnitStateRetained mirrorTus = (TextureUnitStateRetained) mirror;
313:
314: if (this .texture != null)
315: mirrorTus.texture = (TextureRetained) this .texture.mirror;
316: else
317: mirrorTus.texture = null;
318:
319: if (this .texAttrs != null)
320: mirrorTus.texAttrs = (TextureAttributesRetained) this .texAttrs.mirror;
321: else
322: mirrorTus.texAttrs = null;
323:
324: if (this .texGen != null)
325: mirrorTus.texGen = (TexCoordGenerationRetained) this .texGen.mirror;
326: else
327: mirrorTus.texGen = null;
328: }
329:
330: /** Update the "component" field of the mirror object with the
331: * given "value"
332: */
333: synchronized void updateMirrorObject(int component, Object value) {
334:
335: TextureUnitStateRetained mirrorTus = (TextureUnitStateRetained) mirror;
336:
337: if ((component & TEXTURE_CHANGED) != 0) {
338: mirrorTus.texture = (TextureRetained) value;
339: } else if ((component & TEXTURE_ATTRS_CHANGED) != 0) {
340: mirrorTus.texAttrs = (TextureAttributesRetained) value;
341: } else if ((component & TEXCOORD_GEN_CHANGED) != 0) {
342: mirrorTus.texGen = (TexCoordGenerationRetained) value;
343: } else if ((component & ALL_STATE_CHANGED) != 0) {
344: Object[] args = (Object[]) value;
345: mirrorTus.texture = (TextureRetained) args[0];
346: mirrorTus.texAttrs = (TextureAttributesRetained) args[1];
347: mirrorTus.texGen = (TexCoordGenerationRetained) args[2];
348: }
349: }
350:
351: boolean equivalent(TextureUnitStateRetained tr) {
352:
353: if (tr == null) {
354: return (false);
355:
356: } else if ((this .changedFrequent != 0)
357: || (tr.changedFrequent != 0)) {
358: return (this .mirror == tr);
359:
360: } else {
361:
362: if (this .texture != tr.texture) {
363: return false;
364: }
365:
366: if (this .texAttrs != null
367: && !this .texAttrs.equivalent(tr.texAttrs)) {
368: return false;
369: }
370:
371: if (this .texGen != null
372: && !this .texGen.equivalent(tr.texGen)) {
373: return false;
374: }
375: }
376:
377: return true;
378: }
379:
380: protected Object clone() {
381: TextureUnitStateRetained tr = (TextureUnitStateRetained) super
382: .clone();
383:
384: // the cloned object is used for RenderBin only.
385: // In most cases, it will duplicate all attributes in the RenderBin
386: // so that updating a mirror object in one level will not affect the
387: // entire structure of the RenderBin, but will affect only those bins
388: // that got affected by the modified mirror object
389: if (this .texAttrs != null)
390: tr.texAttrs = (TextureAttributesRetained) this .texAttrs
391: .clone();
392:
393: if (this .texGen != null)
394: tr.texGen = (TexCoordGenerationRetained) this .texGen
395: .clone();
396:
397: return tr;
398: }
399:
400: /**
401: * set the texture unit state according to the specified texture
402: * unit state
403: */
404: protected void set(TextureUnitStateRetained tr) {
405: super .set(tr);
406: this .texture = tr.texture;
407:
408: if (tr.texAttrs == null) {
409: this .texAttrs = null;
410: } else {
411: if (this .texAttrs == null) {
412: this .texAttrs = (TextureAttributesRetained) tr.texAttrs
413: .clone();
414: } else {
415: this .texAttrs.set(tr.texAttrs);
416: }
417: }
418:
419: if (tr.texGen == null) {
420: this .texGen = null;
421: } else {
422: if (this .texGen == null) {
423: this .texGen = (TexCoordGenerationRetained) tr.texGen
424: .clone();
425: } else {
426: this .texGen.set(tr.texGen);
427: }
428: }
429: }
430:
431: protected void set(TextureRetained texture,
432: TextureAttributesRetained texAttrs,
433: TexCoordGenerationRetained texGen) {
434: this .texture = texture;
435: this .texAttrs = texAttrs;
436: this .texGen = texGen;
437: }
438:
439: synchronized void addAMirrorUser(Shape3DRetained shape) {
440:
441: super .addAMirrorUser(shape);
442:
443: if (texture != null)
444: texture.addAMirrorUser(shape);
445: if (texAttrs != null)
446: texAttrs.addAMirrorUser(shape);
447: if (texGen != null)
448: texGen.addAMirrorUser(shape);
449: }
450:
451: synchronized void removeAMirrorUser(Shape3DRetained shape) {
452: super .removeAMirrorUser(shape);
453:
454: if (texture != null)
455: texture.removeAMirrorUser(shape);
456: if (texAttrs != null)
457: texAttrs.removeAMirrorUser(shape);
458: if (texGen != null)
459: texGen.removeAMirrorUser(shape);
460: }
461:
462: synchronized void removeMirrorUsers(NodeComponentRetained node) {
463: super .removeMirrorUsers(node);
464:
465: if (texture != null)
466: texture.removeMirrorUsers(node);
467: if (texAttrs != null)
468: texAttrs.removeMirrorUsers(node);
469: if (texGen != null)
470: texGen.removeMirrorUsers(node);
471: }
472:
473: synchronized void copyMirrorUsers(NodeComponentRetained node) {
474: super .copyMirrorUsers(node);
475:
476: if (texture != null)
477: texture.copyMirrorUsers(node);
478: if (texAttrs != null)
479: texAttrs.copyMirrorUsers(node);
480: if (texGen != null)
481: texGen.copyMirrorUsers(node);
482: }
483:
484: void setLive(boolean backgroundGroup, int refCount) {
485: if (texture != null)
486: texture.setLive(backgroundGroup, refCount);
487:
488: if (texAttrs != null)
489: texAttrs.setLive(backgroundGroup, refCount);
490:
491: if (texGen != null)
492: texGen.setLive(backgroundGroup, refCount);
493:
494: // Increment the reference count and initialize the textureUnitState
495: // mirror object
496: super .doSetLive(backgroundGroup, refCount);
497: super .markAsLive();
498:
499: }
500:
501: void clearLive(int refCount) {
502: super .clearLive(refCount);
503:
504: if (texture != null)
505: texture.clearLive(refCount);
506: if (texAttrs != null)
507: texAttrs.clearLive(refCount);
508: if (texGen != null)
509: texGen.clearLive(refCount);
510: }
511:
512: boolean isStatic() {
513:
514: return (source.capabilityBitsEmpty()
515: && ((texture == null) || (texture.isStatic()))
516: && ((texAttrs == null) || (texAttrs.isStatic())) && ((texGen == null) || (texGen
517: .isStatic())));
518: }
519:
520: // Issue 209 - enable this method (was previously commented out)
521: // Simply pass along to the NodeComponent
522: void compile(CompileState compState) {
523: setCompiled();
524:
525: if (texture != null)
526: texture.compile(compState);
527: if (texAttrs != null)
528: texAttrs.compile(compState);
529: if (texGen != null)
530: texGen.compile(compState);
531: }
532:
533: boolean equals(TextureUnitStateRetained ts) {
534: return ((ts == this ) || (ts != null)
535: && ((texture == ts.texture) || ((texture != null) && (texture
536: .equals(ts.texture))))
537: && ((texAttrs == ts.texAttrs) || ((texAttrs != null) && (texAttrs
538: .equals(ts.texAttrs))))
539: && ((texGen == ts.texGen) || ((texGen != null) && (texGen
540: .equals(ts.texGen)))));
541: }
542:
543: void setInImmCtx(boolean flag) {
544: super .setInImmCtx(flag);
545: if (texture != null)
546: texture.setInImmCtx(flag);
547: if (texAttrs != null)
548: texAttrs.setInImmCtx(flag);
549: if (texGen != null)
550: texGen.setInImmCtx(flag);
551: }
552:
553: boolean getInImmCtx() {
554: return (super .getInImmCtx()
555: || ((texture != null) && (texture.getInImmCtx()))
556: || ((texAttrs != null) && (texAttrs.getInImmCtx())) || ((texGen != null) && (texGen
557: .getInImmCtx())));
558: }
559:
560: boolean isLive() {
561: return (source.isLive()
562: || ((texture != null) && (texture.source.isLive()))
563: || ((texAttrs != null) && (texAttrs.source.isLive())) || ((texGen != null) && (texGen.source
564: .isLive())));
565: }
566:
567: final void sendMessage(int attrMask, Object attr) {
568: ArrayList univList = new ArrayList();
569: ArrayList gaList = Shape3DRetained.getGeomAtomsList(
570: mirror.users, univList);
571:
572: // Send to rendering attribute structure, regardless of
573: // whether there are users or not (alternate appearance case ..)
574: J3dMessage createMessage = new J3dMessage();
575: createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
576: createMessage.type = J3dMessage.TEXTURE_UNIT_STATE_CHANGED;
577: createMessage.universe = null;
578: createMessage.args[0] = this ;
579: createMessage.args[1] = new Integer(attrMask);
580: createMessage.args[2] = attr;
581: createMessage.args[3] = new Integer(changedFrequent);
582: VirtualUniverse.mc.processMessage(createMessage);
583:
584: // System.err.println("univList.size is " + univList.size());
585: for (int i = 0; i < univList.size(); i++) {
586: createMessage = new J3dMessage();
587: createMessage.threads = J3dThread.UPDATE_RENDER;
588: createMessage.type = J3dMessage.TEXTURE_UNIT_STATE_CHANGED;
589:
590: createMessage.universe = (VirtualUniverse) univList.get(i);
591: createMessage.args[0] = this ;
592: createMessage.args[1] = new Integer(attrMask);
593: createMessage.args[2] = attr;
594:
595: ArrayList gL = (ArrayList) gaList.get(i);
596: GeometryAtom[] gaArr = new GeometryAtom[gL.size()];
597: gL.toArray(gaArr);
598: createMessage.args[3] = gaArr;
599:
600: VirtualUniverse.mc.processMessage(createMessage);
601: }
602:
603: }
604:
605: boolean isTextureEnabled() {
606: // Check the internal enable , instead of userSpecifiedEnable
607: return (texture != null && texture.enable);
608: }
609:
610: void handleFrequencyChange(int bit) {
611: switch (bit) {
612: case TextureUnitState.ALLOW_STATE_WRITE: {
613: setFrequencyChangeMask(bit, bit);
614: }
615: default:
616: break;
617: }
618: }
619: }
|