+ * @version $Revision$
*/
-public interface GLContext {
+public final class GLContext {
+
+ /** The currently initialised context */
+ private static WeakReference currentContext;
+
+ /** A map of WeakReferences to contexts to LWJGL pointers-to-extension-structs */
+ private static final Map contextMap = new HashMap();
+
+ /*
+ * Available extensions
+ */
+ public static boolean GL_ARB_imaging;
+ public static boolean GL_ARB_depth_texture;
+ public static boolean GL_ARB_fragment_program;
+ public static boolean GL_ARB_fragment_shader;
+ public static boolean GL_ARB_matrix_palette;
+ public static boolean GL_ARB_multisample;
+ public static boolean GL_ARB_multitexture;
+ public static boolean GL_ARB_occlusion_query;
+ public static boolean GL_ARB_point_parameters;
+ public static boolean GL_ARB_point_sprite;
+ public static boolean GL_ARB_shading_language;
+ public static boolean GL_ARB_shader_objects;
+ public static boolean GL_ARB_shadow;
+ public static boolean GL_ARB_shadow_ambient;
+ public static boolean GL_ARB_texture_compression;
+ public static boolean GL_ARB_texture_env_add;
+ public static boolean GL_ARB_texture_env_dot3;
+ public static boolean GL_ARB_texture_env_combine;
+ public static boolean GL_ARB_texture_env_crossbar;
+ public static boolean GL_ARB_texture_border_clamp;
+ public static boolean GL_ARB_texture_cube_map;
+ public static boolean GL_ARB_texture_mirrored_repeat;
+ public static boolean GL_ARB_texture_non_power_of_two;
+ public static boolean GL_ARB_transpose_matrix;
+ public static boolean GL_ARB_vertex_blend;
+ public static boolean GL_ARB_vertex_program;
+ public static boolean GL_ARB_vertex_buffer_object;
+ public static boolean GL_ARB_vertex_shader;
+ public static boolean GL_ARB_window_pos;
+
+ public static boolean GL_EXT_abgr;
+ public static boolean GL_EXT_bgra;
+ public static boolean GL_EXT_blend_function_separate;
+ public static boolean GL_EXT_blend_subtract;
+ public static boolean GL_EXT_compiled_vertex_array;
+ public static boolean GL_EXT_draw_range_elements;
+ public static boolean GL_EXT_multi_draw_arrays;
+ public static boolean GL_EXT_fog_coord;
+ public static boolean GL_EXT_packed_pixels;
+ public static boolean GL_EXT_point_parameters;
+ public static boolean GL_EXT_rescale_normal;
+ public static boolean GL_EXT_secondary_color;
+ public static boolean GL_EXT_separate_specular_color;
+ public static boolean GL_EXT_shadow_funcs;
+ public static boolean GL_EXT_shared_texture_palette;
+ public static boolean GL_EXT_stencil_two_side;
+ public static boolean GL_EXT_stencil_wrap;
+ public static boolean GL_EXT_texture_compression_s3tc;
+ public static boolean GL_EXT_texture_env_combine;
+ public static boolean GL_EXT_texture_env_dot3;
+ public static boolean GL_EXT_texture_filter_anisotropic;
+ public static boolean GL_EXT_texture_lod_bias;
+ public static boolean GL_EXT_texture_rectangle;
+ public static boolean GL_EXT_vertex_shader;
+ public static boolean GL_EXT_vertex_weighting;
+
+ public static boolean GL_ATI_draw_buffers;
+ public static boolean GL_ATI_element_array;
+ public static boolean GL_ATI_envmap_bumpmap;
+ public static boolean GL_ATI_fragment_shader;
+ public static boolean GL_ATI_map_object_buffer;
+ public static boolean GL_ATI_pn_triangles;
+ public static boolean GL_ATI_texture_float;
+ public static boolean GL_ATI_texture_mirror_once;
+ public static boolean GL_ATI_vertex_array_object;
+ public static boolean GL_ATI_vertex_attrib_array_object;
+ public static boolean GL_ATI_vertex_streams;
+ public static boolean GL_ATI_separate_stencil;
+
+ public static boolean GL_ATIX_point_sprites;
+ public static boolean GL_ATIX_texture_env_route;
+
+ public static boolean GL_NV_blend_square;
+ public static boolean GL_NV_copy_depth_to_color;
+ public static boolean GL_NV_depth_clamp;
+ public static boolean GL_NV_evaluators;
+ public static boolean GL_NV_fence;
+ public static boolean GL_NV_fragment_program;
+ public static boolean GL_NV_float_buffer;
+ public static boolean GL_NV_fog_distance;
+ public static boolean GL_NV_half_float;
+ public static boolean GL_NV_light_max_exponent;
+ public static boolean GL_NV_multisample_filter_hint;
+ public static boolean GL_NV_occlusion_query;
+ public static boolean GL_NV_packed_depth_stencil;
+ public static boolean GL_NV_pixel_data_range;
+ public static boolean GL_NV_point_sprite;
+ public static boolean GL_NV_primitive_restart;
+ public static boolean GL_NV_register_combiners;
+ public static boolean GL_NV_register_combiners2;
+ public static boolean GL_NV_texgen_reflection;
+ public static boolean GL_NV_texture_compression_vtc;
+ public static boolean GL_NV_texture_env_combine4;
+ public static boolean GL_NV_texture_expand_normal;
+ public static boolean GL_NV_texture_rectangle;
+ public static boolean GL_NV_texture_shader;
+ public static boolean GL_NV_texture_shader2;
+ public static boolean GL_NV_texture_shader3;
+ public static boolean GL_NV_vertex_array_range;
+ public static boolean GL_NV_vertex_array_range2;
+ public static boolean GL_NV_vertex_program;
+ public static boolean GL_NV_vertex_program1_1;
+ public static boolean GL_NV_vertex_program2;
+
+ public static boolean OpenGL11;
+ public static boolean OpenGL12;
+ public static boolean OpenGL13;
+ public static boolean OpenGL14;
+ public static boolean OpenGL15;
+
+ static {
+ System.loadLibrary(Sys.getLibraryName());
+ }
+
+ private static void setExtensionFields(Set exts, HashMap field_map) {
+ Sys.log("Available extensions:");
+ Iterator it = exts.iterator();
+ while ( it.hasNext() ) {
+ String ext = (String)it.next();
+ Sys.log(ext);
+
+ Field f = (Field)field_map.get(ext);
+ if ( f != null ) {
+ try {
+ f.setBoolean(GLContext.class, true);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace(System.err);
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Determine which extensions are available. Use this to initialize capability fields. Can only be
+ * called _after_ a GLWindow or Pbuffer has been created (or a context from some other GL library).
+ * Using LWJGL, this method is called automatically for you when the LWJGL Window is created and there
+ * is no need to call it yourself.
+ *
+ * @param exts A Set of OpenGL extension string names
+ */
+ public static void determineAvailableExtensions(Set exts) {
+ // Grab all the public static booleans out of this class
+ Field[] fields = GLContext.class.getDeclaredFields();
+ HashMap map = new HashMap(fields.length);
+ for ( int i = 0; i < fields.length; i++ ) {
+ if ( Modifier.isStatic(fields[i].getModifiers()) && fields[i].getType() == boolean.class ) {
+ map.put(fields[i].getName(), fields[i]);
+ // reset fields
+ try {
+ fields[i].setBoolean(GLContext.class, false);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace(System.err);
+ }
+ }
+ }
+
+ setExtensionFields(exts, map);
+ }
/**
- * Make this context the current rendering context for the current Thread.
+ * Makes a GL context the current context. This method does not make the context current though!
+ * Instead it simply ensures that the current context is reflected accurately by GLContext's
+ * extension caps and function pointers.
+ * If the context is the same as last time, then this is a no-op.
+ *
If the context has not been encountered before it will be fully initialized from scratch.
+ * Otherwise a cached set of caps and function pointers will be used.
+ *
The reference to the context is held in a weak reference; therefore if no strong reference
+ * exists to the GL context it will automatically be forgotten by the VM at an indeterminate point
+ * in the future, freeing up a little RAM.
+ * @param context The context object, which uniquely identifies a GL context
*/
- public void makeCurrent();
+ public static synchronized void setContext(Object context) {
+ // Is this the same as last time?
+ Object current = currentContext == null ? null : currentContext.get();
+ if (current == context) {
+ // Yes, so we don't need to do anything. Our caps and function pointers are still valid.
+ return;
+ }
+
+ // Ok, now it's the current context.
+ currentContext = new WeakReference(context);
+
+ // Look in the context map to see if we've encountered this context before
+ Integer encountered = (Integer) contextMap.get(currentContext);
+ if (encountered != null) {
+ reinit(encountered.intValue());
+ } else {
+ contextMap.put(currentContext, new Integer(init()));
+ }
+
+ // Now determine the available extensions
+
+ }
/**
- * Get the width of the context in pixels
- * @return int
+ * Native method to initialize a context from scratch or load its function pointers from a
+ * cache.
+ * @return a LWJGL context-index-pointer
*/
- public int getWidth();
+ private static native int init();
/**
- * Get the height of the context in pixels
- * @return int
+ * Native method to re-initialize a context.
+ * @param context Hash code of the context object
*/
- public int getHeight();
-
+ private static native int reinit(int context);
+
}
diff --git a/src/java/org/lwjgl/opengl/Pbuffer.java b/src/java/org/lwjgl/opengl/Pbuffer.java
index 19d2fb8e..d700a162 100644
--- a/src/java/org/lwjgl/opengl/Pbuffer.java
+++ b/src/java/org/lwjgl/opengl/Pbuffer.java
@@ -47,7 +47,7 @@ import org.lwjgl.Sys;
* @author elias_naur
* @version $Revision$
*/
-public final class Pbuffer implements GLContext {
+public final class Pbuffer {
public static final int PBUFFER_SUPPORTED = 1;
diff --git a/src/java/org/lwjgl/opengl/VBOTracker.java b/src/java/org/lwjgl/opengl/VBOTracker.java
index 4e6ab10d..5637b074 100644
--- a/src/java/org/lwjgl/opengl/VBOTracker.java
+++ b/src/java/org/lwjgl/opengl/VBOTracker.java
@@ -71,7 +71,7 @@ class VBOTracker {
* VBO tracker.
* @param context
*/
- static synchronized void setCurrent(GLContext context) {
+ static synchronized void setCurrent(Object context) {
current_tracker = (VBOTracker) contextToTracker.get(context);
if (current_tracker == null) {
current_tracker = new VBOTracker();
@@ -83,7 +83,7 @@ class VBOTracker {
* Remove a context when it is about to be destroyed.
* @param context
*/
- static synchronized void remove(GLContext context) {
+ static synchronized void remove(Object context) {
contextToTracker.remove(context);
if (current_tracker == context) {
current_tracker = null;
diff --git a/src/java/org/lwjgl/opengl/Window.java b/src/java/org/lwjgl/opengl/Window.java
index 38282001..a81a6c26 100644
--- a/src/java/org/lwjgl/opengl/Window.java
+++ b/src/java/org/lwjgl/opengl/Window.java
@@ -85,24 +85,8 @@ public final class Window {
/** Tracks VBO state for the window context */
private static VBOTracker vbo_tracker;
- /** Context: delegates calls to Window */
- private static class Context implements GLContext {
-
- public void makeCurrent() {
- Window.makeCurrent();
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
- }
-
/** A unique context object, so we can track different contexts between creates() and destroys() */
- private static Context context;
+ private static Window context;
/**
* Only constructed by ourselves
@@ -114,7 +98,7 @@ public final class Window {
* @return the width of the window
*/
public static int getWidth() {
- assert isCreated() : "Cannot get width on uncreated window";
+ assert isCreated() : "Cannot get width on uncreated window";
return width;
}
@@ -122,7 +106,7 @@ public final class Window {
* @return the height of the window
*/
public static int getHeight() {
- assert isCreated() : "Cannot get height on uncreated window";
+ assert isCreated() : "Cannot get height on uncreated window";
return height;
}
@@ -130,7 +114,7 @@ public final class Window {
* @return the title of the window
*/
public static String getTitle() {
- assert isCreated() : "Cannot get title on uncreated window";
+ assert isCreated() : "Cannot get title on uncreated window";
return title;
}
@@ -241,7 +225,7 @@ public final class Window {
public static synchronized void makeCurrent() {
assert isCreated() : "No window has been created.";
nMakeCurrent();
- VBOTracker.setCurrent(context);
+ GLContext.setContext(context);
}
/**
@@ -331,9 +315,9 @@ public final class Window {
private static void createWindow(int bpp, int alpha, int depth, int stencil, int samples) throws Exception {
HashSet extensions = new HashSet();
nCreate(title, x, y, width, height, fullscreen, bpp, alpha, depth, stencil, samples, extensions);
- context = new Context();
- context.makeCurrent();
- GLCaps.determineAvailableExtensions(extensions);
+ context = new Window();
+ makeCurrent();
+ GLContext.determineAvailableExtensions(extensions);
}
/**
@@ -346,14 +330,13 @@ public final class Window {
}
makeCurrent();
nDestroy();
- VBOTracker.remove(context);
context = null;
}
/**
* @return the unique Window context (or null, if the Window has not been created)
*/
- public static GLContext getContext() {
+ public static Object getContext() {
return context;
}
diff --git a/src/java/org/lwjgl/test/opengl/Grass.java b/src/java/org/lwjgl/test/opengl/Grass.java
index 12797611..8f9dd5ca 100644
--- a/src/java/org/lwjgl/test/opengl/Grass.java
+++ b/src/java/org/lwjgl/test/opengl/Grass.java
@@ -54,7 +54,7 @@ import org.lwjgl.DisplayMode;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GLCaps;
+import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.NVVertexProgram;
import org.lwjgl.opengl.Window;
import org.lwjgl.opengl.glu.GLU;
@@ -139,7 +139,7 @@ public class Grass {
public static void main(String[] args) {
ByteBuffer byte_buf = ByteBuffer.allocateDirect(4);
byte_buf.order(ByteOrder.nativeOrder());
- System.out.println("Vertex program supported: " + GLCaps.GL_NV_vertex_program);
+ System.out.println("Vertex program supported: " + GLContext.GL_NV_vertex_program);
NVVertexProgram.glGenProgramsNV(byte_buf.asIntBuffer());
IntBuffer int_buf = byte_buf.asIntBuffer();
if (int_buf.get(0) == 0)
diff --git a/src/java/org/lwjgl/test/opengl/VBOIndexTest.java b/src/java/org/lwjgl/test/opengl/VBOIndexTest.java
index 2025084e..3d9e4fdb 100644
--- a/src/java/org/lwjgl/test/opengl/VBOIndexTest.java
+++ b/src/java/org/lwjgl/test/opengl/VBOIndexTest.java
@@ -53,7 +53,7 @@ import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GLCaps;
+import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.Window;
import org.lwjgl.opengl.glu.GLU;
@@ -206,7 +206,7 @@ public final class VBOIndexTest {
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
- if (!GLCaps.GL_ARB_vertex_buffer_object) {
+ if (!GLContext.GL_ARB_vertex_buffer_object) {
System.out.println("ARB VBO not supported!");
System.exit(1);
}
diff --git a/src/java/org/lwjgl/test/opengl/VBOTest.java b/src/java/org/lwjgl/test/opengl/VBOTest.java
index bd5185a6..fdac7216 100644
--- a/src/java/org/lwjgl/test/opengl/VBOTest.java
+++ b/src/java/org/lwjgl/test/opengl/VBOTest.java
@@ -53,7 +53,7 @@ import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GLCaps;
+import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.Window;
import org.lwjgl.opengl.glu.GLU;
@@ -189,7 +189,7 @@ public final class VBOTest {
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
- if (!GLCaps.GL_ARB_vertex_buffer_object) {
+ if (!GLContext.GL_ARB_vertex_buffer_object) {
System.out.println("ARB VBO not supported!");
System.exit(1);
}