/*
* 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:
*
* depthSize : 16
* doubleBuffer : REQUIRED
* sceneAntialiasing : UNNECESSARY
* stereo : UNNECESSARY
* redSize : 2
* greenSize : 2
* blueSize : 2
* stencilSize : 0
*
*/
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);
}
}