mirror of
https://github.com/shadowfacts/lwjgl2-arm64.git
synced 2026-04-06 15:04:41 +00:00
Added support for OpenGL 3.0 functionality
Added support for OpenGL 3.0 context creation (MAJOR/MINOR versions, DEBUG mode, FORWARD_COMBATIBLE mode) Added support for OpenGL 3.0 context sharing Added support for OpenGL 3.0 extension detection Improved support for floating point PixelFormats (ARB_color_buffer_float) Added support for packed floating point PixelFormats (EXT_packed_float) Added support for sRGB PixelFormats (ARB_framebuffer_sRGB) Added support for pseudo-FORWARD_COMBATIBLE mode (deprecated functions not loaded) Added support for EXT_direct_state_access
This commit is contained in:
parent
0deaed34a5
commit
d7ee23f9b2
73 changed files with 4235 additions and 817 deletions
|
|
@ -31,38 +31,35 @@
|
|||
*/
|
||||
package org.lwjgl.opengl;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.Sys;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.IntBuffer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p/>
|
||||
* Manages GL contexts. Before any rendering is done by a LWJGL system, a call should be made to GLContext.useContext() with a
|
||||
* context. This will ensure that GLContext has an accurate reflection of the current context's capabilities and function
|
||||
* pointers.
|
||||
*
|
||||
* <p/>
|
||||
* This class is thread-safe in the sense that multiple threads can safely call all public methods. The class is also
|
||||
* thread-aware in the sense that it tracks a per-thread current context (including capabilities and function pointers).
|
||||
* That way, multiple threads can have multiple contexts current and render to them concurrently.
|
||||
*
|
||||
* @author elias_naur <elias_naur@users.sourceforge.net>
|
||||
* @version $Revision$
|
||||
* $Id$
|
||||
* $Id$
|
||||
*/
|
||||
public final class GLContext {
|
||||
/**
|
||||
* Maps threads to their current context's ContextCapabilities, if any
|
||||
*/
|
||||
|
||||
/** Maps threads to their current context's ContextCapabilities, if any */
|
||||
private final static ThreadLocal current_capabilities = new ThreadLocal();
|
||||
|
||||
/**
|
||||
|
|
@ -71,18 +68,18 @@ public final class GLContext {
|
|||
* for the function pointers of gl functions. However, the 'current_capabilities' ThreadLocal
|
||||
* is (relatively) expensive to look up, and since most OpenGL applications use are single threaded
|
||||
* rendering, the following two is an optimization for this case.
|
||||
*
|
||||
* <p/>
|
||||
* ThreadLocals can be thought of as a mapping between threads and values, so the idea
|
||||
* is to use a lock-less cache of mappings between threads and the current ContextCapabilities. The cache
|
||||
* could be any size, but in our case, we want a single sized cache for optimal performance
|
||||
* in the single threaded case.
|
||||
*
|
||||
* <p/>
|
||||
* 'fast_path_cache' is the most recent ContextCapabilities (potentially null) and its owner. By
|
||||
* recent I mean the last thread setting the value in setCapabilities(). When getCapabilities()
|
||||
* is called, a check to see if the current is the owner of the ContextCapabilities instance in
|
||||
* fast_path_cache. If so, the instance is returned, if not, some thread has since taken ownership
|
||||
* of the cache entry and the slower current_capabilities ThreadLocal is queried instead.
|
||||
*
|
||||
* <p/>
|
||||
* No locks are needed in get/setCapabilities, because even though fast_path_cache can be accessed
|
||||
* from multiple threads at once, we are guaranteed by the JVM spec that its value is always valid.
|
||||
* Furthermore, if the ownership test in getCapabilities() succeeds, the cache entry can only contain
|
||||
|
|
@ -120,7 +117,7 @@ public final class GLContext {
|
|||
public static ContextCapabilities getCapabilities() {
|
||||
CapabilitiesCacheEntry recent_cache_entry = fast_path_cache;
|
||||
// Check owner of cache entry
|
||||
if (recent_cache_entry.owner == Thread.currentThread()) {
|
||||
if ( recent_cache_entry.owner == Thread.currentThread() ) {
|
||||
/* The owner ship test succeeded, so the cache must contain the current ContextCapabilities instance
|
||||
* assert recent_cache_entry.capabilities == getThreadLocalCapabilities();
|
||||
*/
|
||||
|
|
@ -143,7 +140,7 @@ public final class GLContext {
|
|||
current_capabilities.set(capabilities);
|
||||
|
||||
CapabilitiesCacheEntry thread_cache_entry = (CapabilitiesCacheEntry)thread_cache_entries.get();
|
||||
if (thread_cache_entry == null) {
|
||||
if ( thread_cache_entry == null ) {
|
||||
thread_cache_entry = new CapabilitiesCacheEntry();
|
||||
thread_cache_entries.set(thread_cache_entry);
|
||||
}
|
||||
|
|
@ -163,8 +160,8 @@ public final class GLContext {
|
|||
return System.getProperty("os.name");
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < os_prefixes.length; i++)
|
||||
if (os_name.startsWith(os_prefixes[i])) {
|
||||
for ( int i = 0; i < os_prefixes.length; i++ )
|
||||
if ( os_name.startsWith(os_prefixes[i]) ) {
|
||||
String platform_function_name = function.replaceFirst(function_prefix, os_function_prefixes[i]);
|
||||
long address = getFunctionAddress(platform_function_name);
|
||||
return address;
|
||||
|
|
@ -172,9 +169,7 @@ public final class GLContext {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get a pointer to a named function in the OpenGL library
|
||||
*/
|
||||
/** Helper method to get a pointer to a named function in the OpenGL library */
|
||||
static native long getFunctionAddress(String name);
|
||||
|
||||
/**
|
||||
|
|
@ -183,21 +178,17 @@ public final class GLContext {
|
|||
* @return A Set containing all available extension strings.
|
||||
*/
|
||||
static Set getSupportedExtensions() {
|
||||
Set supported_extensions = new HashSet();
|
||||
String extensions_string = GL11.glGetString(GL11.GL_EXTENSIONS);
|
||||
if (extensions_string == null)
|
||||
throw new IllegalStateException("glGetString(GL_EXTENSIONS) returned null - is there a context current?");
|
||||
StringTokenizer tokenizer = new StringTokenizer(extensions_string);
|
||||
while ( tokenizer.hasMoreTokens() ) {
|
||||
String extension_string = tokenizer.nextToken();
|
||||
supported_extensions.add(extension_string);
|
||||
}
|
||||
String version = GL11.glGetString(GL11.GL_VERSION);
|
||||
if (version == null)
|
||||
final Set supported_extensions = new HashSet();
|
||||
|
||||
// Detect OpenGL version first
|
||||
|
||||
final String version = GL11.glGetString(GL11.GL_VERSION);
|
||||
if ( version == null )
|
||||
throw new IllegalStateException("glGetString(GL_VERSION) returned null - possibly caused by missing current context.");
|
||||
StringTokenizer version_tokenizer = new StringTokenizer(version, ". ");
|
||||
String major_string = version_tokenizer.nextToken();
|
||||
String minor_string = version_tokenizer.nextToken();
|
||||
|
||||
final StringTokenizer version_tokenizer = new StringTokenizer(version, ". ");
|
||||
final String major_string = version_tokenizer.nextToken();
|
||||
final String minor_string = version_tokenizer.nextToken();
|
||||
|
||||
int majorVersion = 0;
|
||||
int minorVersion = 0;
|
||||
|
|
@ -208,39 +199,47 @@ public final class GLContext {
|
|||
LWJGLUtil.log("The major and/or minor OpenGL version is malformed: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (majorVersion >= 2) {
|
||||
// ----------------------[ 2.X ]----------------------
|
||||
switch (minorVersion) {
|
||||
case 1:
|
||||
supported_extensions.add("OpenGL21");
|
||||
// Intentional fall through
|
||||
case 0:
|
||||
supported_extensions.add("OpenGL20");
|
||||
}
|
||||
// ----------------------[ 1.X ]----------------------
|
||||
supported_extensions.add("OpenGL11");
|
||||
supported_extensions.add("OpenGL12");
|
||||
supported_extensions.add("OpenGL13");
|
||||
supported_extensions.add("OpenGL14");
|
||||
// ----------------------[ 3.X ]----------------------
|
||||
if ( 3 <= majorVersion )
|
||||
supported_extensions.add("OpenGL30");
|
||||
|
||||
// ----------------------[ 2.X ]----------------------
|
||||
if ( 2 < majorVersion || (2 == majorVersion && 1 <= minorVersion) )
|
||||
supported_extensions.add("OpenGL21");
|
||||
if ( 2 <= majorVersion )
|
||||
supported_extensions.add("OpenGL20");
|
||||
|
||||
// ----------------------[ 1.X ]----------------------
|
||||
if ( 1 < majorVersion || 5 <= minorVersion )
|
||||
supported_extensions.add("OpenGL15");
|
||||
} else if (majorVersion == 1) {
|
||||
switch (minorVersion) {
|
||||
case 5:
|
||||
supported_extensions.add("OpenGL15");
|
||||
// Intentional fall through
|
||||
case 4:
|
||||
supported_extensions.add("OpenGL14");
|
||||
// Intentional fall through
|
||||
case 3:
|
||||
supported_extensions.add("OpenGL13");
|
||||
// Intentional fall through
|
||||
case 2:
|
||||
supported_extensions.add("OpenGL12");
|
||||
// Intentional fall through
|
||||
case 1:
|
||||
supported_extensions.add("OpenGL11");
|
||||
}
|
||||
if ( 1 < majorVersion || 4 <= minorVersion )
|
||||
supported_extensions.add("OpenGL14");
|
||||
if ( 1 < majorVersion || 3 <= minorVersion )
|
||||
supported_extensions.add("OpenGL13");
|
||||
if ( 1 < majorVersion || 2 <= minorVersion )
|
||||
supported_extensions.add("OpenGL12");
|
||||
if ( 1 < majorVersion || 1 <= minorVersion )
|
||||
supported_extensions.add("OpenGL11");
|
||||
|
||||
if ( majorVersion < 3 ) {
|
||||
// Parse EXTENSIONS string
|
||||
final String extensions_string = GL11.glGetString(GL11.GL_EXTENSIONS);
|
||||
if ( extensions_string == null )
|
||||
throw new IllegalStateException("glGetString(GL_EXTENSIONS) returned null - is there a context current?");
|
||||
|
||||
final StringTokenizer tokenizer = new StringTokenizer(extensions_string);
|
||||
while ( tokenizer.hasMoreTokens() )
|
||||
supported_extensions.add(tokenizer.nextToken());
|
||||
} else {
|
||||
// Use forward compatible indexed EXTENSIONS
|
||||
final IntBuffer buffer = BufferUtils.createIntBuffer(16);
|
||||
GL11.glGetInteger(GL30.GL_NUM_EXTENSIONS, buffer);
|
||||
final int extensionCount = buffer.get(0);
|
||||
|
||||
for ( int i = 0; i < extensionCount; i++ )
|
||||
supported_extensions.add(GL30.glGetStringi(GL11.GL_EXTENSIONS, i));
|
||||
}
|
||||
|
||||
return supported_extensions;
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +249,7 @@ public final class GLContext {
|
|||
*/
|
||||
static void initNativeStubs(final Class extension_class, Set supported_extensions, String ext_name) {
|
||||
resetNativeStubs(extension_class);
|
||||
if (supported_extensions.contains(ext_name)) {
|
||||
if ( supported_extensions.contains(ext_name) ) {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
|
|
@ -281,32 +280,53 @@ public final class GLContext {
|
|||
* @throws LWJGLException if context non-null, and the gl library can't be loaded or the basic GL11 functions can't be loaded
|
||||
*/
|
||||
public static synchronized void useContext(Object context) throws LWJGLException {
|
||||
if (context == null) {
|
||||
useContext(context, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a GL context the current LWJGL context by loading GL function pointers. The context must be current before a call to
|
||||
* this method! Instead it simply ensures that the current context is reflected accurately by GLContext's extension caps and
|
||||
* function pointers. Use useContext(null) when no context is active. <p>If the context is the same as last time, then this is
|
||||
* a no-op. <p>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. <p>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.
|
||||
* <p>If forwardCombatible is true, function pointers of deprecated GL11-GL21 functionality will not be loaded. Calling a deprecated
|
||||
* function using the specified context will result in an <code>IllegalStateException</code>.
|
||||
*
|
||||
* @param context The context object, which uniquely identifies a GL context. If context is null, the native stubs are
|
||||
* unloaded.
|
||||
* @param forwardCombatible If the context is a forward combatible context (does not expose deprecated functionality, see XGL_ARB_create_context)
|
||||
*
|
||||
* @throws LWJGLException if context non-null, and the gl library can't be loaded or the basic GL11 functions can't be loaded
|
||||
*/
|
||||
public static synchronized void useContext(Object context, boolean forwardCombatible) throws LWJGLException {
|
||||
if ( context == null ) {
|
||||
ContextCapabilities.unloadAllStubs();
|
||||
setCapabilities(null);
|
||||
if (did_auto_load)
|
||||
if ( did_auto_load )
|
||||
unloadOpenGLLibrary();
|
||||
return;
|
||||
}
|
||||
if (gl_ref_count == 0) {
|
||||
if ( gl_ref_count == 0 ) {
|
||||
loadOpenGLLibrary();
|
||||
did_auto_load = true;
|
||||
}
|
||||
try {
|
||||
ContextCapabilities capabilities = (ContextCapabilities)capability_cache.get(context);
|
||||
if (capabilities == null) {
|
||||
if ( capabilities == null ) {
|
||||
/*
|
||||
* The capabilities object registers itself as current. This behaviour is caused
|
||||
* by a chicken-and-egg situation where the constructor needs to call GL functions
|
||||
* as part of its capability discovery, but GL functions cannot be called before
|
||||
* a capabilities object has been set.
|
||||
*/
|
||||
new ContextCapabilities();
|
||||
new ContextCapabilities(forwardCombatible);
|
||||
capability_cache.put(context, getCapabilities());
|
||||
} else
|
||||
setCapabilities(capabilities);
|
||||
} catch (LWJGLException e) {
|
||||
if (did_auto_load)
|
||||
if ( did_auto_load )
|
||||
unloadOpenGLLibrary();
|
||||
throw e;
|
||||
}
|
||||
|
|
@ -314,7 +334,7 @@ public final class GLContext {
|
|||
|
||||
/** If the OpenGL reference count is 0, the library is loaded. The reference count is then incremented. */
|
||||
public static synchronized void loadOpenGLLibrary() throws LWJGLException {
|
||||
if (gl_ref_count == 0)
|
||||
if ( gl_ref_count == 0 )
|
||||
nLoadOpenGLLibrary();
|
||||
gl_ref_count++;
|
||||
}
|
||||
|
|
@ -328,7 +348,7 @@ public final class GLContext {
|
|||
* Unload the native OpenGL library unless we're on linux, since
|
||||
* some drivers (NVIDIA proprietary) crash on exit when unloading the library.
|
||||
*/
|
||||
if (gl_ref_count == 0 && LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_LINUX)
|
||||
if ( gl_ref_count == 0 && LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_LINUX )
|
||||
nUnloadOpenGLLibrary();
|
||||
}
|
||||
|
||||
|
|
@ -338,6 +358,7 @@ public final class GLContext {
|
|||
static native void resetNativeStubs(Class clazz);
|
||||
|
||||
private final static class CapabilitiesCacheEntry {
|
||||
|
||||
Thread owner;
|
||||
ContextCapabilities capabilities;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue