/*
* Copyright (c) 2002-2011 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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 THE COPYRIGHT OWNER 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.
*/
package org.lwjgl.opengles;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.Sys;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
import static org.lwjgl.opengles.GLES20.*;
/**
*
* 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.
*
* 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
* @version $Revision: 3279 $
* $Id: GLContext.java 3279 2010-03-11 21:06:49Z spasi $
*/
public final class GLContext {
/** Maps threads to their current context's ContextCapabilities, if any */
private static final ThreadLocal current_capabilities = new ThreadLocal();
/**
* The getCapabilities() method is a potential hot spot in any LWJGL application, since
* it is needed for context capability discovery (e.g. is OpenGL 2.0 supported?), and
* 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.
*
* 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.
*
* '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.
*
* 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
* the correct ContextCapabilites (that is, the one from getThreadLocalCapabilites()),
* since no other thread can set the owner to anyone else than itself.
*/
private static CapabilitiesCacheEntry fast_path_cache = new CapabilitiesCacheEntry();
/**
* Simple lock-free cache of CapabilitesEntryCache to avoid allocating more than one
* cache entry per thread
*/
private static final ThreadLocal thread_cache_entries = new ThreadLocal();
/**
* The weak mapping from context Object instances to ContextCapabilities. Used
* to avoid recreating a ContextCapabilities every time a context is made current.
*/
private static final Map