jogamp.opengl.egl.EGLGraphicsConfigurationFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jogl-all Show documentation
Show all versions of jogl-all Show documentation
Java™ Binding for the OpenGL® API
/*
* Copyright (c) 2008 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.
*/
package jogamp.opengl.egl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLDrawableFactory;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.io.PrintStream;
import java.nio.IntBuffer;
/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits
are used on X11 platforms. Toolkits will likely need to delegate
to this one to change the accepted and returned types of the
GraphicsDevice and GraphicsConfiguration abstractions. */
public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
static VisualIDHolder.VIDComparator EglCfgIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.EGL_CONFIG);
static GraphicsConfigurationFactory nativeGraphicsConfigurationFactory = null;
static GraphicsConfigurationFactory kdeglGraphicsConfigurationFactory = null;
static GraphicsConfigurationFactory fallbackGraphicsConfigurationFactory = null;
static void registerFactory() {
GraphicsConfigurationFactory eglFactory = new EGLGraphicsConfigurationFactory();
// become the pre-selector for X11/.. to match the native visual id w/ EGL, if native ES is selected
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
if(null != nativeGraphicsConfigurationFactory) {
fallbackGraphicsConfigurationFactory = nativeGraphicsConfigurationFactory;
} else {
fallbackGraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class);
}
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, eglFactory);
} else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
// become the selector for KD/EGL ..
kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
}
static void unregisterFactory() {
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory);
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, nativeGraphicsConfigurationFactory);
} else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
nativeGraphicsConfigurationFactory = null;
fallbackGraphicsConfigurationFactory = null;
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, kdeglGraphicsConfigurationFactory);
kdeglGraphicsConfigurationFactory = null;
}
private EGLGraphicsConfigurationFactory() {
}
@Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl (
CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (absScreen == null) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects");
}
if (! (capsChosen instanceof GLCapabilitiesImmutable) ) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen");
}
final GLCapabilitiesImmutable glCapsChosen = (GLCapabilitiesImmutable) capsChosen;
if (! (capsRequested instanceof GLCapabilitiesImmutable) ) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - requested");
}
if (chooser != null &&
!(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
AbstractGraphicsDevice absDevice = absScreen.getDevice();
if(null==absDevice) {
throw new GLException("Null AbstractGraphicsDevice");
}
AbstractGraphicsConfiguration cfg = null;
if( absDevice instanceof EGLGraphicsDevice ) {
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
absScreen, nativeVisualID, false);
} else {
// handle non native cases (X11, ..)
if(null == fallbackGraphicsConfigurationFactory) {
throw new InternalError("Native fallback GraphicsConfigurationFactory is null, but call issued for device: "+absDevice+" of type "+absDevice.getClass().getSimpleName());
}
if(glCapsChosen.getGLProfile().usesNativeGLES()) {
if(DEBUG) {
System.err.println("EGLGraphicsConfigurationFactory.choose..: Handle native device "+absDevice.getClass().getSimpleName());
}
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
absScreen, nativeVisualID, false);
if(null == cfg || VisualIDHolder.VID_UNDEFINED == cfg.getVisualID(VIDType.NATIVE)) {
cfg = null;
if(DEBUG) {
System.err.println("EGLGraphicsConfigurationFactory.choose..: No native visual ID, fallback ..");
}
}
}
if(null == cfg) {
// fwd to native config factory (only X11 for now)
if(DEBUG) {
System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+fallbackGraphicsConfigurationFactory.getClass().getSimpleName());
}
cfg = fallbackGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, nativeVisualID);
}
}
return cfg;
}
protected static List getAvailableCapabilities(EGLDrawableFactory factory, AbstractGraphicsDevice device) {
EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
EGLGraphicsDevice eglDevice = sharedResource.getDevice();
long eglDisplay = eglDevice.getHandle();
if(0 == eglDisplay) {
throw new GLException("null eglDisplay");
}
List availableCaps = null;
IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
if(!EGL.eglGetConfigs(eglDisplay, null, 0, numConfigs)) {
throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if(0 == numConfigs.get(0)) {
throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) no configs");
}
PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs)) {
throw new GLException("Graphics configuration get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
availableCaps = eglConfigs2GLCaps(eglDevice, null, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, false);
if( null != availableCaps && availableCaps.size() > 1) {
Collections.sort(availableCaps, EglCfgIDComparator);
}
}
return availableCaps;
}
public static EGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
AbstractGraphicsScreen absScreen, int nativeVisualID,
boolean forceTransparentFlag) {
if (capsChosen == null) {
capsChosen = new GLCapabilities(null);
}
if(null==absScreen) {
throw new GLException("Null AbstractGraphicsScreen");
}
AbstractGraphicsDevice absDevice = absScreen.getDevice();
if(null==absDevice) {
throw new GLException("Null AbstractGraphicsDevice");
}
final EGLGraphicsDevice eglDevice;
final boolean ownEGLDisplay;
if( absDevice instanceof EGLGraphicsDevice ) {
eglDevice = (EGLGraphicsDevice) absDevice;
if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) {
throw new GLException("Invalid EGL display: "+eglDevice);
}
ownEGLDisplay = false;
} else {
eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID());
ownEGLDisplay = true;
}
final GLProfile glp = capsChosen.getGLProfile();
capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getEGLFactory(), absDevice);
EGLGraphicsConfiguration res = eglChooseConfig(eglDevice, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
if(null==res) {
if(DEBUG) {
System.err.println("eglChooseConfig failed with given capabilities "+capsChosen);
}
// Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..]
//
// rgb888 - d16, s4
final GLCapabilities fixedCaps = new GLCapabilities(glp);
fixedCaps.setSampleBuffers(true);
fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(8);
fixedCaps.setGreenBits(8);
fixedCaps.setBlueBits(8);
fixedCaps.setDepthBits(16);
if( !capsChosen.isOnscreen() ) {
fixedCaps.setOnscreen(false);
fixedCaps.setPBuffer(capsChosen.isPBuffer());
fixedCaps.setFBO(capsChosen.isFBO());
}
if(DEBUG) {
System.err.println("trying fixed caps (1): "+fixedCaps);
}
res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s0
final GLCapabilities fixedCaps = new GLCapabilities(glp);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
if( !capsChosen.isOnscreen() ) {
fixedCaps.setOnscreen(false);
fixedCaps.setPBuffer(capsChosen.isPBuffer());
fixedCaps.setFBO(capsChosen.isFBO());
}
if(DEBUG) {
System.err.println("trying fixed caps (2): "+fixedCaps);
}
res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s4
final GLCapabilities fixedCaps = new GLCapabilities(glp);
fixedCaps.setSampleBuffers(true);
fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
if( !capsChosen.isOnscreen() ) {
fixedCaps.setOnscreen(false);
fixedCaps.setPBuffer(capsChosen.isPBuffer());
fixedCaps.setFBO(capsChosen.isFBO());
}
if(DEBUG) {
System.err.println("trying fixed caps (3): "+fixedCaps);
}
res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]");
}
if(ownEGLDisplay) {
((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
eglDevice.close();
}
return res;
}
static EGLGraphicsConfiguration eglChooseConfig(EGLGraphicsDevice device,
GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
AbstractGraphicsScreen absScreen,
int nativeVisualID, boolean forceTransparentFlag) {
final long eglDisplay = device.getHandle();
final GLProfile glp = capsChosen.getGLProfile();
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
List availableCaps = null;
int recommendedIndex = -1;
long recommendedEGLConfig = -1;
IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
if(!EGL.eglGetConfigs(eglDisplay, null, 0, numConfigs)) {
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if(0 == numConfigs.get(0)) {
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs");
}
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+
", nativeVisualID "+toHexString(nativeVisualID)+
", capsChosen "+capsChosen+", winbits "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString()+
", fboAvail "+GLContext.isFBOAvailable(device, glp)+
", device "+device+", "+device.getUniqueID()+
", numConfigs "+numConfigs.get(0));
}
final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen);
PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
// 1st choice: get GLCapabilities based on users GLCapabilities
// setting recommendedIndex as preferred choice
// skipped if nativeVisualID is given
if( VisualIDHolder.VID_UNDEFINED != nativeVisualID || !EGL.eglChooseConfig(eglDisplay, attrs, configs, configs.capacity(), numConfigs) ) {
if(DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: false");
}
} else if (numConfigs.get(0) > 0) {
availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
if(availableCaps.size() > 0) {
recommendedEGLConfig = configs.get(0);
recommendedIndex = 0;
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: recommended fbcfg " + toHexString(recommendedEGLConfig) + ", idx " + recommendedIndex);
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 fbcfg caps " + availableCaps.get(recommendedIndex));
}
} else if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: no caps for recommended fbcfg " + toHexString(configs.get(0)));
}
} else if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: no configs");
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
if( null == availableCaps || 0 == availableCaps.size() ) {
// reset ..
recommendedEGLConfig = -1;
recommendedIndex = -1;
if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs)) {
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
}
}
if( null == availableCaps || 0 == availableCaps.size() ) {
if(DEBUG) {
// FIXME: this happens on a ATI PC Emulation ..
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs");
availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag);
printCaps("AllCaps", availableCaps, System.err);
}
return null;
}
if(DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: got configs: "+availableCaps.size());
for(int i=0; i removedCaps = new ArrayList();
for(int i=0; i chosenIndex ) {
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 chooseCapabilities failed");
}
return null;
}
final EGLGLCapabilities chosenCaps = (EGLGLCapabilities) availableCaps.get(chosenIndex);
final EGLGraphicsConfiguration res = new EGLGraphicsConfiguration(absScreen, chosenCaps, capsRequested, chooser);
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: X chosen :"+chosenIndex+", eglConfig: "+toHexString(chosenCaps.getEGLConfig())+": "+res);
}
return res;
}
static List eglConfigs2GLCaps(EGLGraphicsDevice device, GLProfile glp, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag) {
List bucket = new ArrayList(num);
for(int i=0; i caps, PrintStream out) {
for(int i=0; i