/*
* Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
* ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
* DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package javax.media.opengl;
import javax.media.nativewindow.Capabilities;
import javax.media.nativewindow.CapabilitiesImmutable;
/** Specifies a set of OpenGL capabilities.
At creation time of a {@link GLDrawable} using {@link GLDrawableFactory},
an instance of this class is passed,
describing the desired capabilities that a rendering context
must support, such as the OpenGL profile, color depth and whether stereo is enabled.
The actual capabilites of created {@link GLDrawable}s are then reflected by their own
GLCapabilites instance, which can be queried with {@link GLDrawable#getGLCapabilities()}.
It currently contains the minimal number of routines which allow
configuration on all supported window systems. */
public class GLCapabilities extends Capabilities implements Cloneable, GLCapabilitiesImmutable {
private GLProfile glProfile = null;
private boolean isPBuffer = false;
private boolean isFBO = false;
private boolean doubleBuffered = true;
private boolean stereo = false;
private boolean hardwareAccelerated = true;
private int depthBits = 16;
private int stencilBits = 0;
private int accumRedBits = 0;
private int accumGreenBits = 0;
private int accumBlueBits = 0;
private int accumAlphaBits = 0;
// Shift bits from PIXELFORMATDESCRIPTOR not present because they
// are unlikely to be supported on Windows anyway
// Support for full-scene antialiasing (FSAA)
private String sampleExtension = DEFAULT_SAMPLE_EXTENSION;
private boolean sampleBuffers = false;
private int numSamples = 2;
// Bits for pbuffer creation
private boolean pbufferFloatingPointBuffers;
private boolean pbufferRenderToTexture;
private boolean pbufferRenderToTextureRectangle;
/** Creates a GLCapabilities object. All attributes are in a default state.
* @param glp GLProfile, or null for the default GLProfile
* @throws GLException if no profile is given and no default profile is available for the default device.
*/
public GLCapabilities(GLProfile glp) throws GLException {
glProfile = (null!=glp)?glp:GLProfile.getDefault(GLProfile.getDefaultDevice());
}
@Override
public Object cloneMutable() {
return clone();
}
@Override
public Object clone() {
try {
return super.clone();
} catch (RuntimeException e) {
throw new GLException(e);
}
}
@Override
public int hashCode() {
// 31 * x == (x << 5) - x
int hash = 31 + this.glProfile.hashCode() ;
hash = ((hash << 5) - hash) + ( this.isFBO ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.isPBuffer ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 );
hash = ((hash << 5) - hash) + this.depthBits;
hash = ((hash << 5) - hash) + this.stencilBits;
hash = ((hash << 5) - hash) + this.accumRedBits;
hash = ((hash << 5) - hash) + this.accumGreenBits;
hash = ((hash << 5) - hash) + this.accumBlueBits;
hash = ((hash << 5) - hash) + this.accumAlphaBits;
hash = ((hash << 5) - hash) + ( this.sampleBuffers ? 1 : 0 );
hash = ((hash << 5) - hash) + this.numSamples;
hash = ((hash << 5) - hash) + this.sampleExtension.hashCode();
hash = ((hash << 5) - hash) + ( this.pbufferFloatingPointBuffers ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.pbufferRenderToTexture ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.pbufferRenderToTextureRectangle ? 1 : 0 );
return hash;
}
@Override
public boolean equals(Object obj) {
if(this == obj) { return true; }
if(!(obj instanceof GLCapabilitiesImmutable)) {
return false;
}
GLCapabilitiesImmutable other = (GLCapabilitiesImmutable)obj;
boolean res = super.equals(obj) &&
other.getGLProfile()==glProfile &&
other.isPBuffer()==isPBuffer &&
other.isFBO()==isFBO &&
other.getStereo()==stereo &&
other.getHardwareAccelerated()==hardwareAccelerated &&
other.getDepthBits()==depthBits &&
other.getStencilBits()==stencilBits &&
other.getAccumRedBits()==accumRedBits &&
other.getAccumGreenBits()==accumGreenBits &&
other.getAccumBlueBits()==accumBlueBits &&
other.getAccumAlphaBits()==accumAlphaBits &&
other.getSampleBuffers()==sampleBuffers &&
other.getPbufferFloatingPointBuffers()==pbufferFloatingPointBuffers &&
other.getPbufferRenderToTexture()==pbufferRenderToTexture &&
other.getPbufferRenderToTextureRectangle()==pbufferRenderToTextureRectangle;
if(sampleBuffers) {
res = res &&
other.getNumSamples()==numSamples &&
other.getSampleExtension().equals(sampleExtension) ;
}
return res;
}
/** comparing hw/sw, stereo, multisample, stencil, RGBA and depth only */
@Override
public int compareTo(final CapabilitiesImmutable o) {
if ( ! ( o instanceof GLCapabilitiesImmutable ) ) {
Class> c = (null != o) ? o.getClass() : null ;
throw new ClassCastException("Not a GLCapabilitiesImmutable object, but " + c);
}
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) o;
if(hardwareAccelerated && !caps.getHardwareAccelerated()) {
return 1;
} else if(!hardwareAccelerated && caps.getHardwareAccelerated()) {
return -1;
}
if(stereo && !caps.getStereo()) {
return 1;
} else if(!stereo && caps.getStereo()) {
return -1;
}
if(doubleBuffered && !caps.getDoubleBuffered()) {
return 1;
} else if(!doubleBuffered && caps.getDoubleBuffered()) {
return -1;
}
final int ms = sampleBuffers ? numSamples : 0;
final int xms = caps.getSampleBuffers() ? caps.getNumSamples() : 0;
if(ms > xms) {
return 1;
} else if( ms < xms ) {
return -1;
}
// ignore the sample extension
if(stencilBits > caps.getStencilBits()) {
return 1;
} else if(stencilBits < caps.getStencilBits()) {
return -1;
}
final int sc = super.compareTo(caps); // RGBA
if(0 != sc) {
return sc;
}
if(depthBits > caps.getDepthBits()) {
return 1;
} else if(depthBits < caps.getDepthBits()) {
return -1;
}
return 0; // they are equal: hw/sw, stereo, multisample, stencil, RGBA and depth
}
@Override
public final GLProfile getGLProfile() {
return glProfile;
}
/** Sets the GL profile you desire */
public void setGLProfile(GLProfile profile) {
glProfile=profile;
}
@Override
public final boolean isPBuffer() {
return isPBuffer;
}
/**
* Enables or disables pbuffer usage.
*
* If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}
* and {@link #setFBO(int) setFBO(false)}
*
* If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}
* and {@link #setPBuffer(int) setPBuffer(false)}
*