package ch.ethz.karto.map3d;
import ika.utils.Sys;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.nio.IntBuffer;
import java.util.StringTokenizer;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.Threading;
/**
* Map3DGLCapabilities provides information about the present version of OpenGL2.
* All information is gathered in a static initialization block. A GL context
* is created and immediately released afterwards. This should avoid issues with
* threading and too many OpenGL contextes allocated.
* @author jenny
*/
public class Map3DGLCapabilities {
private static boolean hasOpenGL = false;
private static boolean hasNonPowerOfTwoTextures = false;
private static boolean hasVBO = false;
private static boolean hasFloatingPointTextures = false;
private static String glVendor;
private static String glRenderer;
private static String glVersion;
private static String glShadingLanguageVersion;
private static int maxTextureSize;
private static int maxDrawBuffers;
private static int maxVertexTextureImageUnits;
private static int maxTextureImageUnits;
public static AbstractGraphicsDevice defaultGraphicsDevice;
public static GLProfile defaultGLProfile;
static {
// initialize all static variables
// Runnable r = new Runnable() {
//
// @Override
// public void run() {
try {
GLProfile defaultGLProfile = GLProfile.getDefault();
defaultGraphicsDevice = GLProfile.getDefaultDevice();
OpenGLCapabilities capabilities = new OpenGLCapabilities(defaultGLProfile, defaultGraphicsDevice);
if (capabilities != null) {
try {
GL gl = capabilities.getGL();
init(gl);
} finally {
capabilities.restoreLastGLContext();
}
}
} catch (Throwable e) {
hasOpenGL = false;
}
// }
// };
// maybeDoSingleThreadedWorkaround(r);
}
private Map3DGLCapabilities() {
}
/**
* Executes a runnable on the OpenGL thread and blocks the calling thread
* until the runnable has finished executing.
* @param action
*/
private static void maybeDoSingleThreadedWorkaround(Runnable action) {
if (Threading.isSingleThreaded() && !Threading.isOpenGLThread()) {
// invokeOnOpenGLThread blocks the calling thread, although this is
// not documented
// http://www.javagaming.org/index.php/topic,18442.0.html
Threading.invokeOnOpenGLThread(true, action);
} else {
action.run();
}
}
private static void init(GL gl) {
hasOpenGL = gl != null;
if (!hasOpenGL) {
return;
}
hasNonPowerOfTwoTextures = gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two");
hasVBO = gl.isExtensionAvailable("GL_ARB_vertex_buffer_object");
hasFloatingPointTextures = gl.isExtensionAvailable("GL_ARB_texture_float");
glVendor = gl.glGetString(GL2.GL_VENDOR);
glRenderer = gl.glGetString(GL2.GL_RENDERER);
glVersion = gl.glGetString(GL2.GL_VERSION);
glShadingLanguageVersion = gl.glGetString(GL2.GL_SHADING_LANGUAGE_VERSION);
maxTextureSize = getInteger(gl, GL2.GL_MAX_TEXTURE_SIZE);
maxDrawBuffers = getInteger(gl, GL2.GL_MAX_DRAW_BUFFERS);
maxVertexTextureImageUnits = getInteger(gl, GL2.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
maxTextureImageUnits = getInteger(gl, GL2.GL_MAX_TEXTURE_IMAGE_UNITS);
}
/**
* Returns whether OpenGL is accessible.
* @return
*/
public static boolean hasOpenGL() {
return hasOpenGL;
}
/**
* Returns whether a required OpenGL version is present.
* @param reqMajorVersion
* @param reqMinorVersion
* @return
*/
public static boolean hasOpenGLVersion(int reqMajorVersion, int reqMinorVersion) {
int foundMajorVersion = 0;
int foundMinorVersion = 0;
if (!hasOpenGL()) {
return false;
}
StringTokenizer tokens = new StringTokenizer(glVersion, ". ");
if (!tokens.hasMoreElements()) {
return false;
}
foundMajorVersion = Integer.parseInt(tokens.nextToken());
if (foundMajorVersion > reqMajorVersion) {
return true;
}
if (foundMajorVersion < reqMajorVersion) {
return false;
}
if (!tokens.hasMoreElements()) {
return false;
}
foundMinorVersion = Integer.parseInt(tokens.nextToken());
return reqMinorVersion <= foundMinorVersion;
}
/**
* Returns whether textures can have dimensions differing from
* power of 2 values.
* @return
*/
public static boolean hasNonPowerOfTwoTextures() {
return hasNonPowerOfTwoTextures;
}
/**
* Returns whether vertex buffer objects are available.
* VBO are available with OpenGL 1.5 or earlier with an extension.
* @return
*/
public static boolean hasVBO() {
return hasVBO;
}
/**
* Returns whether floating point textures are supported.
* @return
*/
public static boolean hasFloatingPointTextures() {
return hasFloatingPointTextures;
}
public static String getGLVendor() {
return glVendor;
}
public static String getGLRenderer() {
return glRenderer;
}
public static String getGLVersion() {
return glVersion;
}
public static String getGLShadingLanguageVersion() {
return glShadingLanguageVersion;
}
public static int getMaxTextureSize() {
return maxTextureSize;
}
public static int getMaxDrawBuffers() {
return maxDrawBuffers;
}
/**
* Returns the maximum number of textures accessible in vertex shader
* @return
*/
public static int getMaxVertexTextureImageUnits() {
return maxVertexTextureImageUnits;
}
/**
* Returns the maximum number of textures accessible in a fragment shader
* @return
*/
public static int getMaxTextureImageUnits() {
return maxTextureImageUnits;
}
/**
* Returns whether PBuffers are available. pbuffers are not supported on
* older graphics cards (pre 1.5)
*/
public static boolean hasPBuffer() {
GLDrawableFactory factory = GLDrawableFactory.getFactory(defaultGLProfile);
return factory.canCreateGLPbuffer(defaultGraphicsDevice, defaultGLProfile);
}
private static int getInteger(GL gl, int id) {
IntBuffer params = IntBuffer.allocate(1);
gl.glGetIntegerv(id, params);
return params.get(0);
}
}