Source Code Cross Referenced for Canvas3D.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: Canvas3D.java,v $
0003:         *
0004:         * Copyright 1997-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.45 $
0028:         * $Date: 2008/02/28 20:17:20 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import javax.vecmath.*;
0035:        import java.awt.*;
0036:        import java.awt.image.BufferedImage;
0037:        import java.util.*;
0038:
0039:        /**
0040:         * The Canvas3D class provides a drawing canvas for 3D rendering.  It
0041:         * is used either for on-screen rendering or off-screen rendering.
0042:         * Canvas3D is an extension of the AWT Canvas class that users may
0043:         * further subclass to implement additional functionality.
0044:         * <p>
0045:         * The Canvas3D object extends the Canvas object to include 
0046:         * 3D-related information such as the size of the canvas in pixels, 
0047:         * the Canvas3D's location, also in pixels, within a Screen3D object, 
0048:         * and whether or not the canvas has stereo enabled.
0049:         * <p>
0050:         * Because all Canvas3D objects contain a 
0051:         * reference to a Screen3D object and because Screen3D objects define 
0052:         * the size of a pixel in physical units, Java 3D can convert a Canvas3D 
0053:         * size in pixels to a physical world size in meters. It can also 
0054:         * determine the Canvas3D's position and orientation in the
0055:         * physical world.
0056:         * <p>
0057:         * <b>On-screen Rendering vs. Off-screen Rendering</b>
0058:         * <p>
0059:         * The Canvas3D class is used either for on-screen rendering or 
0060:         * off-screen rendering.
0061:         * On-screen Canvas3Ds are added to AWT or Swing Container objects
0062:         * like any other canvas.  Java 3D automatically and continuously
0063:         * renders to all on-screen canvases that are attached to an active
0064:         * View object.  On-screen Canvas3Ds can be either single or double
0065:         * buffered and they can be either stereo or monoscopic.
0066:         * <p>
0067:         * Off-screen Canvas3Ds must not be added to any Container.  Java 3D
0068:         * renders to off-screen canvases in response to the
0069:         * <code>renderOffScreenBuffer</code> method.  Off-screen Canvas3Ds
0070:         * are single buffered.  However, on many systems, the actual
0071:         * rendering is done to an off-screen hardware buffer or to a 3D
0072:         * library-specific buffer and only copied to the off-screen buffer of
0073:         * the Canvas when the rendering is complete, at "buffer swap" time.
0074:         * Off-screen Canvas3Ds are monoscopic.
0075:         * <p>
0076:         * The setOffScreenBuffer method sets the off-screen buffer for this 
0077:         * Canvas3D. The specified image is written into by the Java 3D renderer. 
0078:         * The size of the specified ImageComponent determines the size, in 
0079:         * pixels, of this Canvas3D - the size inherited from Component is 
0080:         * ignored. Note that the size, physical width, and physical height of the
0081:         * associated Screen3D must be set
0082:         * explicitly prior to rendering. Failure to do so will result in an 
0083:         * exception.
0084:         * <p>
0085:         * The getOffScreenBuffer method retrieves the off-screen 
0086:         * buffer for this Canvas3D.
0087:         * <p>
0088:         * The renderOffScreenBuffer method schedules the rendering of a frame 
0089:         * into this Canvas3D's off-screen buffer. The rendering is done from 
0090:         * the point of view of the View object to which this Canvas3D has been 
0091:         * added. No rendering is performed if this Canvas3D object has not been 
0092:         * added to an active View. This method does not wait for the rendering 
0093:         * to actually happen. An application that wishes to know when the 
0094:         * rendering is complete must either subclass Canvas3D and
0095:         * override the postSwap method, or call waitForOffScreenRendering.
0096:         * <p>
0097:         * The setOfScreenLocation methods set the location of this off-screen 
0098:         * Canvas3D.  The location is the upper-left corner of the Canvas3D 
0099:         * relative to the upper-left corner of the corresponding off-screen 
0100:         * Screen3D. The function of these methods is similar to that of 
0101:         * Component.setLocation for on-screen Canvas3D objects. The default 
0102:         * location is (0,0).
0103:         * <p>
0104:         * <b>Accessing and Modifying an Eye's Image Plate Position</b>
0105:         * <p>
0106:         * A Canvas3D object provides sophisticated applications with access 
0107:         * to the eye's position information in head-tracked, room-mounted 
0108:         * runtime environments. It also allows applications to manipulate 
0109:         * the position of an eye relative to an image plate in non-head-tracked 
0110:         * runtime environments.
0111:         * <p>
0112:         * The setLeftManualEyeInImagePlate and setRightManualEyeInImagePlate
0113:         * methods set the position of the manual left and right eyes in image 
0114:         * plate coordinates. These values determine eye placement when a head 
0115:         * tracker is not in use and the application is directly controlling the 
0116:         * eye position in image plate coordinates. In head-tracked mode or 
0117:         * when the windowEyepointPolicy is RELATIVE_TO_FIELD_OF_VIEW or
0118:         * RELATIVE_TO_COEXISTENCE, this 
0119:         * value is ignored. When the windowEyepointPolicy is RELATIVE_TO_WINDOW, 
0120:         * only the Z value is used.
0121:         * <p>
0122:         * The getLeftEyeInImagePlate, getRightEyeInImagePlate, and
0123:         * getCenterEyeInImagePlate methods retrieve the actual position of the 
0124:         * left eye, right eye, and center eye in image plate coordinates and 
0125:         * copy that value into the object provided. The center eye is the 
0126:         * fictional eye half-way between the left and right eye. These three 
0127:         * values are a function of the windowEyepointPolicy, the tracking 
0128:         * enable flag, and the manual left, right, and center eye positions.
0129:         * <p>
0130:         * <b>Monoscopic View Policy</b>
0131:         * <p>
0132:         * The setMonoscopicViewPolicy and getMonoscopicViewPolicy methods
0133:         * set and retrieve the policy regarding how Java 3D generates monoscopic 
0134:         * view. If the policy is set to View.LEFT_EYE_VIEW, the view generated 
0135:         * corresponds to the view as seen from the left eye. If set to 
0136:         * View.RIGHT_EYE_VIEW, the view generated corresponds to the view as 
0137:         * seen from the right eye. If set to View.CYCLOPEAN_EYE_VIEW, the view 
0138:         * generated corresponds to the view as seen from the "center eye," the 
0139:         * fictional eye half-way between the left and right eye. The default 
0140:         * monoscopic view policy is View.CYCLOPEAN_EYE_VIEW.
0141:         * <p>
0142:         * <b>Immediate Mode Rendering</b>
0143:         * <p>
0144:         * Pure immediate-mode rendering provides for those applications and 
0145:         * applets that do not want Java 3D to do any automatic rendering of 
0146:         * the scene graph. Such applications may not even wish to build a 
0147:         * scene graph to represent their graphical data. However, they use 
0148:         * Java 3D's attribute objects to set graphics state and Java 3D's 
0149:         * geometric objects to render geometry.
0150:         * <p>
0151:         * A pure immediate mode application must create a minimal set of 
0152:         * Java 3D objects before rendering. In addition to a Canvas3D object, 
0153:         * the application must create a View object, with its associated 
0154:         * PhysicalBody and PhysicalEnvironment objects, and the following 
0155:         * scene graph elements: a VirtualUniverse object, a high-resolution 
0156:         * Locale object, a BranchGroup node object, a TransformGroup node 
0157:         * object with associated transform, and a ViewPlatform 
0158:         * leaf node object that defines the position and orientation within
0159:         * the virtual universe that generates the view.
0160:         * <p>
0161:         * In immediate mode, all rendering is done completely under user 
0162:         * control. It is necessary for the user to clear the 3D canvas, 
0163:         * render all geometry, and swap the buffers.  Additionally, 
0164:         * rendering the right and left eye for stereo viewing becomes the
0165:         * sole responsibility of the application.  In pure immediate mode, 
0166:         * the user must stop the Java 3D renderer, via the
0167:         * Canvas3D object <code>stopRenderer</code> method, prior to adding the 
0168:         * Canvas3D object to an active View object (that is, one that is 
0169:         * attached to a live ViewPlatform object).
0170:         * <p>
0171:         * Other Canvas3D methods related to immediate mode rendering are:
0172:         * <p>
0173:         * <ul>
0174:         * <code>getGraphicsContext3D</code> retrieves the immediate-mode 
0175:         * 3D graphics context associated with this Canvas3D. It creates a 
0176:         * new graphics context if one does not already exist.
0177:         * <p>
0178:         * <code>getGraphics2D</code> retrieves the 
0179:         * 2D graphics object associated with this Canvas3D. It creates a 
0180:         * new 2D graphics object if one does not already exist.
0181:         * <p>
0182:         * <code>swap</code> synchronizes and swaps buffers on a 
0183:         * double-buffered canvas for this Canvas3D object. This method 
0184:         * should only be called if the Java 3D renderer has been stopped. 
0185:         * In the normal case, the renderer automatically swaps
0186:         * the buffer.
0187:         * </ul>
0188:         *
0189:         * <p>
0190:         * <b>Mixed Mode Rendering</b>
0191:         * <p>
0192:         * Mixing immediate mode and retained or compiled-retained mode 
0193:         * requires more structure than pure immediate mode. In mixed mode, 
0194:         * the Java 3D renderer is running continuously, rendering the scene 
0195:         * graph into the canvas.
0196:         *
0197:         * <p>
0198:         * Canvas3D methods related to mixed mode rendering are:
0199:         *
0200:         * <p>
0201:         * <ul>
0202:         * <code>preRender</code> called by the Java 3D rendering loop after 
0203:         * clearing the canvas and before any rendering has been done for 
0204:         * this frame. 
0205:         * <p>
0206:         * <code>postRender</code> called by the Java 3D rendering loop after
0207:         * completing all rendering to the canvas for this frame and before 
0208:         * the buffer swap.
0209:         * <p>
0210:         * <code>postSwap</code> called by the Java 3D rendering loop after 
0211:         * completing all rendering to the canvas, and all other canvases 
0212:         * associated with this view, for this frame following the
0213:         * buffer swap.
0214:         * <p>
0215:         * <code>renderField</code> called by the Java 3D rendering loop 
0216:         * during the execution of the rendering loop. It is called once 
0217:         * for each field (i.e., once per frame on a mono system or once 
0218:         * each for the right eye and left eye on a two-pass stereo system. 
0219:         * </ul>
0220:         * <p>
0221:         * The above callback methods are called by the Java 3D rendering system
0222:         * and should <i>not</i> be called by an application directly.
0223:         *
0224:         * <p>
0225:         * The basic Java 3D <i>stereo</i> rendering loop, 
0226:         * executed for each Canvas3D, is as follows:
0227:         * <ul><pre>
0228:         * clear canvas (both eyes)
0229:         * call preRender()                           // user-supplied method
0230:         * set left eye view
0231:         * render opaque scene graph objects
0232:         * call renderField(FIELD_LEFT)               // user-supplied method
0233:         * render transparent scene graph objects
0234:         * set right eye view
0235:         * render opaque scene graph objects again
0236:         * call renderField(FIELD_RIGHT)              // user-supplied method
0237:         * render transparent scene graph objects again
0238:         * call postRender()                          // user-supplied method
0239:         * synchronize and swap buffers
0240:         * call postSwap()                            // user-supplied method
0241:         * </pre></ul>
0242:         * <p>
0243:         * The basic Java 3D <i>monoscopic</i> rendering loop is as follows:
0244:         * <ul><pre>
0245:         * clear canvas
0246:         * call preRender()                            // user-supplied method
0247:         * set view
0248:         * render opaque scene graph objects
0249:         * call renderField(FIELD_ALL)                 // user-supplied method
0250:         * render transparent scene graph objects
0251:         * call postRender()                           // user-supplied method
0252:         * synchronize and swap buffers
0253:         * call postSwap()                             // user-supplied method
0254:         * </pre></ul>
0255:         * <p>
0256:         * In both cases, the entire loop, beginning with clearing the canvas 
0257:         * and ending with swapping the buffers, defines a frame. The application 
0258:         * is given the opportunity to render immediate-mode geometry at any of 
0259:         * the clearly identified spots in the rendering loop. A user specifies 
0260:         * his or her own rendering methods by extending the Canvas3D class and 
0261:         * overriding the preRender, postRender, postSwap, and/or renderField 
0262:         * methods.
0263:         * Updates to live Geometry, Texture, and ImageComponent objects
0264:         * in the scene graph are not allowed from any of these callback
0265:         * methods.
0266:         *
0267:         * <p>
0268:         * <b>Serialization</b>
0269:         * <p>
0270:         * Canvas3D does <i>not</i> support serialization.  An attempt to
0271:         * serialize a Canvas3D object will result in an
0272:         * UnsupportedOperationException being thrown.
0273:         *
0274:         * <p>
0275:         * <b>Additional Information</b>
0276:         * <p>
0277:         * For more information, see the
0278:         * <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and
0279:         * <a href="doc-files/ViewModel.html">View Model</a>
0280:         * documents.
0281:         *
0282:         * @see Screen3D
0283:         * @see View
0284:         * @see GraphicsContext3D
0285:         */
0286:        public class Canvas3D extends Canvas {
0287:            /**
0288:             * Specifies the left field of a field-sequential stereo rendering loop.
0289:             * A left field always precedes a right field.
0290:             */
0291:            public static final int FIELD_LEFT = 0;
0292:
0293:            /**
0294:             * Specifies the right field of a field-sequential stereo rendering loop.
0295:             * A right field always follows a left field.
0296:             */
0297:            public static final int FIELD_RIGHT = 1;
0298:
0299:            /**
0300:             * Specifies a single-field rendering loop.
0301:             */
0302:            public static final int FIELD_ALL = 2;
0303:
0304:            // 
0305:            // The following constants are bit masks to specify which of the node
0306:            // components are dirty and need updates.
0307:            // 
0308:            // Values for the geometryType field.
0309:            static final int POLYGONATTRS_DIRTY = 0x01;
0310:            static final int LINEATTRS_DIRTY = 0x02;
0311:            static final int POINTATTRS_DIRTY = 0x04;
0312:            static final int MATERIAL_DIRTY = 0x08;
0313:            static final int TRANSPARENCYATTRS_DIRTY = 0x10;
0314:            static final int COLORINGATTRS_DIRTY = 0x20;
0315:
0316:            // Values for lightbin, env set, texture, texture setting etc.
0317:            static final int LIGHTBIN_DIRTY = 0x40;
0318:            static final int LIGHTENABLES_DIRTY = 0x80;
0319:            static final int AMBIENTLIGHT_DIRTY = 0x100;
0320:            static final int ATTRIBUTEBIN_DIRTY = 0x200;
0321:            static final int TEXTUREBIN_DIRTY = 0x400;
0322:            static final int TEXTUREATTRIBUTES_DIRTY = 0x800;
0323:            static final int RENDERMOLECULE_DIRTY = 0x1000;
0324:            static final int FOG_DIRTY = 0x2000;
0325:            static final int MODELCLIP_DIRTY = 0x4000;
0326:            static final int VIEW_MATRIX_DIRTY = 0x8000;
0327:            // static final int SHADER_DIRTY              = 0x10000; Not ready for this yet -- JADA
0328:
0329:            // Use to notify D3D Canvas when window change
0330:            static final int RESIZE = 1;
0331:            static final int TOGGLEFULLSCREEN = 2;
0332:            static final int NOCHANGE = 0;
0333:            static final int RESETSURFACE = 1;
0334:            static final int RECREATEDDRAW = 2;
0335:
0336:            //
0337:            // Flag that indicates whether this Canvas3D is an off-screen Canvas3D
0338:            //
0339:            boolean offScreen = false;
0340:
0341:            //
0342:            // Issue 131: Flag that indicates whether this Canvas3D is a manually
0343:            // rendered Canvas3D (versus an automatically rendered Canvas3D).
0344:            //
0345:            // NOTE: manualRendering only applies to off-screen Canvas3Ds at this time.
0346:            // We have no plans to ever change this, but if we do, it might be necessary
0347:            // to determine which, if any, of the uses of "manualRendering" should be
0348:            // changed to "manualRendering&&offScreen"
0349:            //
0350:            boolean manualRendering = false;
0351:
0352:            // user specified offScreen Canvas location
0353:            Point offScreenCanvasLoc;
0354:
0355:            // user specified offScreen Canvas dimension
0356:            Dimension offScreenCanvasSize;
0357:
0358:            //
0359:            // Flag that indicates whether off-screen rendering is in progress or not
0360:            //
0361:            volatile boolean offScreenRendering = false;
0362:
0363:            //
0364:            // Flag that indicates we are waiting for an off-screen buffer to be
0365:            // created or destroyed by the Renderer.
0366:            //
0367:            volatile boolean offScreenBufferPending = false;
0368:
0369:            //
0370:            // ImageComponent used for off-screen rendering
0371:            //
0372:            ImageComponent2D offScreenBuffer = null;
0373:
0374:            // flag that indicates whether this canvas will use shared context
0375:            boolean useSharedCtx = true;
0376:
0377:            //
0378:            // Read-only flag that indicates whether stereo is supported for this
0379:            // canvas.  This is always false for off-screen canvases.
0380:            //
0381:            boolean stereoAvailable;
0382:
0383:            //
0384:            // Flag to enable stereo rendering, if allowed by the
0385:            // stereoAvailable flag.
0386:            //
0387:            boolean stereoEnable = true;
0388:
0389:            //
0390:            // This flag is set when stereo mode is both enabled and
0391:            // available.  Code that looks at stereo mode should use this
0392:            // flag.
0393:            //
0394:            boolean useStereo;
0395:
0396:            // Indicate whether it is left or right stereo pass currently
0397:            boolean rightStereoPass = false;
0398:
0399:            //
0400:            // Specifies how Java 3D generates monoscopic view
0401:            // (LEFT_EYE_VIEW, RIGHT_EYE_VIEW, or CYCLOPEAN_EYE_VIEW).
0402:            //
0403:            int monoscopicViewPolicy = View.CYCLOPEAN_EYE_VIEW;
0404:
0405:            // User requested stencil size 
0406:            int requestedStencilSize;
0407:
0408:            // Actual stencil size return for this canvas
0409:            int actualStencilSize;
0410:
0411:            // True if stencil buffer is available for user
0412:            boolean userStencilAvailable;
0413:
0414:            // True if stencil buffer is available for system ( decal )
0415:            boolean systemStencilAvailable;
0416:
0417:            //
0418:            // Read-only flag that indicates whether double buffering is supported
0419:            // for this canvas.  This is always false for off-screen canvases.
0420:            //
0421:            boolean doubleBufferAvailable;
0422:
0423:            //
0424:            // Flag to enable double buffered rendering, if allowed by the
0425:            // doubleBufferAvailable flag.
0426:            //
0427:            boolean doubleBufferEnable = true;
0428:
0429:            //
0430:            // This flag is set when doubleBuffering is both enabled and
0431:            // available Code that enables or disables double buffering should
0432:            // use this flag.
0433:            //
0434:            boolean useDoubleBuffer;
0435:
0436:            //
0437:            // Read-only flag that indicates whether scene antialiasing
0438:            // is supported for this canvas.
0439:            //
0440:            boolean sceneAntialiasingAvailable;
0441:            boolean sceneAntialiasingMultiSamplesAvailable;
0442:
0443:            // Use to see whether antialiasing is already set
0444:            boolean antialiasingSet = false;
0445:
0446:            //
0447:            // Read-only flag that indicates the size of the texture color
0448:            // table for this canvas.  A value of 0 indicates that the texture
0449:            // color table is not supported.
0450:            //
0451:            int textureColorTableSize;
0452:
0453:            // number of active/enabled texture unit 
0454:            int numActiveTexUnit = 0;
0455:
0456:            // index iof last enabled texture unit 
0457:            int lastActiveTexUnit = -1;
0458:
0459:            // True if shadingLanguage is supported, otherwise false.
0460:            boolean shadingLanguageGLSL = false;
0461:            boolean shadingLanguageCg = false;
0462:
0463:            // Query properties
0464:            J3dQueryProps queryProps;
0465:
0466:            // Flag indicating a fatal rendering error of some sort
0467:            private boolean fatalError = false;
0468:
0469:            //
0470:            // The positions of the manual left and right eyes in image-plate
0471:            // coordinates.
0472:            // By default, we will use the center of the screen for X and Y values
0473:            // (X values are adjusted for default eye separation), and
0474:            // 0.4572 meters (18 inches) for the Z value.
0475:            // These match defaults elsewhere in the system.
0476:            //
0477:            Point3d leftManualEyeInImagePlate = new Point3d(0.142, 0.135,
0478:                    0.4572);
0479:            Point3d rightManualEyeInImagePlate = new Point3d(0.208, 0.135,
0480:                    0.4572);
0481:
0482:            //
0483:            // View that is attached to this Canvas3D.
0484:            //
0485:            View view = null;
0486:
0487:            // View waiting to be set
0488:            View pendingView;
0489:
0490:            //
0491:            // View cache for this canvas and its associated view.
0492:            //
0493:            CanvasViewCache canvasViewCache = null;
0494:
0495:            // Issue 109: View cache for this canvas, for computing view frustum planes
0496:            CanvasViewCache canvasViewCacheFrustum = null;
0497:
0498:            // Since multiple renderAtomListInfo, share the same vecBounds
0499:            // we want to do the intersection test only once per renderAtom
0500:            // this flag is set to true after the first intersect and set to
0501:            // false during checkForCompaction in renderBin
0502:            boolean raIsVisible = false;
0503:
0504:            RenderAtom ra = null;
0505:
0506:            // Stereo related field has changed.
0507:            static final int STEREO_DIRTY = 0x01;
0508:            // MonoscopicViewPolicy field has changed.
0509:            static final int MONOSCOPIC_VIEW_POLICY_DIRTY = 0x02;
0510:            // Left/right eye in image plate field has changed.
0511:            static final int EYE_IN_IMAGE_PLATE_DIRTY = 0x04;
0512:            // Canvas has moved/resized.
0513:            static final int MOVED_OR_RESIZED_DIRTY = 0x08;
0514:
0515:            // Canvas Background changed (this may affect doInfinite flag)
0516:            static final int BACKGROUND_DIRTY = 0x10;
0517:
0518:            // Canvas Background Image changed
0519:            static final int BACKGROUND_IMAGE_DIRTY = 0x20;
0520:
0521:            // Mask that indicates this Canvas view dependence info. has changed,
0522:            // and CanvasViewCache may need to recompute the final view matries.
0523:            static final int VIEW_INFO_DIRTY = (STEREO_DIRTY
0524:                    | MONOSCOPIC_VIEW_POLICY_DIRTY | EYE_IN_IMAGE_PLATE_DIRTY
0525:                    | MOVED_OR_RESIZED_DIRTY | BACKGROUND_DIRTY | BACKGROUND_IMAGE_DIRTY);
0526:
0527:            // Issue 163: Array of dirty bits is used because the Renderer and
0528:            // RenderBin run asynchronously. Now that they each have a separate
0529:            // instance of CanvasViewCache (due to the fix for Issue 109), they
0530:            // need separate dirty bits. Array element 0 is used for the Renderer and
0531:            // element 1 is used for the RenderBin.
0532:            static final int RENDERER_DIRTY_IDX = 0;
0533:            static final int RENDER_BIN_DIRTY_IDX = 1;
0534:            int[] cvDirtyMask = new int[2];
0535:
0536:            // This boolean informs the J3DGraphics2DImpl that the window is resized
0537:            boolean resizeGraphics2D = true;
0538:            //
0539:            // This boolean allows an application to start and stop the render
0540:            // loop on this canvas.
0541:            //
0542:            volatile boolean isRunning = true;
0543:
0544:            // This is used by MasterControl only. MC relay on this in a
0545:            // single loop to set renderer thread. During this time,
0546:            // the isRunningStatus can't change by user thread.
0547:            volatile boolean isRunningStatus = true;
0548:
0549:            // This is true when the canvas is ready to be rendered into
0550:            boolean active = false;
0551:
0552:            // This is true when the canvas is visible
0553:            boolean visible = false;
0554:
0555:            // This is true if context need to recreate
0556:            boolean ctxReset = true;
0557:
0558:            // The Screen3D that corresponds to this Canvas3D
0559:            Screen3D screen = null;
0560:
0561:            // Flag to indicate that image is render completely 
0562:            // so swap is valid.
0563:            boolean imageReady = false;
0564:
0565:            //
0566:            // The current fog enable state 
0567:            //   
0568:            int fogOn = 0;
0569:
0570:            // The 3D Graphics context used for immediate mode rendering
0571:            // into this canvas.
0572:            GraphicsContext3D graphicsContext3D = null;
0573:            boolean waiting = false;
0574:            boolean swapDone = false;
0575:
0576:            GraphicsConfiguration graphicsConfiguration;
0577:
0578:            // The Java 3D Graphics2D object used for Java2D/AWT rendering
0579:            // into this Canvas3D
0580:            J3DGraphics2DImpl graphics2D = null;
0581:
0582:            // Lock used to synchronize the creation of the 2D and 3D
0583:            // graphics context objects
0584:            Object gfxCreationLock = new Object();
0585:
0586:            // The source of the currently loaded localToVWorld for this Canvas3D
0587:            // (used to only update the model matrix when it changes)
0588:            //    Transform3D	localToVWorldSrc = null;
0589:
0590:            // The current vworldToEc Transform
0591:            Transform3D vworldToEc = new Transform3D();
0592:
0593:            // The view transform (VPC to EC) for the current eye.
0594:            // NOTE that this is *read-only*
0595:            Transform3D vpcToEc;
0596:
0597:            // Opaque object representing the underlying drawable (window). This
0598:            // is defined by the Pipeline.
0599:            Drawable drawable = null;
0600:
0601:            // fbConfig is a pointer to the fbConfig object that is associated with 
0602:            // the GraphicsConfiguration object used to create this Canvas.
0603:            //
0604:            // For Unix : Fix for issue 20.
0605:            // The fbConfig is only used when running X11.  It contains a pointer
0606:            // to the native GLXFBConfig structure list, since in some cases the visual id
0607:            // alone isn't sufficient for the native OpenGL renderer (e.g., when using
0608:            // Solaris OpenGL with Xinerama mode disabled).
0609:            //
0610:            // For Windows : Fix for issue 76.  This is use as a holder of the
0611:            // PixelFormat structure ( see also gldef.h ) to allow value such
0612:            // as offScreen's pixelformat, and ARB function pointers to be stored.
0613:            long fbConfig = 0;
0614:
0615:            // offScreenBufferInfo is a pointer to additional information about the
0616:            // offScreenBuffer in this Canvas.
0617:            //
0618:            // For Windows : Fix for issue 76.
0619:            long offScreenBufferInfo = 0;
0620:
0621:            // graphicsConfigTable is a static hashtable which allows getBestConfiguration()
0622:            // in NativeConfigTemplate3D to map a GraphicsConfiguration to the pointer
0623:            // to the actual GLXFBConfig that glXChooseFBConfig() returns.  The Canvas3D
0624:            // doesn't exist at the time getBestConfiguration() is called, and
0625:            // X11GraphicsConfig neither maintains this pointer nor provides a public
0626:            // constructor to allow Java 3D to extend it.
0627:            static Hashtable<GraphicsConfiguration, GraphicsConfigInfo> graphicsConfigTable = new Hashtable<GraphicsConfiguration, GraphicsConfigInfo>();
0628:
0629:            // The native graphics version, vendor, and renderer information 
0630:            String nativeGraphicsVersion = "<UNKNOWN>";
0631:            String nativeGraphicsVendor = "<UNKNOWN>";
0632:            String nativeGraphicsRenderer = "<UNKNOWN>";
0633:
0634:            boolean firstPaintCalled = false;
0635:
0636:            // This reflects whether or not this canvas has seen an addNotify. It is
0637:            // forced to true for off-screen canvases
0638:            boolean added = false;
0639:
0640:            // Flag indicating whether addNotify has been called (so we don't process it twice).
0641:            private boolean addNotifyCalled = false;
0642:
0643:            // This is the id for the underlying graphics context structure.
0644:            Context ctx = null;
0645:
0646:            // since the ctx id can be the same as the previous one,
0647:            // we need to keep a time stamp to differentiate the contexts with the
0648:            // same id
0649:            volatile long ctxTimeStamp = 0;
0650:
0651:            // The current context setting for local eye lighting
0652:            boolean ctxEyeLightingEnable = false;
0653:
0654:            // This AppearanceRetained Object refelects the current state of this 
0655:            // canvas.  It is used to optimize setting of attributes at render time.
0656:            AppearanceRetained currentAppear = new AppearanceRetained();
0657:
0658:            // This MaterialRetained Object refelects the current state of this canvas.
0659:            // It is used to optimize setting of attributes at render time.
0660:            MaterialRetained currentMaterial = new MaterialRetained();
0661:
0662:            /**
0663:             * The object used for View Frustum Culling
0664:             */
0665:            CachedFrustum viewFrustum = new CachedFrustum();
0666:
0667:            /**
0668:             * The RenderBin bundle references used to decide what the underlying 
0669:             * context contains.
0670:             */
0671:            LightBin lightBin = null;
0672:            EnvironmentSet environmentSet = null;
0673:            AttributeBin attributeBin = null;
0674:            ShaderBin shaderBin = null;
0675:            RenderMolecule renderMolecule = null;
0676:            PolygonAttributesRetained polygonAttributes = null;
0677:            LineAttributesRetained lineAttributes = null;
0678:            PointAttributesRetained pointAttributes = null;
0679:            MaterialRetained material = null;
0680:            boolean enableLighting = false;
0681:            TransparencyAttributesRetained transparency = null;
0682:            ColoringAttributesRetained coloringAttributes = null;
0683:            Transform3D modelMatrix = null;
0684:            Transform3D projTrans = null;
0685:            TextureBin textureBin = null;
0686:
0687:            /**
0688:             * cached RenderBin states for lazy native states update
0689:             */
0690:            LightRetained lights[] = null;
0691:            int frameCount[] = null;
0692:            long enableMask = -1;
0693:            FogRetained fog = null;
0694:            ModelClipRetained modelClip = null;
0695:            Color3f sceneAmbient = new Color3f();
0696:            TextureUnitStateRetained[] texUnitState = null;
0697:
0698:            /**
0699:             * These cached values are only used in Pure Immediate and Mixed Mode rendering
0700:             */
0701:            TextureRetained texture = null;
0702:            TextureAttributesRetained texAttrs = null;
0703:            TexCoordGenerationRetained texCoordGeneration = null;
0704:            RenderingAttributesRetained renderingAttrs = null;
0705:            AppearanceRetained appearance = null;
0706:
0707:            ShaderProgramRetained shaderProgram = null;
0708:
0709:            // only used in Mixed Mode rendering
0710:            Object appHandle = null;
0711:
0712:            /**
0713:             * Set to true when any one of texture state use
0714:             * Texture Generation linear mode. This is used for D3D
0715:             * temporary turn displayList off and do its own coordinate
0716:             * generation since D3D don't support it.
0717:             *
0718:             * TODO aces : is this still true in DX9?
0719:             */
0720:            boolean texLinearMode = false;
0721:
0722:            /**
0723:             * Dirty bit to determine if the NodeComponent needs to be re-sent
0724:             * down to the underlying API
0725:             */
0726:            int canvasDirty = 0xffff;
0727:
0728:            // True when either one of dirtyRenderMoleculeList,
0729:            // dirtyDlistPerRinfoList, dirtyRenderAtomList size > 0
0730:            boolean dirtyDisplayList = false;
0731:
0732:            ArrayList dirtyRenderMoleculeList = new ArrayList();
0733:            ArrayList dirtyRenderAtomList = new ArrayList();
0734:            // List of (Rm, rInfo) pair of individual dlists that need to be rebuilt
0735:            ArrayList dirtyDlistPerRinfoList = new ArrayList();
0736:
0737:            ArrayList displayListResourceFreeList = new ArrayList();
0738:            ArrayList textureIdResourceFreeList = new ArrayList();
0739:
0740:            // an unique bit to identify this canvas
0741:            int canvasBit = 0;
0742:            // an unique number to identify this canvas : ( canvasBit = 1 << canvasId)
0743:            int canvasId = 0;
0744:            // Indicates whether the canvasId has been allocated
0745:            private boolean canvasIdAlloc = false;
0746:
0747:            // Avoid using this as lock, it cause deadlock 
0748:            Object cvLock = new Object();
0749:            Object evaluateLock = new Object();
0750:            Object dirtyMaskLock = new Object();
0751:
0752:            // Use by D3D when toggle between window/fullscreen mode.
0753:            // Note that in fullscreen mode, the width and height get
0754:            // by canvas is smaller than expected.
0755:            boolean fullScreenMode = false;
0756:            int fullscreenWidth;
0757:            int fullscreenHeight;
0758:
0759:            // For D3D, instead of using the same variable in Renderer,
0760:            // each canvas has to build its own displayList.
0761:            boolean needToRebuildDisplayList = false;
0762:
0763:            // Use by D3D when canvas resize/toggle in pure immediate mode
0764:            int reEvaluateCanvasCmd = 0;
0765:
0766:            // Read-only flag that indicates whether the following texture features
0767:            // are supported for this canvas.
0768:
0769:            static final int TEXTURE_3D = 0x0001;
0770:            static final int TEXTURE_COLOR_TABLE = 0x0002;
0771:            static final int TEXTURE_MULTI_TEXTURE = 0x0004;
0772:            static final int TEXTURE_COMBINE = 0x0008;
0773:            static final int TEXTURE_COMBINE_DOT3 = 0x0010;
0774:            static final int TEXTURE_COMBINE_SUBTRACT = 0x0020;
0775:            static final int TEXTURE_REGISTER_COMBINERS = 0x0040;
0776:            static final int TEXTURE_CUBE_MAP = 0x0080;
0777:            static final int TEXTURE_SHARPEN = 0x0100;
0778:            static final int TEXTURE_DETAIL = 0x0200;
0779:            static final int TEXTURE_FILTER4 = 0x0400;
0780:            static final int TEXTURE_ANISOTROPIC_FILTER = 0x0800;
0781:            static final int TEXTURE_LOD_RANGE = 0x1000;
0782:            static final int TEXTURE_LOD_OFFSET = 0x2000;
0783:            // Use by D3D to indicate using one pass Blend mode 
0784:            // if Texture interpolation mode is support.
0785:            static final int TEXTURE_LERP = 0x4000;
0786:            static final int TEXTURE_NON_POWER_OF_TWO = 0x8000;
0787:            static final int TEXTURE_AUTO_MIPMAP_GENERATION = 0x10000;
0788:
0789:            int textureExtendedFeatures = 0;
0790:
0791:            // Extensions supported by the underlying canvas
0792:            //
0793:            // NOTE: we should remove EXT_BGR and EXT_ABGR when the imaging code is
0794:            // rewritten
0795:            static final int SUN_GLOBAL_ALPHA = 0x1;
0796:            static final int EXT_ABGR = 0x2;
0797:            static final int EXT_BGR = 0x4;
0798:            static final int MULTISAMPLE = 0x8;
0799:
0800:            // The following 10 variables are set by the native
0801:            // createNewContext()/createQueryContext() methods
0802:
0803:            // Supported Extensions
0804:            int extensionsSupported = 0;
0805:
0806:            // Anisotropic Filter degree
0807:            float anisotropicDegreeMax = 1.0f;
0808:
0809:            // Texture Boundary Width Max
0810:            int textureBoundaryWidthMax = 0;
0811:
0812:            boolean multiTexAccelerated = false;
0813:
0814:            // Max number of texture coordinate sets
0815:            int maxTexCoordSets = 1;
0816:
0817:            // Max number of fixed-function texture units
0818:            int maxTextureUnits = 1;
0819:
0820:            // Max number of fragment shader texture units
0821:            int maxTextureImageUnits = 0;
0822:
0823:            // Max number of vertex shader texture units
0824:            int maxVertexTextureImageUnits = 0;
0825:
0826:            // Max number of combined shader texture units
0827:            int maxCombinedTextureImageUnits = 0;
0828:
0829:            // Max number of vertex attrs (not counting coord, etc.)
0830:            int maxVertexAttrs = 0;
0831:
0832:            // End of variables set by createNewContext()/createQueryContext()
0833:
0834:            // The total available number of texture units used by either the
0835:            // fixed-function or programmable shader pipeline.
0836:            // This is computed as: max(maxTextureUnits, maxTextureImageUnits)
0837:            int maxAvailableTextureUnits;
0838:
0839:            // Texture Width, Height Max
0840:            int textureWidthMax = 0;
0841:            int textureHeightMax = 0;
0842:
0843:            // Texture3D Width, Heigh, Depth Max
0844:            int texture3DWidthMax = -1;
0845:            int texture3DHeightMax = -1;
0846:            int texture3DDepthMax = -1;
0847:
0848:            // Cached position & size for CanvasViewCache.
0849:            // We don't want to call canvas.getxx method in Renderer
0850:            // since it will cause deadlock as removeNotify() need to get
0851:            // component lock of Canvas also and need to wait Renderer to
0852:            // finish before continue. So we invoke the method now in 
0853:            // CanvasViewEventCatcher.
0854:            Point newPosition = new Point();
0855:            Dimension newSize = new Dimension();
0856:
0857:            // Remember OGL context resources to free
0858:            // before context is destroy.
0859:            // It is used when sharedCtx = false;
0860:            ArrayList textureIDResourceTable = new ArrayList(5);
0861:
0862:            // The following variables are used by the lazy download of
0863:            // states code to keep track of the set of current to be update bins
0864:
0865:            static final int LIGHTBIN_BIT = 0x0;
0866:            static final int ENVIRONMENTSET_BIT = 0x1;
0867:            static final int ATTRIBUTEBIN_BIT = 0x2;
0868:            static final int TEXTUREBIN_BIT = 0x3;
0869:            static final int RENDERMOLECULE_BIT = 0x4;
0870:            static final int TRANSPARENCY_BIT = 0x5;
0871:            static final int SHADERBIN_BIT = 0x6;
0872:
0873:            // bitmask to specify if the corresponding "bin" needs to be updated
0874:            int stateUpdateMask = 0;
0875:
0876:            // the set of current "bins" that is to be updated, the stateUpdateMask
0877:            // specifies if each bin in this set is updated or not.
0878:            Object curStateToUpdate[] = new Object[7];
0879:
0880:            /**
0881:             * The list of lights that are currently being represented in the native
0882:             * graphics context.
0883:             */
0884:            LightRetained[] currentLights = null;
0885:
0886:            /**
0887:             * Flag to override RenderAttributes.depthBufferWriteEnable
0888:             */
0889:            boolean depthBufferWriteEnableOverride = false;
0890:
0891:            /**
0892:             * Flag to override RenderAttributes.depthBufferEnable
0893:             */
0894:            boolean depthBufferEnableOverride = false;
0895:
0896:            // current state of depthBufferWriteEnable
0897:            boolean depthBufferWriteEnable = true;
0898:
0899:            boolean vfPlanesValid = false;
0900:
0901:            // The event catcher for this canvas.
0902:            EventCatcher eventCatcher;
0903:
0904:            // The view event catcher for this canvas.
0905:            private CanvasViewEventCatcher canvasViewEventCatcher;
0906:
0907:            // The top-level parent window for this canvas.
0908:            private Window windowParent;
0909:
0910:            // Issue 458 - list of all parent containers for this canvas
0911:            // (includes top-level parent window)
0912:            private LinkedList<Container> containerParentList = new LinkedList<Container>();
0913:
0914:            // flag that indicates if light has changed
0915:            boolean lightChanged = false;
0916:
0917:            // resource control object
0918:            DrawingSurfaceObject drawingSurfaceObject;
0919:
0920:            // true if context is valid for rendering
0921:            boolean validCtx = false;
0922:
0923:            // true if canvas is valid for rendering
0924:            boolean validCanvas = false;
0925:
0926:            // true if ctx changed between render and swap. In this case
0927:            // cv.canvasDirty flag will not reset in Renderer.
0928:            // This case happen when GraphicsContext3D invoked doClear()
0929:            // and canvas removeNotify() called while Renderer is running
0930:            boolean ctxChanged = false;
0931:
0932:            // Default graphics configuration
0933:            private static GraphicsConfiguration defaultGcfg = null;
0934:
0935:            // Returns default graphics configuration if user passes null
0936:            // into the Canvas3D constructor
0937:            private static synchronized GraphicsConfiguration defaultGraphicsConfiguration() {
0938:                if (defaultGcfg == null) {
0939:                    GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
0940:                    defaultGcfg = GraphicsEnvironment
0941:                            .getLocalGraphicsEnvironment()
0942:                            .getDefaultScreenDevice().getBestConfiguration(
0943:                                    template);
0944:                }
0945:                return defaultGcfg;
0946:            }
0947:
0948:            // Returns true if this is a valid graphics configuration, obtained
0949:            // via a GraphicsConfigTemplate3D.
0950:            private static boolean isValidConfig(GraphicsConfiguration gconfig) {
0951:                // If this is a valid GraphicsConfiguration object, then it will
0952:                // be in the graphicsConfigTable
0953:                return graphicsConfigTable.containsKey(gconfig);
0954:            }
0955:
0956:            // Checks the given graphics configuration, and throws an exception if
0957:            // the config is null or invalid.
0958:            private static synchronized GraphicsConfiguration checkForValidGraphicsConfig(
0959:                    GraphicsConfiguration gconfig, boolean offScreen) {
0960:
0961:                // Issue 266 - for backwards compatibility with legacy applications,
0962:                // we will accept a null GraphicsConfiguration for an on-screen Canvas3D
0963:                // only if the "allowNullGraphicsConfig" system property is set to true.
0964:                if (!offScreen && VirtualUniverse.mc.allowNullGraphicsConfig) {
0965:                    if (gconfig == null) {
0966:                        // Print out warning if Canvas3D is called with a
0967:                        // null GraphicsConfiguration
0968:                        System.err.println(J3dI18N.getString("Canvas3D7"));
0969:                        System.err.println("    "
0970:                                + J3dI18N.getString("Canvas3D18"));
0971:
0972:                        // Use a default graphics config
0973:                        gconfig = defaultGraphicsConfiguration();
0974:                    }
0975:                }
0976:
0977:                // Validate input graphics config
0978:                if (gconfig == null) {
0979:                    throw new NullPointerException(J3dI18N
0980:                            .getString("Canvas3D19"));
0981:                } else if (!isValidConfig(gconfig)) {
0982:                    throw new IllegalArgumentException(J3dI18N
0983:                            .getString("Canvas3D17"));
0984:                }
0985:
0986:                return gconfig;
0987:            }
0988:
0989:            // Return the actual graphics config that will be used to construct
0990:            // the AWT Canvas. This is permitted to be non-unique or null.
0991:            private static GraphicsConfiguration getGraphicsConfig(
0992:                    GraphicsConfiguration gconfig) {
0993:                return Pipeline.getPipeline().getGraphicsConfig(gconfig);
0994:            }
0995:
0996:            /**
0997:             * Constructs and initializes a new Canvas3D object that Java 3D
0998:             * can render into. The following Canvas3D attributes are initialized
0999:             * to default values as shown:
1000:             * <ul>
1001:             * left manual eye in image plate : (0.142, 0.135, 0.4572)<br>
1002:             * right manual eye in image plate : (0.208, 0.135, 0.4572)<br>
1003:             * stereo enable : true<br>
1004:             * double buffer enable : true<br>
1005:             * monoscopic view policy : View.CYCLOPEAN_EYE_VIEW<br>
1006:             * off-screen mode : false<br>
1007:             * off-screen buffer : null<br>
1008:             * off-screen location : (0,0)<br>
1009:             * </ul>
1010:             *
1011:             * @param graphicsConfiguration a valid GraphicsConfiguration object that
1012:             * will be used to create the canvas.  This object should not be null and
1013:             * should be created using a GraphicsConfigTemplate3D or the
1014:             * getPreferredConfiguration() method of the SimpleUniverse utility.  For
1015:             * backward compatibility with earlier versions of Java 3D, a null or
1016:             * default GraphicsConfiguration will still work when used to create a
1017:             * Canvas3D on the default screen, but an error message will be printed.
1018:             * A NullPointerException or IllegalArgumentException will be thrown in a
1019:             * subsequent release.
1020:             *
1021:             * @exception IllegalArgumentException if the specified
1022:             * GraphicsConfiguration does not support 3D rendering
1023:             */
1024:            public Canvas3D(GraphicsConfiguration graphicsConfiguration) {
1025:                this (null, checkForValidGraphicsConfig(graphicsConfiguration,
1026:                        false), false);
1027:            }
1028:
1029:            /**
1030:             * Constructs and initializes a new Canvas3D object that Java 3D
1031:             * can render into.
1032:             *
1033:             * @param graphicsConfiguration a valid GraphicsConfiguration object
1034:             * that will be used to create the canvas.  This must be created either
1035:             * with a GraphicsConfigTemplate3D or by using the
1036:             * getPreferredConfiguration() method of the SimpleUniverse utility.
1037:             *
1038:             * @param offScreen a flag that indicates whether this canvas is
1039:             * an off-screen 3D rendering canvas.  Note that if offScreen
1040:             * is set to true, this Canvas3D object cannot be used for normal
1041:             * rendering; it should not be added to any Container object.
1042:             *
1043:             * @exception NullPointerException if the GraphicsConfiguration
1044:             * is null.
1045:             *
1046:             * @exception IllegalArgumentException if the specified
1047:             * GraphicsConfiguration does not support 3D rendering
1048:             *
1049:             * @since Java 3D 1.2
1050:             */
1051:            public Canvas3D(GraphicsConfiguration graphicsConfiguration,
1052:                    boolean offScreen) {
1053:                this (null, checkForValidGraphicsConfig(graphicsConfiguration,
1054:                        offScreen), offScreen);
1055:            }
1056:
1057:            // Private constructor only called by the two public constructors after
1058:            // they have validated the graphics config (and possibly constructed a new
1059:            // default config).
1060:            // The graphics config must be valid, unique, and non-null.
1061:            private Canvas3D(Object dummyObj1,
1062:                    GraphicsConfiguration graphicsConfiguration,
1063:                    boolean offScreen) {
1064:                this (dummyObj1, graphicsConfiguration,
1065:                        getGraphicsConfig(graphicsConfiguration), offScreen);
1066:            }
1067:
1068:            // Private constructor only called by the previous private constructor.
1069:            // The graphicsConfiguration parameter is used by Canvas3D to lookup the
1070:            // graphics device and graphics template. The graphicsConfiguration2
1071:            // parameter is generated by the Pipeline from graphicsConfiguration and
1072:            // is only used to initialize the java.awt.Canvas.
1073:            private Canvas3D(Object dummyObj1,
1074:                    GraphicsConfiguration graphicsConfiguration,
1075:                    GraphicsConfiguration graphicsConfiguration2,
1076:                    boolean offScreen) {
1077:
1078:                super (graphicsConfiguration2);
1079:
1080:                this .offScreen = offScreen;
1081:                this .graphicsConfiguration = graphicsConfiguration;
1082:
1083:                // Issue 131: Set the autoOffScreen variable based on whether this
1084:                // canvas3d implements the AutoOffScreenCanvas3D tagging interface.
1085:                // Eventually, we may replace this with an actual API.
1086:                boolean autoOffScreenCanvas3D = false;
1087:                if (this  instanceof  com.sun.j3d.exp.swing.impl.AutoOffScreenCanvas3D) {
1088:                    autoOffScreenCanvas3D = true;
1089:                }
1090:
1091:                // Throw an illegal argument exception if an on-screen canvas is tagged
1092:                // as an  auto-off-screen canvas
1093:                if (autoOffScreenCanvas3D && !offScreen) {
1094:                    throw new IllegalArgumentException(J3dI18N
1095:                            .getString("Canvas3D25"));
1096:                }
1097:
1098:                // Issue 163 : Set dirty bits for both Renderer and RenderBin
1099:                cvDirtyMask[0] = VIEW_INFO_DIRTY;
1100:                cvDirtyMask[1] = VIEW_INFO_DIRTY;
1101:
1102:                GraphicsConfigInfo gcInfo = graphicsConfigTable
1103:                        .get(graphicsConfiguration);
1104:                requestedStencilSize = gcInfo.getGraphicsConfigTemplate3D()
1105:                        .getStencilSize();
1106:
1107:                fbConfig = Pipeline.getPipeline().getFbConfig(gcInfo);
1108:
1109:                if (offScreen) {
1110:
1111:                    // Issue 131: set manual rendering flag based on whether this is
1112:                    // an auto-off-screen Canvas3D.
1113:                    manualRendering = !autoOffScreenCanvas3D;
1114:
1115:                    screen = new Screen3D(graphicsConfiguration, offScreen);
1116:
1117:                    // QUESTION: keep a list of off-screen Screen3D objects?
1118:                    // Does this list need to be grouped by GraphicsDevice?
1119:
1120:                    synchronized (dirtyMaskLock) {
1121:                        cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY;
1122:                        cvDirtyMask[1] |= MOVED_OR_RESIZED_DIRTY;
1123:                    }
1124:
1125:                    // this canvas will not receive the paint callback,
1126:                    // so we need to set the necessary flags here
1127:                    firstPaintCalled = true;
1128:
1129:                    if (manualRendering) {
1130:                        // since this canvas will not receive the addNotify
1131:                        // callback from AWT, set the added flag here for
1132:                        // evaluateActive to work correctly
1133:                        added = true;
1134:                    }
1135:
1136:                    evaluateActive();
1137:
1138:                    // create the rendererStructure object
1139:                    //rendererStructure = new RendererStructure();
1140:                    offScreenCanvasLoc = new Point(0, 0);
1141:                    offScreenCanvasSize = new Dimension(0, 0);
1142:
1143:                    this .setLocation(offScreenCanvasLoc);
1144:                    this .setSize(offScreenCanvasSize);
1145:                    newSize = offScreenCanvasSize;
1146:                    newPosition = offScreenCanvasLoc;
1147:
1148:                    // Issue 131: create event catchers for auto-offScreen
1149:                    if (!manualRendering) {
1150:                        eventCatcher = new EventCatcher(this );
1151:                        canvasViewEventCatcher = new CanvasViewEventCatcher(
1152:                                this );
1153:                    }
1154:                } else {
1155:
1156:                    GraphicsDevice graphicsDevice;
1157:                    graphicsDevice = graphicsConfiguration.getDevice();
1158:
1159:                    eventCatcher = new EventCatcher(this );
1160:                    canvasViewEventCatcher = new CanvasViewEventCatcher(this );
1161:
1162:                    synchronized (VirtualUniverse.mc.deviceScreenMap) {
1163:                        screen = (Screen3D) VirtualUniverse.mc.deviceScreenMap
1164:                                .get(graphicsDevice);
1165:
1166:                        if (screen == null) {
1167:                            screen = new Screen3D(graphicsConfiguration,
1168:                                    offScreen);
1169:                            VirtualUniverse.mc.deviceScreenMap.put(
1170:                                    graphicsDevice, screen);
1171:                        }
1172:                    }
1173:
1174:                }
1175:
1176:                lights = new LightRetained[VirtualUniverse.mc.maxLights];
1177:                frameCount = new int[VirtualUniverse.mc.maxLights];
1178:                for (int i = 0; i < frameCount.length; i++) {
1179:                    frameCount[i] = -1;
1180:                }
1181:
1182:                // Construct the drawing surface object for this Canvas3D
1183:                drawingSurfaceObject = Pipeline.getPipeline()
1184:                        .createDrawingSurfaceObject(this );
1185:
1186:                // Get double buffer, stereo available, scene antialiasing
1187:                // flags from graphics config
1188:                GraphicsConfigTemplate3D.getGraphicsConfigFeatures(this );
1189:
1190:                useDoubleBuffer = doubleBufferEnable && doubleBufferAvailable;
1191:                useStereo = stereoEnable && stereoAvailable;
1192:                useSharedCtx = VirtualUniverse.mc.isSharedCtx;
1193:
1194:                // Issue 131: assert that only an off-screen canvas can be demand-driven
1195:                assert (!offScreen && manualRendering) == false;
1196:
1197:                // Assert that offScreen is *not* double-buffered or stereo
1198:                assert (offScreen && useDoubleBuffer) == false;
1199:                assert (offScreen && useStereo) == false;
1200:            }
1201:
1202:            /**
1203:             * This method overrides AWT's handleEvent class...
1204:             */
1205:            void sendEventToBehaviorScheduler(AWTEvent evt) {
1206:
1207:                ViewPlatform vp;
1208:
1209:                if ((view != null) && ((vp = view.getViewPlatform()) != null)) {
1210:                    VirtualUniverse univ = ((ViewPlatformRetained) (vp.retained)).universe;
1211:                    if (univ != null) {
1212:                        univ.behaviorStructure.handleAWTEvent(evt);
1213:                    }
1214:                }
1215:            }
1216:
1217:            /**
1218:             * Method to return whether or not the Canvas3D is recursively visible;
1219:             * that is, whether the Canas3D is currently visible on the screen. Note
1220:             * that we don't directly use isShowing() because that won't work for an
1221:             * auto-offScreen Canvas3D.
1222:             */
1223:            private boolean isRecursivelyVisible() {
1224:                Container parent = getParent();
1225:                return isVisible() && parent != null && parent.isShowing();
1226:            }
1227:
1228:            /**
1229:             * Method to return whether the top-level Window parent is iconified
1230:             */
1231:            private boolean isIconified() {
1232:                if (windowParent instanceof  Frame) {
1233:                    return (((Frame) windowParent).getExtendedState() & Frame.ICONIFIED) != 0;
1234:                }
1235:
1236:                return false;
1237:            }
1238:
1239:            // Issue 458 - evaluate this Canvas3D's visibility whenever we get a
1240:            // Window or Component Event that could change it.
1241:            void evaluateVisiblilty() {
1242:                boolean nowVisible = isRecursivelyVisible() && !isIconified();
1243:
1244:                // Only need to reevaluate and repaint if visibility has changed
1245:                if (this .visible != nowVisible) {
1246:                    this .visible = nowVisible;
1247:                    evaluateActive();
1248:                    if (nowVisible) {
1249:                        if (view != null) {
1250:                            view.repaint();
1251:                        }
1252:                    }
1253:                }
1254:            }
1255:
1256:            /**
1257:             * This version looks for the view and notifies it.
1258:             */
1259:            void redraw() {
1260:                if ((view != null) && active && isRunning) {
1261:                    view.repaint();
1262:                }
1263:            }
1264:
1265:            /**
1266:             * Canvas3D uses the paint callback to track when it is possible to
1267:             * render into the canvas.  Subclasses of Canvas3D that override this
1268:             * method need to call super.paint() in their paint method for Java 3D
1269:             * to function properly.
1270:             * @param g the graphics context
1271:             */
1272:            public void paint(Graphics g) {
1273:
1274:                if (!firstPaintCalled && added && validCanvas
1275:                        && validGraphicsMode()) {
1276:
1277:                    try {
1278:                        newSize = getSize();
1279:                        newPosition = getLocationOnScreen();
1280:                    } catch (IllegalComponentStateException e) {
1281:                        return;
1282:                    }
1283:
1284:                    synchronized (drawingSurfaceObject) {
1285:                        drawingSurfaceObject.getDrawingSurfaceObjectInfo();
1286:                    }
1287:
1288:                    firstPaintCalled = true;
1289:                    visible = true;
1290:                    evaluateActive();
1291:                }
1292:                redraw();
1293:            }
1294:
1295:            // When this canvas is added to a frame, this notification gets called.  We
1296:            // can get drawing surface information at this time.  Note: we cannot get 
1297:            // the X11 window id yet, unless it is a reset condition.
1298:            /**
1299:             * Canvas3D uses the addNotify callback to track when it is added
1300:             * to a container.  Subclasses of Canvas3D that override this
1301:             * method need to call super.addNotify() in their addNotify() method for Java 3D
1302:             * to function properly.
1303:             */
1304:            public void addNotify() {
1305:                // Return immediately if addNotify called twice with no removeNotify
1306:                if (addNotifyCalled) {
1307:                    return;
1308:                }
1309:                addNotifyCalled = true;
1310:
1311:                // Issue 131: This method is now being called by JCanvas3D for its
1312:                // off-screen Canvas3D, so we need to handle off-screen properly here.
1313:                // Do nothing for manually-rendered off-screen canvases
1314:                if (manualRendering) {
1315:                    return;
1316:                }
1317:
1318:                Renderer rdr = null;
1319:
1320:                if (isRunning && (screen != null)) {
1321:                    // If there is other Canvas3D in the same screen
1322:                    // rendering, stop it before JDK create new Canvas
1323:
1324:                    rdr = screen.renderer;
1325:                    if (rdr != null) {
1326:                        VirtualUniverse.mc.postRequest(
1327:                                MasterControl.STOP_RENDERER, rdr);
1328:                        while (!rdr.userStop) {
1329:                            MasterControl.threadYield();
1330:                        }
1331:                    }
1332:                }
1333:
1334:                // Issue 131: Don't call super for off-screen Canvas3D
1335:                if (!offScreen) {
1336:                    super .addNotify();
1337:                }
1338:                screen.addUser(this );
1339:
1340:                // Issue 458 - Add the eventCatcher as a component listener for each
1341:                // parent container in the window hierarchy
1342:                assert containerParentList.isEmpty();
1343:
1344:                windowParent = null;
1345:                Container container = this .getParent();
1346:                while (container != null) {
1347:                    if (container instanceof  Window) {
1348:                        windowParent = (Window) container;
1349:                    }
1350:                    container.addComponentListener(eventCatcher);
1351:                    container.addComponentListener(canvasViewEventCatcher);
1352:                    containerParentList.add(container);
1353:                    container = container.getParent();
1354:                }
1355:
1356:                this .addComponentListener(eventCatcher);
1357:                this .addComponentListener(canvasViewEventCatcher);
1358:
1359:                if (windowParent != null) {
1360:                    windowParent.addWindowListener(eventCatcher);
1361:                }
1362:
1363:                synchronized (dirtyMaskLock) {
1364:                    cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY;
1365:                    cvDirtyMask[1] |= MOVED_OR_RESIZED_DIRTY;
1366:                }
1367:
1368:                allocateCanvasId();
1369:
1370:                validCanvas = true;
1371:                added = true;
1372:
1373:                // Since we won't get a paint call for off-screen canvases, we need
1374:                // to set the first paint and visible flags here. We also need to
1375:                // call evaluateActive for the same reason.
1376:                if (offScreen) {
1377:                    firstPaintCalled = true;
1378:                    visible = true;
1379:                    evaluateActive();
1380:                }
1381:
1382:                // In case the same canvas is removed and add back,
1383:                // we have to change isRunningStatus back to true;
1384:                if (isRunning && !fatalError) {
1385:                    isRunningStatus = true;
1386:                }
1387:
1388:                ctxTimeStamp = 0;
1389:                if ((view != null) && (view.universe != null)) {
1390:                    view.universe.checkForEnableEvents();
1391:                }
1392:
1393:                if (rdr != null) {
1394:                    // Issue 84: Send a message to MC to restart renderer
1395:                    // Note that this also obviates the need for the earlier fix to
1396:                    // issue 131 which called redraw() for auto-off-screen Canvas3Ds
1397:                    // (and this is a more robust fix)
1398:                    VirtualUniverse.mc.postRequest(
1399:                            MasterControl.START_RENDERER, rdr);
1400:                    while (rdr.userStop) {
1401:                        MasterControl.threadYield();
1402:                    }
1403:                }
1404:            }
1405:
1406:            // When this canvas is removed a frame, this notification gets called.  We
1407:            // need to release the native context at this time.  The underlying window
1408:            // is about to go away.
1409:            /**
1410:             * Canvas3D uses the removeNotify callback to track when it is removed
1411:             * from a container.  Subclasses of Canvas3D that override this
1412:             * method need to call super.removeNotify() in their removeNotify()
1413:             * method for Java 3D to function properly.
1414:             */
1415:            public void removeNotify() {
1416:                // Return immediately if addNotify not called first
1417:                if (!addNotifyCalled) {
1418:                    return;
1419:                }
1420:                addNotifyCalled = false;
1421:
1422:                // Do nothing for manually-rendered off-screen canvases
1423:                if (manualRendering) {
1424:                    return;
1425:                }
1426:
1427:                Renderer rdr = null;
1428:
1429:                if (isRunning && (screen != null)) {
1430:                    // If there is other Canvas3D in the same screen
1431:                    // rendering, stop it before JDK create new Canvas
1432:
1433:                    rdr = screen.renderer;
1434:                    if (rdr != null) {
1435:                        VirtualUniverse.mc.postRequest(
1436:                                MasterControl.STOP_RENDERER, rdr);
1437:                        while (!rdr.userStop) {
1438:                            MasterControl.threadYield();
1439:                        }
1440:                    }
1441:                }
1442:
1443:                // Note that although renderer userStop is true,
1444:                // MasterControl can still schedule renderer to run through
1445:                // runMonotor(RUN_RENDERER_CLEANUP) which skip userStop
1446:                // thread checking.
1447:                // For non-offscreen rendering the following call will
1448:                // block waiting until all resources is free before 
1449:                // continue
1450:
1451:                synchronized (drawingSurfaceObject) {
1452:                    validCtx = false;
1453:                    validCanvas = false;
1454:                }
1455:
1456:                removeCtx();
1457:
1458:                Pipeline.getPipeline().freeDrawingSurface(this ,
1459:                        drawingSurfaceObject);
1460:
1461:                // Clear first paint and visible flags
1462:                firstPaintCalled = false;
1463:                visible = false;
1464:
1465:                screen.removeUser(this );
1466:                evaluateActive();
1467:
1468:                freeCanvasId();
1469:
1470:                ra = null;
1471:                graphicsContext3D = null;
1472:
1473:                ctx = null;
1474:                // must be after removeCtx() because 
1475:                // it will free graphics2D textureID
1476:                graphics2D = null;
1477:
1478:                super .removeNotify();
1479:
1480:                // Release and clear.
1481:                for (Container container : containerParentList) {
1482:                    container.removeComponentListener(eventCatcher);
1483:                    container.removeComponentListener(canvasViewEventCatcher);
1484:                }
1485:                containerParentList.clear();
1486:                this .removeComponentListener(eventCatcher);
1487:                this .removeComponentListener(canvasViewEventCatcher);
1488:
1489:                if (eventCatcher != null) {
1490:                    this .removeFocusListener(eventCatcher);
1491:                    this .removeKeyListener(eventCatcher);
1492:                    this .removeMouseListener(eventCatcher);
1493:                    this .removeMouseMotionListener(eventCatcher);
1494:                    this .removeMouseWheelListener(eventCatcher);
1495:                    eventCatcher.reset();
1496:                }
1497:
1498:                if (windowParent != null) {
1499:                    windowParent.removeWindowListener(eventCatcher);
1500:                    windowParent.requestFocus();
1501:                }
1502:
1503:                added = false;
1504:
1505:                if (rdr != null) {
1506:                    // Issue 84: Send a message to MC to restart renderer
1507:                    VirtualUniverse.mc.postRequest(
1508:                            MasterControl.START_RENDERER, rdr);
1509:                    while (rdr.userStop) {
1510:                        MasterControl.threadYield();
1511:                    }
1512:                }
1513:
1514:                // Fix for issue 102 removing strong reference and avoiding memory leak
1515:                // due retention of parent container
1516:                this .windowParent = null;
1517:            }
1518:
1519:            void allocateCanvasId() {
1520:                if (!canvasIdAlloc) {
1521:                    canvasId = VirtualUniverse.mc.getCanvasId();
1522:                    canvasBit = 1 << canvasId;
1523:                    canvasIdAlloc = true;
1524:                }
1525:            }
1526:
1527:            void freeCanvasId() {
1528:                if (canvasIdAlloc) {
1529:                    VirtualUniverse.mc.freeCanvasId(canvasId);
1530:                    canvasBit = 0;
1531:                    canvasId = 0;
1532:                    canvasIdAlloc = false;
1533:                }
1534:            }
1535:
1536:            // This decides if the canvas is active
1537:            void evaluateActive() {
1538:                // Note that no need to check for isRunning, we want
1539:                // view register in order to create scheduler in pure immedite mode
1540:                // Also we can't use this as lock, otherwise there is a
1541:                // deadlock where updateViewCache get a lock of this and
1542:                // get a lock of this component. But Container 
1543:                // remove will get a lock of this component follows by evaluateActive.
1544:
1545:                synchronized (evaluateLock) {
1546:                    if ((visible || manualRendering) && firstPaintCalled) {
1547:
1548:                        if (!active) {
1549:                            active = true;
1550:                            if (pendingView != null) {
1551:                                pendingView.evaluateActive();
1552:                            }
1553:                        } else {
1554:                            if ((pendingView != null)
1555:                                    && !pendingView.activeStatus) {
1556:                                pendingView.evaluateActive();
1557:                            }
1558:                        }
1559:                    } else {
1560:                        if (active) {
1561:                            active = false;
1562:                            if (view != null) {
1563:                                view.evaluateActive();
1564:                            }
1565:                        }
1566:                    }
1567:                }
1568:
1569:                if ((view != null) && (!active)) {
1570:                    VirtualUniverse u = view.universe;
1571:                    if ((u != null) && !u.isSceneGraphLock) {
1572:                        u.waitForMC();
1573:                    }
1574:                }
1575:            }
1576:
1577:            void setFrustumPlanes(Vector4d[] planes) {
1578:
1579:                if (VirtualUniverse.mc.viewFrustumCulling) {
1580:                    /* System.err.println("Canvas3D.setFrustumPlanes()"); */
1581:                    viewFrustum.set(planes);
1582:                }
1583:            }
1584:
1585:            /**
1586:             * Retrieve the Screen3D object that this Canvas3D is attached to.
1587:             * If this Canvas3D is an off-screen buffer, a new Screen3D object
1588:             * is created corresponding to the off-screen buffer.
1589:             * @return the 3D screen object that this Canvas3D is attached to
1590:             */
1591:            public Screen3D getScreen3D() {
1592:                return screen;
1593:            }
1594:
1595:            /**
1596:             * Get the immediate mode 3D graphics context associated with
1597:             * this Canvas3D.  A new graphics context object is created if one does
1598:             * not already exist.
1599:             * @return a GraphicsContext3D object that can be used for immediate
1600:             * mode rendering to this Canvas3D.
1601:             */
1602:            public GraphicsContext3D getGraphicsContext3D() {
1603:
1604:                synchronized (gfxCreationLock) {
1605:                    if (graphicsContext3D == null)
1606:                        graphicsContext3D = new GraphicsContext3D(this );
1607:                }
1608:
1609:                return graphicsContext3D;
1610:            }
1611:
1612:            /**
1613:             * Get the 2D graphics object associated with
1614:             * this Canvas3D.  A new 2D graphics object is created if one does
1615:             * not already exist.
1616:             *
1617:             * @return a Graphics2D object that can be used for Java 2D
1618:             * rendering into this Canvas3D.
1619:             *
1620:             * @since Java 3D 1.2
1621:             */
1622:            public J3DGraphics2D getGraphics2D() {
1623:                synchronized (gfxCreationLock) {
1624:                    if (graphics2D == null)
1625:                        graphics2D = new J3DGraphics2DImpl(this );
1626:                }
1627:
1628:                return graphics2D;
1629:            }
1630:
1631:            /**
1632:             * This routine is called by the Java 3D rendering loop after clearing
1633:             * the canvas and before any rendering has been done for this frame.
1634:             * Applications that wish to perform operations in the rendering loop,
1635:             * prior to any actual rendering may override this function.
1636:             *
1637:             * <p>
1638:             * Updates to live Geometry, Texture, and ImageComponent objects
1639:             * in the scene graph are not allowed from this method.
1640:             *
1641:             * <p>
1642:             * NOTE: Applications should <i>not</i> call this method.
1643:             */
1644:            public void preRender() {
1645:                // Do nothing; the user overrides this to cause some action
1646:            }
1647:
1648:            /**
1649:             * This routine is called by the Java 3D rendering loop after completing
1650:             * all rendering to the canvas for this frame and before the buffer swap.
1651:             * Applications that wish to perform operations in the rendering loop,
1652:             * following any actual rendering may override this function.
1653:             *
1654:             * <p>
1655:             * Updates to live Geometry, Texture, and ImageComponent objects
1656:             * in the scene graph are not allowed from this method.
1657:             *
1658:             * <p>
1659:             * NOTE: Applications should <i>not</i> call this method.
1660:             */
1661:            public void postRender() {
1662:                // Do nothing; the user overrides this to cause some action
1663:            }
1664:
1665:            /**
1666:             * This routine is called by the Java 3D rendering loop after completing
1667:             * all rendering to the canvas, and all other canvases associated with
1668:             * this view, for this frame following the buffer swap.
1669:             * Applications that wish to perform operations at the very
1670:             * end of the rendering loop may override this function.
1671:             * In off-screen mode, all rendering is copied to the off-screen
1672:             * buffer before this method is called.
1673:             *
1674:             * <p>
1675:             * Updates to live Geometry, Texture, and ImageComponent objects
1676:             * in the scene graph are not allowed from this method.
1677:             *
1678:             * <p>
1679:             * NOTE: Applications should <i>not</i> call this method.
1680:             */
1681:            public void postSwap() {
1682:                // Do nothing; the user overrides this to cause some action
1683:            }
1684:
1685:            /**
1686:             * This routine is called by the Java 3D rendering loop during the
1687:             * execution of the rendering loop.  It is called once for each
1688:             * field (i.e., once per frame on
1689:             * a mono system or once each for the right eye and left eye on a
1690:             * two-pass stereo system.  This is intended for use by applications that
1691:             * want to mix retained/compiled-retained mode rendering with some
1692:             * immediate mode rendering.  Applications that wish to perform
1693:             * operations during the rendering loop, may override this
1694:             * function.
1695:             *
1696:             * <p>
1697:             * Updates to live Geometry, Texture, and ImageComponent objects
1698:             * in the scene graph are not allowed from this method.
1699:             *
1700:             * <p>
1701:             * NOTE: Applications should <i>not</i> call this method.
1702:             * <p>
1703:             *
1704:             * @param fieldDesc field description, one of: FIELD_LEFT, FIELD_RIGHT or
1705:             * FIELD_ALL.  Applications that wish to work correctly in stereo mode
1706:             * should render the same image for both FIELD_LEFT and FIELD_RIGHT calls.
1707:             * If Java 3D calls the renderer with FIELD_ALL then the immediate mode
1708:             * rendering only needs to be done once.
1709:             */
1710:            public void renderField(int fieldDesc) {
1711:                // Do nothing; the user overrides this to cause some action
1712:            }
1713:
1714:            /**
1715:             * Stop the Java 3D renderer on this Canvas3D object.  If the
1716:             * Java 3D renderer is currently running, the rendering will be
1717:             * synchronized before being stopped.  No further rendering will be done
1718:             * to this canvas by Java 3D until the renderer is started again.
1719:             * In pure immediate mode this method should be called prior to adding
1720:             * this canvas to an active View object.
1721:             *
1722:             * @exception IllegalStateException if this Canvas3D is in
1723:             * off-screen mode.
1724:             */
1725:            public final void stopRenderer() {
1726:                // Issue 131: renderer can't be stopped only if it is an offscreen,
1727:                // manual canvas. Otherwise, it has to be seen as an onscreen canvas.
1728:                if (manualRendering)
1729:                    throw new IllegalStateException(J3dI18N
1730:                            .getString("Canvas3D14"));
1731:
1732:                if (isRunning) {
1733:                    VirtualUniverse.mc.postRequest(MasterControl.STOP_RENDERER,
1734:                            this );
1735:                    isRunning = false;
1736:                }
1737:            }
1738:
1739:            /**
1740:             * Start the Java 3D renderer on this Canvas3D object.  If the
1741:             * Java 3D renderer is not currently running, any rendering to other
1742:             * Canvas3D objects sharing the same View will be synchronized before this
1743:             * Canvas3D's renderer is (re)started.  When a Canvas3D is created, it is
1744:             * initially marked as being started.  This means that as soon as the
1745:             * Canvas3D is added to an active View object, the rendering loop will
1746:             * render the scene graph to the canvas.
1747:             */
1748:            public final void startRenderer() {
1749:                // Issue 260 : ignore attempt to start renderer if fatal error
1750:                if (fatalError) {
1751:                    return;
1752:                }
1753:
1754:                if (!isRunning) {
1755:                    VirtualUniverse.mc.postRequest(
1756:                            MasterControl.START_RENDERER, this );
1757:                    isRunning = true;
1758:                    redraw();
1759:                }
1760:            }
1761:
1762:            /**
1763:             * Retrieves the state of the renderer for this Canvas3D object.
1764:             * @return the state of the renderer
1765:             *
1766:             * @since Java 3D 1.2
1767:             */
1768:            public final boolean isRendererRunning() {
1769:                return isRunning;
1770:            }
1771:
1772:            // Returns the state of the fatal error flag
1773:            boolean isFatalError() {
1774:                return fatalError;
1775:            }
1776:
1777:            // Sets the fatal error flag to true; stop the renderer for this canvas
1778:            void setFatalError() {
1779:                fatalError = true;
1780:
1781:                if (isRunning) {
1782:                    isRunning = false;
1783:
1784:                    if (!manualRendering) {
1785:                        VirtualUniverse.mc.postRequest(
1786:                                MasterControl.STOP_RENDERER, this );
1787:                    }
1788:                }
1789:            }
1790:
1791:            /**
1792:             * Retrieves a flag indicating whether this Canvas3D is an
1793:             * off-screen canvas.
1794:             *
1795:             * @return <code>true</code> if this Canvas3D is an off-screen canvas;
1796:             * <code>false</code> if this is an on-screen canvas.
1797:             *
1798:             * @since Java 3D 1.2
1799:             */
1800:            public boolean isOffScreen() {
1801:                return offScreen;
1802:            }
1803:
1804:            /**
1805:             * Sets the off-screen buffer for this Canvas3D.  The specified
1806:             * image is written into by the Java 3D renderer.  The size of the
1807:             * specified ImageComponent determines the size, in pixels, of
1808:             * this Canvas3D--the size inherited from Component is ignored.
1809:             * <p>
1810:             * NOTE: the size, physical width, and physical height of the associated
1811:             * Screen3D must be set explicitly prior to rendering.
1812:             * Failure to do so will result in an exception.
1813:             * <p>
1814:             *
1815:             * @param buffer the image component that will be rendered into by
1816:             * subsequent calls to renderOffScreenBuffer. The image component must not
1817:             * be part of a live scene graph, nor may it subsequently be made part of a
1818:             * live scene graph while being used as an off-screen buffer; an
1819:             * IllegalSharingException is thrown in such cases. The buffer may be null,
1820:             * indicating that the previous off-screen buffer is released without a new
1821:             * buffer being set.
1822:             *
1823:             * @exception IllegalStateException if this Canvas3D is not in
1824:             * off-screen mode.
1825:             *
1826:             * @exception RestrictedAccessException if an off-screen rendering
1827:             * is in process for this Canvas3D.
1828:             *
1829:             * @exception IllegalSharingException if the specified ImageComponent2D
1830:             * is part of a live scene graph
1831:             *
1832:             * @exception IllegalSharingException if the specified ImageComponent2D is
1833:             * being used by an immediate mode context, or by another Canvas3D as
1834:             * an off-screen buffer.
1835:             *
1836:             * @exception IllegalArgumentException if the image class of the specified
1837:             * ImageComponent2D is <i>not</i> ImageClass.BUFFERED_IMAGE.
1838:             *
1839:             * @exception IllegalArgumentException if the specified
1840:             * ImageComponent2D is in by-reference mode and its
1841:             * RenderedImage is null.
1842:             *
1843:             * @exception IllegalArgumentException if the ImageComponent2D format
1844:             * is <i>not</i> a 3-component format (e.g., FORMAT_RGB)
1845:             * or a 4-component format (e.g., FORMAT_RGBA).
1846:             *
1847:             * @see #renderOffScreenBuffer
1848:             * @see Screen3D#setSize(int, int)
1849:             * @see Screen3D#setSize(Dimension)
1850:             * @see Screen3D#setPhysicalScreenWidth
1851:             * @see Screen3D#setPhysicalScreenHeight
1852:             *
1853:             * @since Java 3D 1.2
1854:             */
1855:            public void setOffScreenBuffer(ImageComponent2D buffer) {
1856:                int width, height;
1857:                boolean freeCanvasId = false;
1858:
1859:                if (!offScreen)
1860:                    throw new IllegalStateException(J3dI18N
1861:                            .getString("Canvas3D1"));
1862:
1863:                if (offScreenRendering)
1864:                    throw new RestrictedAccessException(J3dI18N
1865:                            .getString("Canvas3D2"));
1866:
1867:                // Check that offScreenBufferPending is not already set
1868:                J3dDebug.doAssert(!offScreenBufferPending,
1869:                        "!offScreenBufferPending");
1870:
1871:                if (offScreenBuffer != null && offScreenBuffer != buffer) {
1872:                    ImageComponent2DRetained i2dRetained = (ImageComponent2DRetained) offScreenBuffer.retained;
1873:                    i2dRetained.setUsedByOffScreen(false);
1874:                }
1875:
1876:                if (buffer != null) {
1877:                    ImageComponent2DRetained bufferRetained = (ImageComponent2DRetained) buffer.retained;
1878:
1879:                    if (bufferRetained.byReference
1880:                            && !(bufferRetained.getRefImage(0) instanceof  BufferedImage)) {
1881:
1882:                        throw new IllegalArgumentException(J3dI18N
1883:                                .getString("Canvas3D15"));
1884:                    }
1885:
1886:                    if (bufferRetained.getNumberOfComponents() < 3) {
1887:                        throw new IllegalArgumentException(J3dI18N
1888:                                .getString("Canvas3D16"));
1889:                    }
1890:
1891:                    if (buffer.isLive()) {
1892:                        throw new IllegalSharingException(J3dI18N
1893:                                .getString("Canvas3D26"));
1894:                    }
1895:
1896:                    if (bufferRetained.getInImmCtx()) {
1897:                        throw new IllegalSharingException(J3dI18N
1898:                                .getString("Canvas3D27"));
1899:                    }
1900:
1901:                    if (buffer != offScreenBuffer
1902:                            && bufferRetained.getUsedByOffScreen()) {
1903:                        throw new IllegalSharingException(J3dI18N
1904:                                .getString("Canvas3D28"));
1905:                    }
1906:
1907:                    bufferRetained.setUsedByOffScreen(true);
1908:
1909:                    width = bufferRetained.width;
1910:                    height = bufferRetained.height;
1911:
1912:                    // Issues 347, 348 - assign a canvasId for off-screen Canvas3D
1913:                    if (manualRendering) {
1914:                        sendAllocateCanvasId();
1915:                    }
1916:                } else {
1917:                    width = height = 0;
1918:
1919:                    // Issues 347, 348 - release canvasId for off-screen Canvas3D
1920:                    if (manualRendering) {
1921:                        freeCanvasId = true;
1922:                    }
1923:                }
1924:
1925:                if ((offScreenCanvasSize.width != width)
1926:                        || (offScreenCanvasSize.height != height)) {
1927:
1928:                    if (drawable != null) {
1929:                        // Fix for Issue 18 and Issue 175
1930:                        // Will do destroyOffScreenBuffer in the Renderer thread. 
1931:                        sendDestroyCtxAndOffScreenBuffer();
1932:                        drawable = null;
1933:                    }
1934:                    // Issue 396. Since context is invalid here, we should set it to null.
1935:                    ctx = null;
1936:
1937:                    // set the canvas dimension according to the buffer dimension
1938:                    offScreenCanvasSize.setSize(width, height);
1939:                    this .setSize(offScreenCanvasSize);
1940:
1941:                    if (width > 0 && height > 0) {
1942:                        sendCreateOffScreenBuffer();
1943:                    }
1944:
1945:                } else if (ctx != null) {
1946:                    removeCtx();
1947:                }
1948:
1949:                if (freeCanvasId) {
1950:                    sendFreeCanvasId();
1951:                }
1952:
1953:                offScreenBuffer = buffer;
1954:
1955:                synchronized (dirtyMaskLock) {
1956:                    cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY;
1957:                    cvDirtyMask[1] |= MOVED_OR_RESIZED_DIRTY;
1958:                }
1959:            }
1960:
1961:            /**
1962:             * Retrieves the off-screen buffer for this Canvas3D.
1963:             *
1964:             * @return the current off-screen buffer for this Canvas3D.
1965:             *
1966:             * @exception IllegalStateException if this Canvas3D is not in
1967:             * off-screen mode.
1968:             *
1969:             * @since Java 3D 1.2
1970:             */
1971:            public ImageComponent2D getOffScreenBuffer() {
1972:
1973:                if (!offScreen)
1974:                    throw new IllegalStateException(J3dI18N
1975:                            .getString("Canvas3D1"));
1976:
1977:                return (offScreenBuffer);
1978:            }
1979:
1980:            /**
1981:             * Schedules the rendering of a frame into this Canvas3D's
1982:             * off-screen buffer.  The rendering is done from the point of
1983:             * view of the View object to which this Canvas3D has been added.
1984:             * No rendering is performed if this Canvas3D object has not been
1985:             * added to an active View.  This method does not wait for the rendering
1986:             * to actually happen.  An application that wishes to know when
1987:             * the rendering is complete must either subclass Canvas3D and
1988:             * override the <code>postSwap</code> method, or call
1989:             * <code>waitForOffScreenRendering</code>.
1990:             *
1991:             * @exception NullPointerException if the off-screen buffer is null.
1992:             * @exception IllegalStateException if this Canvas3D is not in
1993:             * off-screen mode, or if either the width or the height of
1994:             * the associated Screen3D's size is <= 0, or if the associated
1995:             * Screen3D's physical width or height is <= 0.
1996:             * @exception RestrictedAccessException if an off-screen rendering
1997:             * is already in process for this Canvas3D or if the Java 3D renderer
1998:             * is stopped.
1999:             *
2000:             * @see #setOffScreenBuffer
2001:             * @see Screen3D#setSize(int, int)
2002:             * @see Screen3D#setSize(Dimension)
2003:             * @see Screen3D#setPhysicalScreenWidth
2004:             * @see Screen3D#setPhysicalScreenHeight
2005:             * @see #waitForOffScreenRendering
2006:             * @see #postSwap
2007:             *
2008:             * @since Java 3D 1.2
2009:             */
2010:            public void renderOffScreenBuffer() {
2011:
2012:                if (!offScreen)
2013:                    throw new IllegalStateException(J3dI18N
2014:                            .getString("Canvas3D1"));
2015:
2016:                // Issue 131: Cannot manually render to an automatic canvas.
2017:                if (!manualRendering)
2018:                    throw new IllegalStateException(J3dI18N
2019:                            .getString("Canvas3D24"));
2020:
2021:                // Issue 260 : Cannot render if we already have a fatal error
2022:                if (fatalError) {
2023:                    throw new IllegalRenderingStateException(J3dI18N
2024:                            .getString("Canvas3D30"));
2025:                }
2026:
2027:                if (offScreenBuffer == null)
2028:                    throw new NullPointerException(J3dI18N
2029:                            .getString("Canvas3D10"));
2030:
2031:                Dimension screenSize = screen.getSize();
2032:
2033:                if (screenSize.width <= 0)
2034:                    throw new IllegalStateException(J3dI18N
2035:                            .getString("Canvas3D8"));
2036:
2037:                if (screenSize.height <= 0)
2038:                    throw new IllegalStateException(J3dI18N
2039:                            .getString("Canvas3D9"));
2040:
2041:                if (screen.getPhysicalScreenWidth() <= 0.0)
2042:                    throw new IllegalStateException(J3dI18N
2043:                            .getString("Canvas3D12"));
2044:
2045:                if (screen.getPhysicalScreenHeight() <= 0.0)
2046:                    throw new IllegalStateException(J3dI18N
2047:                            .getString("Canvas3D13"));
2048:
2049:                if (offScreenRendering)
2050:                    throw new RestrictedAccessException(J3dI18N
2051:                            .getString("Canvas3D2"));
2052:
2053:                if (!isRunning)
2054:                    throw new RestrictedAccessException(J3dI18N
2055:                            .getString("Canvas3D11"));
2056:
2057:                // Fix to issue 66
2058:                if ((!active) || (pendingView == null)) {
2059:                    /* No rendering is performed if this Canvas3D object has not been 
2060:                       added to an active View. */
2061:                    return;
2062:                }
2063:
2064:                // Issue 131: moved code that determines off-screen boundary to separate
2065:                // method that is called from the renderer
2066:
2067:                offScreenRendering = true;
2068:
2069:                // Fix to issue 66.
2070:                /* This is an attempt to do the following check in one atomic operation :
2071:                   ((view != null) && (view.inCanvasCallback)) */
2072:
2073:                boolean inCanvasCallback = false;
2074:                try {
2075:                    inCanvasCallback = view.inCanvasCallback;
2076:
2077:                } catch (NullPointerException npe) {
2078:                    /* Do nothing here */
2079:                }
2080:
2081:                if (inCanvasCallback) {
2082:                    // Here we assume that view is stable if inCanvasCallback
2083:                    // is true. This assumption is valid among all j3d threads as 
2084:                    // all access to view is synchronized by MasterControl.
2085:                    // Issue : user threads access to view isn't synchronize hence
2086:                    // is model will break.
2087:                    if (screen.renderer == null) {
2088:
2089:                        // It is possible that screen.renderer = null when this View
2090:                        // is shared by another onScreen Canvas and this callback
2091:                        // is from that Canvas. In this case it need one more
2092:                        // round before the renderer.
2093:                        screen.renderer = (Renderer) screen.deviceRendererMap
2094:                                .get(screen.graphicsDevice);
2095:                        // screen.renderer may equal to null when multiple
2096:                        // screen is used and this Canvas3D is in different
2097:                        // screen sharing the same View not yet initialize.
2098:                    }
2099:
2100:                    // if called from render call back, send a message directly to 
2101:                    // the renderer message queue, and call renderer doWork
2102:                    // to do the offscreen rendering now
2103:                    if (Thread.currentThread() == screen.renderer) {
2104:
2105:                        J3dMessage createMessage = new J3dMessage();
2106:                        createMessage.threads = J3dThread.RENDER_THREAD;
2107:                        createMessage.type = J3dMessage.RENDER_OFFSCREEN;
2108:                        createMessage.universe = this .view.universe;
2109:                        createMessage.view = this .view;
2110:                        createMessage.args[0] = this ;
2111:
2112:                        screen.renderer.rendererStructure
2113:                                .addMessage(createMessage);
2114:
2115:                        // modify the args to reflect offScreen rendering
2116:                        screen.renderer.args = new Object[4];
2117:                        ((Object[]) screen.renderer.args)[0] = new Integer(
2118:                                Renderer.REQUESTRENDER);
2119:                        ((Object[]) screen.renderer.args)[1] = this ;
2120:                        ((Object[]) screen.renderer.args)[2] = view;
2121:                        // This extra argument 3 is needed in MasterControl to
2122:                        // test whether offscreen Rendering is used or not
2123:                        ((Object[]) screen.renderer.args)[3] = null;
2124:
2125:                        // call renderer doWork directly since we are already in
2126:                        // the renderer thread
2127:                        screen.renderer.doWork(0);
2128:                    } else {
2129:
2130:                        // XXXX: 
2131:                        // Now we are in trouble, this will cause deadlock if
2132:                        // waitForOffScreenRendering() is invoked
2133:                        J3dMessage createMessage = new J3dMessage();
2134:                        createMessage.threads = J3dThread.RENDER_THREAD;
2135:                        createMessage.type = J3dMessage.RENDER_OFFSCREEN;
2136:                        createMessage.universe = this .view.universe;
2137:                        createMessage.view = this .view;
2138:                        createMessage.args[0] = this ;
2139:                        screen.renderer.rendererStructure
2140:                                .addMessage(createMessage);
2141:                        VirtualUniverse.mc.setWorkForRequestRenderer();
2142:                    }
2143:
2144:                } else if (Thread.currentThread() instanceof  BehaviorScheduler) {
2145:
2146:                    // If called from behavior scheduler, send a message directly to 
2147:                    // the renderer message queue.
2148:                    // Note that we didn't use 
2149:                    // currentThread() == view.universe.behaviorScheduler
2150:                    // since the caller may be another universe Behavior
2151:                    // scheduler.
2152:                    J3dMessage createMessage = new J3dMessage();
2153:                    createMessage.threads = J3dThread.RENDER_THREAD;
2154:                    createMessage.type = J3dMessage.RENDER_OFFSCREEN;
2155:                    createMessage.universe = this .view.universe;
2156:                    createMessage.view = this .view;
2157:                    createMessage.args[0] = this ;
2158:                    screen.renderer.rendererStructure.addMessage(createMessage);
2159:                    VirtualUniverse.mc.setWorkForRequestRenderer();
2160:
2161:                } else {
2162:                    // send a message to renderBin
2163:                    // Fix for issue 66 : Since view might not been set yet, 
2164:                    // we have to use pendingView instead.
2165:                    J3dMessage createMessage = new J3dMessage();
2166:                    createMessage.threads = J3dThread.UPDATE_RENDER;
2167:                    createMessage.type = J3dMessage.RENDER_OFFSCREEN;
2168:                    createMessage.universe = this .pendingView.universe;
2169:                    createMessage.view = this .pendingView;
2170:                    createMessage.args[0] = this ;
2171:                    createMessage.args[1] = offScreenBuffer;
2172:                    VirtualUniverse.mc.processMessage(createMessage);
2173:                }
2174:            }
2175:
2176:            /**
2177:             * Waits for this Canvas3D's off-screen rendering to be done.
2178:             * This method will wait until the <code>postSwap</code> method of this
2179:             * off-screen Canvas3D has completed.  If this Canvas3D has not
2180:             * been added to an active view or if the renderer is stopped for this
2181:             * Canvas3D, then this method will return
2182:             * immediately.  This method must not be called from a render
2183:             * callback method of an off-screen Canvas3D.
2184:             *
2185:             * @exception IllegalStateException if this Canvas3D is not in
2186:             * off-screen mode, or if this method is called from a render
2187:             * callback method of an off-screen Canvas3D.
2188:             *
2189:             * @see #renderOffScreenBuffer
2190:             * @see #postSwap
2191:             *
2192:             * @since Java 3D 1.2
2193:             */
2194:            public void waitForOffScreenRendering() {
2195:
2196:                if (!offScreen) {
2197:                    throw new IllegalStateException(J3dI18N
2198:                            .getString("Canvas3D1"));
2199:                }
2200:
2201:                if (Thread.currentThread() instanceof  Renderer) {
2202:                    throw new IllegalStateException(J3dI18N
2203:                            .getString("Canvas3D31"));
2204:                }
2205:
2206:                while (offScreenRendering) {
2207:                    MasterControl.threadYield();
2208:                }
2209:            }
2210:
2211:            /**
2212:             * Sets the location of this off-screen Canvas3D.  The location is
2213:             * the upper-left corner of the Canvas3D relative to the
2214:             * upper-left corner of the corresponding off-screen Screen3D.
2215:             * The function of this method is similar to that of
2216:             * <code>Component.setLocation</code> for on-screen Canvas3D
2217:             * objects.  The default location is (0,0).
2218:             *
2219:             * @param x the <i>x</i> coordinate of the upper-left corner of
2220:             * the new location.
2221:             * @param y the <i>y</i> coordinate of the upper-left corner of
2222:             * the new location.
2223:             *
2224:             * @exception IllegalStateException if this Canvas3D is not in
2225:             * off-screen mode.
2226:             *
2227:             * @since Java 3D 1.2
2228:             */
2229:            public void setOffScreenLocation(int x, int y) {
2230:
2231:                if (!offScreen)
2232:                    throw new IllegalStateException(J3dI18N
2233:                            .getString("Canvas3D1"));
2234:
2235:                synchronized (cvLock) {
2236:                    offScreenCanvasLoc.setLocation(x, y);
2237:                }
2238:            }
2239:
2240:            /**
2241:             * Sets the location of this off-screen Canvas3D.  The location is
2242:             * the upper-left corner of the Canvas3D relative to the
2243:             * upper-left corner of the corresponding off-screen Screen3D.
2244:             * The function of this method is similar to that of
2245:             * <code>Component.setLocation</code> for on-screen Canvas3D
2246:             * objects.  The default location is (0,0).
2247:             *
2248:             * @param p the point defining the upper-left corner of the new
2249:             * location.
2250:             *
2251:             * @exception IllegalStateException if this Canvas3D is not in
2252:             * off-screen mode.
2253:             *
2254:             * @since Java 3D 1.2
2255:             */
2256:            public void setOffScreenLocation(Point p) {
2257:
2258:                if (!offScreen)
2259:                    throw new IllegalStateException(J3dI18N
2260:                            .getString("Canvas3D1"));
2261:
2262:                synchronized (cvLock) {
2263:                    offScreenCanvasLoc.setLocation(p);
2264:                }
2265:            }
2266:
2267:            /**
2268:             * Retrieves the location of this off-screen Canvas3D.  The
2269:             * location is the upper-left corner of the Canvas3D relative to
2270:             * the upper-left corner of the corresponding off-screen Screen3D.
2271:             * The function of this method is similar to that of
2272:             * <code>Component.getLocation</code> for on-screen Canvas3D
2273:             * objects.
2274:             *
2275:             * @return a new point representing the upper-left corner of the
2276:             * location of this off-screen Canvas3D.
2277:             *
2278:             * @exception IllegalStateException if this Canvas3D is not in
2279:             * off-screen mode.
2280:             *
2281:             * @since Java 3D 1.2
2282:             */
2283:            public Point getOffScreenLocation() {
2284:                if (!offScreen)
2285:                    throw new IllegalStateException(J3dI18N
2286:                            .getString("Canvas3D1"));
2287:
2288:                return (new Point(offScreenCanvasLoc));
2289:            }
2290:
2291:            /**
2292:             * Retrieves the location of this off-screen Canvas3D and stores
2293:             * it in the specified Point object.  The location is the
2294:             * upper-left corner of the Canvas3D relative to the upper-left
2295:             * corner of the corresponding off-screen Screen3D.  The function
2296:             * of this method is similar to that of
2297:             * <code>Component.getLocation</code> for on-screen Canvas3D
2298:             * objects. This version of <code>getOffScreenLocation</code> is
2299:             * useful if the caller wants to avoid allocating a new Point
2300:             * object on the heap.
2301:             *
2302:             * @param rv Point object into which the upper-left corner of the
2303:             * location of this off-screen Canvas3D is copied.
2304:             * If <code>rv</code> is null, a new Point is allocated.
2305:             *
2306:             * @return <code>rv</code>
2307:             *
2308:             * @exception IllegalStateException if this Canvas3D is not in
2309:             * off-screen mode.
2310:             *
2311:             * @since Java 3D 1.2
2312:             */
2313:            public Point getOffScreenLocation(Point rv) {
2314:
2315:                if (!offScreen)
2316:                    throw new IllegalStateException(J3dI18N
2317:                            .getString("Canvas3D1"));
2318:
2319:                if (rv == null)
2320:                    return (new Point(offScreenCanvasLoc));
2321:
2322:                else {
2323:                    rv.setLocation(offScreenCanvasLoc);
2324:                    return rv;
2325:                }
2326:            }
2327:
2328:            void endOffScreenRendering() {
2329:
2330:                ImageComponent2DRetained icRetained = (ImageComponent2DRetained) offScreenBuffer.retained;
2331:                boolean isByRef = icRetained.isByReference();
2332:                boolean isYUp = icRetained.isYUp();
2333:                ImageComponentRetained.ImageData imageData = icRetained
2334:                        .getImageData(false);
2335:
2336:                if (!isByRef) {
2337:                    // If icRetained has a null image ( BufferedImage)
2338:                    if (imageData == null) {
2339:                        assert (!isByRef);
2340:                        icRetained.createBlankImageData();
2341:                        imageData = icRetained.getImageData(false);
2342:                    }
2343:                    // Check for possible format conversion in imageData
2344:                    else {
2345:                        // Format convert imageData if format is unsupported.
2346:                        icRetained.evaluateExtensions(this );
2347:                    }
2348:                    // read the image from the offscreen buffer
2349:                    readOffScreenBuffer(ctx, icRetained
2350:                            .getImageFormatTypeIntValue(false), icRetained
2351:                            .getImageDataTypeIntValue(), imageData.get(),
2352:                            offScreenCanvasSize.width,
2353:                            offScreenCanvasSize.height);
2354:
2355:                } else {
2356:                    icRetained.geomLock.getLock();
2357:                    // Create a copy of format converted image in imageData if format is unsupported.
2358:                    icRetained.evaluateExtensions(this );
2359:
2360:                    // read the image from the offscreen buffer
2361:                    readOffScreenBuffer(ctx, icRetained
2362:                            .getImageFormatTypeIntValue(false), icRetained
2363:                            .getImageDataTypeIntValue(), imageData.get(),
2364:                            offScreenCanvasSize.width,
2365:                            offScreenCanvasSize.height);
2366:
2367:                    // For byRef, we might have to copy buffer back into
2368:                    // the user's referenced ImageComponent2D
2369:                    if (!imageData.isDataByRef()) {
2370:                        if (icRetained.isImageTypeSupported()) {
2371:                            icRetained.copyToRefImage(0);
2372:                        } else {
2373:                            // This method only handle RGBA conversion.
2374:                            icRetained.copyToRefImageWithFormatConversion(0);
2375:                        }
2376:                    }
2377:
2378:                    icRetained.geomLock.unLock();
2379:                }
2380:            }
2381:
2382:            /**
2383:             * Synchronize and swap buffers on a double buffered canvas for
2384:             * this Canvas3D object.  This method should only be called if the
2385:             * Java 3D renderer has been stopped.  In the normal case, the renderer
2386:             * automatically swaps the buffer.
2387:             * This method calls the <code>flush(true)</code> methods of the
2388:             * associated 2D and 3D graphics contexts, if they have been allocated.
2389:             *
2390:             * @exception RestrictedAccessException if the Java 3D renderer is
2391:             * running.
2392:             * @exception IllegalStateException if this Canvas3D is in
2393:             * off-screen mode.
2394:             *
2395:             * @see #stopRenderer
2396:             * @see GraphicsContext3D#flush
2397:             * @see J3DGraphics2D#flush
2398:             */
2399:            public void swap() {
2400:                if (offScreen)
2401:                    throw new IllegalStateException(J3dI18N
2402:                            .getString("Canvas3D14"));
2403:
2404:                if (isRunning)
2405:                    throw new RestrictedAccessException(J3dI18N
2406:                            .getString("Canvas3D0"));
2407:
2408:                if (!firstPaintCalled) {
2409:                    return;
2410:                }
2411:
2412:                if (view != null && graphicsContext3D != null) {
2413:                    if ((view.universe != null)
2414:                            && (Thread.currentThread() == view.universe.behaviorScheduler)) {
2415:                        graphicsContext3D.sendRenderMessage(false,
2416:                                GraphicsContext3D.SWAP, null, null);
2417:                    } else {
2418:                        graphicsContext3D.sendRenderMessage(true,
2419:                                GraphicsContext3D.SWAP, null, null);
2420:                    }
2421:                    graphicsContext3D.runMonitor(J3dThread.WAIT);
2422:                }
2423:            }
2424:
2425:            void doSwap() {
2426:
2427:                if (firstPaintCalled && useDoubleBuffer) {
2428:                    try {
2429:                        if (validCtx && (ctx != null) && (view != null)) {
2430:                            synchronized (drawingSurfaceObject) {
2431:                                if (validCtx) {
2432:                                    if (!drawingSurfaceObject.renderLock()) {
2433:                                        graphicsContext3D
2434:                                                .runMonitor(J3dThread.NOTIFY);
2435:                                        return;
2436:                                    }
2437:                                    this .syncRender(ctx, true);
2438:                                    int status = swapBuffers(ctx,
2439:                                            screen.display, drawable);
2440:                                    if (status != NOCHANGE) {
2441:                                        resetImmediateRendering(status);
2442:                                    }
2443:                                    drawingSurfaceObject.unLock();
2444:                                }
2445:                            }
2446:                        }
2447:                    } catch (NullPointerException ne) {
2448:                        drawingSurfaceObject.unLock();
2449:                    }
2450:                }
2451:                // Increment the elapsedFrame for the behavior structure
2452:                // to trigger any interpolators
2453:                view.universe.behaviorStructure.incElapsedFrames();
2454:                // waitup user thread in PureImmediate mode to continue
2455:                if (reEvaluateCanvasCmd != 0) {
2456:                    int status;
2457:
2458:                    antialiasingSet = false;
2459:                    if (reEvaluateCanvasCmd == RESIZE) {
2460:                        assert VirtualUniverse.mc.isD3D();
2461:                        status = resizeD3DCanvas(ctx);
2462:                    } else {
2463:                        status = toggleFullScreenMode(ctx);
2464:                    }
2465:                    // reset everything
2466:                    if (status != NOCHANGE) {
2467:                        resetImmediateRendering(status);
2468:                    }
2469:                    reEvaluateCanvasCmd = 0;
2470:                }
2471:                graphicsContext3D.runMonitor(J3dThread.NOTIFY);
2472:            }
2473:
2474:            /**
2475:             * Wrapper for native createNewContext method.
2476:             */
2477:            Context createNewContext(Context shareCtx, boolean isSharedCtx) {
2478:                Context retVal = createNewContext(this .screen.display,
2479:                        this .drawable, this .fbConfig, shareCtx, isSharedCtx,
2480:                        this .offScreen,
2481:                        VirtualUniverse.mc.glslLibraryAvailable,
2482:                        VirtualUniverse.mc.cgLibraryAvailable);
2483:                // compute the max available texture units
2484:                maxAvailableTextureUnits = Math.max(maxTextureUnits,
2485:                        maxTextureImageUnits);
2486:
2487:                return retVal;
2488:            }
2489:
2490:            /**
2491:             * Make the context associated with the specified canvas current.
2492:             */
2493:            final void makeCtxCurrent() {
2494:                makeCtxCurrent(ctx, screen.display, drawable);
2495:            }
2496:
2497:            /**
2498:             * Make the specified context current.
2499:             */
2500:            final void makeCtxCurrent(Context ctx) {
2501:                makeCtxCurrent(ctx, screen.display, drawable);
2502:            }
2503:
2504:            final void makeCtxCurrent(Context ctx, long dpy, Drawable drawable) {
2505:                if (ctx != screen.renderer.currentCtx
2506:                        || drawable != screen.renderer.currentDrawable) {
2507:                    if (!drawingSurfaceObject.isLocked()) {
2508:                        drawingSurfaceObject.renderLock();
2509:                        useCtx(ctx, dpy, drawable);
2510:                        drawingSurfaceObject.unLock();
2511:                    } else {
2512:                        useCtx(ctx, dpy, drawable);
2513:                    }
2514:                    screen.renderer.currentCtx = ctx;
2515:                    screen.renderer.currentDrawable = drawable;
2516:                }
2517:            }
2518:
2519:            // Give the pipeline a chance to release the context; the Pipeline may
2520:            // or may not ignore this call.
2521:            void releaseCtx() {
2522:                if (screen.renderer.currentCtx != null) {
2523:                    boolean needLock = !drawingSurfaceObject.isLocked();
2524:                    if (needLock) {
2525:                        drawingSurfaceObject.renderLock();
2526:                    }
2527:                    if (releaseCtx(screen.renderer.currentCtx, screen.display)) {
2528:                        screen.renderer.currentCtx = null;
2529:                        screen.renderer.currentDrawable = null;
2530:                    }
2531:                    if (needLock) {
2532:                        drawingSurfaceObject.unLock();
2533:                    }
2534:                }
2535:            }
2536:
2537:            /**
2538:             * Sets the position of the manual left eye in image-plate
2539:             * coordinates.  This value determines eye placement when a head
2540:             * tracker is not in use and the application is directly controlling
2541:             * the eye position in image-plate coordinates.
2542:             * In head-tracked mode or when the windowEyePointPolicy is
2543:             * RELATIVE_TO_FIELD_OF_VIEW or RELATIVE_TO_COEXISTENCE, this value
2544:             * is ignored.  When the
2545:             * windowEyepointPolicy is RELATIVE_TO_WINDOW only the Z value is
2546:             * used.
2547:             * @param position the new manual left eye position
2548:             */
2549:            public void setLeftManualEyeInImagePlate(Point3d position) {
2550:
2551:                this .leftManualEyeInImagePlate.set(position);
2552:                synchronized (dirtyMaskLock) {
2553:                    cvDirtyMask[0] |= EYE_IN_IMAGE_PLATE_DIRTY;
2554:                    cvDirtyMask[1] |= EYE_IN_IMAGE_PLATE_DIRTY;
2555:                }
2556:                redraw();
2557:            }
2558:
2559:            /**
2560:             * Sets the position of the manual right eye in image-plate
2561:             * coordinates.  This value determines eye placement when a head
2562:             * tracker is not in use and the application is directly controlling
2563:             * the eye position in image-plate coordinates.
2564:             * In head-tracked mode or when the windowEyePointPolicy is
2565:             * RELATIVE_TO_FIELD_OF_VIEW or RELATIVE_TO_COEXISTENCE, this value
2566:             * is ignored.  When the
2567:             * windowEyepointPolicy is RELATIVE_TO_WINDOW only the Z value is
2568:             * used.
2569:             * @param position the new manual right eye position
2570:             */
2571:            public void setRightManualEyeInImagePlate(Point3d position) {
2572:
2573:                this .rightManualEyeInImagePlate.set(position);
2574:                synchronized (dirtyMaskLock) {
2575:                    cvDirtyMask[0] |= EYE_IN_IMAGE_PLATE_DIRTY;
2576:                    cvDirtyMask[1] |= EYE_IN_IMAGE_PLATE_DIRTY;
2577:                }
2578:                redraw();
2579:            }
2580:
2581:            /**
2582:             * Retrieves the position of the user-specified, manual left eye
2583:             * in image-plate
2584:             * coordinates and copies that value into the object provided.
2585:             * @param position the object that will receive the position
2586:             */
2587:            public void getLeftManualEyeInImagePlate(Point3d position) {
2588:                position.set(this .leftManualEyeInImagePlate);
2589:            }
2590:
2591:            /**
2592:             * Retrieves the position of the user-specified, manual right eye
2593:             * in image-plate
2594:             * coordinates and copies that value into the object provided.
2595:             * @param position the object that will receive the position
2596:             */
2597:            public void getRightManualEyeInImagePlate(Point3d position) {
2598:                position.set(this .rightManualEyeInImagePlate);
2599:            }
2600:
2601:            /**
2602:             * Retrieves the actual position of the left eye
2603:             * in image-plate
2604:             * coordinates and copies that value into the object provided.
2605:             * This value is a function of the windowEyepointPolicy, the tracking
2606:             * enable flag, and the manual left eye position.
2607:             * @param position the object that will receive the position
2608:             */
2609:            public void getLeftEyeInImagePlate(Point3d position) {
2610:                if (canvasViewCache != null) {
2611:                    synchronized (canvasViewCache) {
2612:                        position.set(canvasViewCache.getLeftEyeInImagePlate());
2613:                    }
2614:                } else {
2615:                    position.set(leftManualEyeInImagePlate);
2616:                }
2617:            }
2618:
2619:            /**
2620:             * Retrieves the actual position of the right eye
2621:             * in image-plate
2622:             * coordinates and copies that value into the object provided.
2623:             * This value is a function of the windowEyepointPolicy, the tracking
2624:             * enable flag, and the manual right eye position.
2625:             * @param position the object that will receive the position
2626:             */
2627:            public void getRightEyeInImagePlate(Point3d position) {
2628:                if (canvasViewCache != null) {
2629:                    synchronized (canvasViewCache) {
2630:                        position.set(canvasViewCache.getRightEyeInImagePlate());
2631:                    }
2632:                } else {
2633:                    position.set(rightManualEyeInImagePlate);
2634:                }
2635:            }
2636:
2637:            /**
2638:             * Retrieves the actual position of the center eye
2639:             * in image-plate
2640:             * coordinates and copies that value into the object provided.
2641:             * The center eye is the fictional eye half-way between the left and
2642:             * right eye.
2643:             * This value is a function of the windowEyepointPolicy, the tracking
2644:             * enable flag, and the manual right and left eye positions.
2645:             * @param position the object that will receive the position
2646:             * @see #setMonoscopicViewPolicy
2647:             */
2648:            // XXXX: This might not make sense for field-sequential HMD. 
2649:            public void getCenterEyeInImagePlate(Point3d position) {
2650:                if (canvasViewCache != null) {
2651:                    synchronized (canvasViewCache) {
2652:                        position
2653:                                .set(canvasViewCache.getCenterEyeInImagePlate());
2654:                    }
2655:                } else {
2656:                    Point3d cenEye = new Point3d();
2657:                    cenEye.add(leftManualEyeInImagePlate,
2658:                            rightManualEyeInImagePlate);
2659:                    cenEye.scale(0.5);
2660:                    position.set(cenEye);
2661:                }
2662:            }
2663:
2664:            /**
2665:             * Retrieves the current ImagePlate coordinates to Virtual World
2666:             * coordinates transform and places it into the specified object.
2667:             * @param t the Transform3D object that will receive the
2668:             * transform
2669:             */
2670:            // TODO: Document -- This will return the transform of left plate.
2671:            public void getImagePlateToVworld(Transform3D t) {
2672:                if (canvasViewCache != null) {
2673:                    synchronized (canvasViewCache) {
2674:                        t.set(canvasViewCache.getImagePlateToVworld());
2675:                    }
2676:                } else {
2677:                    t.setIdentity();
2678:                }
2679:            }
2680:
2681:            /**
2682:             * Computes the position of the specified AWT pixel value
2683:             * in image-plate
2684:             * coordinates and copies that value into the object provided.
2685:             * @param x the X coordinate of the pixel relative to the upper-left
2686:             * hand corner of the window.
2687:             * @param y the Y coordinate of the pixel relative to the upper-left
2688:             * hand corner of the window.
2689:             * @param imagePlatePoint the object that will receive the position in
2690:             * physical image plate coordinates (relative to the lower-left
2691:             * corner of the screen).
2692:             */
2693:            // TODO: Document -- This transform the pixel location to the left image plate.
2694:            public void getPixelLocationInImagePlate(int x, int y,
2695:                    Point3d imagePlatePoint) {
2696:
2697:                if (canvasViewCache != null) {
2698:                    synchronized (canvasViewCache) {
2699:                        imagePlatePoint.x = canvasViewCache
2700:                                .getWindowXInImagePlate((double) x);
2701:                        imagePlatePoint.y = canvasViewCache
2702:                                .getWindowYInImagePlate((double) y);
2703:                        imagePlatePoint.z = 0.0;
2704:                    }
2705:                } else {
2706:                    imagePlatePoint.set(0.0, 0.0, 0.0);
2707:                }
2708:            }
2709:
2710:            void getPixelLocationInImagePlate(double x, double y, double z,
2711:                    Point3d imagePlatePoint) {
2712:                if (canvasViewCache != null) {
2713:                    synchronized (canvasViewCache) {
2714:                        canvasViewCache.getPixelLocationInImagePlate(x, y, z,
2715:                                imagePlatePoint);
2716:                    }
2717:                } else {
2718:                    imagePlatePoint.set(0.0, 0.0, 0.0);
2719:                }
2720:            }
2721:
2722:            /**
2723:             * Computes the position of the specified AWT pixel value
2724:             * in image-plate
2725:             * coordinates and copies that value into the object provided.
2726:             * @param pixelLocation the coordinates of the pixel relative to
2727:             * the upper-left hand corner of the window.
2728:             * @param imagePlatePoint the object that will receive the position in
2729:             * physical image plate coordinates (relative to the lower-left
2730:             * corner of the screen).
2731:             *
2732:             * @since Java 3D 1.2
2733:             */
2734:            // TODO: Document -- This transform the pixel location to the left image plate.    
2735:            public void getPixelLocationInImagePlate(Point2d pixelLocation,
2736:                    Point3d imagePlatePoint) {
2737:
2738:                if (canvasViewCache != null) {
2739:                    synchronized (canvasViewCache) {
2740:                        imagePlatePoint.x = canvasViewCache
2741:                                .getWindowXInImagePlate(pixelLocation.x);
2742:                        imagePlatePoint.y = canvasViewCache
2743:                                .getWindowYInImagePlate(pixelLocation.y);
2744:                        imagePlatePoint.z = 0.0;
2745:                    }
2746:                } else {
2747:                    imagePlatePoint.set(0.0, 0.0, 0.0);
2748:                }
2749:            }
2750:
2751:            /**
2752:             * Projects the specified point from image plate coordinates
2753:             * into AWT pixel coordinates.  The AWT pixel coordinates are
2754:             * copied into the object provided.
2755:             * @param imagePlatePoint the position in
2756:             * physical image plate coordinates (relative to the lower-left
2757:             * corner of the screen).
2758:             * @param pixelLocation the object that will receive the coordinates
2759:             * of the pixel relative to the upper-left hand corner of the window.
2760:             *
2761:             * @since Java 3D 1.2
2762:             */
2763:            // TODO: Document -- This transform the pixel location from the left image plate.
2764:            public void getPixelLocationFromImagePlate(Point3d imagePlatePoint,
2765:                    Point2d pixelLocation) {
2766:                if (canvasViewCache != null) {
2767:                    synchronized (canvasViewCache) {
2768:                        canvasViewCache.getPixelLocationFromImagePlate(
2769:                                imagePlatePoint, pixelLocation);
2770:                    }
2771:                } else {
2772:                    pixelLocation.set(0.0, 0.0);
2773:                }
2774:            }
2775:
2776:            /**
2777:             * Copies the current Vworld projection transform for each eye
2778:             * into the specified Transform3D objects.  This transform takes
2779:             * points in virtual world coordinates and projects them into
2780:             * clipping coordinates, which are in the range [-1,1] in
2781:             * <i>X</i>, <i>Y</i>, and <i>Z</i> after clipping and perspective
2782:             * division.
2783:             * In monoscopic mode, the same projection transform will be
2784:             * copied into both the right and left eye Transform3D objects.
2785:             *
2786:             * @param leftProjection the Transform3D object that will receive
2787:             * a copy of the current projection transform for the left eye.
2788:             *
2789:             * @param rightProjection the Transform3D object that will receive
2790:             * a copy of the current projection transform for the right eye.
2791:             *
2792:             * @since Java 3D 1.3
2793:             */
2794:            public void getVworldProjection(Transform3D leftProjection,
2795:                    Transform3D rightProjection) {
2796:                if (canvasViewCache != null) {
2797:                    ViewPlatformRetained viewPlatformRetained = (ViewPlatformRetained) view
2798:                            .getViewPlatform().retained;
2799:
2800:                    synchronized (canvasViewCache) {
2801:                        leftProjection.mul(canvasViewCache.getLeftProjection(),
2802:                                canvasViewCache.getLeftVpcToEc());
2803:                        leftProjection.mul(viewPlatformRetained
2804:                                .getVworldToVpc());
2805:
2806:                        // caluclate right eye if in stereo, otherwise
2807:                        // this is the same as the left eye.
2808:                        if (useStereo) {
2809:                            rightProjection.mul(canvasViewCache
2810:                                    .getRightProjection(), canvasViewCache
2811:                                    .getRightVpcToEc());
2812:                            rightProjection.mul(viewPlatformRetained
2813:                                    .getVworldToVpc());
2814:                        } else {
2815:                            rightProjection.set(leftProjection);
2816:                        }
2817:                    }
2818:                } else {
2819:                    leftProjection.setIdentity();
2820:                    rightProjection.setIdentity();
2821:                }
2822:            }
2823:
2824:            /**
2825:             * Copies the inverse of the current Vworld projection transform
2826:             * for each eye into the specified Transform3D objects.  This
2827:             * transform takes points in clipping coordinates, which are in
2828:             * the range [-1,1] in <i>X</i>, <i>Y</i>, and <i>Z</i> after
2829:             * clipping and perspective division, and transforms them into
2830:             * virtual world coordinates.
2831:             * In monoscopic mode, the same inverse projection transform will
2832:             * be copied into both the right and left eye Transform3D objects.
2833:             *
2834:             * @param leftInverseProjection the Transform3D object that will
2835:             * receive a copy of the current inverse projection transform for
2836:             * the left eye.
2837:             * @param rightInverseProjection the Transform3D object that will
2838:             * receive a copy of the current inverse projection transform for
2839:             * the right eye.
2840:             *
2841:             * @since Java 3D 1.3
2842:             */
2843:            public void getInverseVworldProjection(
2844:                    Transform3D leftInverseProjection,
2845:                    Transform3D rightInverseProjection) {
2846:                if (canvasViewCache != null) {
2847:                    ViewPlatformRetained viewPlatformRetained = (ViewPlatformRetained) view
2848:                            .getViewPlatform().retained;
2849:
2850:                    synchronized (canvasViewCache) {
2851:                        leftInverseProjection.set(canvasViewCache
2852:                                .getLeftCcToVworld());
2853:
2854:                        // caluclate right eye if in stereo, otherwise
2855:                        // this is the same as the left eye.
2856:                        if (useStereo) {
2857:                            rightInverseProjection.set(canvasViewCache
2858:                                    .getRightCcToVworld());
2859:                        } else {
2860:                            rightInverseProjection.set(leftInverseProjection);
2861:                        }
2862:                    }
2863:
2864:                } else {
2865:                    leftInverseProjection.setIdentity();
2866:                    rightInverseProjection.setIdentity();
2867:                }
2868:            }
2869:
2870:            /**
2871:             * Retrieves the physical width of this canvas window in meters.
2872:             * @return the physical window width in meters.
2873:             */
2874:            public double getPhysicalWidth() {
2875:                double width = 0.0;
2876:
2877:                if (canvasViewCache != null) {
2878:                    synchronized (canvasViewCache) {
2879:                        width = canvasViewCache.getPhysicalWindowWidth();
2880:                    }
2881:                }
2882:
2883:                return width;
2884:            }
2885:
2886:            /**
2887:             * Retrieves the physical height of this canvas window in meters.
2888:             * @return the physical window height in meters.
2889:             */
2890:            public double getPhysicalHeight() {
2891:                double height = 0.0;
2892:
2893:                if (canvasViewCache != null) {
2894:                    synchronized (canvasViewCache) {
2895:                        height = canvasViewCache.getPhysicalWindowHeight();
2896:                    }
2897:                }
2898:
2899:                return height;
2900:            }
2901:
2902:            /**
2903:             * Retrieves the current Virtual World coordinates to ImagePlate
2904:             * coordinates transform and places it into the specified object.
2905:             * @param t the Transform3D object that will receive the
2906:             * transform
2907:             */
2908:            // TODO: Document -- This will return the transform of left plate.
2909:            public void getVworldToImagePlate(Transform3D t) {
2910:                if (canvasViewCache != null) {
2911:                    synchronized (canvasViewCache) {
2912:                        t.set(canvasViewCache.getVworldToImagePlate());
2913:                    }
2914:                } else {
2915:                    t.setIdentity();
2916:                }
2917:            }
2918:
2919:            void getLastVworldToImagePlate(Transform3D t) {
2920:                if (canvasViewCache != null) {
2921:                    synchronized (canvasViewCache) {
2922:                        t.set(canvasViewCache.getLastVworldToImagePlate());
2923:                    }
2924:                } else {
2925:                    t.setIdentity();
2926:                }
2927:            }
2928:
2929:            /**
2930:             * Sets view that points to this Canvas3D.
2931:             * @param view view object that points to this Canvas3D
2932:             */
2933:            void setView(View view) {
2934:                pendingView = view;
2935:
2936:                // We can't set View directly here in user thread since
2937:                // other threads may using canvas.view
2938:                // e.g. In Renderer, we use canvas3d.view.inCallBack
2939:                // before and after postSwap(), if view change in between
2940:                // than view.inCallBack may never reset to false.
2941:                VirtualUniverse.mc.postRequest(MasterControl.SET_VIEW, this );
2942:                evaluateActive();
2943:            }
2944:
2945:            void computeViewCache() {
2946:                synchronized (cvLock) {
2947:                    if (view == null) {
2948:                        canvasViewCache = null;
2949:                        canvasViewCacheFrustum = null;
2950:                    } else {
2951:
2952:                        canvasViewCache = new CanvasViewCache(this ,
2953:                                screen.screenViewCache, view.viewCache);
2954:                        // Issue 109 : construct a separate canvasViewCache for
2955:                        // computing view frustum
2956:                        canvasViewCacheFrustum = new CanvasViewCache(this ,
2957:                                screen.screenViewCache, view.viewCache);
2958:                        synchronized (dirtyMaskLock) {
2959:                            cvDirtyMask[0] = VIEW_INFO_DIRTY;
2960:                            cvDirtyMask[1] = VIEW_INFO_DIRTY;
2961:                        }
2962:                    }
2963:                }
2964:            }
2965:
2966:            /**
2967:             * Gets view that points to this Canvas3D.
2968:             * @return view object that points to this Canvas3D
2969:             */
2970:            public View getView() {
2971:                return pendingView;
2972:            }
2973:
2974:            /**
2975:             * Returns a status flag indicating whether or not stereo
2976:             * is available.
2977:             * This is equivalent to:
2978:             * <ul>
2979:             * <code>
2980:             * ((Boolean)queryProperties().
2981:             * get("stereoAvailable")).
2982:             * booleanValue()
2983:             * </code>
2984:             * </ul>
2985:             *
2986:             * @return a flag indicating whether stereo is available
2987:             */
2988:            public boolean getStereoAvailable() {
2989:                return ((Boolean) queryProperties().get("stereoAvailable"))
2990:                        .booleanValue();
2991:            }
2992:
2993:            /**
2994:             * Turns stereo on or off.  Note that this attribute is used
2995:             * only when stereo is available.  Enabling stereo on a Canvas3D
2996:             * that does not support stereo has no effect.
2997:             * @param flag enables or disables the display of stereo
2998:             *
2999:             * @see #queryProperties
3000:             */
3001:            public void setStereoEnable(boolean flag) {
3002:                stereoEnable = flag;
3003:                useStereo = stereoEnable && stereoAvailable;
3004:                synchronized (dirtyMaskLock) {
3005:                    cvDirtyMask[0] |= STEREO_DIRTY;
3006:                    cvDirtyMask[1] |= STEREO_DIRTY;
3007:                }
3008:                redraw();
3009:            }
3010:
3011:            /**
3012:             * Returns a status flag indicating whether or not stereo
3013:             * is enabled.
3014:             * @return a flag indicating whether stereo is enabled
3015:             */
3016:            public boolean getStereoEnable() {
3017:                return this .stereoEnable;
3018:            }
3019:
3020:            /**
3021:             * Specifies how Java 3D generates monoscopic view. If set to
3022:             * View.LEFT_EYE_VIEW, the view generated corresponds to the view as
3023:             * seen from the left eye. If set to View.RIGHT_EYE_VIEW, the view
3024:             * generated corresponds to the view as seen from the right
3025:             * eye. If set to View.CYCLOPEAN_EYE_VIEW, the view generated
3026:             * corresponds to the view as seen from the 'center eye', the
3027:             * fictional eye half-way between the left and right eye.  The
3028:             * default monoscopic view policy is View.CYCLOPEAN_EYE_VIEW.
3029:             * <p>
3030:             * NOTE: for backward compatibility with Java 3D 1.1, if this
3031:             * attribute is set to its default value of
3032:             * View.CYCLOPEAN_EYE_VIEW, the monoscopic view policy in the
3033:             * View object will be used.  An application should not use both
3034:             * the deprecated View method and this Canvas3D method at the same
3035:             * time.
3036:             * @param policy one of View.LEFT_EYE_VIEW, View.RIGHT_EYE_VIEW, or
3037:             * View.CYCLOPEAN_EYE_VIEW.
3038:             *
3039:             * @exception IllegalStateException if the specified
3040:             * policy is CYCLOPEAN_EYE_VIEW, the canvas is a stereo canvas,
3041:             * and the viewPolicy for the associated view is HMD_VIEW
3042:             *
3043:             * @since Java 3D 1.2
3044:             */
3045:            public void setMonoscopicViewPolicy(int policy) {
3046:
3047:                if ((view != null) && (view.viewPolicy == View.HMD_VIEW)
3048:                        && (monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW)
3049:                        && (!useStereo)) {
3050:                    throw new IllegalStateException(J3dI18N.getString("View31"));
3051:                }
3052:
3053:                monoscopicViewPolicy = policy;
3054:                synchronized (dirtyMaskLock) {
3055:                    cvDirtyMask[0] |= MONOSCOPIC_VIEW_POLICY_DIRTY;
3056:                    cvDirtyMask[1] |= MONOSCOPIC_VIEW_POLICY_DIRTY;
3057:                }
3058:                redraw();
3059:            }
3060:
3061:            /**
3062:             * Returns policy on how Java 3D generates monoscopic view.
3063:             * @return policy one of View.LEFT_EYE_VIEW, View.RIGHT_EYE_VIEW or
3064:             * View.CYCLOPEAN_EYE_VIEW.
3065:             *
3066:             * @since Java 3D 1.2
3067:             */
3068:            public int getMonoscopicViewPolicy() {
3069:                return this .monoscopicViewPolicy;
3070:            }
3071:
3072:            /**
3073:             * Returns a status flag indicating whether or not double
3074:             * buffering is available.
3075:             * This is equivalent to:
3076:             * <ul>
3077:             * <code>
3078:             * ((Boolean)queryProperties().
3079:             * get("doubleBufferAvailable")).
3080:             * booleanValue()
3081:             * </code>
3082:             * </ul>
3083:             *
3084:             * @return a flag indicating whether double buffering is available.
3085:             */
3086:            public boolean getDoubleBufferAvailable() {
3087:                return ((Boolean) queryProperties()
3088:                        .get("doubleBufferAvailable")).booleanValue();
3089:            }
3090:
3091:            /**
3092:             * Turns double buffering on or off.  If double buffering
3093:             * is off, all drawing is to the front buffer and no buffer swap
3094:             * is done between frames. It should be stressed that running
3095:             * Java 3D with double buffering disabled is not recommended.
3096:             * Enabling double buffering on a Canvas3D
3097:             * that does not support double buffering has no effect.
3098:             *
3099:             * @param flag enables or disables double buffering.
3100:             *
3101:             * @see #queryProperties
3102:             */
3103:            public void setDoubleBufferEnable(boolean flag) {
3104:                doubleBufferEnable = flag;
3105:                useDoubleBuffer = doubleBufferEnable && doubleBufferAvailable;
3106:                if (Thread.currentThread() == screen.renderer) {
3107:                    setRenderMode(ctx, FIELD_ALL, useDoubleBuffer);
3108:                }
3109:                redraw();
3110:            }
3111:
3112:            /**
3113:             * Returns a status flag indicating whether or not double
3114:             * buffering is enabled.
3115:             * @return a flag indicating if double buffering is enabled.
3116:             */
3117:            public boolean getDoubleBufferEnable() {
3118:                return doubleBufferEnable;
3119:            }
3120:
3121:            /**
3122:             * Returns a status flag indicating whether or not scene
3123:             * antialiasing is available.
3124:             * This is equivalent to:
3125:             * <ul>
3126:             * <code>
3127:             * ((Boolean)queryProperties().
3128:             * get("sceneAntialiasingAvailable")).
3129:             * booleanValue()
3130:             * </code>
3131:             * </ul>
3132:             *
3133:             * @return a flag indicating whether scene antialiasing is available.
3134:             */
3135:            public boolean getSceneAntialiasingAvailable() {
3136:                return ((Boolean) queryProperties().get(
3137:                        "sceneAntialiasingAvailable")).booleanValue();
3138:            }
3139:
3140:            /**
3141:             * Returns a flag indicating whether or not the specified shading
3142:             * language is supported. A ShaderError will be generated if an
3143:             * unsupported shading language is used.
3144:             *
3145:             * @param shadingLanguage the shading language being queried, one of:
3146:             * <code>Shader.SHADING_LANGUAGE_GLSL</code> or
3147:             * <code>Shader.SHADING_LANGUAGE_CG</code>.
3148:             *
3149:             * @return true if the specified shading language is supported,
3150:             * false otherwise.
3151:             *
3152:             * @since Java 3D 1.4
3153:             */
3154:            public boolean isShadingLanguageSupported(int shadingLanguage) {
3155:                // Call queryProperties to ensure that the shading language flags are valid
3156:                queryProperties();
3157:
3158:                // Return flag for specified shading language
3159:                switch (shadingLanguage) {
3160:                case Shader.SHADING_LANGUAGE_GLSL:
3161:                    return shadingLanguageGLSL;
3162:                case Shader.SHADING_LANGUAGE_CG:
3163:                    return shadingLanguageCg;
3164:                }
3165:
3166:                return false;
3167:            }
3168:
3169:            /**
3170:             * Returns a read-only Map object containing key-value pairs that define
3171:             * various properties for this Canvas3D.  All of the keys are
3172:             * String objects.  The values are key-specific, but most will be
3173:             * Boolean, Integer, Float, Double, or String objects.
3174:             *
3175:             * <p>
3176:             * The currently defined keys are:
3177:             *
3178:             * <p>
3179:             * <ul>
3180:             * <table BORDER=1 CELLSPACING=1 CELLPADDING=1>
3181:             * <tr>
3182:             * <td><b>Key (String)</b></td>
3183:             * <td><b>Value Type</b></td>
3184:             * </tr>
3185:             * <tr>
3186:             * <td><code>shadingLanguageCg</code></td>
3187:             * <td>Boolean</td>
3188:             * </tr>
3189:             * <tr>
3190:             * <td><code>shadingLanguageGLSL</code></td>
3191:             * <td>Boolean</td>
3192:             * </tr>
3193:             * <tr>
3194:             * <td><code>doubleBufferAvailable</code></td>
3195:             * <td>Boolean</td>
3196:             * </tr>
3197:             * <tr>
3198:             * <td><code>stereoAvailable</code></td>
3199:             * <td>Boolean</td>
3200:             * </tr>
3201:             * <tr>
3202:             * <td><code>sceneAntialiasingAvailable</code></td>
3203:             * <td>Boolean</td>
3204:             * </tr>
3205:             * <tr>
3206:             * <td><code>sceneAntialiasingNumPasses</code></td>
3207:             * <td>Integer</td>
3208:             * </tr>
3209:             * <tr>
3210:             * <td><code>stencilSize</code></td>
3211:             * <td>Integer</td>
3212:             * </tr>
3213:             * <tr>
3214:             * <td><code>texture3DAvailable</code></td>
3215:             * <td>Boolean</td>
3216:             * </tr>
3217:             * <tr>
3218:             * <td><code>textureColorTableSize</code></td>
3219:             * <td>Integer</td>
3220:             * </tr>
3221:             * <tr>
3222:             * <td><code>textureLodRangeAvailable</code></td>
3223:             * <td>Boolean</td>
3224:             * </tr>
3225:             * <tr>
3226:             * <td><code>textureLodOffsetAvailable</code></td>
3227:             * <td>Boolean</td>
3228:             * </tr>
3229:             * <tr>
3230:             * <td><code>textureWidthMax</code></td>
3231:             * <td>Integer</td>
3232:             * </tr>
3233:             * <tr>
3234:             * <td><code>textureHeightMax</code></td>
3235:             * <td>Integer</td>
3236:             * </tr>
3237:             * <tr>
3238:             * <td><code>textureBoundaryWidthMax</code></td>
3239:             * <td>Integer</td>
3240:             * </tr>
3241:             * <tr>
3242:             * <td><code>textureEnvCombineAvailable</code></td>
3243:             * <td>Boolean</td>
3244:             * </tr>
3245:             * <tr>
3246:             * <td><code>textureCombineDot3Available</code></td>
3247:             * <td>Boolean</td>
3248:             * </tr>
3249:             * <tr>
3250:             * <td><code>textureCombineSubtractAvailable</code></td>
3251:             * <td>Boolean</td>
3252:             * </tr>
3253:             * <tr>
3254:             * <td><code>textureCoordSetsMax</code></td>
3255:             * <td>Integer</td>
3256:             * </tr>
3257:             * <tr>
3258:             * <td><code>textureUnitStateMax</code></td>
3259:             * <td>Integer</td>
3260:             * </tr>
3261:             * <tr>
3262:             * <td><code>textureImageUnitsMax</code></td>
3263:             * <td>Integer</td>
3264:             * </tr>
3265:             * <tr>
3266:             * <td><code>textureImageUnitsVertexMax</code></td>
3267:             * <td>Integer</td>
3268:             * </tr>
3269:             * <tr>
3270:             * <td><code>textureImageUnitsCombinedMax</code></td>
3271:             * <td>Integer</td>
3272:             * </tr>
3273:             * <tr>
3274:             * <td><code>textureCubeMapAvailable</code></td>
3275:             * <td>Boolean</td>
3276:             * </tr>
3277:             * <tr>
3278:             * <td><code>textureDetailAvailable</code></td>
3279:             * <td>Boolean</td>
3280:             * </tr>
3281:             * <tr>
3282:             * <td><code>textureSharpenAvailable</code></td>
3283:             * <td>Boolean</td>
3284:             * </tr>
3285:             * <tr>
3286:             * <td><code>textureFilter4Available</code></td>
3287:             * <td>Boolean</td>
3288:             * </tr>
3289:             * <tr>
3290:             * <td><code>textureAnisotropicFilterDegreeMax</code></td>
3291:             * <td>Float</td>
3292:             * </tr>
3293:             * <tr>
3294:             * <td><code>textureNonPowerOfTwoAvailable</code></td>
3295:             * <td>Boolean</td>
3296:             * </tr>
3297:             * <tr>
3298:             * <td><code>vertexAttrsMax</code></td>
3299:             * <td>Integer</td>
3300:             * </tr>
3301:             * <tr>
3302:             * <td><code>compressedGeometry.majorVersionNumber</code></td>
3303:             * <td>Integer</td>
3304:             * </tr>
3305:             * <tr>
3306:             * <td><code>compressedGeometry.minorVersionNumber</code></td>
3307:             * <td>Integer</td>
3308:             * </tr>
3309:             * <tr>
3310:             * <td><code>compressedGeometry.minorMinorVersionNumber</code></td>
3311:             * <td>Integer</td>
3312:             * </tr>
3313:             * <tr>
3314:             * <td><code>native.version</code></td>
3315:             * <td>String</td>
3316:             * </tr>
3317:             * </table>
3318:             * </ul>
3319:             *
3320:             * <p>
3321:             * The descriptions of the values returned for each key are as follows:
3322:             *
3323:             * <p>
3324:             * <ul>
3325:             * <li>
3326:             * <code>shadingLanguageCg</code>
3327:             * <ul>
3328:             * A Boolean indicating whether or not Cg shading Language
3329:             * is available for this Canvas3D. 
3330:             * </ul>
3331:             * </li>
3332:             *
3333:             * <li>
3334:             * <code>shadingLanguageGLSL</code>
3335:             * <ul>
3336:             * A Boolean indicating whether or not GLSL shading Language
3337:             * is available for this Canvas3D.     
3338:             * </ul>
3339:             * </li>
3340:             *
3341:             * <li>
3342:             * <code>doubleBufferAvailable</code>
3343:             * <ul>
3344:             * A Boolean indicating whether or not double buffering
3345:             * is available for this Canvas3D.  This is equivalent to
3346:             * the getDoubleBufferAvailable method.  If this flag is false,
3347:             * the Canvas3D will be rendered in single buffer mode; requests
3348:             * to enable double buffering will be ignored.
3349:             * </ul>
3350:             * </li>
3351:             *
3352:             * <li>
3353:             * <code>stereoAvailable</code>
3354:             * <ul>
3355:             * A Boolean indicating whether or not stereo
3356:             * is available for this Canvas3D.  This is equivalent to
3357:             * the getStereoAvailable method.  If this flag is false,
3358:             * the Canvas3D will be rendered in monoscopic mode; requests
3359:             * to enable stereo will be ignored.
3360:             * </ul>
3361:             * </li>
3362:             *
3363:             * <li>
3364:             * <code>sceneAntialiasingAvailable</code>
3365:             * <ul>
3366:             * A Boolean indicating whether or not scene antialiasing
3367:             * is available for this Canvas3D.  This is equivalent to
3368:             * the getSceneAntialiasingAvailable method.  If this flag is false,
3369:             * requests to enable scene antialiasing will be ignored.
3370:             * </ul>
3371:             * </li>
3372:             *
3373:             * <li>
3374:             * <code>sceneAntialiasingNumPasses</code>
3375:             * <ul>
3376:             * An Integer indicating the number of passes scene antialiasing
3377:             * requires to render a single frame for this Canvas3D.  
3378:             * If this value is zero, scene antialiasing is not supported.  
3379:             * If this value is one, multisampling antialiasing is used.
3380:             * Otherwise, the number indicates the number of rendering passes
3381:             * needed. 
3382:             * </ul>
3383:             * </li>
3384:             *
3385:             * <li>
3386:             * <code>stencilSize</code>
3387:             * <ul>
3388:             * An Integer indicating the number of stencil bits that are available
3389:             * for this Canvas3D. 
3390:             * </ul>
3391:             * </li>
3392:             *
3393:             * <li>
3394:             * <code>texture3DAvailable</code>
3395:             * <ul>
3396:             * A Boolean indicating whether or not 3D Texture mapping
3397:             * is available for this Canvas3D.  If this flag is false,
3398:             * 3D texture mapping is either not supported by the underlying
3399:             * rendering layer or is otherwise unavailable for this
3400:             * particular Canvas3D.  All use of 3D texture mapping will be
3401:             * ignored in this case.
3402:             * </ul>
3403:             * </li>
3404:             *
3405:             * <li>
3406:             * <code>textureColorTableSize</code>
3407:             * <ul>
3408:             * An Integer indicating the maximum size of the texture color
3409:             * table for this Canvas3D.  If the size is 0, the texture
3410:             * color table is either not supported by the underlying rendering
3411:             * layer or is otherwise unavailable for this particular
3412:             * Canvas3D.  An attempt to use a texture color table larger than
3413:             * textureColorTableSize will be ignored; no color lookup will be
3414:             * performed.
3415:             * </ul>
3416:             * </li>
3417:             *
3418:             * <li>
3419:             * <code>textureLodRangeAvailable</code>
3420:             * <ul>
3421:             * A Boolean indicating whether or not setting only a subset of mipmap
3422:             * levels and setting a range of texture LOD are available for this 
3423:             * Canvas3D. 
3424:             * If it indicates false, setting a subset of mipmap levels and
3425:             * setting a texture LOD range are not supported by the underlying 
3426:             * rendering layer, and an attempt to set base level, or maximum level,
3427:             * or minimum LOD, or maximum LOD will be ignored. In this case,
3428:             * images for all mipmap levels must be defined for the texture to be
3429:             * valid.
3430:             * </ul>
3431:             * </li>
3432:             *
3433:             * <li>
3434:             * <code>textureLodOffsetAvailable</code>
3435:             * <ul>
3436:             * A Boolean indicating whether or not setting texture LOD offset is
3437:             * available for this Canvas3D. If it indicates false, setting
3438:             * texture LOD offset is not supported by the underlying rendering 
3439:             * layer, and an attempt to set the texture LOD offset will be ignored.
3440:             * </ul>
3441:             * </li>
3442:             *
3443:             * <li>
3444:             * <code>textureWidthMax</code>
3445:             * <ul>
3446:             * An Integer indicating the maximum texture width supported by
3447:             * this Canvas3D. If the width of a texture exceeds the maximum texture
3448:             * width for a Canvas3D, then the texture will be effectively disabled
3449:             * for that Canvas3D. 
3450:             * </ul>
3451:             * </li>
3452:             *
3453:             * <li>
3454:             * <code>textureHeightMax</code>
3455:             * <ul>
3456:             * An Integer indicating the maximum texture height supported by
3457:             * this Canvas3D. If the height of a texture exceeds the maximum texture
3458:             * height for a Canvas3D, then the texture will be effectively disabled
3459:             * for that Canvas3D.
3460:             * </ul>
3461:             * </li>
3462:             *
3463:             * <li>
3464:             * <code>textureBoundaryWidthMax</code>
3465:             * <ul>
3466:             * An Integer indicating the maximum texture boundary width
3467:             * supported by the underlying rendering layer for this Canvas3D. If 
3468:             * the maximum supported texture boundary width is 0, then texture
3469:             * boundary is not supported by the underlying rendering layer.
3470:             * An attempt to specify a texture boundary width > the 
3471:             * textureBoundaryWidthMax will effectively disable the texture.
3472:             * </ul>
3473:             * </li>
3474:             *
3475:             * <li>
3476:             * <code>textureEnvCombineAvailable</code>
3477:             * <ul>
3478:             * A Boolean indicating whether or not texture environment combine
3479:             * operation is supported for this Canvas3D. If it indicates false,
3480:             * then texture environment combine is not supported by the
3481:             * underlying rendering layer, and an attempt to specify COMBINE
3482:             * as the texture mode will be ignored. The texture mode in effect
3483:             * will be REPLACE.
3484:             * </ul>
3485:             * </li>
3486:             *
3487:             * <li>
3488:             * <code>textureCombineDot3Available</code>
3489:             * <ul>
3490:             * A Boolean indicating whether or not texture combine mode 
3491:             * COMBINE_DOT3 is
3492:             * supported for this Canvas3D. If it indicates false, then
3493:             * texture combine mode COMBINE_DOT3 is not supported by
3494:             * the underlying rendering layer, and an attempt to specify
3495:             * COMBINE_DOT3 as the texture combine mode will be ignored.
3496:             * The texture combine mode in effect will be COMBINE_REPLACE.
3497:             * </ul>
3498:             * </li>
3499:             *
3500:             * <li>
3501:             * <code>textureCombineSubtractAvailable</code>
3502:             * <ul>
3503:             * A Boolean indicating whether or not texture combine mode 
3504:             * COMBINE_SUBTRACT is
3505:             * supported for this Canvas3D. If it indicates false, then
3506:             * texture combine mode COMBINE_SUBTRACT is not supported by
3507:             * the underlying rendering layer, and an attempt to specify
3508:             * COMBINE_SUBTRACT as the texture combine mode will be ignored.
3509:             * The texture combine mode in effect will be COMBINE_REPLACE.
3510:             * </ul>
3511:             * </li>
3512:             *
3513:             * <li>
3514:             * <code>textureCoordSetsMax</code>
3515:             * <ul>
3516:             * An Integer indicating the maximum number of texture coordinate sets
3517:             * supported by the underlying rendering layer.
3518:             * </ul>
3519:             * </li>
3520:             *
3521:             * <li>
3522:             * <code>textureUnitStateMax</code>
3523:             * <ul>
3524:             * An Integer indicating the maximum number of fixed-function texture units
3525:             * supported by the underlying rendering layer. If the number of
3526:             * application-sepcified texture unit states exceeds the maximum number
3527:             * for a Canvas3D, and the fixed-function rendering pipeline is used, then
3528:             * the texture will be effectively disabled for that Canvas3D.
3529:             * </ul>
3530:             * </li>
3531:             *
3532:             * <li>
3533:             * <code>textureImageUnitsMax</code>
3534:             * <ul>
3535:             * An Integer indicating the maximum number of texture image units
3536:             * that can be accessed by the fragment shader when programmable shaders
3537:             * are used.
3538:             * </ul>
3539:             * </li>
3540:             *
3541:             * <li>
3542:             * <code>textureImageUnitsVertexMax</code>
3543:             * <ul>
3544:             * An Integer indicating the maximum number of texture image units
3545:             * that can be accessed by the vertex shader when programmable shaders
3546:             * are used.
3547:             * </ul>
3548:             * </li>
3549:             *
3550:             * <li>
3551:             * <code>textureImageUnitsCombinedMax</code>
3552:             * <ul>
3553:             * An Integer indicating the combined maximum number of texture image units
3554:             * that can be accessed by the vertex shader and the fragment shader when
3555:             * programmable shaders are used.
3556:             * </ul>
3557:             * </li>
3558:             *
3559:             * <li>
3560:             * <code>textureCubeMapAvailable</code>
3561:             * <ul>
3562:             * A Boolean indicating whether or not texture cube map is supported
3563:             * for this Canvas3D. If it indicates false, then texture cube map
3564:             * is not supported by the underlying rendering layer, and an attempt
3565:             * to specify NORMAL_MAP or REFLECTION_MAP as the texture generation
3566:             * mode will be ignored. The texture generation mode in effect will
3567:             * be SPHERE_MAP.
3568:             * </ul>
3569:             * </li>
3570:             *
3571:             * <li>
3572:             * <code>textureDetailAvailable</code>
3573:             * <ul>
3574:             * A Boolean indicating whether or not detail texture is supported
3575:             * for this Canvas3D. If it indicates false, then detail texture is
3576:             * not supported by the underlying rendering layer, and an attempt
3577:             * to specify LINEAR_DETAIL, LINEAR_DETAIL_ALPHA or
3578:             * LINEAR_DETAIL_RGB as the texture magnification filter mode will
3579:             * be ignored. The texture magnification filter mode in effect will
3580:             * be BASE_LEVEL_LINEAR.
3581:             * As of Java 3D 1.5, this property is always false.
3582:             * </ul>
3583:             * </li>
3584:             *
3585:             * <li>
3586:             * <code>textureSharpenAvailable</code>
3587:             * <ul>
3588:             * A Boolean indicating whether or not sharpen texture is supported
3589:             * for this Canvas3D. If it indicates false, then sharpen texture
3590:             * is not supported by the underlying rendering layer, and an attempt
3591:             * to specify LINEAR_SHARPEN, LINEAR_SHARPEN_ALPHA or
3592:             * LINEAR_SHARPEN_RGB as the texture magnification filter mode
3593:             * will be ignored. The texture magnification filter mode in effect
3594:             * will be BASE_LEVEL_LINEAR.
3595:             * </ul>
3596:             * </li>
3597:             *
3598:             * <li>
3599:             * <code>textureFilter4Available</code>
3600:             * <ul>
3601:             * A Boolean indicating whether or not filter4 is supported for this
3602:             * Canvas3D. If it indicates flase, then filter4 is not supported
3603:             * by the underlying rendering layer, and an attempt to specify
3604:             * FILTER_4 as the texture minification filter mode or texture
3605:             * magnification filter mode will be ignored. The texture filter mode
3606:             * in effect will be BASE_LEVEL_LINEAR.
3607:             * </ul>
3608:             * </li>
3609:             *
3610:             * <li>
3611:             * <code>textureAnisotropicFilterDegreeMax</code>
3612:             * <ul>
3613:             * A Float indicating the maximum degree of anisotropic filter
3614:             * available for this Canvas3D. If it indicates 1.0, setting
3615:             * anisotropic filter is not supported by the underlying rendering
3616:             * layer, and an attempt to set anisotropic filter degree will be ignored.
3617:             * </ul>
3618:             * </li>
3619:
3620:             * <li>
3621:             * <code>textureNonPowerOfTwoAvailable</code>
3622:             * <ul>
3623:             * A Boolean indicating whether or not texture dimensions that are
3624:             * not powers of two are supported for
3625:             * for this Canvas3D. If it indicates false, then textures with
3626:             * non power of two sizes will be ignored. Set the property 
3627:             * j3d.textureEnforcePowerOfTwo to revert to the pre-1.5 behavior
3628:             * of throwing exceptions for non power of two textures.
3629:             * </ul>
3630:             * </li>
3631:             *
3632:             * <li>
3633:             * <code>vertexAttrsMax</code>
3634:             * <ul>
3635:             * An Integer indicating the maximum number of vertex attributes
3636:             * supported by the underlying rendering layer. This is in addition to
3637:             * the vertex coordinate (position), color, normal, and so forth.
3638:             * </ul>
3639:             * </li>
3640:             *
3641:             * <li>
3642:             * <code>compressedGeometry.majorVersionNumber</code><br>
3643:             * <code>compressedGeometry.minorVersionNumber</code><br>
3644:             * <code>compressedGeometry.minorMinorVersionNumber</code>
3645:             * <ul>
3646:             * Integers indicating the major, minor, and minor-minor
3647:             * version numbers, respectively, of the version of compressed
3648:             * geometry supported by this version of Java 3D.
3649:             * </ul>
3650:             * </li>
3651:             *
3652:             * <li>
3653:             * <code>native.version</code>
3654:             * <ul>
3655:             * A String indicating the version number of the native graphics
3656:             * library.  The format of this string is defined by the native
3657:             * library.
3658:             * </ul>
3659:             * </li>
3660:             * </ul>
3661:             *
3662:             * @return the properties of this Canavs3D
3663:             *
3664:             * @since Java 3D 1.2
3665:             */
3666:            public final Map queryProperties() {
3667:                if (queryProps == null) {
3668:                    boolean createDummyCtx = false;
3669:
3670:                    synchronized (VirtualUniverse.mc.contextCreationLock) {
3671:                        if (ctx == null) {
3672:                            createDummyCtx = true;
3673:                        }
3674:                    }
3675:
3676:                    if (createDummyCtx) {
3677:                        GraphicsConfigTemplate3D.setQueryProps(this );
3678:                    }
3679:
3680:                    //create query Properties
3681:                    createQueryProps();
3682:                }
3683:
3684:                if (fatalError) {
3685:                    throw new IllegalStateException(J3dI18N
3686:                            .getString("Canvas3D29"));
3687:                }
3688:
3689:                return queryProps;
3690:            }
3691:
3692:            void createQueryContext() {
3693:                // create a dummy context to query for support of certain
3694:                // extensions, the context will destroy immediately
3695:                // inside the native code after setting the various 
3696:                // fields in this object
3697:                createQueryContext(screen.display, drawable, fbConfig,
3698:                        offScreen, 1, 1,
3699:                        VirtualUniverse.mc.glslLibraryAvailable,
3700:                        VirtualUniverse.mc.cgLibraryAvailable);
3701:                // compute the max available texture units
3702:                maxAvailableTextureUnits = Math.max(maxTextureUnits,
3703:                        maxTextureImageUnits);
3704:            }
3705:
3706:            /**
3707:             * Creates the query properties for this Canvas.
3708:             */
3709:            private void createQueryProps() {
3710:                // Create lists of keys and values
3711:                ArrayList keys = new ArrayList();
3712:                ArrayList values = new ArrayList();
3713:                int pass = 0;
3714:
3715:                // properties not associated with graphics context
3716:                keys.add("doubleBufferAvailable");
3717:                values.add(new Boolean(doubleBufferAvailable));
3718:
3719:                keys.add("stereoAvailable");
3720:                values.add(new Boolean(stereoAvailable));
3721:
3722:                keys.add("sceneAntialiasingAvailable");
3723:                values.add(new Boolean(sceneAntialiasingAvailable));
3724:
3725:                keys.add("sceneAntialiasingNumPasses");
3726:
3727:                if (sceneAntialiasingAvailable) {
3728:                    pass = (sceneAntialiasingMultiSamplesAvailable ? 1
3729:                            : Renderer.NUM_ACCUMULATION_SAMPLES);
3730:                }
3731:                values.add(new Integer(pass));
3732:
3733:                keys.add("stencilSize");
3734:                // Return the actual stencil size if the user owns it, otherwise
3735:                // return 0
3736:                if (userStencilAvailable) {
3737:                    values.add(new Integer(actualStencilSize));
3738:                } else {
3739:                    values.add(new Integer(0));
3740:                }
3741:
3742:                keys.add("compressedGeometry.majorVersionNumber");
3743:                values
3744:                        .add(new Integer(
3745:                                GeometryDecompressor.majorVersionNumber));
3746:                keys.add("compressedGeometry.minorVersionNumber");
3747:                values
3748:                        .add(new Integer(
3749:                                GeometryDecompressor.minorVersionNumber));
3750:                keys.add("compressedGeometry.minorMinorVersionNumber");
3751:                values.add(new Integer(
3752:                        GeometryDecompressor.minorMinorVersionNumber));
3753:
3754:                // Properties associated with graphics context
3755:                keys.add("texture3DAvailable");
3756:                values.add(new Boolean(
3757:                        (textureExtendedFeatures & TEXTURE_3D) != 0));
3758:
3759:                keys.add("textureColorTableSize");
3760:                values.add(new Integer(textureColorTableSize));
3761:
3762:                keys.add("textureEnvCombineAvailable");
3763:                values.add(new Boolean(
3764:                        (textureExtendedFeatures & TEXTURE_COMBINE) != 0));
3765:
3766:                keys.add("textureCombineDot3Available");
3767:                values.add(new Boolean(
3768:                        (textureExtendedFeatures & TEXTURE_COMBINE_DOT3) != 0));
3769:
3770:                keys.add("textureCombineSubtractAvailable");
3771:                values
3772:                        .add(new Boolean(
3773:                                (textureExtendedFeatures & TEXTURE_COMBINE_SUBTRACT) != 0));
3774:
3775:                keys.add("textureCubeMapAvailable");
3776:                values.add(new Boolean(
3777:                        (textureExtendedFeatures & TEXTURE_CUBE_MAP) != 0));
3778:
3779:                keys.add("textureSharpenAvailable");
3780:                values.add(new Boolean(
3781:                        (textureExtendedFeatures & TEXTURE_SHARPEN) != 0));
3782:
3783:                keys.add("textureDetailAvailable");
3784:                values.add(new Boolean(
3785:                        (textureExtendedFeatures & TEXTURE_DETAIL) != 0));
3786:
3787:                keys.add("textureFilter4Available");
3788:                values.add(new Boolean(
3789:                        (textureExtendedFeatures & TEXTURE_FILTER4) != 0));
3790:
3791:                keys.add("textureAnisotropicFilterDegreeMax");
3792:                values.add(new Float(anisotropicDegreeMax));
3793:
3794:                keys.add("textureWidthMax");
3795:                values.add(new Integer(textureWidthMax));
3796:
3797:                keys.add("textureHeightMax");
3798:                values.add(new Integer(textureHeightMax));
3799:
3800:                keys.add("texture3DWidthMax");
3801:                values.add(new Integer(texture3DWidthMax));
3802:
3803:                keys.add("texture3DHeightMax");
3804:                values.add(new Integer(texture3DHeightMax));
3805:
3806:                keys.add("texture3DDepthMax");
3807:                values.add(new Integer(texture3DDepthMax));
3808:
3809:                keys.add("textureBoundaryWidthMax");
3810:                values.add(new Integer(textureBoundaryWidthMax));
3811:
3812:                keys.add("textureLodRangeAvailable");
3813:                values.add(new Boolean(
3814:                        (textureExtendedFeatures & TEXTURE_LOD_RANGE) != 0));
3815:
3816:                keys.add("textureLodOffsetAvailable");
3817:                values.add(new Boolean(
3818:                        (textureExtendedFeatures & TEXTURE_LOD_OFFSET) != 0));
3819:
3820:                keys.add("textureNonPowerOfTwoAvailable");
3821:                values
3822:                        .add(new Boolean(
3823:                                (textureExtendedFeatures & TEXTURE_NON_POWER_OF_TWO) != 0));
3824:
3825:                keys.add("textureAutoMipMapGenerationAvailable");
3826:                values
3827:                        .add(new Boolean(
3828:                                (textureExtendedFeatures & TEXTURE_AUTO_MIPMAP_GENERATION) != 0));
3829:
3830:                keys.add("textureCoordSetsMax");
3831:                values.add(new Integer(maxTexCoordSets));
3832:
3833:                keys.add("textureUnitStateMax");
3834:                values.add(new Integer(maxTextureUnits));
3835:
3836:                keys.add("textureImageUnitsMax");
3837:                values.add(new Integer(maxTextureImageUnits));
3838:
3839:                keys.add("textureImageUnitsVertexMax");
3840:                values.add(new Integer(maxVertexTextureImageUnits));
3841:
3842:                keys.add("textureImageUnitsCombinedMax");
3843:                values.add(new Integer(maxCombinedTextureImageUnits));
3844:
3845:                keys.add("vertexAttrsMax");
3846:                values.add(new Integer(maxVertexAttrs));
3847:
3848:                keys.add("shadingLanguageGLSL");
3849:                values.add(new Boolean(shadingLanguageGLSL));
3850:
3851:                keys.add("shadingLanguageCg");
3852:                values.add(new Boolean(shadingLanguageCg));
3853:
3854:                keys.add("native.version");
3855:                values.add(nativeGraphicsVersion);
3856:
3857:                keys.add("native.vendor");
3858:                values.add(nativeGraphicsVendor);
3859:
3860:                keys.add("native.renderer");
3861:                values.add(nativeGraphicsRenderer);
3862:
3863:                // Now Create read-only properties object
3864:                queryProps = new J3dQueryProps((String[]) keys
3865:                        .toArray(new String[0]), values.toArray());
3866:            }
3867:
3868:            /**
3869:             * Update the view cache associated with this canvas.
3870:             */
3871:            void updateViewCache(boolean flag, CanvasViewCache cvc,
3872:                    BoundingBox frustumBBox, boolean doInfinite) {
3873:
3874:                assert cvc == null;
3875:                synchronized (cvLock) {
3876:                    if (firstPaintCalled && (canvasViewCache != null)) {
3877:                        assert canvasViewCacheFrustum != null;
3878:                        // Issue 109 : choose the appropriate cvCache
3879:                        if (frustumBBox != null) {
3880:                            canvasViewCacheFrustum.snapshot(true);
3881:                            canvasViewCacheFrustum.computeDerivedData(flag,
3882:                                    null, frustumBBox, doInfinite);
3883:                        } else {
3884:                            canvasViewCache.snapshot(false);
3885:                            canvasViewCache.computeDerivedData(flag, null,
3886:                                    null, doInfinite);
3887:                        }
3888:                    }
3889:                }
3890:            }
3891:
3892:            /**
3893:             * Set depthBufferWriteEnableOverride flag
3894:             */
3895:            void setDepthBufferWriteEnableOverride(boolean flag) {
3896:                depthBufferWriteEnableOverride = flag;
3897:            }
3898:
3899:            /**
3900:             * Set depthBufferEnableOverride flag
3901:             */
3902:            void setDepthBufferEnableOverride(boolean flag) {
3903:                depthBufferEnableOverride = flag;
3904:            }
3905:
3906:            // Static initializer for Canvas3D class
3907:            static {
3908:                VirtualUniverse.loadLibraries();
3909:            }
3910:
3911:            void resetTexture(Context ctx, int texUnitIndex) {
3912:                // D3D also need to reset texture attributes 
3913:                this .resetTextureNative(ctx, texUnitIndex);
3914:
3915:                if (texUnitIndex < 0) {
3916:                    texUnitIndex = 0;
3917:                }
3918:                texUnitState[texUnitIndex].mirror = null;
3919:                texUnitState[texUnitIndex].texture = null;
3920:
3921:                if (VirtualUniverse.mc.isD3D()) {
3922:                    texUnitState[texUnitIndex].texAttrs = null;
3923:                    texUnitState[texUnitIndex].texGen = null;
3924:                }
3925:            }
3926:
3927:            // use by D3D only
3928:            void resetTextureBin() {
3929:                Object obj;
3930:                TextureRetained tex;
3931:
3932:                // We don't use rdr.objectId for background texture in D3D
3933:                // so there is no need to handle rdr.objectId
3934:                if ((graphics2D != null) && (graphics2D.objectId != -1)) {
3935:                    VirtualUniverse.mc.freeTexture2DId(graphics2D.objectId);
3936:                    // let J3DGraphics2DImpl to initialize texture again
3937:                    graphics2D.objectId = -1;
3938:                }
3939:
3940:                for (int id = textureIDResourceTable.size() - 1; id >= 0; id--) {
3941:                    obj = textureIDResourceTable.get(id);
3942:                    if (obj != null) {
3943:                        if (obj instanceof  TextureRetained) {
3944:                            tex = (TextureRetained) obj;
3945:                            tex.resourceCreationMask &= ~canvasBit;
3946:                        }
3947:                    }
3948:                }
3949:            }
3950:
3951:            void d3dResize() {
3952:                assert VirtualUniverse.mc.isD3D();
3953:                int status = resizeD3DCanvas(ctx);
3954:
3955:                antialiasingSet = false;
3956:
3957:                // We need to reevaluate everything since d3d may create
3958:                // a new ctx 
3959:                if (status != NOCHANGE) {
3960:                    resetRendering(status);
3961:                }
3962:            }
3963:
3964:            void d3dToggle() {
3965:                assert VirtualUniverse.mc.isD3D();
3966:                int status = toggleFullScreenMode(ctx);
3967:
3968:                antialiasingSet = false;
3969:                if (status != NOCHANGE) {
3970:                    resetRendering(status);
3971:                }
3972:            }
3973:
3974:            // use by D3D only
3975:            void notifyD3DPeer(int cmd) {
3976:                assert VirtualUniverse.mc.isD3D();
3977:                if (active) {
3978:                    if (isRunning) {
3979:                        if ((view != null) && (view.active) &&
3980:                        // it is possible that view is set active by MC
3981:                                // but renderer not yet set 
3982:                                (screen.renderer != null)) {
3983:                            VirtualUniverse.mc.postRequest(
3984:                                    MasterControl.STOP_RENDERER, this );
3985:
3986:                            while (isRunningStatus) {
3987:                                MasterControl.threadYield();
3988:                            }
3989:                            J3dMessage renderMessage = new J3dMessage();
3990:                            renderMessage.threads = J3dThread.RENDER_THREAD;
3991:                            if (cmd == RESIZE) {
3992:                                renderMessage.type = J3dMessage.RESIZE_CANVAS;
3993:                            } else {
3994:                                renderMessage.type = J3dMessage.TOGGLE_CANVAS;
3995:                            }
3996:                            renderMessage.universe = null;
3997:                            renderMessage.view = null;
3998:                            renderMessage.args[0] = this ;
3999:
4000:                            screen.renderer.rendererStructure
4001:                                    .addMessage(renderMessage);
4002:                            VirtualUniverse.mc.postRequest(
4003:                                    MasterControl.START_RENDERER, this );
4004:                            VirtualUniverse.mc.sendRunMessage(view,
4005:                                    J3dThread.RENDER_THREAD);
4006:                        }
4007:                    } else {
4008:                        // may be in immediate mode
4009:                        reEvaluateCanvasCmd = cmd;
4010:                    }
4011:                }
4012:            }
4013:
4014:            // reset all attributes so that everything e.g. display list,
4015:            // texture will recreate again in the next frame
4016:            void resetRendering(int status) {
4017:
4018:                if (status == RECREATEDDRAW) {
4019:                    // D3D use MANAGE_POOL when createTexture, so there
4020:                    // is no need to download texture again in case of RESETSURFACE
4021:                    resetTextureBin();
4022:                    screen.renderer.needToResendTextureDown = true;
4023:                }
4024:
4025:                reset();
4026:
4027:                synchronized (dirtyMaskLock) {
4028:                    cvDirtyMask[0] |= VIEW_INFO_DIRTY;
4029:                    cvDirtyMask[1] |= VIEW_INFO_DIRTY;
4030:                }
4031:
4032:            }
4033:
4034:            void reset() {
4035:                int i;
4036:                currentAppear = new AppearanceRetained();
4037:                currentMaterial = new MaterialRetained();
4038:                viewFrustum = new CachedFrustum();
4039:                canvasDirty = 0xffff;
4040:                lightBin = null;
4041:                environmentSet = null;
4042:                attributeBin = null;
4043:                shaderBin = null;
4044:                textureBin = null;
4045:                renderMolecule = null;
4046:                polygonAttributes = null;
4047:                lineAttributes = null;
4048:                pointAttributes = null;
4049:                material = null;
4050:                enableLighting = false;
4051:                transparency = null;
4052:                coloringAttributes = null;
4053:                shaderProgram = null;
4054:                texture = null;
4055:                texAttrs = null;
4056:                if (texUnitState != null) {
4057:                    TextureUnitStateRetained tus;
4058:                    for (i = 0; i < texUnitState.length; i++) {
4059:                        tus = texUnitState[i];
4060:                        if (tus != null) {
4061:                            tus.texAttrs = null;
4062:                            tus.texGen = null;
4063:                        }
4064:                    }
4065:                }
4066:                texCoordGeneration = null;
4067:                renderingAttrs = null;
4068:                appearance = null;
4069:                appHandle = null;
4070:                dirtyRenderMoleculeList.clear();
4071:                displayListResourceFreeList.clear();
4072:
4073:                dirtyDlistPerRinfoList.clear();
4074:                textureIdResourceFreeList.clear();
4075:
4076:                lightChanged = true;
4077:                modelMatrix = null;
4078:                modelClip = null;
4079:                fog = null;
4080:                texLinearMode = false;
4081:                sceneAmbient = new Color3f();
4082:
4083:                for (i = 0; i < frameCount.length; i++) {
4084:                    frameCount[i] = -1;
4085:                }
4086:
4087:                for (i = 0; i < lights.length; i++) {
4088:                    lights[i] = null;
4089:                }
4090:
4091:                if (currentLights != null) {
4092:                    for (i = 0; i < currentLights.length; i++) {
4093:                        currentLights[i] = null;
4094:                    }
4095:                }
4096:
4097:                enableMask = -1;
4098:                stateUpdateMask = 0;
4099:                depthBufferWriteEnableOverride = false;
4100:                depthBufferEnableOverride = false;
4101:                depthBufferWriteEnable = true;
4102:                vfPlanesValid = false;
4103:                lightChanged = false;
4104:
4105:                for (i = 0; i < curStateToUpdate.length; i++) {
4106:                    curStateToUpdate[i] = null;
4107:                }
4108:
4109:                // Issue 362 - need to reset display lists and ctxTimeStamp in this
4110:                // method, so that display lists  will be recreated when canvas is
4111:                // removed from a view and then added back into a view with another
4112:                // canvas
4113:                needToRebuildDisplayList = true;
4114:                ctxTimeStamp = VirtualUniverse.mc.getContextTimeStamp();
4115:            }
4116:
4117:            void resetImmediateRendering(int status) {
4118:                canvasDirty = 0xffff;
4119:                ra = null;
4120:
4121:                setSceneAmbient(ctx, 0.0f, 0.0f, 0.0f);
4122:                disableFog(ctx);
4123:                resetRenderingAttributes(ctx, false, false);
4124:
4125:                resetTexture(ctx, -1);
4126:                resetTexCoordGeneration(ctx);
4127:                resetTextureAttributes(ctx);
4128:                texUnitState[0].texAttrs = null;
4129:                texUnitState[0].texGen = null;
4130:
4131:                resetPolygonAttributes(ctx);
4132:                resetLineAttributes(ctx);
4133:                resetPointAttributes(ctx);
4134:                resetTransparency(ctx, RenderMolecule.SURFACE,
4135:                        PolygonAttributes.POLYGON_FILL, false, false);
4136:                resetColoringAttributes(ctx, 1.0f, 1.0f, 1.0f, 1.0f, false);
4137:                updateMaterial(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
4138:                resetRendering(NOCHANGE);
4139:                makeCtxCurrent();
4140:                synchronized (dirtyMaskLock) {
4141:                    cvDirtyMask[0] |= VIEW_INFO_DIRTY;
4142:                    cvDirtyMask[1] |= VIEW_INFO_DIRTY;
4143:                }
4144:                needToRebuildDisplayList = true;
4145:
4146:                ctxTimeStamp = VirtualUniverse.mc.getContextTimeStamp();
4147:                if (status == RECREATEDDRAW) {
4148:                    screen.renderer.needToResendTextureDown = true;
4149:                }
4150:            }
4151:
4152:            // overide Canvas.getSize()
4153:            public Dimension getSize() {
4154:                if (!fullScreenMode) {
4155:                    return super .getSize();
4156:                } else {
4157:                    return new Dimension(fullscreenWidth, fullscreenHeight);
4158:                }
4159:            }
4160:
4161:            public Dimension getSize(Dimension rv) {
4162:                if (!fullScreenMode) {
4163:                    return super .getSize(rv);
4164:                } else {
4165:                    if (rv == null) {
4166:                        return new Dimension(fullscreenWidth, fullscreenHeight);
4167:                    } else {
4168:                        rv.setSize(fullscreenWidth, fullscreenHeight);
4169:                        return rv;
4170:                    }
4171:                }
4172:            }
4173:
4174:            public Point getLocationOnScreen() {
4175:                if (!fullScreenMode) {
4176:                    try {
4177:                        return super .getLocationOnScreen();
4178:                    } catch (IllegalComponentStateException e) {
4179:                    }
4180:                }
4181:                return new Point();
4182:            }
4183:
4184:            public int getX() {
4185:                if (!fullScreenMode) {
4186:                    return super .getX();
4187:                } else {
4188:                    return 0;
4189:                }
4190:            }
4191:
4192:            public int getY() {
4193:                if (!fullScreenMode) {
4194:                    return super .getY();
4195:                } else {
4196:                    return 0;
4197:                }
4198:            }
4199:
4200:            public int getWidth() {
4201:                if (!fullScreenMode) {
4202:                    return super .getWidth();
4203:                } else {
4204:                    return screen.screenSize.width;
4205:                }
4206:            }
4207:
4208:            public int getHeight() {
4209:                if (!fullScreenMode) {
4210:                    return super .getHeight();
4211:                } else {
4212:                    return screen.screenSize.height;
4213:                }
4214:            }
4215:
4216:            public Point getLocation(Point rv) {
4217:                if (!fullScreenMode) {
4218:                    return super .getLocation(rv);
4219:                } else {
4220:                    if (rv != null) {
4221:                        rv.setLocation(0, 0);
4222:                        return rv;
4223:                    } else {
4224:                        return new Point();
4225:                    }
4226:                }
4227:            }
4228:
4229:            public Point getLocation() {
4230:                if (!fullScreenMode) {
4231:                    return super .getLocation();
4232:                } else {
4233:                    return new Point();
4234:                }
4235:            }
4236:
4237:            public Rectangle getBounds() {
4238:                if (!fullScreenMode) {
4239:                    return super .getBounds();
4240:                } else {
4241:                    return new Rectangle(0, 0, screen.screenSize.width,
4242:                            screen.screenSize.height);
4243:                }
4244:            }
4245:
4246:            public Rectangle getBounds(Rectangle rv) {
4247:                if (!fullScreenMode) {
4248:                    return super .getBounds(rv);
4249:                } else {
4250:                    if (rv != null) {
4251:                        rv.setBounds(0, 0, screen.screenSize.width,
4252:                                screen.screenSize.height);
4253:                        return rv;
4254:                    } else {
4255:                        return new Rectangle(0, 0, screen.screenSize.width,
4256:                                screen.screenSize.height);
4257:                    }
4258:                }
4259:            }
4260:
4261:            void setProjectionMatrix(Context ctx, Transform3D projTrans) {
4262:                this .projTrans = projTrans;
4263:                setProjectionMatrix(ctx, projTrans.mat);
4264:            }
4265:
4266:            void setModelViewMatrix(Context ctx, double[] viewMatrix,
4267:                    Transform3D mTrans) {
4268:                setModelViewMatrix(ctx, viewMatrix, mTrans.mat);
4269:                if (!useStereo) {
4270:                    this .modelMatrix = mTrans;
4271:                } else {
4272:                    // TODO : This seems wrong to do only for the right eye.
4273:                    // A possible approach is to invalidate the cache at begin of 
4274:                    // each eye.            
4275:                    if (rightStereoPass) {
4276:                        //  Only set cache in right stereo pass, otherwise
4277:                        //  if the left stereo pass set the cache value, 
4278:                        //  setModelViewMatrix() in right stereo pass will not 
4279:                        //  perform in RenderMolecules.
4280:                        this .modelMatrix = mTrans;
4281:                    }
4282:                }
4283:            }
4284:
4285:            void setDepthBufferWriteEnable(boolean mode) {
4286:                depthBufferWriteEnable = mode;
4287:                setDepthBufferWriteEnable(ctx, mode);
4288:            }
4289:
4290:            void setNumActiveTexUnit(int n) {
4291:                numActiveTexUnit = n;
4292:            }
4293:
4294:            int getNumActiveTexUnit() {
4295:                return numActiveTexUnit;
4296:            }
4297:
4298:            void setLastActiveTexUnit(int n) {
4299:                lastActiveTexUnit = n;
4300:            }
4301:
4302:            int getLastActiveTexUnit() {
4303:                return lastActiveTexUnit;
4304:            }
4305:
4306:            // Create the texture state array
4307:            void createTexUnitState() {
4308:                texUnitState = new TextureUnitStateRetained[maxAvailableTextureUnits];
4309:                for (int t = 0; t < maxAvailableTextureUnits; t++) {
4310:                    texUnitState[t] = new TextureUnitStateRetained();
4311:                    texUnitState[t].texture = null;
4312:                    texUnitState[t].mirror = null;
4313:                }
4314:            }
4315:
4316:            boolean supportGlobalAlpha() {
4317:                return ((extensionsSupported & SUN_GLOBAL_ALPHA) != 0);
4318:            }
4319:
4320:            /**
4321:             * Enable separate specular color if it is not overriden by the
4322:             * property j3d.disableSeparateSpecular.
4323:             */
4324:            void enableSeparateSpecularColor() {
4325:                boolean enable = !VirtualUniverse.mc.disableSeparateSpecularColor;
4326:                updateSeparateSpecularColorEnable(ctx, enable);
4327:            }
4328:
4329:            final void beginScene() {
4330:                beginScene(ctx);
4331:            }
4332:
4333:            final void endScene() {
4334:                endScene(ctx);
4335:            }
4336:
4337:            // Send a createOffScreenBuffer message to Renderer (via
4338:            // MasterControl) and wait for it to be done
4339:            private void sendCreateOffScreenBuffer() {
4340:                // Wait for the buffer to be created unless called from
4341:                // a Behavior or from a Rendering thread
4342:                if (!(Thread.currentThread() instanceof  BehaviorScheduler)
4343:                        && !(Thread.currentThread() instanceof  Renderer)) {
4344:
4345:                    offScreenBufferPending = true;
4346:                }
4347:
4348:                // Send message to Renderer thread to perform createOffScreenBuffer.
4349:                VirtualUniverse.mc.sendCreateOffScreenBuffer(this );
4350:
4351:                // Wait for off-screen buffer to be created
4352:                while (offScreenBufferPending) {
4353:                    // Issue 364: create master control thread if needed
4354:                    VirtualUniverse.mc.createMasterControlThread();
4355:                    MasterControl.threadYield();
4356:                }
4357:            }
4358:
4359:            // Send a destroyOffScreenBuffer message to Renderer (via
4360:            // MasterControl) and wait for it to be done
4361:            private void sendDestroyCtxAndOffScreenBuffer() {
4362:                // Wait for the buffer to be destroyed unless called from
4363:                // a Behavior or from a Rendering thread
4364:                Thread currentThread = Thread.currentThread();
4365:                if (!(currentThread instanceof  BehaviorScheduler)
4366:                        && !(currentThread instanceof  Renderer)) {
4367:
4368:                    offScreenBufferPending = true;
4369:                }
4370:
4371:                // Fix for Issue 18 and Issue 175
4372:                // Send message to Renderer thread to perform remove Ctx and destroyOffScreenBuffer.
4373:
4374:                VirtualUniverse.mc.sendDestroyCtxAndOffScreenBuffer(this );
4375:
4376:                // Wait for ctx and off-screen buffer to be destroyed
4377:                while (offScreenBufferPending) {
4378:                    // Issue 364: create master control thread if needed
4379:                    VirtualUniverse.mc.createMasterControlThread();
4380:                    MasterControl.threadYield();
4381:                }
4382:            }
4383:
4384:            // Send a allocateCanvasId message to Renderer (via MasterControl) without
4385:            // waiting for it to be done
4386:            private void sendAllocateCanvasId() {
4387:                // Send message to Renderer thread to allocate a canvasId
4388:                VirtualUniverse.mc.sendAllocateCanvasId(this );
4389:            }
4390:
4391:            // Send a freeCanvasId message to Renderer (via MasterControl) without
4392:            // waiting for it to be done
4393:            private void sendFreeCanvasId() {
4394:                // Send message to Renderer thread to free the canvasId
4395:                VirtualUniverse.mc.sendFreeCanvasId(this );
4396:            }
4397:
4398:            private void removeCtx() {
4399:
4400:                if ((screen != null) && (screen.renderer != null)
4401:                        && (ctx != null)) {
4402:                    VirtualUniverse.mc.postRequest(MasterControl.FREE_CONTEXT,
4403:                            new Object[] { this , new Long(screen.display),
4404:                                    drawable, ctx });
4405:                    // Fix for Issue 19
4406:                    // Wait for the context to be freed unless called from
4407:                    // a Behavior or from a Rendering thread
4408:                    Thread currentThread = Thread.currentThread();
4409:                    if (!(currentThread instanceof  BehaviorScheduler)
4410:                            && !(currentThread instanceof  Renderer)) {
4411:                        while (ctxTimeStamp != 0) {
4412:                            MasterControl.threadYield();
4413:                        }
4414:                    }
4415:                    ctx = null;
4416:                }
4417:            }
4418:
4419:            /**
4420:             * Serialization of Canvas3D objects is not supported.
4421:             *
4422:             * @exception UnsupportedOperationException this method is not supported
4423:             *
4424:             * @since Java 3D 1.3
4425:             */
4426:            private void writeObject(java.io.ObjectOutputStream out)
4427:                    throws java.io.IOException {
4428:
4429:                throw new UnsupportedOperationException(J3dI18N
4430:                        .getString("Canvas3D20"));
4431:            }
4432:
4433:            /**
4434:             * Serialization of Canvas3D objects is not supported.
4435:             *
4436:             * @exception UnsupportedOperationException this method is not supported
4437:             *
4438:             * @since Java 3D 1.3
4439:             */
4440:            private void readObject(java.io.ObjectInputStream in)
4441:                    throws java.io.IOException, ClassNotFoundException {
4442:
4443:                throw new UnsupportedOperationException(J3dI18N
4444:                        .getString("Canvas3D20"));
4445:            }
4446:
4447:            // mark that the current bin specified by the bit is already updated
4448:            void setStateIsUpdated(int bit) {
4449:                stateUpdateMask &= ~(1 << bit);
4450:            }
4451:
4452:            // mark that the bin specified by the bit needs to be updated
4453:            void setStateToUpdate(int bit, Object bin) {
4454:                stateUpdateMask |= 1 << bit;
4455:                curStateToUpdate[bit] = bin;
4456:            }
4457:
4458:            // update LightBin, EnvironmentSet, AttributeBin & ShaderBin if neccessary
4459:            // according to the stateUpdateMask
4460:
4461:            static int ENV_STATE_MASK = (1 << LIGHTBIN_BIT)
4462:                    | (1 << ENVIRONMENTSET_BIT) | (1 << ATTRIBUTEBIN_BIT)
4463:                    | (1 << SHADERBIN_BIT);
4464:
4465:            void updateEnvState() {
4466:
4467:                if ((stateUpdateMask & ENV_STATE_MASK) == 0)
4468:                    return;
4469:
4470:                if ((stateUpdateMask & (1 << LIGHTBIN_BIT)) != 0) {
4471:                    ((LightBin) curStateToUpdate[LIGHTBIN_BIT])
4472:                            .updateAttributes(this );
4473:                }
4474:
4475:                if ((stateUpdateMask & (1 << ENVIRONMENTSET_BIT)) != 0) {
4476:                    ((EnvironmentSet) curStateToUpdate[ENVIRONMENTSET_BIT])
4477:                            .updateAttributes(this );
4478:                }
4479:
4480:                if ((stateUpdateMask & (1 << ATTRIBUTEBIN_BIT)) != 0) {
4481:                    ((AttributeBin) curStateToUpdate[ATTRIBUTEBIN_BIT])
4482:                            .updateAttributes(this );
4483:                }
4484:
4485:                if ((stateUpdateMask & (1 << SHADERBIN_BIT)) != 0) {
4486:                    ((ShaderBin) curStateToUpdate[SHADERBIN_BIT])
4487:                            .updateAttributes(this );
4488:                }
4489:
4490:                // reset the state update mask for those environment state bits
4491:                stateUpdateMask &= ~ENV_STATE_MASK;
4492:            }
4493:
4494:            /**
4495:             * update state if neccessary according to the stateUpdatedMask
4496:             */
4497:            void updateState(int dirtyBits) {
4498:
4499:                if (stateUpdateMask == 0)
4500:                    return;
4501:
4502:                updateEnvState();
4503:
4504:                if ((stateUpdateMask & (1 << TEXTUREBIN_BIT)) != 0) {
4505:                    ((TextureBin) curStateToUpdate[TEXTUREBIN_BIT])
4506:                            .updateAttributes(this );
4507:                }
4508:
4509:                if ((stateUpdateMask & (1 << RENDERMOLECULE_BIT)) != 0) {
4510:                    ((RenderMolecule) curStateToUpdate[RENDERMOLECULE_BIT])
4511:                            .updateAttributes(this , dirtyBits);
4512:
4513:                }
4514:
4515:                if ((stateUpdateMask & (1 << TRANSPARENCY_BIT)) != 0) {
4516:                    ((RenderMolecule) curStateToUpdate[RENDERMOLECULE_BIT])
4517:                            .updateTransparencyAttributes(this );
4518:                    stateUpdateMask &= ~(1 << TRANSPARENCY_BIT);
4519:                }
4520:
4521:                // reset state update mask 
4522:                stateUpdateMask = 0;
4523:            }
4524:
4525:            // This method updates this Texture2D for raster. 
4526:            // Note : No multi-texture is not used.
4527:            void updateTextureForRaster(Texture2DRetained texture) {
4528:
4529:                // Setup texture and texture attributes for texture unit 0.
4530:                Pipeline.getPipeline().updateTextureUnitState(ctx, 0, true);
4531:                setLastActiveTexUnit(0);
4532:                setNumActiveTexUnit(1);
4533:
4534:                texture.updateNative(this );
4535:                resetTextureAttributes(ctx);
4536:
4537:                for (int i = 1; i < maxTextureUnits; i++) {
4538:                    resetTexture(ctx, i);
4539:                }
4540:
4541:                // set the active texture unit back to 0
4542:                activeTextureUnit(ctx, 0);
4543:
4544:                // Force the next textureBin to reload.
4545:                canvasDirty |= Canvas3D.TEXTUREBIN_DIRTY
4546:                        | Canvas3D.TEXTUREATTRIBUTES_DIRTY;
4547:            }
4548:
4549:            void restoreTextureBin() {
4550:
4551:                // Need to check TextureBin's shaderBin for null
4552:                // TextureBin can get clear() if there isn't any RM under it.
4553:                if ((textureBin != null) && (textureBin.shaderBin != null)) {
4554:                    textureBin.updateAttributes(this );
4555:                }
4556:            }
4557:
4558:            void textureFill(RasterRetained raster, Point2d winCoord,
4559:                    float mapZ, float alpha) {
4560:
4561:                int winWidth = canvasViewCache.getCanvasWidth();
4562:                int winHeight = canvasViewCache.getCanvasHeight();
4563:
4564:                int rasterImageWidth = raster.image.width;
4565:                int rasterImageHeight = raster.image.height;
4566:
4567:                float texMinU = 0, texMinV = 0, texMaxU = 0, texMaxV = 0;
4568:                float mapMinX = 0, mapMinY = 0, mapMaxX = 0, mapMaxY = 0;
4569:
4570:                Point rasterSrcOffset = new Point();
4571:                raster.getSrcOffset(rasterSrcOffset);
4572:
4573:                Dimension rasterSize = new Dimension();
4574:                raster.getSize(rasterSize);
4575:
4576:                //        System.err.println("rasterImageWidth " + rasterImageWidth + " rasterImageHeight " + rasterImageHeight);
4577:                //        System.err.println("rasterSrcOffset " + rasterSrcOffset + " rasterSize " + rasterSize);
4578:
4579:                int rasterMinX = rasterSrcOffset.x;
4580:                int rasterMaxX = rasterSrcOffset.x + rasterSize.width;
4581:                int rasterMinY = rasterSrcOffset.y;
4582:                int rasterMaxY = rasterSrcOffset.y + rasterSize.height;
4583:
4584:                if ((rasterMinX >= rasterImageWidth)
4585:                        || (rasterMinY >= rasterImageHeight)
4586:                        || (rasterMaxX <= 0) || (rasterMaxY <= 0)) {
4587:                    return;
4588:                }
4589:
4590:                if (rasterMinX < 0) {
4591:                    rasterMinX = 0;
4592:                }
4593:                if (rasterMinY < 0) {
4594:                    rasterMinY = 0;
4595:                }
4596:
4597:                if (rasterMaxX > rasterImageWidth) {
4598:                    rasterMaxX = rasterImageWidth;
4599:                }
4600:
4601:                if (rasterMaxY > rasterImageHeight) {
4602:                    rasterMaxY = rasterImageHeight;
4603:                }
4604:
4605:                texMinU = (float) rasterMinX / (float) rasterImageWidth;
4606:                texMaxU = (float) rasterMaxX / (float) rasterImageWidth;
4607:                mapMinX = (float) winCoord.x / (float) winWidth;
4608:                mapMaxX = (float) (winCoord.x + (rasterMaxX - rasterMinX))
4609:                        / (float) winWidth;
4610:
4611:                if (raster.image.isYUp()) {
4612:                    texMinV = (float) rasterMinY / (float) rasterImageHeight;
4613:                    texMaxV = (float) rasterMaxY / (float) rasterImageHeight;
4614:                } else {
4615:                    //  System.err.println("In yUp is false case");
4616:                    texMinV = 1.0f - (float) rasterMaxY
4617:                            / (float) rasterImageHeight;
4618:                    texMaxV = 1.0f - (float) rasterMinY
4619:                            / (float) rasterImageHeight;
4620:                }
4621:
4622:                mapMinY = 1.0f - ((float) (winCoord.y + (rasterMaxY - rasterMinY)) / (float) winHeight);
4623:                mapMaxY = 1.0f - ((float) winCoord.y / (float) winHeight);
4624:
4625:                textureFillRaster(ctx, texMinU, texMaxU, texMinV, texMaxV,
4626:                        mapMinX, mapMaxX, mapMinY, mapMaxY, mapZ, alpha,
4627:                        raster.image.useBilinearFilter());
4628:
4629:            }
4630:
4631:            void textureFill(BackgroundRetained bg, int winWidth, int winHeight) {
4632:
4633:                final int maxX = bg.image.width;
4634:                final int maxY = bg.image.height;
4635:
4636:                //        System.err.println("maxX " + maxX + " maxY " + maxY);
4637:
4638:                float xzoom = (float) winWidth / maxX;
4639:                float yzoom = (float) winHeight / maxY;
4640:                float zoom = 0;
4641:                float texMinU = 0, texMinV = 0, texMaxU = 0, texMaxV = 0, adjustV = 0;
4642:                float mapMinX = 0, mapMinY = 0, mapMaxX = 0, mapMaxY = 0;
4643:                float halfWidth = 0, halfHeight = 0;
4644:
4645:                switch (bg.imageScaleMode) {
4646:                case Background.SCALE_NONE:
4647:                    texMinU = 0.0f;
4648:                    texMinV = 0.0f;
4649:                    texMaxU = 1.0f;
4650:                    texMaxV = 1.0f;
4651:                    halfWidth = (float) winWidth / 2.0f;
4652:                    halfHeight = (float) winHeight / 2.0f;
4653:                    mapMinX = (float) ((0 - halfWidth) / halfWidth);
4654:                    mapMinY = (float) ((0 - halfHeight) / halfHeight);
4655:                    mapMaxX = (float) ((maxX - halfWidth) / halfWidth);
4656:                    mapMaxY = (float) ((maxY - halfHeight) / halfHeight);
4657:                    adjustV = ((float) winHeight - (float) maxY) / halfHeight;
4658:                    mapMinY += adjustV;
4659:                    mapMaxY += adjustV;
4660:                    break;
4661:                case Background.SCALE_FIT_MIN:
4662:                    zoom = Math.min(xzoom, yzoom);
4663:                    texMinU = 0.0f;
4664:                    texMinV = 0.0f;
4665:                    texMaxU = 1.0f;
4666:                    texMaxV = 1.0f;
4667:                    mapMinX = -1.0f;
4668:                    mapMaxY = 1.0f;
4669:                    if (xzoom < yzoom) {
4670:                        mapMaxX = 1.0f;
4671:                        mapMinY = -1.0f
4672:                                + 2.0f
4673:                                * (1.0f - zoom * (float) maxY
4674:                                        / (float) winHeight);
4675:                    } else {
4676:                        mapMaxX = -1.0f + zoom * (float) maxX / winWidth * 2;
4677:                        mapMinY = -1.0f;
4678:                    }
4679:                    break;
4680:                case Background.SCALE_FIT_MAX:
4681:                    zoom = Math.max(xzoom, yzoom);
4682:                    mapMinX = -1.0f;
4683:                    mapMinY = -1.0f;
4684:                    mapMaxX = 1.0f;
4685:                    mapMaxY = 1.0f;
4686:                    if (xzoom < yzoom) {
4687:                        texMinU = 0.0f;
4688:                        texMinV = 0.0f;
4689:                        texMaxU = (float) winWidth / maxX / zoom;
4690:                        texMaxV = 1.0f;
4691:                    } else {
4692:                        texMinU = 0.0f;
4693:                        texMinV = 1.0f - (float) winHeight / maxY / zoom;
4694:                        texMaxU = 1.0f;
4695:                        texMaxV = 1.0f;
4696:                    }
4697:                    break;
4698:                case Background.SCALE_FIT_ALL:
4699:                    texMinU = 0.0f;
4700:                    texMinV = 0.0f;
4701:                    texMaxU = 1.0f;
4702:                    texMaxV = 1.0f;
4703:                    mapMinX = -1.0f;
4704:                    mapMinY = -1.0f;
4705:                    mapMaxX = 1.0f;
4706:                    mapMaxY = 1.0f;
4707:                    break;
4708:                case Background.SCALE_REPEAT:
4709:
4710:                    texMinU = 0.0f;
4711:                    texMinV = -yzoom;
4712:                    texMaxU = xzoom;
4713:                    texMaxV = 0.0f;
4714:                    mapMinX = -1.0f;
4715:                    mapMinY = -1.0f;
4716:                    mapMaxX = 1.0f;
4717:                    mapMaxY = 1.0f;
4718:                    break;
4719:                case Background.SCALE_NONE_CENTER:
4720:                    // TODO : Why is there a zoom ? 
4721:                    if (xzoom >= 1.0f) {
4722:                        texMinU = 0.0f;
4723:                        texMaxU = 1.0f;
4724:                        mapMinX = -(float) maxX / winWidth;
4725:                        mapMaxX = (float) maxX / winWidth;
4726:                    } else {
4727:                        texMinU = 0.5f - (float) winWidth / maxX / 2;
4728:                        texMaxU = 0.5f + (float) winWidth / maxX / 2;
4729:                        mapMinX = -1.0f;
4730:                        mapMaxX = 1.0f;
4731:                    }
4732:                    if (yzoom >= 1.0f) {
4733:                        texMinV = 0.0f;
4734:                        texMaxV = 1.0f;
4735:                        mapMinY = -(float) maxY / winHeight;
4736:                        mapMaxY = (float) maxY / winHeight;
4737:                    } else {
4738:                        texMinV = 0.5f - (float) winHeight / maxY / 2;
4739:                        texMaxV = 0.5f + (float) winHeight / maxY / 2;
4740:                        mapMinY = -1.0f;
4741:                        mapMaxY = 1.0f;
4742:                    }
4743:                    break;
4744:                }
4745:
4746:                //        System.err.println("Java 3D : mapMinX " + mapMinX + " mapMinY " + mapMinY + 
4747:                //                           " mapMaxX " + mapMaxX + " mapMaxY " + mapMaxY);
4748:                textureFillBackground(ctx, texMinU, texMaxU, texMinV, texMaxV,
4749:                        mapMinX, mapMaxX, mapMinY, mapMaxY, bg.image
4750:                                .useBilinearFilter());
4751:
4752:            }
4753:
4754:            void clear(BackgroundRetained bg, int winWidth, int winHeight) {
4755:
4756:                // Issue 239 - clear stencil if requested and available
4757:                // Note that this is a partial solution, since we eventually want an API
4758:                // to control this.
4759:                boolean clearStencil = VirtualUniverse.mc.stencilClear
4760:                        && userStencilAvailable;
4761:
4762:                clear(ctx, bg.color.x, bg.color.y, bg.color.z, clearStencil);
4763:
4764:                // TODO : This is a bug on not mirror bg. Will fix this as a bug after 1.5 beta.
4765:                // For now, as a workaround, we will check bg.image and bg.image.imageData not null.
4766:                if ((bg.image != null) && (bg.image.imageData != null)) {
4767:                    // setup Texture pipe.
4768:                    updateTextureForRaster(bg.texture);
4769:
4770:                    textureFill(bg, winWidth, winHeight);
4771:
4772:                    // Restore texture pipe.
4773:                    restoreTextureBin();
4774:                }
4775:            }
4776:
4777:            /**
4778:             * obj is either TextureRetained or DetailTextureImage 
4779:             * if obj is DetailTextureImage then we just clear
4780:             * the resourceCreationMask of all the formats 
4781:             * no matter it is create or not since we don't 
4782:             * remember the format information for simplicity.
4783:             * We don't need to check duplicate value of id in the
4784:             * table since this procedure is invoke only when id 
4785:             * of texture is -1 one time only.
4786:             * This is always call from Renderer thread.
4787:             */
4788:            void addTextureResource(int id, Object obj) {
4789:                if (id <= 0) {
4790:                    return;
4791:                }
4792:
4793:                if (useSharedCtx) {
4794:                    screen.renderer.addTextureResource(id, obj);
4795:                } else {
4796:                    // This will replace the previous key if exists
4797:                    if (textureIDResourceTable.size() <= id) {
4798:                        for (int i = textureIDResourceTable.size(); i < id; i++) {
4799:                            textureIDResourceTable.add(null);
4800:                        }
4801:                        textureIDResourceTable.add(obj);
4802:                    } else {
4803:                        textureIDResourceTable.set(id, obj);
4804:                    }
4805:
4806:                }
4807:            }
4808:
4809:            // handle free resource in the FreeList
4810:            void freeResourcesInFreeList(Context ctx) {
4811:                Iterator it;
4812:                ArrayList list;
4813:                int i, val;
4814:                GeometryArrayRetained geo;
4815:
4816:                // free resource for those canvases that
4817:                // don't use shared ctx
4818:                if (displayListResourceFreeList.size() > 0) {
4819:                    for (it = displayListResourceFreeList.iterator(); it
4820:                            .hasNext();) {
4821:                        val = ((Integer) it.next()).intValue();
4822:                        if (val <= 0) {
4823:                            continue;
4824:                        }
4825:                        freeDisplayList(ctx, val);
4826:                    }
4827:                    displayListResourceFreeList.clear();
4828:                }
4829:
4830:                if (textureIdResourceFreeList.size() > 0) {
4831:                    for (it = textureIdResourceFreeList.iterator(); it
4832:                            .hasNext();) {
4833:                        val = ((Integer) it.next()).intValue();
4834:                        if (val <= 0) {
4835:                            continue;
4836:                        }
4837:                        if (val >= textureIDResourceTable.size()) {
4838:                            System.err
4839:                                    .println("Error in freeResourcesInFreeList : ResourceIDTableSize = "
4840:                                            + textureIDResourceTable.size()
4841:                                            + " val = " + val);
4842:                        } else {
4843:                            Object obj = textureIDResourceTable.get(val);
4844:                            if (obj instanceof  TextureRetained) {
4845:                                TextureRetained tex = (TextureRetained) obj;
4846:                                synchronized (tex.resourceLock) {
4847:                                    tex.resourceCreationMask &= ~canvasBit;
4848:                                    if (tex.resourceCreationMask == 0) {
4849:                                        tex.freeTextureId(val);
4850:                                    }
4851:                                }
4852:                            }
4853:
4854:                            textureIDResourceTable.set(val, null);
4855:                        }
4856:                        freeTexture(ctx, val);
4857:                    }
4858:                    textureIdResourceFreeList.clear();
4859:                }
4860:            }
4861:
4862:            void freeContextResources(Renderer rdr, boolean freeBackground,
4863:                    Context ctx) {
4864:
4865:                Object obj;
4866:                TextureRetained tex;
4867:
4868:                // Just return if we don't have a valid renderer or context
4869:                if (rdr == null || ctx == null) {
4870:                    return;
4871:                }
4872:
4873:                if (freeBackground) {
4874:                    // Dispose of Graphics2D Texture
4875:                    if (graphics2D != null) {
4876:                        graphics2D.dispose();
4877:                    }
4878:                }
4879:
4880:                for (int id = textureIDResourceTable.size() - 1; id >= 0; id--) {
4881:                    obj = textureIDResourceTable.get(id);
4882:                    if (obj == null) {
4883:                        continue;
4884:                    }
4885:
4886:                    // Issue 403 : this assertion doesn't hold in some cases
4887:                    // TODO KCR : determine why this is the case
4888:                    //            assert id == ((TextureRetained)obj).objectId;
4889:
4890:                    freeTexture(ctx, id);
4891:                    if (obj instanceof  TextureRetained) {
4892:                        tex = (TextureRetained) obj;
4893:                        synchronized (tex.resourceLock) {
4894:                            tex.resourceCreationMask &= ~canvasBit;
4895:                            if (tex.resourceCreationMask == 0) {
4896:
4897:                                tex.freeTextureId(id);
4898:                            }
4899:                        }
4900:                    }
4901:                }
4902:                textureIDResourceTable.clear();
4903:
4904:                freeAllDisplayListResources(ctx);
4905:            }
4906:
4907:            void freeAllDisplayListResources(Context ctx) {
4908:                if ((view != null) && (view.renderBin != null)) {
4909:                    view.renderBin.freeAllDisplayListResources(this , ctx);
4910:                    if (useSharedCtx) {
4911:                        // We need to rebuild all other Canvas3D resource
4912:                        // shared by this Canvas3D. Since we didn't
4913:                        // remember resource in Renderer but RenderBin only.
4914:                        if ((screen != null) && (screen.renderer != null)) {
4915:                            screen.renderer.needToRebuildDisplayList = true;
4916:                        }
4917:                    }
4918:                }
4919:
4920:            }
4921:
4922:            // *****************************************************************
4923:            // Wrappers for native methods go below here
4924:            // *****************************************************************
4925:
4926:            // This is the native method for creating the underlying graphics context.
4927:            private Context createNewContext(long display, Drawable drawable,
4928:                    long fbConfig, Context shareCtx, boolean isSharedCtx,
4929:                    boolean offScreen, boolean glslLibraryAvailable,
4930:                    boolean cgLibraryAvailable) {
4931:                return Pipeline.getPipeline().createNewContext(this , display,
4932:                        drawable, fbConfig, shareCtx, isSharedCtx, offScreen,
4933:                        glslLibraryAvailable, cgLibraryAvailable);
4934:            }
4935:
4936:            private void createQueryContext(long display, Drawable drawable,
4937:                    long fbConfig, boolean offScreen, int width, int height,
4938:                    boolean glslLibraryAvailable, boolean cgLibraryAvailable) {
4939:                Pipeline.getPipeline().createQueryContext(this , display,
4940:                        drawable, fbConfig, offScreen, width, height,
4941:                        glslLibraryAvailable, cgLibraryAvailable);
4942:            }
4943:
4944:            // This is the native for creating offscreen buffer
4945:            Drawable createOffScreenBuffer(Context ctx, long display,
4946:                    long fbConfig, int width, int height) {
4947:                return Pipeline.getPipeline().createOffScreenBuffer(this , ctx,
4948:                        display, fbConfig, width, height);
4949:            }
4950:
4951:            void destroyOffScreenBuffer(Context ctx, long display,
4952:                    long fbConfig, Drawable drawable) {
4953:                assert drawable != null;
4954:                Pipeline.getPipeline().destroyOffScreenBuffer(this , ctx,
4955:                        display, fbConfig, drawable);
4956:            }
4957:
4958:            // This is the native for reading the image from the offscreen buffer
4959:            private void readOffScreenBuffer(Context ctx, int format, int type,
4960:                    Object data, int width, int height) {
4961:                Pipeline.getPipeline().readOffScreenBuffer(this , ctx, format,
4962:                        type, data, width, height);
4963:            }
4964:
4965:            // The native method for swapBuffers
4966:            int swapBuffers(Context ctx, long dpy, Drawable drawable) {
4967:                return Pipeline.getPipeline().swapBuffers(this , ctx, dpy,
4968:                        drawable);
4969:            }
4970:
4971:            // notify D3D that Canvas is resize
4972:            private int resizeD3DCanvas(Context ctx) {
4973:                return Pipeline.getPipeline().resizeD3DCanvas(this , ctx);
4974:            }
4975:
4976:            // notify D3D to toggle between FullScreen and window mode
4977:            private int toggleFullScreenMode(Context ctx) {
4978:                return Pipeline.getPipeline().toggleFullScreenMode(this , ctx);
4979:            }
4980:
4981:            // -----------------------------------------------------------------------------
4982:
4983:            // native method for setting Material when no material is present
4984:            void updateMaterial(Context ctx, float r, float g, float b, float a) {
4985:                Pipeline.getPipeline().updateMaterialColor(ctx, r, g, b, a);
4986:            }
4987:
4988:            static void destroyContext(long display, Drawable drawable,
4989:                    Context ctx) {
4990:                Pipeline.getPipeline().destroyContext(display, drawable, ctx);
4991:            }
4992:
4993:            // This is the native method for doing accumulation.
4994:            void accum(Context ctx, float value) {
4995:                Pipeline.getPipeline().accum(ctx, value);
4996:            }
4997:
4998:            // This is the native method for doing accumulation return.
4999:            void accumReturn(Context ctx) {
5000:                Pipeline.getPipeline().accumReturn(ctx);
5001:            }
5002:
5003:            // This is the native method for clearing the accumulation buffer.
5004:            void clearAccum(Context ctx) {
5005:                Pipeline.getPipeline().clearAccum(ctx);
5006:            }
5007:
5008:            // This is the native method for getting the number of lights the underlying
5009:            // native library can support.
5010:            int getNumCtxLights(Context ctx) {
5011:                return Pipeline.getPipeline().getNumCtxLights(ctx);
5012:            }
5013:
5014:            // Native method for decal 1st child setup
5015:            boolean decal1stChildSetup(Context ctx) {
5016:                return Pipeline.getPipeline().decal1stChildSetup(ctx);
5017:            }
5018:
5019:            // Native method for decal nth child setup
5020:            void decalNthChildSetup(Context ctx) {
5021:                Pipeline.getPipeline().decalNthChildSetup(ctx);
5022:            }
5023:
5024:            // Native method for decal reset
5025:            void decalReset(Context ctx, boolean depthBufferEnable) {
5026:                Pipeline.getPipeline().decalReset(ctx, depthBufferEnable);
5027:            }
5028:
5029:            // Native method for decal reset
5030:            void ctxUpdateEyeLightingEnable(Context ctx,
5031:                    boolean localEyeLightingEnable) {
5032:                Pipeline.getPipeline().ctxUpdateEyeLightingEnable(ctx,
5033:                        localEyeLightingEnable);
5034:            }
5035:
5036:            // The following three methods are used in multi-pass case
5037:
5038:            // native method for setting blend color
5039:            void setBlendColor(Context ctx, float red, float green, float blue,
5040:                    float alpha) {
5041:                Pipeline.getPipeline().setBlendColor(ctx, red, green, blue,
5042:                        alpha);
5043:            }
5044:
5045:            // native method for setting blend func
5046:            void setBlendFunc(Context ctx, int src, int dst) {
5047:                Pipeline.getPipeline().setBlendFunc(ctx, src, dst);
5048:            }
5049:
5050:            // native method for setting fog enable flag
5051:            void setFogEnableFlag(Context ctx, boolean enableFlag) {
5052:                Pipeline.getPipeline().setFogEnableFlag(ctx, enableFlag);
5053:            }
5054:
5055:            // Setup the full scene antialising in D3D and ogl when GL_ARB_multisamle supported
5056:            void setFullSceneAntialiasing(Context ctx, boolean enable) {
5057:                Pipeline.getPipeline().setFullSceneAntialiasing(ctx, enable);
5058:            }
5059:
5060:            void setGlobalAlpha(Context ctx, float alpha) {
5061:                Pipeline.getPipeline().setGlobalAlpha(ctx, alpha);
5062:            }
5063:
5064:            // Native method to update separate specular color control
5065:            void updateSeparateSpecularColorEnable(Context ctx, boolean control) {
5066:                Pipeline.getPipeline().updateSeparateSpecularColorEnable(ctx,
5067:                        control);
5068:            }
5069:
5070:            // Initialization for D3D when scene begin
5071:            private void beginScene(Context ctx) {
5072:                Pipeline.getPipeline().beginScene(ctx);
5073:            }
5074:
5075:            private void endScene(Context ctx) {
5076:                Pipeline.getPipeline().endScene(ctx);
5077:            }
5078:
5079:            // True under Solaris,
5080:            // False under windows when display mode <= 8 bit
5081:            private boolean validGraphicsMode() {
5082:                return Pipeline.getPipeline().validGraphicsMode();
5083:            }
5084:
5085:            // native method for setting light enables
5086:            void setLightEnables(Context ctx, long enableMask, int maxLights) {
5087:                Pipeline.getPipeline().setLightEnables(ctx, enableMask,
5088:                        maxLights);
5089:            }
5090:
5091:            // native method for setting scene ambient
5092:            void setSceneAmbient(Context ctx, float red, float green, float blue) {
5093:                Pipeline.getPipeline().setSceneAmbient(ctx, red, green, blue);
5094:            }
5095:
5096:            // native method for disabling fog
5097:            void disableFog(Context ctx) {
5098:                Pipeline.getPipeline().disableFog(ctx);
5099:            }
5100:
5101:            // native method for disabling modelClip
5102:            void disableModelClip(Context ctx) {
5103:                Pipeline.getPipeline().disableModelClip(ctx);
5104:            }
5105:
5106:            // native method for setting default RenderingAttributes
5107:            void resetRenderingAttributes(Context ctx,
5108:                    boolean depthBufferWriteEnableOverride,
5109:                    boolean depthBufferEnableOverride) {
5110:                Pipeline.getPipeline().resetRenderingAttributes(ctx,
5111:                        depthBufferWriteEnableOverride,
5112:                        depthBufferEnableOverride);
5113:            }
5114:
5115:            // native method for setting default texture
5116:            void resetTextureNative(Context ctx, int texUnitIndex) {
5117:                Pipeline.getPipeline().resetTextureNative(ctx, texUnitIndex);
5118:            }
5119:
5120:            // native method for activating a particular texture unit
5121:            void activeTextureUnit(Context ctx, int texUnitIndex) {
5122:                Pipeline.getPipeline().activeTextureUnit(ctx, texUnitIndex);
5123:            }
5124:
5125:            // native method for setting default TexCoordGeneration
5126:            void resetTexCoordGeneration(Context ctx) {
5127:                Pipeline.getPipeline().resetTexCoordGeneration(ctx);
5128:            }
5129:
5130:            // native method for setting default TextureAttributes
5131:            void resetTextureAttributes(Context ctx) {
5132:                Pipeline.getPipeline().resetTextureAttributes(ctx);
5133:            }
5134:
5135:            // native method for setting default PolygonAttributes
5136:            void resetPolygonAttributes(Context ctx) {
5137:                Pipeline.getPipeline().resetPolygonAttributes(ctx);
5138:            }
5139:
5140:            // native method for setting default LineAttributes
5141:            void resetLineAttributes(Context ctx) {
5142:                Pipeline.getPipeline().resetLineAttributes(ctx);
5143:            }
5144:
5145:            // native method for setting default PointAttributes
5146:            void resetPointAttributes(Context ctx) {
5147:                Pipeline.getPipeline().resetPointAttributes(ctx);
5148:            }
5149:
5150:            // native method for setting default TransparencyAttributes
5151:            void resetTransparency(Context ctx, int geometryType,
5152:                    int polygonMode, boolean lineAA, boolean pointAA) {
5153:                Pipeline.getPipeline().resetTransparency(ctx, geometryType,
5154:                        polygonMode, lineAA, pointAA);
5155:            }
5156:
5157:            // native method for setting default ColoringAttributes
5158:            void resetColoringAttributes(Context ctx, float r, float g,
5159:                    float b, float a, boolean enableLight) {
5160:                Pipeline.getPipeline().resetColoringAttributes(ctx, r, g, b, a,
5161:                        enableLight);
5162:            }
5163:
5164:            /**
5165:             *  This native method makes sure that the rendering for this canvas
5166:             *  gets done now.
5167:             */
5168:            void syncRender(Context ctx, boolean wait) {
5169:                Pipeline.getPipeline().syncRender(ctx, wait);
5170:            }
5171:
5172:            // The native method that sets this ctx to be the current one
5173:            static boolean useCtx(Context ctx, long display, Drawable drawable) {
5174:                return Pipeline.getPipeline().useCtx(ctx, display, drawable);
5175:            }
5176:
5177:            // Give the Pipeline a chance to release the context. The return
5178:            // value indicates whether the context was released.
5179:            private boolean releaseCtx(Context ctx, long dpy) {
5180:                return Pipeline.getPipeline().releaseCtx(ctx, dpy);
5181:            }
5182:
5183:            void clear(Context ctx, float r, float g, float b,
5184:                    boolean clearStencil) {
5185:                Pipeline.getPipeline().clear(ctx, r, g, b, clearStencil);
5186:            }
5187:
5188:            void textureFillBackground(Context ctx, float texMinU,
5189:                    float texMaxU, float texMinV, float texMaxV, float mapMinX,
5190:                    float mapMaxX, float mapMinY, float mapMaxY,
5191:                    boolean useBiliearFilter) {
5192:                Pipeline.getPipeline().textureFillBackground(ctx, texMinU,
5193:                        texMaxU, texMinV, texMaxV, mapMinX, mapMaxX, mapMinY,
5194:                        mapMaxY, useBiliearFilter);
5195:            }
5196:
5197:            void textureFillRaster(Context ctx, float texMinU, float texMaxU,
5198:                    float texMinV, float texMaxV, float mapMinX, float mapMaxX,
5199:                    float mapMinY, float mapMaxY, float mapZ, float alpha,
5200:                    boolean useBiliearFilter) {
5201:                Pipeline.getPipeline().textureFillRaster(ctx, texMinU, texMaxU,
5202:                        texMinV, texMaxV, mapMinX, mapMaxX, mapMinY, mapMaxY,
5203:                        mapZ, alpha, useBiliearFilter);
5204:            }
5205:
5206:            void executeRasterDepth(Context ctx, float posX, float posY,
5207:                    float posZ, int srcOffsetX, int srcOffsetY,
5208:                    int rasterWidth, int rasterHeight, int depthWidth,
5209:                    int depthHeight, int depthType, Object depthData) {
5210:                Pipeline.getPipeline().executeRasterDepth(ctx, posX, posY,
5211:                        posZ, srcOffsetX, srcOffsetY, rasterWidth,
5212:                        rasterHeight, depthWidth, depthHeight, depthType,
5213:                        depthData);
5214:            }
5215:
5216:            // The native method for setting the ModelView matrix.
5217:            void setModelViewMatrix(Context ctx, double[] viewMatrix,
5218:                    double[] modelMatrix) {
5219:                Pipeline.getPipeline().setModelViewMatrix(ctx, viewMatrix,
5220:                        modelMatrix);
5221:            }
5222:
5223:            // The native method for setting the Projection matrix.
5224:            void setProjectionMatrix(Context ctx, double[] projMatrix) {
5225:                Pipeline.getPipeline().setProjectionMatrix(ctx, projMatrix);
5226:            }
5227:
5228:            // The native method for setting the Viewport.
5229:            void setViewport(Context ctx, int x, int y, int width, int height) {
5230:                Pipeline.getPipeline().setViewport(ctx, x, y, width, height);
5231:            }
5232:
5233:            // used for display Lists
5234:            void newDisplayList(Context ctx, int displayListId) {
5235:                Pipeline.getPipeline().newDisplayList(ctx, displayListId);
5236:            }
5237:
5238:            void endDisplayList(Context ctx) {
5239:                Pipeline.getPipeline().endDisplayList(ctx);
5240:            }
5241:
5242:            void callDisplayList(Context ctx, int id, boolean isNonUniformScale) {
5243:                Pipeline.getPipeline().callDisplayList(ctx, id,
5244:                        isNonUniformScale);
5245:            }
5246:
5247:            static void freeDisplayList(Context ctx, int id) {
5248:                Pipeline.getPipeline().freeDisplayList(ctx, id);
5249:            }
5250:
5251:            static void freeTexture(Context ctx, int id) {
5252:                Pipeline.getPipeline().freeTexture(ctx, id);
5253:            }
5254:
5255:            void texturemapping(Context ctx, int px, int py, int xmin,
5256:                    int ymin, int xmax, int ymax, int texWidth, int texHeight,
5257:                    int rasWidth, int format, int objectId, byte[] image,
5258:                    int winWidth, int winHeight) {
5259:                Pipeline.getPipeline().texturemapping(ctx, px, py, xmin, ymin,
5260:                        xmax, ymax, texWidth, texHeight, rasWidth, format,
5261:                        objectId, image, winWidth, winHeight);
5262:            }
5263:
5264:            boolean initTexturemapping(Context ctx, int texWidth,
5265:                    int texHeight, int objectId) {
5266:                return Pipeline.getPipeline().initTexturemapping(ctx, texWidth,
5267:                        texHeight, objectId);
5268:            }
5269:
5270:            // Set internal render mode to one of FIELD_ALL, FIELD_LEFT or
5271:            // FIELD_RIGHT.  Note that it is up to the caller to ensure that
5272:            // stereo is available before setting the mode to FIELD_LEFT or
5273:            // FIELD_RIGHT.  The boolean isTRUE for double buffered mode, FALSE
5274:            // foe single buffering.
5275:            void setRenderMode(Context ctx, int mode, boolean doubleBuffer) {
5276:                Pipeline.getPipeline().setRenderMode(ctx, mode, doubleBuffer);
5277:            }
5278:
5279:            // Set glDepthMask.
5280:            void setDepthBufferWriteEnable(Context ctx, boolean mode) {
5281:                Pipeline.getPipeline().setDepthBufferWriteEnable(ctx, mode);
5282:            }
5283:
5284:            // Methods to get actual capabilities from Canvas3D
5285:
5286:            boolean hasDoubleBuffer() {
5287:                return Pipeline.getPipeline().hasDoubleBuffer(this );
5288:            }
5289:
5290:            boolean hasStereo() {
5291:                return Pipeline.getPipeline().hasStereo(this );
5292:            }
5293:
5294:            int getStencilSize() {
5295:                return Pipeline.getPipeline().getStencilSize(this );
5296:            }
5297:
5298:            boolean hasSceneAntialiasingMultisample() {
5299:                return Pipeline.getPipeline().hasSceneAntialiasingMultisample(
5300:                        this );
5301:            }
5302:
5303:            boolean hasSceneAntialiasingAccum() {
5304:                return Pipeline.getPipeline().hasSceneAntialiasingAccum(this);
5305:            }
5306:
5307:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.