jogamp.opengl.GLGraphicsConfigurationUtil Maven / Gradle / Ivy
/**
* Copyright 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:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions 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.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package jogamp.opengl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLRendererQuirks;
public class GLGraphicsConfigurationUtil {
public static final String NV_coverage_sample = "NV_coverage_sample";
public static final int WINDOW_BIT = 1 << 0;
public static final int BITMAP_BIT = 1 << 1;
public static final int PBUFFER_BIT = 1 << 2;
public static final int FBO_BIT = 1 << 3; // generic bit must be mapped to native one at impl. level
public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT | FBO_BIT ;
public static final StringBuilder winAttributeBits2String(StringBuilder sb, int winattrbits) {
if(null==sb) {
sb = new StringBuilder();
}
boolean seperator = false;
if( 0 != ( WINDOW_BIT & winattrbits ) ) {
sb.append("WINDOW");
seperator=true;
}
if( 0 != ( BITMAP_BIT & winattrbits ) ) {
if(seperator) {
sb.append(", ");
}
sb.append("BITMAP");
seperator=true;
}
if( 0 != ( PBUFFER_BIT & winattrbits ) ) {
if(seperator) {
sb.append(", ");
}
sb.append("PBUFFER");
seperator=true;
}
if( 0 != ( FBO_BIT & winattrbits ) ) {
if(seperator) {
sb.append(", ");
}
sb.append("FBO");
}
return sb;
}
/**
public static final int getWinAttributeBits(boolean isOnscreen, boolean isFBO, boolean isPBuffer, boolean isBitmap) {
int winattrbits = 0;
if(isOnscreen) {
winattrbits |= WINDOW_BIT;
}
if(isFBO) {
winattrbits |= FBO_BIT;
}
if(isPBuffer ){
winattrbits |= PBUFFER_BIT;
}
if(isBitmap) {
winattrbits |= BITMAP_BIT;
}
return winattrbits;
}
public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) {
return getWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap());
} */
/**
* @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set.
*/
public static final int getExclusiveWinAttributeBits(boolean isOnscreen, boolean isFBO, boolean isPBuffer, boolean isBitmap) {
final int winattrbits;
if(isOnscreen) {
winattrbits = WINDOW_BIT;
} else if(isFBO) {
winattrbits = FBO_BIT;
} else if(isPBuffer ){
winattrbits = PBUFFER_BIT;
} else if(isBitmap) {
winattrbits = BITMAP_BIT;
} else {
throw new InternalError("Empty bitmask");
}
return winattrbits;
}
/**
* @see #getExclusiveWinAttributeBits(boolean, boolean, boolean, boolean)
*/
public static final int getExclusiveWinAttributeBits(GLCapabilitiesImmutable caps) {
return getExclusiveWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap());
}
public static final GLCapabilities fixWinAttribBitsAndHwAccel(AbstractGraphicsDevice device, int winattrbits, GLCapabilities caps) {
caps.setBitmap ( 0 != ( BITMAP_BIT & winattrbits ) );
caps.setPBuffer ( 0 != ( PBUFFER_BIT & winattrbits ) );
caps.setFBO ( 0 != ( FBO_BIT & winattrbits ) );
// we reflect availability semantics, hence setting onscreen at last (maybe overwritten above)!
caps.setOnscreen( 0 != ( WINDOW_BIT & winattrbits ) );
final int accel = GLContext.isHardwareRasterizer( device, caps.getGLProfile() );
if(0 == accel && caps.getHardwareAccelerated() ) {
caps.setHardwareAccelerated(false);
}
return caps;
}
/**
* Fixes the requested {@link GLCapabilitiesImmutable} according to on- and offscreen usage.
*
* No modification will be made for onscreen usage, for offscreen usage see
* {@link #fixOffscreenGLCapabilities(GLCapabilitiesImmutable, GLDrawableFactory, AbstractGraphicsDevice)}.
*
* @param capsRequested the requested {@link GLCapabilitiesImmutable}
* @param factory the {@link GLDrawableFactory} used to validate the requested capabilities and later used to create the drawable.
* @param device the device on which the drawable will be created, maybe null for the {@link GLDrawableFactory#getDefaultDevice() default device}.
* @return either the given requested {@link GLCapabilitiesImmutable} instance if no modifications were required, or a modified {@link GLCapabilitiesImmutable} instance.
*/
public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested,
GLDrawableFactory factory, AbstractGraphicsDevice device) {
if( !capsRequested.isOnscreen() ) {
return fixOffscreenGLCapabilities(capsRequested, factory, device);
}
return capsRequested;
}
public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested)
{
if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) {
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setBitmap (false);
caps2.setPBuffer (false);
caps2.setFBO (false);
caps2.setOnscreen(true);
return caps2;
}
return capsRequested;
}
public static GLCapabilitiesImmutable fixOffscreenBitOnly(GLCapabilitiesImmutable capsRequested)
{
if( capsRequested.isOnscreen() ) {
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setOnscreen(false);
return caps2;
}
return capsRequested;
}
/**
* Fixes the requested {@link GLCapabilitiesImmutable} according to:
*
* - offscreen usage
* - availability of FBO, PBuffer, Bitmap
* - {@link GLRendererQuirks}
*
* @param capsRequested the requested {@link GLCapabilitiesImmutable}
* @param factory the {@link GLDrawableFactory} used to validate the requested capabilities and later used to create the drawable.
* @param device the device on which the drawable will be created, maybe null for the {@link GLDrawableFactory#getDefaultDevice() default device}.
* @return either the given requested {@link GLCapabilitiesImmutable} instance if no modifications were required, or a modified {@link GLCapabilitiesImmutable} instance.
*/
public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested,
GLDrawableFactory factory, AbstractGraphicsDevice device) {
if(null == device) {
device = factory.getDefaultDevice();
}
final GLProfile glp = capsRequested.getGLProfile();
final boolean fboAvailable = GLContext.isFBOAvailable(device, glp);
final boolean pbufferAvailable = factory.canCreateGLPbuffer(device, glp);
final GLRendererQuirks glrq = factory.getRendererQuirks(device);
final boolean bitmapAvailable;
final boolean doubleBufferAvailable;
if(null != glrq) {
bitmapAvailable = !glrq.exist(GLRendererQuirks.NoOffscreenBitmap);
if( capsRequested.getDoubleBuffered() &&
( capsRequested.isPBuffer() && glrq.exist(GLRendererQuirks.NoDoubleBufferedPBuffer) ) ||
( capsRequested.isBitmap() && glrq.exist(GLRendererQuirks.NoDoubleBufferedBitmap) ) ) {
doubleBufferAvailable = false;
} else {
doubleBufferAvailable = true;
}
} else {
bitmapAvailable = true;
doubleBufferAvailable = true;
}
final boolean auto = !( fboAvailable && capsRequested.isFBO() ) &&
!( pbufferAvailable && capsRequested.isPBuffer() ) &&
!( bitmapAvailable && capsRequested.isBitmap() ) ;
final boolean useFBO = fboAvailable && ( auto || capsRequested.isFBO() ) ;
final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || capsRequested.isPBuffer() ) ;
final boolean useBitmap = !useFBO && !usePbuffer && bitmapAvailable && ( auto || capsRequested.isBitmap() ) ;
if( capsRequested.isOnscreen() ||
useFBO != capsRequested.isFBO() ||
usePbuffer != capsRequested.isPBuffer() ||
useBitmap != capsRequested.isBitmap() ||
!doubleBufferAvailable && capsRequested.getDoubleBuffered() )
{
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setOnscreen(false);
caps2.setFBO( useFBO );
caps2.setPBuffer( usePbuffer );
caps2.setBitmap( useBitmap );
if( !doubleBufferAvailable ) {
caps2.setDoubleBuffered(false);
}
return caps2;
}
return capsRequested;
}
public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(GLCapabilitiesImmutable capsRequested)
{
if( capsRequested.isOnscreen() ||
!capsRequested.isPBuffer() ||
capsRequested.isFBO() )
{
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setOnscreen(false);
caps2.setFBO(false);
caps2.setPBuffer(true);
caps2.setBitmap(false);
return caps2;
}
return capsRequested;
}
/** Fix opaque setting while preserve alpha bits */
public static GLCapabilities fixOpaqueGLCapabilities(GLCapabilities capsRequested, boolean isOpaque)
{
if( capsRequested.isBackgroundOpaque() != isOpaque) {
final int alphaBits = capsRequested.getAlphaBits();
capsRequested.setBackgroundOpaque(isOpaque);
capsRequested.setAlphaBits(alphaBits);
}
return capsRequested;
}
/** Fix double buffered setting */
public static GLCapabilitiesImmutable fixDoubleBufferedGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean doubleBuffered)
{
if( capsRequested.getDoubleBuffered() != doubleBuffered) {
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setDoubleBuffered(doubleBuffered);
return caps2;
}
return capsRequested;
}
public static GLCapabilitiesImmutable clipRGBAGLCapabilities(GLCapabilitiesImmutable caps, boolean allowRGB555, boolean allowAlpha)
{
final int iR = caps.getRedBits();
final int iG = caps.getGreenBits();
final int iB = caps.getBlueBits();
final int iA = caps.getAlphaBits();
final int oR = clipColor(iR, allowRGB555);
final int oG = clipColor(iG, allowRGB555);
final int oB = clipColor(iB, allowRGB555);
final int oA = ( allowAlpha && 0 < iA ) ? oR : 0 ; // align alpha to red if requested and allowed
if( iR != oR || iG != oG || iB != oB || iA != oA ) {
final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
caps2.setRedBits(oR);
caps2.setGreenBits(oG);
caps2.setBlueBits(oB);
caps2.setAlphaBits(oA);
return caps2;
}
return caps;
}
public static int clipColor(final int compIn, final boolean allowRGB555) {
final int compOut;
if( 5 < compIn || !allowRGB555 ) {
compOut = 8;
} else {
compOut = 5;
}
return compOut;
}
public static GLCapabilitiesImmutable fixGLProfile(GLCapabilitiesImmutable caps, GLProfile glp)
{
if( caps.getGLProfile() != glp ) {
final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
caps2.setGLProfile(glp);
return caps2;
}
return caps;
}
}