001: /*
002: * $RCSfile: ShaderBin.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.8 $
028: * $Date: 2008/02/28 20:17:30 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.Map;
036: import java.util.HashMap;
037: import java.util.ArrayList;
038:
039: // XXXX : We should have a common Bin object that all other Bins extend from.
040:
041: //class ShaderBin extends Object implements ObjectUpdate, NodeComponentUpdate {
042: class ShaderBin implements ObjectUpdate {
043:
044: /**
045: * Node component dirty mask.
046: */
047: static final int SHADER_PROGRAM_DIRTY = 0x1;
048: static final int SHADER_ATTRIBUTE_SET_DIRTY = 0x2;
049:
050: /**
051: * The RenderBin for this object
052: */
053: RenderBin renderBin = null;
054:
055: /**
056: * The AttributeBin that this ShaderBin resides
057: */
058: AttributeBin attributeBin = null;
059:
060: /**
061: * The references to the next and previous ShaderBins in the
062: * list.
063: */
064: ShaderBin next = null;
065: ShaderBin prev = null;
066:
067: /**
068: * The list of TextureBins in this ShaderBin
069: */
070: TextureBin textureBinList = null;
071:
072: /**
073: * The list of TextureBins to be added for the next frame
074: */
075: ArrayList addTextureBins = new ArrayList();
076:
077: boolean onUpdateList = false;
078:
079: int numEditingTextureBins = 0;
080:
081: int componentDirty = 0;
082: ShaderAppearanceRetained shaderAppearance = null;
083: ShaderProgramRetained shaderProgram = null;
084: ShaderAttributeSetRetained shaderAttributeSet = new ShaderAttributeSetRetained();
085:
086: ShaderBin(ShaderAppearanceRetained sApp, RenderBin rBin) {
087: reset(sApp, rBin);
088: }
089:
090: void reset(ShaderAppearanceRetained sApp, RenderBin rBin) {
091: prev = null;
092: next = null;
093: renderBin = rBin;
094: attributeBin = null;
095: textureBinList = null;
096: onUpdateList = false;
097: numEditingTextureBins = 0;
098: addTextureBins.clear();
099: if (sApp != null) {
100: shaderProgram = sApp.shaderProgram;
101: shaderAttributeSet = sApp.shaderAttributeSet;
102: } else {
103: shaderProgram = null;
104: shaderAttributeSet = null;
105: }
106: shaderAppearance = sApp;
107: }
108:
109: void clear() {
110: reset(null, null);
111: }
112:
113: /**
114: * This tests if the qiven ra.shaderProgram match this shaderProgram
115: */
116: boolean equals(ShaderAppearanceRetained sApp) {
117:
118: ShaderProgramRetained sp;
119: ShaderAttributeSetRetained ss;
120:
121: if (sApp == null) {
122: sp = null;
123: ss = null;
124: } else {
125: sp = sApp.shaderProgram;
126: ss = sApp.shaderAttributeSet;
127: }
128:
129: if ((shaderProgram != sp) || (shaderAttributeSet != ss)) {
130: return false;
131: }
132:
133: return true;
134:
135: }
136:
137: public void updateObject() {
138: TextureBin t;
139: int i;
140:
141: if (addTextureBins.size() > 0) {
142: t = (TextureBin) addTextureBins.get(0);
143: if (textureBinList == null) {
144: textureBinList = t;
145:
146: } else {
147: // Look for a TextureBin that has the same texture
148: insertTextureBin(t);
149: }
150: for (i = 1; i < addTextureBins.size(); i++) {
151: t = (TextureBin) addTextureBins.get(i);
152: // Look for a TextureBin that has the same texture
153: insertTextureBin(t);
154:
155: }
156: }
157: addTextureBins.clear();
158: onUpdateList = false;
159:
160: }
161:
162: void insertTextureBin(TextureBin t) {
163: TextureBin tb;
164: int i;
165: TextureRetained texture = null;
166:
167: if (t.texUnitState != null && t.texUnitState.length > 0) {
168: if (t.texUnitState[0] != null) {
169: texture = t.texUnitState[0].texture;
170: }
171: }
172:
173: // use the texture in the first texture unit as the sorting criteria
174: if (texture != null) {
175: tb = textureBinList;
176: while (tb != null) {
177: if (tb.texUnitState == null
178: || tb.texUnitState[0] == null
179: || tb.texUnitState[0].texture != texture) {
180: tb = tb.next;
181: } else {
182: // put it here
183: t.next = tb;
184: t.prev = tb.prev;
185: if (tb.prev == null) {
186: textureBinList = t;
187: } else {
188: tb.prev.next = t;
189: }
190: tb.prev = t;
191: return;
192: }
193: }
194: }
195: // Just put it up front
196: t.prev = null;
197: t.next = textureBinList;
198: textureBinList.prev = t;
199: textureBinList = t;
200:
201: t.tbFlag &= ~TextureBin.RESORT;
202: }
203:
204: /**
205: * reInsert textureBin if the first texture is different from
206: * the previous bin and different from the next bin
207: */
208: void reInsertTextureBin(TextureBin tb) {
209:
210: TextureRetained texture = null, prevTexture = null, nextTexture = null;
211:
212: if (tb.texUnitState != null && tb.texUnitState[0] != null) {
213: texture = tb.texUnitState[0].texture;
214: }
215:
216: if (tb.prev != null && tb.prev.texUnitState != null) {
217: prevTexture = tb.prev.texUnitState[0].texture;
218: }
219:
220: if (texture != prevTexture) {
221: if (tb.next != null && tb.next.texUnitState != null) {
222: nextTexture = tb.next.texUnitState[0].texture;
223: }
224: if (texture != nextTexture) {
225: if (tb.prev != null && tb.next != null) {
226: tb.prev.next = tb.next;
227: tb.next.prev = tb.prev;
228: insertTextureBin(tb);
229: }
230: }
231: }
232: }
233:
234: /**
235: * Adds the given TextureBin to this AttributeBin.
236: */
237: void addTextureBin(TextureBin t, RenderBin rb, RenderAtom ra) {
238:
239: t.environmentSet = this .attributeBin.environmentSet;
240: t.attributeBin = this .attributeBin;
241: t.shaderBin = this ;
242:
243: attributeBin.updateFromShaderBin(ra);
244: addTextureBins.add(t);
245:
246: if (!onUpdateList) {
247: rb.objUpdateList.add(this );
248: onUpdateList = true;
249: }
250: }
251:
252: /**
253: * Removes the given TextureBin from this ShaderBin.
254: */
255: void removeTextureBin(TextureBin t) {
256:
257: // If the TextureBin being remove is contained in addTextureBins,
258: // then remove the TextureBin from the addList
259: if (addTextureBins.contains(t)) {
260: addTextureBins.remove(addTextureBins.indexOf(t));
261: } else {
262: if (t.prev == null) { // At the head of the list
263: textureBinList = t.next;
264: if (t.next != null) {
265: t.next.prev = null;
266: }
267: } else { // In the middle or at the end.
268: t.prev.next = t.next;
269: if (t.next != null) {
270: t.next.prev = t.prev;
271: }
272: }
273: }
274:
275: t.shaderBin = null;
276: t.prev = null;
277: t.next = null;
278:
279: t.clear();
280:
281: if (textureBinList == null && addTextureBins.size() == 0) {
282: // Note: Removal of this shaderBin as a user of the rendering
283: // atttrs is done during removeRenderAtom() in RenderMolecule.java
284: attributeBin.removeShaderBin(this );
285: }
286: }
287:
288: /**
289: * Renders this ShaderBin
290: */
291: void render(Canvas3D cv) {
292:
293: TextureBin tb;
294:
295: // System.err.println("ShaderBin.render() shaderProgram = " + shaderProgram);
296:
297: // include this ShaderBin to the to-be-updated list in canvas
298: cv.setStateToUpdate(Canvas3D.SHADERBIN_BIT, this );
299:
300: tb = textureBinList;
301: while (tb != null) {
302: tb.render(cv);
303: tb = tb.next;
304: }
305: }
306:
307: void updateAttributes(Canvas3D cv) {
308:
309: // System.err.println("ShaderBin.updateAttributes() shaderProgram is " + shaderProgram);
310: if (shaderProgram != null) {
311: // Compile, link, and enable shader program
312: shaderProgram.updateNative(cv, true);
313:
314: if (shaderAttributeSet != null) {
315: shaderAttributeSet.updateNative(cv, shaderProgram);
316: }
317:
318: } else {
319: if (cv.shaderProgram != null) {
320: // Disable shader program
321: cv.shaderProgram.updateNative(cv, false);
322: }
323: }
324:
325: cv.shaderBin = this ;
326: cv.shaderProgram = shaderProgram;
327: }
328:
329: void updateNodeComponent() {
330: // System.err.println("ShaderBin.updateNodeComponent() ...");
331:
332: // We don't need to clone shaderProgram.
333: // ShaderProgram object can't be modified once it is live,
334: // so each update should be a new reference.
335: if ((componentDirty & SHADER_PROGRAM_DIRTY) != 0) {
336: // System.err.println(" - SHADER_PROGRAM_DIRTY");
337:
338: shaderProgram = shaderAppearance.shaderProgram;
339: }
340:
341: // We need to clone the shaderAttributeSet.
342: if ((componentDirty & SHADER_ATTRIBUTE_SET_DIRTY) != 0) {
343: // System.err.println(" - SHADER_ATTRIBUTE_SET_DIRTY");
344:
345: HashMap attrs = (HashMap) shaderAttributeSet.getAttrs();
346: attrs.clear();
347: if (shaderAppearance.shaderAttributeSet != null) {
348: attrs.putAll(shaderAppearance.shaderAttributeSet
349: .getAttrs());
350: }
351: }
352:
353: componentDirty = 0;
354: }
355:
356: void incrActiveTextureBin() {
357: numEditingTextureBins++;
358: }
359:
360: void decrActiveTextureBin() {
361: numEditingTextureBins--;
362: }
363: }
|