/* * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. * */ package javax.media.j3d; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; /** * This class is used to obtain a valid GraphicsConfiguration that can be used by Java 3D. * A user instantiates one of these objects and then sets all * non-default attributes as desired. The getBestConfiguration() * method in the GraphicsDevice class is then called with this * GraphicsConfigTemplate and the "best" GraphicsConfiguration is returned. The "best" * GraphicsConfiguration means that this GraphicsConfiguration is supported and it * meets or exceeds what was requested in the GraphicsConfigTemplate. * Null is returned if no such "best" GraphicsConfiguration is found. * * @see GraphicsConfigTemplate * @see GraphicsDevice * @see GraphicsConfiguration */ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { int depthSize; int doubleBuffer; int blueSize; int greenSize; int redSize; int sceneAntialiasing; int stereo; int stencilSize; // Temporary variables use for passing argument to/from Request Renderer Object testCfg; static Object globalLock = new Object(); static Object monitorLock = new Object(); static volatile boolean threadWaiting = false; /** * Constructs a GraphicsConfigTemplate3D object with default parameters. * The default values are as follows: * */ public GraphicsConfigTemplate3D() { doubleBuffer = REQUIRED; stereo = UNNECESSARY; depthSize = 16; stencilSize = 0; redSize = greenSize = blueSize = 2; sceneAntialiasing = UNNECESSARY; } /** * Sets the double buffering requirement. It should be * GraphicsConfigTemplate.REQUIRED, GraphicsConfigTemplate.PREFERRED, * or GraphicsConfigTemplate.UNNECESSARY. * If an invalid value is passed in, it is ignored. * If the value of double buffering is * GraphicsConfigTemplate.REQUIRED, and no GraphicsConfiguration is found * that meets this requirement, null will be returned in getBestConfiguration(). * @param value the value to set this field to */ public void setDoubleBuffer(int value) { if (value < REQUIRED && value > UNNECESSARY) return; doubleBuffer = value; } /** * Retrieves the double buffering value. * @return the current value of the doubleBuffer attribute */ public int getDoubleBuffer() { return doubleBuffer; } /** * Sets the stereo requirement. It should be * GraphicsConfigTemplate.REQUIRED, GraphicsConfigTemplate.PREFERRED, * or GraphicsConfigTemplate.UNNECESSARY. If an invalid value * is passed in, it is ignored. If the value of stereo requirement is * GraphicsConfigTemplate.REQUIRED, and no GraphicsConfiguration is found * that meets this requirement, null will be returned in getBestConfiguration(). * @param value the value to set this field to */ public void setStereo(int value) { if (value < REQUIRED && value > UNNECESSARY) return; stereo = value; } /** * Retrieves the stereo value. * @return the current value of the stereo attribute. */ public int getStereo() { return stereo; } /** * Sets the scene antialiasing requirement. It should be * GraphicsConfigTemplate.REQUIRED, GraphicsConfigTemplate.PREFERRED, * or GraphicsConfigTemplate.UNNECESSARY. If an invalid value * is passed in, it is ignored. If the value of scene antialiasing is * GraphicsConfigTemplate.REQUIRED, and no GraphicsConfiguration is found * that meets this requirement, null will be returned in getBestConfiguration(). * @param value the value to set this field to */ public void setSceneAntialiasing(int value) { if (value < REQUIRED && value > UNNECESSARY) return; sceneAntialiasing = value; } /** * Retrieves the scene antialiasing value. * @return the current value of the scene antialiasing attribute. */ public int getSceneAntialiasing() { return sceneAntialiasing; } /** * Sets the depth buffer size requirement. This is the minimum requirement. * If no GraphicsConfiguration is found that meets or * exceeds this minimum requirement, null will be returned in * getBestConfiguration(). * @param value the value to set this field to */ public void setDepthSize(int value) { if (value < 0) return; depthSize = value; } /** * Retrieves the size of the depth buffer. * @return the current value of the depthSize attribute */ public int getDepthSize() { return depthSize; } /** * Sets the stencil buffer size requirement. * This is the minimum requirement. * If no GraphicsConfiguration is found that meets or * exceeds this minimum requirement, null will be returned in * getBestConfiguration(). * * @param value the value to set this field to * * @since Java 3D 1.4 */ public void setStencilSize(int value) { if (value < 0) return; stencilSize = value; } /** * Retrieves the size of the stencil buffer. * * @return the current value of the stencilSize attribute * * @since Java 3D 1.4 */ public int getStencilSize() { return stencilSize; } /** * Sets the number of red bits required. This is the minimum requirement. * If no GraphicsConfiguration is found that meets or * exceeds this minimum requirement, null will be returned in * getBestConfiguration(). * @param value the value to set this field to */ public void setRedSize(int value) { if (value < 0) return; redSize = value; } /** * Retrieves the number of red bits requested by this template. * @return the current value of the redSize attribute. */ public int getRedSize() { return redSize; } /** * Sets the number of green bits required. This is the minimum requirement. * If no GraphicsConfiguration is found that meets or * exceeds this minimum requirement, null will be returned in * getBestConfiguration(). * @param value the value to set this field to */ public void setGreenSize(int value) { if (value < 0) return; greenSize = value; } /** * Retrieves the number of green bits requested by this template. * @return the current value of the greenSize attribute. */ public int getGreenSize() { return greenSize; } /** * Sets the number of blue bits required. This is the minimum requirement. * If no GraphicsConfiguration is found that meets or * exceeds this minimum requirement, null will be returned in * getBestConfiguration(). * @param value the value to set this field to */ public void setBlueSize(int value) { if (value < 0) return; blueSize = value; } /** * Retrieves the number of blue bits requested by this template. * @return the current value of the blueSize attribute. */ public int getBlueSize() { return blueSize; } /** * Implement the abstract function of getBestConfiguration() in GraphicsConfigTemplate. * Usually this function is not directly called by the user. It is * implicitly called by getBestConfiguration() in GraphicsDevice. * The method getBestConfiguration() in GraphicsDevice will return whatever this function returns. * This function will return the "best" GraphicsConfiguration. The "best" GraphicsConfiguration * means that this GraphicsConfiguration is supported and it meets or exceeds what was requested in the * GraphicsConfigTemplate. If no such "best" GraphicsConfiguration is found, null is returned. * @param gc the array of GraphicsConfigurations to choose from * * @return the best GraphicsConfiguration * * @see GraphicsDevice */ @Override public GraphicsConfiguration getBestConfiguration(GraphicsConfiguration[] gc) { if ((gc == null) || (gc.length == 0) || (gc[0] == null)) { return null; } synchronized (globalLock) { testCfg = gc; // It is possible that the followign postRequest will // cause request renderer run immediately before // runMonitor(WAIT). So we need to set // threadWaiting to true. threadWaiting = true; // Prevent deadlock if invoke from Behavior callback since // this thread has to wait Renderer thread to finish but // MC can only handle postRequest and put it in Renderer // queue when free. if (Thread.currentThread() instanceof BehaviorScheduler) { VirtualUniverse.mc.sendRenderMessage(gc[0], this, MasterControl.GETBESTCONFIG); } else { VirtualUniverse.mc.postRequest(MasterControl.GETBESTCONFIG, this); } runMonitor(J3dThread.WAIT); return (GraphicsConfiguration) testCfg; } } /** * Returns a boolean indicating whether or not the given * GraphicsConfiguration can be used to create a drawing * surface that can be rendered to. * * @param gc the GraphicsConfiguration object to test * * @return true if this GraphicsConfiguration object * can be used to create surfaces that can be rendered to, * false if the GraphicsConfiguration can not be used * to create a drawing surface usable by this API. */ @Override public boolean isGraphicsConfigSupported(GraphicsConfiguration gc) { if (gc == null) { return false; } synchronized (globalLock) { testCfg = gc; threadWaiting = true; if (Thread.currentThread() instanceof BehaviorScheduler) { VirtualUniverse.mc.sendRenderMessage(gc, this, MasterControl.ISCONFIGSUPPORT); } else { VirtualUniverse.mc.postRequest(MasterControl.ISCONFIGSUPPORT, this); } runMonitor(J3dThread.WAIT); return ((Boolean) testCfg).booleanValue(); } } /** * Set the stereo/doubleBuffer/sceneAntialiasingAccum * and hasSceneAntialiasingMultiSamples flags in Canvas3D */ static void getGraphicsConfigFeatures(Canvas3D c) { synchronized (globalLock) { threadWaiting = true; if (Thread.currentThread() instanceof BehaviorScheduler) { VirtualUniverse.mc.sendRenderMessage(c.graphicsConfiguration, c, MasterControl.SET_GRAPHICSCONFIG_FEATURES); } else { VirtualUniverse.mc.postRequest(MasterControl.SET_GRAPHICSCONFIG_FEATURES, c); } runMonitor(J3dThread.WAIT); } } /** * Set the queryProperties() map in Canvas3D */ static void setQueryProps(Canvas3D c) { synchronized (globalLock) { threadWaiting = true; if (Thread.currentThread() instanceof BehaviorScheduler) { VirtualUniverse.mc.sendRenderMessage(c.graphicsConfiguration, c, MasterControl.SET_QUERYPROPERTIES); } else { VirtualUniverse.mc.postRequest(MasterControl.SET_QUERYPROPERTIES, c); } runMonitor(J3dThread.WAIT); } } static void runMonitor(int action) { // user thread will locked the globalLock when Renderer // thread invoke this function so we can't use // the same lock. synchronized (monitorLock) { switch (action) { case J3dThread.WAIT: // Issue 279 - loop until ready while (threadWaiting) { try { monitorLock.wait(); } catch (InterruptedException e) { System.err.println(e); } } break; case J3dThread.NOTIFY: monitorLock.notify(); threadWaiting = false; break; } } } // Return a string representing the value, one of: // REQUIRED, PREFERRED, or UNNECESSARY private static final String enumStr(int val) { switch (val) { case REQUIRED: return "REQUIRED"; case PREFERRED: return "PREFERRED"; case UNNECESSARY: return "UNNECESSARY"; } return "UNDEFINED"; } /** * Returns a string representation of this object. * @return a string representation of this object. */ @Override public String toString() { return "redSize : " + redSize + ", " + "greenSize : " + greenSize + ", " + "blueSize : " + blueSize + ", " + "depthSize : " + depthSize + ", " + "doubleBuffer : " + enumStr(doubleBuffer) + ", " + "sceneAntialiasing : " + enumStr(sceneAntialiasing) + ", " + "stereo : " + enumStr(stereo); } }