1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.opengl; 33 34 import org.lwjgl.LWJGLException; 35 import org.lwjgl.LWJGLUtil; 36 import org.lwjgl.Sys; 37 import org.lwjgl.opengles.EGLContext; 38 import org.lwjgl.opengles.GLContext; 39 import org.lwjgl.opengles.GLES20; 40 import org.lwjgl.opengles.PowerManagementEventException; 41 42 import static org.lwjgl.opengles.EGL.*; 43 44 /** 45 * <p/> 46 * Context encapsulates an OpenGL ES context. 47 * <p/> 48 * <p/> 49 * This class is thread-safe. 50 * 51 * @author elias_naur <elias_naur@users.sourceforge.net> 52 * @version $Revision: 3332 $ 53 * $Id: Context.java 3332 2010-04-20 18:21:05Z spasi $ 54 */ 55 final class ContextGLES implements org.lwjgl.opengl.Context { 56 57 /** The current Context */ 58 private static final ThreadLocal<ContextGLES> current_context_local = new ThreadLocal<ContextGLES>(); 59 60 /** Handle to the native GL rendering context */ 61 private final DrawableGLES drawable; 62 private final EGLContext eglContext; 63 64 private final org.lwjgl.opengles.ContextAttribs contextAttribs; 65 66 /** Whether the context has been destroyed */ 67 private boolean destroyed; 68 69 private boolean destroy_requested; 70 71 /** The thread that has this context current, or null. */ 72 private Thread thread; 73 74 static { Sys.initialize()75 Sys.initialize(); 76 } 77 getEGLContext()78 public EGLContext getEGLContext() { 79 return eglContext; 80 } 81 getContextAttribs()82 org.lwjgl.opengles.ContextAttribs getContextAttribs() { 83 return contextAttribs; 84 } 85 getCurrentContext()86 static ContextGLES getCurrentContext() { 87 return current_context_local.get(); 88 } 89 90 /** Create a context with the specified peer info and shared context */ ContextGLES(DrawableGLES drawable, org.lwjgl.opengles.ContextAttribs attribs, ContextGLES shared_context)91 ContextGLES(DrawableGLES drawable, org.lwjgl.opengles.ContextAttribs attribs, ContextGLES shared_context) throws LWJGLException { 92 if ( drawable == null ) 93 throw new IllegalArgumentException(); 94 95 ContextGLES context_lock = shared_context != null ? shared_context : this; 96 // If shared_context is not null, synchronize on it to make sure it is not deleted 97 // while this context is created. Otherwise, simply synchronize on ourself to avoid NPE 98 synchronized ( context_lock ) { 99 if ( shared_context != null && shared_context.destroyed ) 100 throw new IllegalArgumentException("Shared context is destroyed"); 101 102 this.drawable = drawable; 103 this.contextAttribs = attribs; 104 this.eglContext = drawable.getEGLDisplay().createContext(drawable.getEGLConfig(), 105 shared_context == null ? null : shared_context.eglContext, 106 attribs == null ? new org.lwjgl.opengles.ContextAttribs(2).getAttribList() : attribs.getAttribList()); 107 } 108 } 109 110 /** Release the current context (if any). After this call, no context is current. */ releaseCurrent()111 public void releaseCurrent() throws LWJGLException, PowerManagementEventException { 112 eglReleaseCurrent(drawable.getEGLDisplay()); 113 org.lwjgl.opengles.GLContext.useContext(null); 114 current_context_local.set(null); 115 116 synchronized ( this ) { 117 thread = null; 118 checkDestroy(); 119 } 120 } 121 122 /** Swap the buffers on the current context. Only valid for double-buffered contexts */ swapBuffers()123 public static void swapBuffers() throws LWJGLException, PowerManagementEventException { 124 ContextGLES current_context = getCurrentContext(); 125 if ( current_context != null ) 126 current_context.drawable.getEGLSurface().swapBuffers(); 127 } 128 canAccess()129 private boolean canAccess() { 130 return thread == null || Thread.currentThread() == thread; 131 } 132 checkAccess()133 private void checkAccess() { 134 if ( !canAccess() ) 135 throw new IllegalStateException("From thread " + Thread.currentThread() + ": " + thread + " already has the context current"); 136 } 137 138 /** Make the context current */ makeCurrent()139 public synchronized void makeCurrent() throws LWJGLException, PowerManagementEventException { 140 checkAccess(); 141 if ( destroyed ) 142 throw new IllegalStateException("Context is destroyed"); 143 thread = Thread.currentThread(); 144 current_context_local.set(this); 145 eglContext.makeCurrent(drawable.getEGLSurface()); 146 org.lwjgl.opengles.GLContext.useContext(this); 147 } 148 149 /** Query whether the context is current */ isCurrent()150 public synchronized boolean isCurrent() throws LWJGLException { 151 if ( destroyed ) 152 throw new IllegalStateException("Context is destroyed"); 153 return eglIsCurrentContext(eglContext); 154 } 155 checkDestroy()156 private void checkDestroy() { 157 if ( !destroyed && destroy_requested ) { 158 try { 159 eglContext.destroy(); 160 destroyed = true; 161 thread = null; 162 } catch (LWJGLException e) { 163 LWJGLUtil.log("Exception occurred while destroying context: " + e); 164 } 165 } 166 } 167 168 /** 169 * Set the buffer swap interval. This call is a best-attempt at changing 170 * the monitor swap interval, which is the minimum periodicity of color buffer swaps, 171 * measured in video frame periods, and is not guaranteed to be successful. 172 * <p/> 173 * A video frame period is the time required to display a full frame of video data. 174 */ setSwapInterval(int value)175 public static void setSwapInterval(int value) { 176 ContextGLES current_context = getCurrentContext(); 177 if ( current_context != null ) { 178 try { 179 current_context.drawable.getEGLDisplay().setSwapInterval(value); 180 } catch (LWJGLException e) { 181 LWJGLUtil.log("Failed to set swap interval. Reason: " + e.getMessage()); 182 } 183 } 184 } 185 186 /** 187 * Destroy the context. This method behaves the same as destroy() with the extra 188 * requirement that the context must be either current to the current thread or not 189 * current at all. 190 */ forceDestroy()191 public synchronized void forceDestroy() throws LWJGLException { 192 checkAccess(); 193 destroy(); 194 } 195 196 /** 197 * Request destruction of the Context. If the context is current, no context will be current after this call. 198 * The context is destroyed when no thread has it current. 199 */ destroy()200 public synchronized void destroy() throws LWJGLException { 201 if ( destroyed ) 202 return; 203 destroy_requested = true; 204 boolean was_current = isCurrent(); 205 int error = GLES20.GL_NO_ERROR; 206 if ( was_current ) { 207 if ( org.lwjgl.opengles.GLContext.getCapabilities() != null && GLContext.getCapabilities().OpenGLES20 ) 208 error = GLES20.glGetError(); 209 210 try { 211 releaseCurrent(); 212 } catch (PowerManagementEventException e) { 213 // Ignore 214 } 215 } 216 checkDestroy(); 217 if ( was_current && error != GLES20.GL_NO_ERROR ) 218 throw new OpenGLException(error); 219 } 220 releaseDrawable()221 public void releaseDrawable() throws LWJGLException { 222 } 223 224 } 225