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: }
|