1cfd74d65d832137e20e193c960802afba73b5d38sm/* 23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project 3cfd74d65d832137e20e193c960802afba73b5d38sm * 4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License"); 5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License. 6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at 7cfd74d65d832137e20e193c960802afba73b5d38sm * 8cfd74d65d832137e20e193c960802afba73b5d38sm * http://www.apache.org/licenses/LICENSE-2.0 9cfd74d65d832137e20e193c960802afba73b5d38sm * 10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software 11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS, 12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and 14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License. 15cfd74d65d832137e20e193c960802afba73b5d38sm */ 16cfd74d65d832137e20e193c960802afba73b5d38sm 17cfd74d65d832137e20e193c960802afba73b5d38smpackage com.replica.replicaisland; 18cfd74d65d832137e20e193c960802afba73b5d38sm 19cfd74d65d832137e20e193c960802afba73b5d38smimport java.io.Writer; 20cfd74d65d832137e20e193c960802afba73b5d38smimport java.util.ArrayList; 21cfd74d65d832137e20e193c960802afba73b5d38sm 22cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGL10; 23cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGL11; 24cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLConfig; 25cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLContext; 26cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLDisplay; 27cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLSurface; 28cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.opengles.GL; 29cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.opengles.GL10; 30cfd74d65d832137e20e193c960802afba73b5d38sm 31cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.Context; 32cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.pm.ConfigurationInfo; 33cfd74d65d832137e20e193c960802afba73b5d38smimport android.opengl.GLDebugHelper; 34cfd74d65d832137e20e193c960802afba73b5d38smimport android.util.AttributeSet; 35cfd74d65d832137e20e193c960802afba73b5d38smimport android.view.SurfaceHolder; 36cfd74d65d832137e20e193c960802afba73b5d38smimport android.view.SurfaceView; 37cfd74d65d832137e20e193c960802afba73b5d38sm 38cfd74d65d832137e20e193c960802afba73b5d38sm/** 39cfd74d65d832137e20e193c960802afba73b5d38sm * An implementation of SurfaceView that uses the dedicated surface for 40cfd74d65d832137e20e193c960802afba73b5d38sm * displaying OpenGL rendering. 41cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 42cfd74d65d832137e20e193c960802afba73b5d38sm * A GLSurfaceView provides the following features: 43cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 44cfd74d65d832137e20e193c960802afba73b5d38sm * <ul> 45cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Manages a surface, which is a special piece of memory that can be 46cfd74d65d832137e20e193c960802afba73b5d38sm * composited into the Android view system. 47cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Manages an EGL display, which enables OpenGL to render into a surface. 48cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Accepts a user-provided Renderer object that does the actual rendering. 49cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Renders on a dedicated thread to decouple rendering performance from the 50cfd74d65d832137e20e193c960802afba73b5d38sm * UI thread. 51cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Supports both on-demand and continuous rendering. 52cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls. 53cfd74d65d832137e20e193c960802afba73b5d38sm * </ul> 54cfd74d65d832137e20e193c960802afba73b5d38sm * 55cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Using GLSurfaceView</h3> 56cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 57cfd74d65d832137e20e193c960802afba73b5d38sm * Typically you use GLSurfaceView by subclassing it and overriding one or more of the 58cfd74d65d832137e20e193c960802afba73b5d38sm * View system input event methods. If your application does not need to override event 59cfd74d65d832137e20e193c960802afba73b5d38sm * methods then GLSurfaceView can be used as-is. For the most part 60cfd74d65d832137e20e193c960802afba73b5d38sm * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. 61cfd74d65d832137e20e193c960802afba73b5d38sm * For example, unlike a regular View, drawing is delegated to a separate Renderer object which 62cfd74d65d832137e20e193c960802afba73b5d38sm * is registered with the GLSurfaceView 63cfd74d65d832137e20e193c960802afba73b5d38sm * using the {@link #setRenderer(Renderer)} call. 64cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 65cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Initializing GLSurfaceView</h3> 66cfd74d65d832137e20e193c960802afba73b5d38sm * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. 67cfd74d65d832137e20e193c960802afba73b5d38sm * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or 68cfd74d65d832137e20e193c960802afba73b5d38sm * more of these methods before calling setRenderer: 69cfd74d65d832137e20e193c960802afba73b5d38sm * <ul> 70cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setDebugFlags(int)} 71cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(boolean)} 72cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 73cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 74cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setGLWrapper(GLWrapper)} 75cfd74d65d832137e20e193c960802afba73b5d38sm * </ul> 76cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 77cfd74d65d832137e20e193c960802afba73b5d38sm * <h4>Choosing an EGL Configuration</h4> 78cfd74d65d832137e20e193c960802afba73b5d38sm * A given Android device may support multiple possible types of drawing surfaces. 79cfd74d65d832137e20e193c960802afba73b5d38sm * The available surfaces may differ in how may channels of data are present, as 80cfd74d65d832137e20e193c960802afba73b5d38sm * well as how many bits are allocated to each channel. Therefore, the first thing 81cfd74d65d832137e20e193c960802afba73b5d38sm * GLSurfaceView has to do when starting to render is choose what type of surface to use. 82cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 83cfd74d65d832137e20e193c960802afba73b5d38sm * By default GLSurfaceView chooses an available surface that's closest to a 16-bit R5G6B5 surface 84cfd74d65d832137e20e193c960802afba73b5d38sm * with a 16-bit depth buffer and no stencil. If you would prefer a different surface (for example, 85cfd74d65d832137e20e193c960802afba73b5d38sm * if you do not need a depth buffer) you can override the default behavior by calling one of the 86cfd74d65d832137e20e193c960802afba73b5d38sm * setEGLConfigChooser methods. 87cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 88cfd74d65d832137e20e193c960802afba73b5d38sm * <h4>Debug Behavior</h4> 89cfd74d65d832137e20e193c960802afba73b5d38sm * You can optionally modify the behavior of GLSurfaceView by calling 90cfd74d65d832137e20e193c960802afba73b5d38sm * one or more of the debugging methods {@link #setDebugFlags(int)}, 91cfd74d65d832137e20e193c960802afba73b5d38sm * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but 92cfd74d65d832137e20e193c960802afba73b5d38sm * typically they are called before setRenderer so that they take effect immediately. 93cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 94cfd74d65d832137e20e193c960802afba73b5d38sm * <h4>Setting a Renderer</h4> 95cfd74d65d832137e20e193c960802afba73b5d38sm * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. 96cfd74d65d832137e20e193c960802afba73b5d38sm * The renderer is 97cfd74d65d832137e20e193c960802afba73b5d38sm * responsible for doing the actual OpenGL rendering. 98cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 99cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Rendering Mode</h3> 100cfd74d65d832137e20e193c960802afba73b5d38sm * Once the renderer is set, you can control whether the renderer draws 101cfd74d65d832137e20e193c960802afba73b5d38sm * continuously or on-demand by calling 102cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #setRenderMode}. The default is continuous rendering. 103cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 104cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Activity Life-cycle</h3> 105cfd74d65d832137e20e193c960802afba73b5d38sm * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients 106cfd74d65d832137e20e193c960802afba73b5d38sm * are required to call {@link #onPause()} when the activity pauses and 107cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to 108cfd74d65d832137e20e193c960802afba73b5d38sm * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate 109cfd74d65d832137e20e193c960802afba73b5d38sm * the OpenGL display. 110cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 111cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Handling events</h3> 112cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 113cfd74d65d832137e20e193c960802afba73b5d38sm * To handle an event you will typically subclass GLSurfaceView and override the 114cfd74d65d832137e20e193c960802afba73b5d38sm * appropriate method, just as you would with any other View. However, when handling 115cfd74d65d832137e20e193c960802afba73b5d38sm * the event, you may need to communicate with the Renderer object 116cfd74d65d832137e20e193c960802afba73b5d38sm * that's running in the rendering thread. You can do this using any 117cfd74d65d832137e20e193c960802afba73b5d38sm * standard Java cross-thread communication mechanism. In addition, 118cfd74d65d832137e20e193c960802afba73b5d38sm * one relatively easy way to communicate with your renderer is 119cfd74d65d832137e20e193c960802afba73b5d38sm * to call 120cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #queueEvent(Runnable)}. For example: 121cfd74d65d832137e20e193c960802afba73b5d38sm * <pre class="prettyprint"> 122cfd74d65d832137e20e193c960802afba73b5d38sm * class MyGLSurfaceView extends GLSurfaceView { 123cfd74d65d832137e20e193c960802afba73b5d38sm * 124cfd74d65d832137e20e193c960802afba73b5d38sm * private MyRenderer mMyRenderer; 125cfd74d65d832137e20e193c960802afba73b5d38sm * 126cfd74d65d832137e20e193c960802afba73b5d38sm * public void start() { 127cfd74d65d832137e20e193c960802afba73b5d38sm * mMyRenderer = ...; 128cfd74d65d832137e20e193c960802afba73b5d38sm * setRenderer(mMyRenderer); 129cfd74d65d832137e20e193c960802afba73b5d38sm * } 130cfd74d65d832137e20e193c960802afba73b5d38sm * 131cfd74d65d832137e20e193c960802afba73b5d38sm * public boolean onKeyDown(int keyCode, KeyEvent event) { 132cfd74d65d832137e20e193c960802afba73b5d38sm * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 133cfd74d65d832137e20e193c960802afba73b5d38sm * queueEvent(new Runnable() { 134cfd74d65d832137e20e193c960802afba73b5d38sm * // This method will be called on the rendering 135cfd74d65d832137e20e193c960802afba73b5d38sm * // thread: 136cfd74d65d832137e20e193c960802afba73b5d38sm * public void run() { 137cfd74d65d832137e20e193c960802afba73b5d38sm * mMyRenderer.handleDpadCenter(); 138cfd74d65d832137e20e193c960802afba73b5d38sm * }}); 139cfd74d65d832137e20e193c960802afba73b5d38sm * return true; 140cfd74d65d832137e20e193c960802afba73b5d38sm * } 141cfd74d65d832137e20e193c960802afba73b5d38sm * return super.onKeyDown(keyCode, event); 142cfd74d65d832137e20e193c960802afba73b5d38sm * } 143cfd74d65d832137e20e193c960802afba73b5d38sm * } 144cfd74d65d832137e20e193c960802afba73b5d38sm * </pre> 145cfd74d65d832137e20e193c960802afba73b5d38sm * 146cfd74d65d832137e20e193c960802afba73b5d38sm */ 147cfd74d65d832137e20e193c960802afba73b5d38smpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 148cfd74d65d832137e20e193c960802afba73b5d38sm private final static boolean LOG_THREADS = false; 149cfd74d65d832137e20e193c960802afba73b5d38sm private final static boolean LOG_SURFACE = true; 150cfd74d65d832137e20e193c960802afba73b5d38sm private final static boolean LOG_RENDERER = false; 151cfd74d65d832137e20e193c960802afba73b5d38sm // Work-around for bug 2263168 152cfd74d65d832137e20e193c960802afba73b5d38sm private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true; 153cfd74d65d832137e20e193c960802afba73b5d38sm /** 154cfd74d65d832137e20e193c960802afba73b5d38sm * The renderer only renders 155cfd74d65d832137e20e193c960802afba73b5d38sm * when the surface is created, or when {@link #requestRender} is called. 156cfd74d65d832137e20e193c960802afba73b5d38sm * 157cfd74d65d832137e20e193c960802afba73b5d38sm * @see #getRenderMode() 158cfd74d65d832137e20e193c960802afba73b5d38sm * @see #setRenderMode(int) 159cfd74d65d832137e20e193c960802afba73b5d38sm */ 160cfd74d65d832137e20e193c960802afba73b5d38sm public final static int RENDERMODE_WHEN_DIRTY = 0; 161cfd74d65d832137e20e193c960802afba73b5d38sm /** 162cfd74d65d832137e20e193c960802afba73b5d38sm * The renderer is called 163cfd74d65d832137e20e193c960802afba73b5d38sm * continuously to re-render the scene. 164cfd74d65d832137e20e193c960802afba73b5d38sm * 165cfd74d65d832137e20e193c960802afba73b5d38sm * @see #getRenderMode() 166cfd74d65d832137e20e193c960802afba73b5d38sm * @see #setRenderMode(int) 167cfd74d65d832137e20e193c960802afba73b5d38sm * @see #requestRender() 168cfd74d65d832137e20e193c960802afba73b5d38sm */ 169cfd74d65d832137e20e193c960802afba73b5d38sm public final static int RENDERMODE_CONTINUOUSLY = 1; 170cfd74d65d832137e20e193c960802afba73b5d38sm 171cfd74d65d832137e20e193c960802afba73b5d38sm /** 172cfd74d65d832137e20e193c960802afba73b5d38sm * Check glError() after every GL call and throw an exception if glError indicates 173cfd74d65d832137e20e193c960802afba73b5d38sm * that an error has occurred. This can be used to help track down which OpenGL ES call 174cfd74d65d832137e20e193c960802afba73b5d38sm * is causing an error. 175cfd74d65d832137e20e193c960802afba73b5d38sm * 176cfd74d65d832137e20e193c960802afba73b5d38sm * @see #getDebugFlags 177cfd74d65d832137e20e193c960802afba73b5d38sm * @see #setDebugFlags 178cfd74d65d832137e20e193c960802afba73b5d38sm */ 179cfd74d65d832137e20e193c960802afba73b5d38sm public final static int DEBUG_CHECK_GL_ERROR = 1; 180cfd74d65d832137e20e193c960802afba73b5d38sm 181cfd74d65d832137e20e193c960802afba73b5d38sm /** 182cfd74d65d832137e20e193c960802afba73b5d38sm * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". 183cfd74d65d832137e20e193c960802afba73b5d38sm * 184cfd74d65d832137e20e193c960802afba73b5d38sm * @see #getDebugFlags 185cfd74d65d832137e20e193c960802afba73b5d38sm * @see #setDebugFlags 186cfd74d65d832137e20e193c960802afba73b5d38sm */ 187cfd74d65d832137e20e193c960802afba73b5d38sm public final static int DEBUG_LOG_GL_CALLS = 2; 188cfd74d65d832137e20e193c960802afba73b5d38sm 189cfd74d65d832137e20e193c960802afba73b5d38sm /** 190cfd74d65d832137e20e193c960802afba73b5d38sm * Standard View constructor. In order to render something, you 191cfd74d65d832137e20e193c960802afba73b5d38sm * must call {@link #setRenderer} to register a renderer. 192cfd74d65d832137e20e193c960802afba73b5d38sm */ 193cfd74d65d832137e20e193c960802afba73b5d38sm public GLSurfaceView(Context context) { 194cfd74d65d832137e20e193c960802afba73b5d38sm super(context); 195cfd74d65d832137e20e193c960802afba73b5d38sm init(); 196cfd74d65d832137e20e193c960802afba73b5d38sm } 197cfd74d65d832137e20e193c960802afba73b5d38sm 198cfd74d65d832137e20e193c960802afba73b5d38sm /** 199cfd74d65d832137e20e193c960802afba73b5d38sm * Standard View constructor. In order to render something, you 200cfd74d65d832137e20e193c960802afba73b5d38sm * must call {@link #setRenderer} to register a renderer. 201cfd74d65d832137e20e193c960802afba73b5d38sm */ 202cfd74d65d832137e20e193c960802afba73b5d38sm public GLSurfaceView(Context context, AttributeSet attrs) { 203cfd74d65d832137e20e193c960802afba73b5d38sm super(context, attrs); 204cfd74d65d832137e20e193c960802afba73b5d38sm init(); 205cfd74d65d832137e20e193c960802afba73b5d38sm } 206cfd74d65d832137e20e193c960802afba73b5d38sm 207cfd74d65d832137e20e193c960802afba73b5d38sm private void init() { 208cfd74d65d832137e20e193c960802afba73b5d38sm // Install a SurfaceHolder.Callback so we get notified when the 209cfd74d65d832137e20e193c960802afba73b5d38sm // underlying surface is created and destroyed 210cfd74d65d832137e20e193c960802afba73b5d38sm SurfaceHolder holder = getHolder(); 211cfd74d65d832137e20e193c960802afba73b5d38sm holder.addCallback(this); 212cfd74d65d832137e20e193c960802afba73b5d38sm holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); 213cfd74d65d832137e20e193c960802afba73b5d38sm 214cfd74d65d832137e20e193c960802afba73b5d38sm } 215cfd74d65d832137e20e193c960802afba73b5d38sm 216cfd74d65d832137e20e193c960802afba73b5d38sm /** 217cfd74d65d832137e20e193c960802afba73b5d38sm * Set the glWrapper. If the glWrapper is not null, its 218cfd74d65d832137e20e193c960802afba73b5d38sm * {@link GLWrapper#wrap(GL)} method is called 219cfd74d65d832137e20e193c960802afba73b5d38sm * whenever a surface is created. A GLWrapper can be used to wrap 220cfd74d65d832137e20e193c960802afba73b5d38sm * the GL object that's passed to the renderer. Wrapping a GL 221cfd74d65d832137e20e193c960802afba73b5d38sm * object enables examining and modifying the behavior of the 222cfd74d65d832137e20e193c960802afba73b5d38sm * GL calls made by the renderer. 223cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 224cfd74d65d832137e20e193c960802afba73b5d38sm * Wrapping is typically used for debugging purposes. 225cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 226cfd74d65d832137e20e193c960802afba73b5d38sm * The default value is null. 227cfd74d65d832137e20e193c960802afba73b5d38sm * @param glWrapper the new GLWrapper 228cfd74d65d832137e20e193c960802afba73b5d38sm */ 229cfd74d65d832137e20e193c960802afba73b5d38sm public void setGLWrapper(GLWrapper glWrapper) { 230cfd74d65d832137e20e193c960802afba73b5d38sm mGLWrapper = glWrapper; 231cfd74d65d832137e20e193c960802afba73b5d38sm } 232cfd74d65d832137e20e193c960802afba73b5d38sm 233cfd74d65d832137e20e193c960802afba73b5d38sm /** 234cfd74d65d832137e20e193c960802afba73b5d38sm * Set the debug flags to a new value. The value is 235cfd74d65d832137e20e193c960802afba73b5d38sm * constructed by OR-together zero or more 236cfd74d65d832137e20e193c960802afba73b5d38sm * of the DEBUG_CHECK_* constants. The debug flags take effect 237cfd74d65d832137e20e193c960802afba73b5d38sm * whenever a surface is created. The default value is zero. 238cfd74d65d832137e20e193c960802afba73b5d38sm * @param debugFlags the new debug flags 239cfd74d65d832137e20e193c960802afba73b5d38sm * @see #DEBUG_CHECK_GL_ERROR 240cfd74d65d832137e20e193c960802afba73b5d38sm * @see #DEBUG_LOG_GL_CALLS 241cfd74d65d832137e20e193c960802afba73b5d38sm */ 242cfd74d65d832137e20e193c960802afba73b5d38sm public void setDebugFlags(int debugFlags) { 243cfd74d65d832137e20e193c960802afba73b5d38sm mDebugFlags = debugFlags; 244cfd74d65d832137e20e193c960802afba73b5d38sm } 245cfd74d65d832137e20e193c960802afba73b5d38sm 246cfd74d65d832137e20e193c960802afba73b5d38sm /** 247cfd74d65d832137e20e193c960802afba73b5d38sm * Get the current value of the debug flags. 248cfd74d65d832137e20e193c960802afba73b5d38sm * @return the current value of the debug flags. 249cfd74d65d832137e20e193c960802afba73b5d38sm */ 250cfd74d65d832137e20e193c960802afba73b5d38sm public int getDebugFlags() { 251cfd74d65d832137e20e193c960802afba73b5d38sm return mDebugFlags; 252cfd74d65d832137e20e193c960802afba73b5d38sm } 253cfd74d65d832137e20e193c960802afba73b5d38sm 254cfd74d65d832137e20e193c960802afba73b5d38sm /** 255cfd74d65d832137e20e193c960802afba73b5d38sm * Set the renderer associated with this view. Also starts the thread that 256cfd74d65d832137e20e193c960802afba73b5d38sm * will call the renderer, which in turn causes the rendering to start. 257cfd74d65d832137e20e193c960802afba73b5d38sm * <p>This method should be called once and only once in the life-cycle of 258cfd74d65d832137e20e193c960802afba73b5d38sm * a GLSurfaceView. 259cfd74d65d832137e20e193c960802afba73b5d38sm * <p>The following GLSurfaceView methods can only be called <em>before</em> 260cfd74d65d832137e20e193c960802afba73b5d38sm * setRenderer is called: 261cfd74d65d832137e20e193c960802afba73b5d38sm * <ul> 262cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(boolean)} 263cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 264cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 265cfd74d65d832137e20e193c960802afba73b5d38sm * </ul> 266cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 267cfd74d65d832137e20e193c960802afba73b5d38sm * The following GLSurfaceView methods can only be called <em>after</em> 268cfd74d65d832137e20e193c960802afba73b5d38sm * setRenderer is called: 269cfd74d65d832137e20e193c960802afba73b5d38sm * <ul> 270cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #getRenderMode()} 271cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #onPause()} 272cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #onResume()} 273cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #queueEvent(Runnable)} 274cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #requestRender()} 275cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setRenderMode(int)} 276cfd74d65d832137e20e193c960802afba73b5d38sm * </ul> 277cfd74d65d832137e20e193c960802afba73b5d38sm * 278cfd74d65d832137e20e193c960802afba73b5d38sm * @param renderer the renderer to use to perform OpenGL drawing. 279cfd74d65d832137e20e193c960802afba73b5d38sm */ 280cfd74d65d832137e20e193c960802afba73b5d38sm public void setRenderer(Renderer renderer) { 281cfd74d65d832137e20e193c960802afba73b5d38sm checkRenderThreadState(); 282cfd74d65d832137e20e193c960802afba73b5d38sm if (mEGLConfigChooser == null) { 283cfd74d65d832137e20e193c960802afba73b5d38sm mEGLConfigChooser = new SimpleEGLConfigChooser(true); 284cfd74d65d832137e20e193c960802afba73b5d38sm } 285cfd74d65d832137e20e193c960802afba73b5d38sm if (mEGLContextFactory == null) { 286cfd74d65d832137e20e193c960802afba73b5d38sm mEGLContextFactory = new DefaultContextFactory(); 287cfd74d65d832137e20e193c960802afba73b5d38sm } 288cfd74d65d832137e20e193c960802afba73b5d38sm if (mEGLWindowSurfaceFactory == null) { 289cfd74d65d832137e20e193c960802afba73b5d38sm mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); 290cfd74d65d832137e20e193c960802afba73b5d38sm } 291cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread = new GLThread(renderer); 292cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.start(); 293cfd74d65d832137e20e193c960802afba73b5d38sm } 294cfd74d65d832137e20e193c960802afba73b5d38sm 295cfd74d65d832137e20e193c960802afba73b5d38sm /** 296cfd74d65d832137e20e193c960802afba73b5d38sm * Install a custom EGLContextFactory. 297cfd74d65d832137e20e193c960802afba73b5d38sm * <p>If this method is 298cfd74d65d832137e20e193c960802afba73b5d38sm * called, it must be called before {@link #setRenderer(Renderer)} 299cfd74d65d832137e20e193c960802afba73b5d38sm * is called. 300cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 301cfd74d65d832137e20e193c960802afba73b5d38sm * If this method is not called, then by default 302cfd74d65d832137e20e193c960802afba73b5d38sm * a context will be created with no shared context and 303cfd74d65d832137e20e193c960802afba73b5d38sm * with a null attribute list. 304cfd74d65d832137e20e193c960802afba73b5d38sm */ 305cfd74d65d832137e20e193c960802afba73b5d38sm public void setEGLContextFactory(EGLContextFactory factory) { 306cfd74d65d832137e20e193c960802afba73b5d38sm checkRenderThreadState(); 307cfd74d65d832137e20e193c960802afba73b5d38sm mEGLContextFactory = factory; 308cfd74d65d832137e20e193c960802afba73b5d38sm } 309cfd74d65d832137e20e193c960802afba73b5d38sm 310cfd74d65d832137e20e193c960802afba73b5d38sm /** 311cfd74d65d832137e20e193c960802afba73b5d38sm * Install a custom EGLWindowSurfaceFactory. 312cfd74d65d832137e20e193c960802afba73b5d38sm * <p>If this method is 313cfd74d65d832137e20e193c960802afba73b5d38sm * called, it must be called before {@link #setRenderer(Renderer)} 314cfd74d65d832137e20e193c960802afba73b5d38sm * is called. 315cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 316cfd74d65d832137e20e193c960802afba73b5d38sm * If this method is not called, then by default 317cfd74d65d832137e20e193c960802afba73b5d38sm * a window surface will be created with a null attribute list. 318cfd74d65d832137e20e193c960802afba73b5d38sm */ 319cfd74d65d832137e20e193c960802afba73b5d38sm public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { 320cfd74d65d832137e20e193c960802afba73b5d38sm checkRenderThreadState(); 321cfd74d65d832137e20e193c960802afba73b5d38sm mEGLWindowSurfaceFactory = factory; 322cfd74d65d832137e20e193c960802afba73b5d38sm } 323cfd74d65d832137e20e193c960802afba73b5d38sm 324cfd74d65d832137e20e193c960802afba73b5d38sm /** 325cfd74d65d832137e20e193c960802afba73b5d38sm * Install a custom EGLConfigChooser. 326cfd74d65d832137e20e193c960802afba73b5d38sm * <p>If this method is 327cfd74d65d832137e20e193c960802afba73b5d38sm * called, it must be called before {@link #setRenderer(Renderer)} 328cfd74d65d832137e20e193c960802afba73b5d38sm * is called. 329cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 330cfd74d65d832137e20e193c960802afba73b5d38sm * If no setEGLConfigChooser method is called, then by default the 331cfd74d65d832137e20e193c960802afba73b5d38sm * view will choose a config as close to 16-bit RGB as possible, with 332cfd74d65d832137e20e193c960802afba73b5d38sm * a depth buffer as close to 16 bits as possible. 333cfd74d65d832137e20e193c960802afba73b5d38sm * @param configChooser 334cfd74d65d832137e20e193c960802afba73b5d38sm */ 335cfd74d65d832137e20e193c960802afba73b5d38sm public void setEGLConfigChooser(EGLConfigChooser configChooser) { 336cfd74d65d832137e20e193c960802afba73b5d38sm checkRenderThreadState(); 337cfd74d65d832137e20e193c960802afba73b5d38sm mEGLConfigChooser = configChooser; 338cfd74d65d832137e20e193c960802afba73b5d38sm } 339cfd74d65d832137e20e193c960802afba73b5d38sm 340cfd74d65d832137e20e193c960802afba73b5d38sm /** 341cfd74d65d832137e20e193c960802afba73b5d38sm * Install a config chooser which will choose a config 342cfd74d65d832137e20e193c960802afba73b5d38sm * as close to 16-bit RGB as possible, with or without an optional depth 343cfd74d65d832137e20e193c960802afba73b5d38sm * buffer as close to 16-bits as possible. 344cfd74d65d832137e20e193c960802afba73b5d38sm * <p>If this method is 345cfd74d65d832137e20e193c960802afba73b5d38sm * called, it must be called before {@link #setRenderer(Renderer)} 346cfd74d65d832137e20e193c960802afba73b5d38sm * is called. 347cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 348cfd74d65d832137e20e193c960802afba73b5d38sm * If no setEGLConfigChooser method is called, then by default the 349cfd74d65d832137e20e193c960802afba73b5d38sm * view will choose a config as close to 16-bit RGB as possible, with 350cfd74d65d832137e20e193c960802afba73b5d38sm * a depth buffer as close to 16 bits as possible. 351cfd74d65d832137e20e193c960802afba73b5d38sm * 352cfd74d65d832137e20e193c960802afba73b5d38sm * @param needDepth 353cfd74d65d832137e20e193c960802afba73b5d38sm */ 354cfd74d65d832137e20e193c960802afba73b5d38sm public void setEGLConfigChooser(boolean needDepth) { 355cfd74d65d832137e20e193c960802afba73b5d38sm setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); 356cfd74d65d832137e20e193c960802afba73b5d38sm } 357cfd74d65d832137e20e193c960802afba73b5d38sm 358cfd74d65d832137e20e193c960802afba73b5d38sm /** 359cfd74d65d832137e20e193c960802afba73b5d38sm * Install a config chooser which will choose a config 360cfd74d65d832137e20e193c960802afba73b5d38sm * with at least the specified component sizes, and as close 361cfd74d65d832137e20e193c960802afba73b5d38sm * to the specified component sizes as possible. 362cfd74d65d832137e20e193c960802afba73b5d38sm * <p>If this method is 363cfd74d65d832137e20e193c960802afba73b5d38sm * called, it must be called before {@link #setRenderer(Renderer)} 364cfd74d65d832137e20e193c960802afba73b5d38sm * is called. 365cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 366cfd74d65d832137e20e193c960802afba73b5d38sm * If no setEGLConfigChooser method is called, then by default the 367cfd74d65d832137e20e193c960802afba73b5d38sm * view will choose a config as close to 16-bit RGB as possible, with 368cfd74d65d832137e20e193c960802afba73b5d38sm * a depth buffer as close to 16 bits as possible. 369cfd74d65d832137e20e193c960802afba73b5d38sm * 370cfd74d65d832137e20e193c960802afba73b5d38sm */ 371cfd74d65d832137e20e193c960802afba73b5d38sm public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, 372cfd74d65d832137e20e193c960802afba73b5d38sm int alphaSize, int depthSize, int stencilSize) { 373cfd74d65d832137e20e193c960802afba73b5d38sm setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, 374cfd74d65d832137e20e193c960802afba73b5d38sm blueSize, alphaSize, depthSize, stencilSize)); 375cfd74d65d832137e20e193c960802afba73b5d38sm } 376cfd74d65d832137e20e193c960802afba73b5d38sm 377cfd74d65d832137e20e193c960802afba73b5d38sm /** 378cfd74d65d832137e20e193c960802afba73b5d38sm * Inform the default EGLContextFactory and default EGLConfigChooser 379cfd74d65d832137e20e193c960802afba73b5d38sm * which EGLContext client version to pick. 380cfd74d65d832137e20e193c960802afba73b5d38sm * <p>Use this method to create an OpenGL ES 2.0-compatible context. 381cfd74d65d832137e20e193c960802afba73b5d38sm * Example: 382cfd74d65d832137e20e193c960802afba73b5d38sm * <pre class="prettyprint"> 383cfd74d65d832137e20e193c960802afba73b5d38sm * public MyView(Context context) { 384cfd74d65d832137e20e193c960802afba73b5d38sm * super(context); 385cfd74d65d832137e20e193c960802afba73b5d38sm * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context. 386cfd74d65d832137e20e193c960802afba73b5d38sm * setRenderer(new MyRenderer()); 387cfd74d65d832137e20e193c960802afba73b5d38sm * } 388cfd74d65d832137e20e193c960802afba73b5d38sm * </pre> 389cfd74d65d832137e20e193c960802afba73b5d38sm * <p>Note: Activities which require OpenGL ES 2.0 should indicate this by 390cfd74d65d832137e20e193c960802afba73b5d38sm * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's 391cfd74d65d832137e20e193c960802afba73b5d38sm * AndroidManifest.xml file. 392cfd74d65d832137e20e193c960802afba73b5d38sm * <p>If this method is called, it must be called before {@link #setRenderer(Renderer)} 393cfd74d65d832137e20e193c960802afba73b5d38sm * is called. 394cfd74d65d832137e20e193c960802afba73b5d38sm * <p>This method only affects the behavior of the default EGLContexFactory and the 395cfd74d65d832137e20e193c960802afba73b5d38sm * default EGLConfigChooser. If 396cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied 397cfd74d65d832137e20e193c960802afba73b5d38sm * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. 398cfd74d65d832137e20e193c960802afba73b5d38sm * If 399cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied 400cfd74d65d832137e20e193c960802afba73b5d38sm * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. 401cfd74d65d832137e20e193c960802afba73b5d38sm * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 402cfd74d65d832137e20e193c960802afba73b5d38sm */ 403cfd74d65d832137e20e193c960802afba73b5d38sm public void setEGLContextClientVersion(int version) { 404cfd74d65d832137e20e193c960802afba73b5d38sm checkRenderThreadState(); 405cfd74d65d832137e20e193c960802afba73b5d38sm mEGLContextClientVersion = version; 406cfd74d65d832137e20e193c960802afba73b5d38sm } 407cfd74d65d832137e20e193c960802afba73b5d38sm 408cfd74d65d832137e20e193c960802afba73b5d38sm /** 409cfd74d65d832137e20e193c960802afba73b5d38sm * Set the rendering mode. When renderMode is 410cfd74d65d832137e20e193c960802afba73b5d38sm * RENDERMODE_CONTINUOUSLY, the renderer is called 411cfd74d65d832137e20e193c960802afba73b5d38sm * repeatedly to re-render the scene. When renderMode 412cfd74d65d832137e20e193c960802afba73b5d38sm * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface 413cfd74d65d832137e20e193c960802afba73b5d38sm * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. 414cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 415cfd74d65d832137e20e193c960802afba73b5d38sm * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance 416cfd74d65d832137e20e193c960802afba73b5d38sm * by allowing the GPU and CPU to idle when the view does not need to be updated. 417cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 418cfd74d65d832137e20e193c960802afba73b5d38sm * This method can only be called after {@link #setRenderer(Renderer)} 419cfd74d65d832137e20e193c960802afba73b5d38sm * 420cfd74d65d832137e20e193c960802afba73b5d38sm * @param renderMode one of the RENDERMODE_X constants 421cfd74d65d832137e20e193c960802afba73b5d38sm * @see #RENDERMODE_CONTINUOUSLY 422cfd74d65d832137e20e193c960802afba73b5d38sm * @see #RENDERMODE_WHEN_DIRTY 423cfd74d65d832137e20e193c960802afba73b5d38sm */ 424cfd74d65d832137e20e193c960802afba73b5d38sm public void setRenderMode(int renderMode) { 425cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.setRenderMode(renderMode); 426cfd74d65d832137e20e193c960802afba73b5d38sm } 427cfd74d65d832137e20e193c960802afba73b5d38sm 428cfd74d65d832137e20e193c960802afba73b5d38sm /** 429cfd74d65d832137e20e193c960802afba73b5d38sm * Get the current rendering mode. May be called 430cfd74d65d832137e20e193c960802afba73b5d38sm * from any thread. Must not be called before a renderer has been set. 431cfd74d65d832137e20e193c960802afba73b5d38sm * @return the current rendering mode. 432cfd74d65d832137e20e193c960802afba73b5d38sm * @see #RENDERMODE_CONTINUOUSLY 433cfd74d65d832137e20e193c960802afba73b5d38sm * @see #RENDERMODE_WHEN_DIRTY 434cfd74d65d832137e20e193c960802afba73b5d38sm */ 435cfd74d65d832137e20e193c960802afba73b5d38sm public int getRenderMode() { 436cfd74d65d832137e20e193c960802afba73b5d38sm return mGLThread.getRenderMode(); 437cfd74d65d832137e20e193c960802afba73b5d38sm } 438cfd74d65d832137e20e193c960802afba73b5d38sm 439cfd74d65d832137e20e193c960802afba73b5d38sm /** 440cfd74d65d832137e20e193c960802afba73b5d38sm * Request that the renderer render a frame. 441cfd74d65d832137e20e193c960802afba73b5d38sm * This method is typically used when the render mode has been set to 442cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. 443cfd74d65d832137e20e193c960802afba73b5d38sm * May be called 444cfd74d65d832137e20e193c960802afba73b5d38sm * from any thread. Must not be called before a renderer has been set. 445cfd74d65d832137e20e193c960802afba73b5d38sm */ 446cfd74d65d832137e20e193c960802afba73b5d38sm public void requestRender() { 447cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.requestRender(); 448cfd74d65d832137e20e193c960802afba73b5d38sm } 449cfd74d65d832137e20e193c960802afba73b5d38sm 450cfd74d65d832137e20e193c960802afba73b5d38sm /** 451cfd74d65d832137e20e193c960802afba73b5d38sm * This method is part of the SurfaceHolder.Callback interface, and is 452cfd74d65d832137e20e193c960802afba73b5d38sm * not normally called or subclassed by clients of GLSurfaceView. 453cfd74d65d832137e20e193c960802afba73b5d38sm */ 454cfd74d65d832137e20e193c960802afba73b5d38sm public void surfaceCreated(SurfaceHolder holder) { 455cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.surfaceCreated(); 456cfd74d65d832137e20e193c960802afba73b5d38sm } 457cfd74d65d832137e20e193c960802afba73b5d38sm 458cfd74d65d832137e20e193c960802afba73b5d38sm /** 459cfd74d65d832137e20e193c960802afba73b5d38sm * This method is part of the SurfaceHolder.Callback interface, and is 460cfd74d65d832137e20e193c960802afba73b5d38sm * not normally called or subclassed by clients of GLSurfaceView. 461cfd74d65d832137e20e193c960802afba73b5d38sm */ 462cfd74d65d832137e20e193c960802afba73b5d38sm public void surfaceDestroyed(SurfaceHolder holder) { 463cfd74d65d832137e20e193c960802afba73b5d38sm // Surface will be destroyed when we return 464cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.surfaceDestroyed(); 465cfd74d65d832137e20e193c960802afba73b5d38sm } 466cfd74d65d832137e20e193c960802afba73b5d38sm 467cfd74d65d832137e20e193c960802afba73b5d38sm /** 468cfd74d65d832137e20e193c960802afba73b5d38sm * This method is part of the SurfaceHolder.Callback interface, and is 469cfd74d65d832137e20e193c960802afba73b5d38sm * not normally called or subclassed by clients of GLSurfaceView. 470cfd74d65d832137e20e193c960802afba73b5d38sm */ 471cfd74d65d832137e20e193c960802afba73b5d38sm public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 472cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.onWindowResize(w, h); 473cfd74d65d832137e20e193c960802afba73b5d38sm } 474cfd74d65d832137e20e193c960802afba73b5d38sm 475cfd74d65d832137e20e193c960802afba73b5d38sm /** 476cfd74d65d832137e20e193c960802afba73b5d38sm * Inform the view that the activity is paused. The owner of this view must 477cfd74d65d832137e20e193c960802afba73b5d38sm * call this method when the activity is paused. Calling this method will 478cfd74d65d832137e20e193c960802afba73b5d38sm * pause the rendering thread. 479cfd74d65d832137e20e193c960802afba73b5d38sm * Must not be called before a renderer has been set. 480cfd74d65d832137e20e193c960802afba73b5d38sm */ 481cfd74d65d832137e20e193c960802afba73b5d38sm public void onPause() { 4826cb78e547641bcab6f18ec34badca0840e000992Keun young Park mWatchDog.stop(); 483cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.onPause(); 484cfd74d65d832137e20e193c960802afba73b5d38sm } 485cfd74d65d832137e20e193c960802afba73b5d38sm 486cfd74d65d832137e20e193c960802afba73b5d38sm /** 487cfd74d65d832137e20e193c960802afba73b5d38sm * Inform the view that the activity is resumed. The owner of this view must 488cfd74d65d832137e20e193c960802afba73b5d38sm * call this method when the activity is resumed. Calling this method will 489cfd74d65d832137e20e193c960802afba73b5d38sm * recreate the OpenGL display and resume the rendering 490cfd74d65d832137e20e193c960802afba73b5d38sm * thread. 491cfd74d65d832137e20e193c960802afba73b5d38sm * Must not be called before a renderer has been set. 492cfd74d65d832137e20e193c960802afba73b5d38sm */ 493cfd74d65d832137e20e193c960802afba73b5d38sm public void onResume() { 4946cb78e547641bcab6f18ec34badca0840e000992Keun young Park mWatchDog.start(); 495cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.onResume(); 496cfd74d65d832137e20e193c960802afba73b5d38sm } 497cfd74d65d832137e20e193c960802afba73b5d38sm 498cfd74d65d832137e20e193c960802afba73b5d38sm public void flushTextures(TextureLibrary library) { 499cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.flushTextures(library); 500cfd74d65d832137e20e193c960802afba73b5d38sm } 501cfd74d65d832137e20e193c960802afba73b5d38sm 502cfd74d65d832137e20e193c960802afba73b5d38sm public void loadTextures(TextureLibrary library) { 503cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.loadTextures(library); 504cfd74d65d832137e20e193c960802afba73b5d38sm } 505cfd74d65d832137e20e193c960802afba73b5d38sm 506cfd74d65d832137e20e193c960802afba73b5d38sm public void flushBuffers(BufferLibrary library) { 507cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.flushBuffers(library); 508cfd74d65d832137e20e193c960802afba73b5d38sm } 509cfd74d65d832137e20e193c960802afba73b5d38sm 510cfd74d65d832137e20e193c960802afba73b5d38sm public void loadBuffers(BufferLibrary library) { 511cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.loadBuffers(library); 512cfd74d65d832137e20e193c960802afba73b5d38sm } 5139d4cc2572d37983607df38b0f4216ed76ac51814sm 5149d4cc2572d37983607df38b0f4216ed76ac51814sm public void setSafeMode(boolean safeMode) { 5159d4cc2572d37983607df38b0f4216ed76ac51814sm mGLThread.setSafeMode(safeMode); 5169d4cc2572d37983607df38b0f4216ed76ac51814sm } 517cfd74d65d832137e20e193c960802afba73b5d38sm 518cfd74d65d832137e20e193c960802afba73b5d38sm /** 519cfd74d65d832137e20e193c960802afba73b5d38sm * Queue a runnable to be run on the GL rendering thread. This can be used 520cfd74d65d832137e20e193c960802afba73b5d38sm * to communicate with the Renderer on the rendering thread. 521cfd74d65d832137e20e193c960802afba73b5d38sm * Must not be called before a renderer has been set. 522cfd74d65d832137e20e193c960802afba73b5d38sm * @param r the runnable to be run on the GL rendering thread. 523cfd74d65d832137e20e193c960802afba73b5d38sm */ 524cfd74d65d832137e20e193c960802afba73b5d38sm public void queueEvent(Runnable r) { 525cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.queueEvent(r); 526cfd74d65d832137e20e193c960802afba73b5d38sm } 527cfd74d65d832137e20e193c960802afba73b5d38sm 528cfd74d65d832137e20e193c960802afba73b5d38sm /** 529cfd74d65d832137e20e193c960802afba73b5d38sm * Inform the view that the window focus has changed. 530cfd74d65d832137e20e193c960802afba73b5d38sm */ 531cfd74d65d832137e20e193c960802afba73b5d38sm @Override 532cfd74d65d832137e20e193c960802afba73b5d38sm public void onWindowFocusChanged(boolean hasFocus) { 533cfd74d65d832137e20e193c960802afba73b5d38sm super.onWindowFocusChanged(hasFocus); 534cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.onWindowFocusChanged(hasFocus); 535cfd74d65d832137e20e193c960802afba73b5d38sm } 536cfd74d65d832137e20e193c960802afba73b5d38sm 537cfd74d65d832137e20e193c960802afba73b5d38sm /** 538cfd74d65d832137e20e193c960802afba73b5d38sm * This method is used as part of the View class and is not normally 539cfd74d65d832137e20e193c960802afba73b5d38sm * called or subclassed by clients of GLSurfaceView. 540cfd74d65d832137e20e193c960802afba73b5d38sm * Must not be called before a renderer has been set. 541cfd74d65d832137e20e193c960802afba73b5d38sm */ 542cfd74d65d832137e20e193c960802afba73b5d38sm @Override 543cfd74d65d832137e20e193c960802afba73b5d38sm protected void onDetachedFromWindow() { 544cfd74d65d832137e20e193c960802afba73b5d38sm super.onDetachedFromWindow(); 545cfd74d65d832137e20e193c960802afba73b5d38sm mGLThread.requestExitAndWait(); 546cfd74d65d832137e20e193c960802afba73b5d38sm } 547cfd74d65d832137e20e193c960802afba73b5d38sm 548cfd74d65d832137e20e193c960802afba73b5d38sm // ---------------------------------------------------------------------- 549cfd74d65d832137e20e193c960802afba73b5d38sm 550cfd74d65d832137e20e193c960802afba73b5d38sm /** 551cfd74d65d832137e20e193c960802afba73b5d38sm * An interface used to wrap a GL interface. 552cfd74d65d832137e20e193c960802afba73b5d38sm * <p>Typically 553cfd74d65d832137e20e193c960802afba73b5d38sm * used for implementing debugging and tracing on top of the default 554cfd74d65d832137e20e193c960802afba73b5d38sm * GL interface. You would typically use this by creating your own class 555cfd74d65d832137e20e193c960802afba73b5d38sm * that implemented all the GL methods by delegating to another GL instance. 556cfd74d65d832137e20e193c960802afba73b5d38sm * Then you could add your own behavior before or after calling the 557cfd74d65d832137e20e193c960802afba73b5d38sm * delegate. All the GLWrapper would do was instantiate and return the 558cfd74d65d832137e20e193c960802afba73b5d38sm * wrapper GL instance: 559cfd74d65d832137e20e193c960802afba73b5d38sm * <pre class="prettyprint"> 560cfd74d65d832137e20e193c960802afba73b5d38sm * class MyGLWrapper implements GLWrapper { 561cfd74d65d832137e20e193c960802afba73b5d38sm * GL wrap(GL gl) { 562cfd74d65d832137e20e193c960802afba73b5d38sm * return new MyGLImplementation(gl); 563cfd74d65d832137e20e193c960802afba73b5d38sm * } 564cfd74d65d832137e20e193c960802afba73b5d38sm * static class MyGLImplementation implements GL,GL10,GL11,... { 565cfd74d65d832137e20e193c960802afba73b5d38sm * ... 566cfd74d65d832137e20e193c960802afba73b5d38sm * } 567cfd74d65d832137e20e193c960802afba73b5d38sm * } 568cfd74d65d832137e20e193c960802afba73b5d38sm * </pre> 569cfd74d65d832137e20e193c960802afba73b5d38sm * @see #setGLWrapper(GLWrapper) 570cfd74d65d832137e20e193c960802afba73b5d38sm */ 571cfd74d65d832137e20e193c960802afba73b5d38sm public interface GLWrapper { 572cfd74d65d832137e20e193c960802afba73b5d38sm /** 573cfd74d65d832137e20e193c960802afba73b5d38sm * Wraps a gl interface in another gl interface. 574cfd74d65d832137e20e193c960802afba73b5d38sm * @param gl a GL interface that is to be wrapped. 575cfd74d65d832137e20e193c960802afba73b5d38sm * @return either the input argument or another GL object that wraps the input argument. 576cfd74d65d832137e20e193c960802afba73b5d38sm */ 577cfd74d65d832137e20e193c960802afba73b5d38sm GL wrap(GL gl); 578cfd74d65d832137e20e193c960802afba73b5d38sm } 579cfd74d65d832137e20e193c960802afba73b5d38sm 580cfd74d65d832137e20e193c960802afba73b5d38sm /** 581cfd74d65d832137e20e193c960802afba73b5d38sm * A generic renderer interface. 582cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 583cfd74d65d832137e20e193c960802afba73b5d38sm * The renderer is responsible for making OpenGL calls to render a frame. 584cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 585cfd74d65d832137e20e193c960802afba73b5d38sm * GLSurfaceView clients typically create their own classes that implement 586cfd74d65d832137e20e193c960802afba73b5d38sm * this interface, and then call {@link GLSurfaceView#setRenderer} to 587cfd74d65d832137e20e193c960802afba73b5d38sm * register the renderer with the GLSurfaceView. 588cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 589cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Threading</h3> 590cfd74d65d832137e20e193c960802afba73b5d38sm * The renderer will be called on a separate thread, so that rendering 591cfd74d65d832137e20e193c960802afba73b5d38sm * performance is decoupled from the UI thread. Clients typically need to 592cfd74d65d832137e20e193c960802afba73b5d38sm * communicate with the renderer from the UI thread, because that's where 593cfd74d65d832137e20e193c960802afba73b5d38sm * input events are received. Clients can communicate using any of the 594cfd74d65d832137e20e193c960802afba73b5d38sm * standard Java techniques for cross-thread communication, or they can 595cfd74d65d832137e20e193c960802afba73b5d38sm * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. 596cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 597cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>EGL Context Lost</h3> 598cfd74d65d832137e20e193c960802afba73b5d38sm * There are situations where the EGL rendering context will be lost. This 599cfd74d65d832137e20e193c960802afba73b5d38sm * typically happens when device wakes up after going to sleep. When 600cfd74d65d832137e20e193c960802afba73b5d38sm * the EGL context is lost, all OpenGL resources (such as textures) that are 601cfd74d65d832137e20e193c960802afba73b5d38sm * associated with that context will be automatically deleted. In order to 602cfd74d65d832137e20e193c960802afba73b5d38sm * keep rendering correctly, a renderer must recreate any lost resources 603cfd74d65d832137e20e193c960802afba73b5d38sm * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method 604cfd74d65d832137e20e193c960802afba73b5d38sm * is a convenient place to do this. 605cfd74d65d832137e20e193c960802afba73b5d38sm * 606cfd74d65d832137e20e193c960802afba73b5d38sm * 607cfd74d65d832137e20e193c960802afba73b5d38sm * @see #setRenderer(Renderer) 608cfd74d65d832137e20e193c960802afba73b5d38sm */ 609cfd74d65d832137e20e193c960802afba73b5d38sm public interface Renderer { 610cfd74d65d832137e20e193c960802afba73b5d38sm /** 611cfd74d65d832137e20e193c960802afba73b5d38sm * Called when the surface is created or recreated. 612cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 613cfd74d65d832137e20e193c960802afba73b5d38sm * Called when the rendering thread 614cfd74d65d832137e20e193c960802afba73b5d38sm * starts and whenever the EGL context is lost. The context will typically 615cfd74d65d832137e20e193c960802afba73b5d38sm * be lost when the Android device awakes after going to sleep. 616cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 617cfd74d65d832137e20e193c960802afba73b5d38sm * Since this method is called at the beginning of rendering, as well as 618cfd74d65d832137e20e193c960802afba73b5d38sm * every time the EGL context is lost, this method is a convenient place to put 619cfd74d65d832137e20e193c960802afba73b5d38sm * code to create resources that need to be created when the rendering 620cfd74d65d832137e20e193c960802afba73b5d38sm * starts, and that need to be recreated when the EGL context is lost. 621cfd74d65d832137e20e193c960802afba73b5d38sm * Textures are an example of a resource that you might want to create 622cfd74d65d832137e20e193c960802afba73b5d38sm * here. 623cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 624cfd74d65d832137e20e193c960802afba73b5d38sm * Note that when the EGL context is lost, all OpenGL resources associated 625cfd74d65d832137e20e193c960802afba73b5d38sm * with that context will be automatically deleted. You do not need to call 626cfd74d65d832137e20e193c960802afba73b5d38sm * the corresponding "glDelete" methods such as glDeleteTextures to 627cfd74d65d832137e20e193c960802afba73b5d38sm * manually delete these lost resources. 628cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 629cfd74d65d832137e20e193c960802afba73b5d38sm * @param gl the GL interface. Use <code>instanceof</code> to 630cfd74d65d832137e20e193c960802afba73b5d38sm * test if the interface supports GL11 or higher interfaces. 631cfd74d65d832137e20e193c960802afba73b5d38sm * @param config the EGLConfig of the created surface. Can be used 632cfd74d65d832137e20e193c960802afba73b5d38sm * to create matching pbuffers. 633cfd74d65d832137e20e193c960802afba73b5d38sm */ 634cfd74d65d832137e20e193c960802afba73b5d38sm void onSurfaceCreated(GL10 gl, EGLConfig config); 635cfd74d65d832137e20e193c960802afba73b5d38sm 636cfd74d65d832137e20e193c960802afba73b5d38sm /** 637cfd74d65d832137e20e193c960802afba73b5d38sm * Called when the surface changed size. 638cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 639cfd74d65d832137e20e193c960802afba73b5d38sm * Called after the surface is created and whenever 640cfd74d65d832137e20e193c960802afba73b5d38sm * the OpenGL ES surface size changes. 641cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 642cfd74d65d832137e20e193c960802afba73b5d38sm * Typically you will set your viewport here. If your camera 643cfd74d65d832137e20e193c960802afba73b5d38sm * is fixed then you could also set your projection matrix here: 644cfd74d65d832137e20e193c960802afba73b5d38sm * <pre class="prettyprint"> 645cfd74d65d832137e20e193c960802afba73b5d38sm * void onSurfaceChanged(GL10 gl, int width, int height) { 646cfd74d65d832137e20e193c960802afba73b5d38sm * gl.glViewport(0, 0, width, height); 647cfd74d65d832137e20e193c960802afba73b5d38sm * // for a fixed camera, set the projection too 648cfd74d65d832137e20e193c960802afba73b5d38sm * float ratio = (float) width / height; 649cfd74d65d832137e20e193c960802afba73b5d38sm * gl.glMatrixMode(GL10.GL_PROJECTION); 650cfd74d65d832137e20e193c960802afba73b5d38sm * gl.glLoadIdentity(); 651cfd74d65d832137e20e193c960802afba73b5d38sm * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 652cfd74d65d832137e20e193c960802afba73b5d38sm * } 653cfd74d65d832137e20e193c960802afba73b5d38sm * </pre> 654cfd74d65d832137e20e193c960802afba73b5d38sm * @param gl the GL interface. Use <code>instanceof</code> to 655cfd74d65d832137e20e193c960802afba73b5d38sm * test if the interface supports GL11 or higher interfaces. 656cfd74d65d832137e20e193c960802afba73b5d38sm * @param width 657cfd74d65d832137e20e193c960802afba73b5d38sm * @param height 658cfd74d65d832137e20e193c960802afba73b5d38sm */ 659cfd74d65d832137e20e193c960802afba73b5d38sm void onSurfaceChanged(GL10 gl, int width, int height); 660cfd74d65d832137e20e193c960802afba73b5d38sm 661cfd74d65d832137e20e193c960802afba73b5d38sm /** 662cfd74d65d832137e20e193c960802afba73b5d38sm * Called when the OpenGL context has been lost is about 663cfd74d65d832137e20e193c960802afba73b5d38sm * to be recreated. onSurfaceCreated() will be called after 664cfd74d65d832137e20e193c960802afba73b5d38sm * onSurfaceLost(). 665cfd74d65d832137e20e193c960802afba73b5d38sm * */ 666cfd74d65d832137e20e193c960802afba73b5d38sm void onSurfaceLost(); 667cfd74d65d832137e20e193c960802afba73b5d38sm 668cfd74d65d832137e20e193c960802afba73b5d38sm /** 669cfd74d65d832137e20e193c960802afba73b5d38sm * Called to draw the current frame. 670cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 671cfd74d65d832137e20e193c960802afba73b5d38sm * This method is responsible for drawing the current frame. 672cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 673cfd74d65d832137e20e193c960802afba73b5d38sm * The implementation of this method typically looks like this: 674cfd74d65d832137e20e193c960802afba73b5d38sm * <pre class="prettyprint"> 675cfd74d65d832137e20e193c960802afba73b5d38sm * void onDrawFrame(GL10 gl) { 676cfd74d65d832137e20e193c960802afba73b5d38sm * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 677cfd74d65d832137e20e193c960802afba73b5d38sm * //... other gl calls to render the scene ... 678cfd74d65d832137e20e193c960802afba73b5d38sm * } 679cfd74d65d832137e20e193c960802afba73b5d38sm * </pre> 680cfd74d65d832137e20e193c960802afba73b5d38sm * @param gl the GL interface. Use <code>instanceof</code> to 681cfd74d65d832137e20e193c960802afba73b5d38sm * test if the interface supports GL11 or higher interfaces. 682cfd74d65d832137e20e193c960802afba73b5d38sm */ 683cfd74d65d832137e20e193c960802afba73b5d38sm void onDrawFrame(GL10 gl); 684cfd74d65d832137e20e193c960802afba73b5d38sm 685cfd74d65d832137e20e193c960802afba73b5d38sm void loadTextures(GL10 gl, TextureLibrary library); 686cfd74d65d832137e20e193c960802afba73b5d38sm void flushTextures(GL10 gl, TextureLibrary library); 687cfd74d65d832137e20e193c960802afba73b5d38sm void loadBuffers(GL10 gl, BufferLibrary library); 688cfd74d65d832137e20e193c960802afba73b5d38sm void flushBuffers(GL10 gl, BufferLibrary library); 689cfd74d65d832137e20e193c960802afba73b5d38sm 690cfd74d65d832137e20e193c960802afba73b5d38sm 691cfd74d65d832137e20e193c960802afba73b5d38sm 692cfd74d65d832137e20e193c960802afba73b5d38sm } 693cfd74d65d832137e20e193c960802afba73b5d38sm 694cfd74d65d832137e20e193c960802afba73b5d38sm /** 695cfd74d65d832137e20e193c960802afba73b5d38sm * An interface for customizing the eglCreateContext and eglDestroyContext calls. 696cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 697cfd74d65d832137e20e193c960802afba73b5d38sm * This interface must be implemented by clients wishing to call 698cfd74d65d832137e20e193c960802afba73b5d38sm * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)} 699cfd74d65d832137e20e193c960802afba73b5d38sm */ 700cfd74d65d832137e20e193c960802afba73b5d38sm public interface EGLContextFactory { 701cfd74d65d832137e20e193c960802afba73b5d38sm EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); 702cfd74d65d832137e20e193c960802afba73b5d38sm void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); 703cfd74d65d832137e20e193c960802afba73b5d38sm } 704cfd74d65d832137e20e193c960802afba73b5d38sm 705cfd74d65d832137e20e193c960802afba73b5d38sm private class DefaultContextFactory implements EGLContextFactory { 706cfd74d65d832137e20e193c960802afba73b5d38sm private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 707cfd74d65d832137e20e193c960802afba73b5d38sm 708cfd74d65d832137e20e193c960802afba73b5d38sm public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { 709cfd74d65d832137e20e193c960802afba73b5d38sm int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, 710cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_NONE }; 711cfd74d65d832137e20e193c960802afba73b5d38sm 712cfd74d65d832137e20e193c960802afba73b5d38sm return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, 713cfd74d65d832137e20e193c960802afba73b5d38sm mEGLContextClientVersion != 0 ? attrib_list : null); 714cfd74d65d832137e20e193c960802afba73b5d38sm } 715cfd74d65d832137e20e193c960802afba73b5d38sm 716cfd74d65d832137e20e193c960802afba73b5d38sm public void destroyContext(EGL10 egl, EGLDisplay display, 717cfd74d65d832137e20e193c960802afba73b5d38sm EGLContext context) { 718cfd74d65d832137e20e193c960802afba73b5d38sm egl.eglDestroyContext(display, context); 719cfd74d65d832137e20e193c960802afba73b5d38sm } 720cfd74d65d832137e20e193c960802afba73b5d38sm } 721cfd74d65d832137e20e193c960802afba73b5d38sm 722cfd74d65d832137e20e193c960802afba73b5d38sm /** 723cfd74d65d832137e20e193c960802afba73b5d38sm * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. 724cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 725cfd74d65d832137e20e193c960802afba73b5d38sm * This interface must be implemented by clients wishing to call 726cfd74d65d832137e20e193c960802afba73b5d38sm * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} 727cfd74d65d832137e20e193c960802afba73b5d38sm */ 728cfd74d65d832137e20e193c960802afba73b5d38sm public interface EGLWindowSurfaceFactory { 729cfd74d65d832137e20e193c960802afba73b5d38sm EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, 730cfd74d65d832137e20e193c960802afba73b5d38sm Object nativeWindow); 731cfd74d65d832137e20e193c960802afba73b5d38sm void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); 732cfd74d65d832137e20e193c960802afba73b5d38sm } 733cfd74d65d832137e20e193c960802afba73b5d38sm 734cfd74d65d832137e20e193c960802afba73b5d38sm private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { 735cfd74d65d832137e20e193c960802afba73b5d38sm 736cfd74d65d832137e20e193c960802afba73b5d38sm public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, 737cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig config, Object nativeWindow) { 738cfd74d65d832137e20e193c960802afba73b5d38sm return egl.eglCreateWindowSurface(display, config, nativeWindow, null); 739cfd74d65d832137e20e193c960802afba73b5d38sm } 740cfd74d65d832137e20e193c960802afba73b5d38sm 741cfd74d65d832137e20e193c960802afba73b5d38sm public void destroySurface(EGL10 egl, EGLDisplay display, 742cfd74d65d832137e20e193c960802afba73b5d38sm EGLSurface surface) { 743cfd74d65d832137e20e193c960802afba73b5d38sm egl.eglDestroySurface(display, surface); 744cfd74d65d832137e20e193c960802afba73b5d38sm } 745cfd74d65d832137e20e193c960802afba73b5d38sm } 746cfd74d65d832137e20e193c960802afba73b5d38sm 747cfd74d65d832137e20e193c960802afba73b5d38sm /** 748cfd74d65d832137e20e193c960802afba73b5d38sm * An interface for choosing an EGLConfig configuration from a list of 749cfd74d65d832137e20e193c960802afba73b5d38sm * potential configurations. 750cfd74d65d832137e20e193c960802afba73b5d38sm * <p> 751cfd74d65d832137e20e193c960802afba73b5d38sm * This interface must be implemented by clients wishing to call 752cfd74d65d832137e20e193c960802afba73b5d38sm * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} 753cfd74d65d832137e20e193c960802afba73b5d38sm */ 754cfd74d65d832137e20e193c960802afba73b5d38sm public interface EGLConfigChooser { 755cfd74d65d832137e20e193c960802afba73b5d38sm /** 756cfd74d65d832137e20e193c960802afba73b5d38sm * Choose a configuration from the list. Implementors typically 757cfd74d65d832137e20e193c960802afba73b5d38sm * implement this method by calling 758cfd74d65d832137e20e193c960802afba73b5d38sm * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the 759cfd74d65d832137e20e193c960802afba73b5d38sm * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. 760cfd74d65d832137e20e193c960802afba73b5d38sm * @param egl the EGL10 for the current display. 761cfd74d65d832137e20e193c960802afba73b5d38sm * @param display the current display. 762cfd74d65d832137e20e193c960802afba73b5d38sm * @return the chosen configuration. 763cfd74d65d832137e20e193c960802afba73b5d38sm */ 764cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); 765cfd74d65d832137e20e193c960802afba73b5d38sm } 766cfd74d65d832137e20e193c960802afba73b5d38sm 767cfd74d65d832137e20e193c960802afba73b5d38sm private abstract class BaseConfigChooser 768cfd74d65d832137e20e193c960802afba73b5d38sm implements EGLConfigChooser { 769cfd74d65d832137e20e193c960802afba73b5d38sm public BaseConfigChooser(int[] configSpec) { 770cfd74d65d832137e20e193c960802afba73b5d38sm mConfigSpec = filterConfigSpec(configSpec); 771cfd74d65d832137e20e193c960802afba73b5d38sm } 772cfd74d65d832137e20e193c960802afba73b5d38sm 773cfd74d65d832137e20e193c960802afba73b5d38sm public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 774cfd74d65d832137e20e193c960802afba73b5d38sm int[] num_config = new int[1]; 775cfd74d65d832137e20e193c960802afba73b5d38sm if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, 776cfd74d65d832137e20e193c960802afba73b5d38sm num_config)) { 777cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalArgumentException("eglChooseConfig failed"); 778cfd74d65d832137e20e193c960802afba73b5d38sm } 779cfd74d65d832137e20e193c960802afba73b5d38sm 780cfd74d65d832137e20e193c960802afba73b5d38sm int numConfigs = num_config[0]; 781cfd74d65d832137e20e193c960802afba73b5d38sm 782cfd74d65d832137e20e193c960802afba73b5d38sm if (numConfigs <= 0) { 783cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalArgumentException( 784cfd74d65d832137e20e193c960802afba73b5d38sm "No configs match configSpec"); 785cfd74d65d832137e20e193c960802afba73b5d38sm } 786cfd74d65d832137e20e193c960802afba73b5d38sm 787cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig[] configs = new EGLConfig[numConfigs]; 788cfd74d65d832137e20e193c960802afba73b5d38sm if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, 789cfd74d65d832137e20e193c960802afba73b5d38sm num_config)) { 790cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalArgumentException("eglChooseConfig#2 failed"); 791cfd74d65d832137e20e193c960802afba73b5d38sm } 792cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig config = chooseConfig(egl, display, configs); 793cfd74d65d832137e20e193c960802afba73b5d38sm if (config == null) { 794cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalArgumentException("No config chosen"); 795cfd74d65d832137e20e193c960802afba73b5d38sm } 796cfd74d65d832137e20e193c960802afba73b5d38sm return config; 797cfd74d65d832137e20e193c960802afba73b5d38sm } 798cfd74d65d832137e20e193c960802afba73b5d38sm 799cfd74d65d832137e20e193c960802afba73b5d38sm abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 800cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig[] configs); 801cfd74d65d832137e20e193c960802afba73b5d38sm 802cfd74d65d832137e20e193c960802afba73b5d38sm protected int[] mConfigSpec; 803cfd74d65d832137e20e193c960802afba73b5d38sm 804cfd74d65d832137e20e193c960802afba73b5d38sm private int[] filterConfigSpec(int[] configSpec) { 805cfd74d65d832137e20e193c960802afba73b5d38sm if (mEGLContextClientVersion != 2) { 806cfd74d65d832137e20e193c960802afba73b5d38sm return configSpec; 807cfd74d65d832137e20e193c960802afba73b5d38sm } 808cfd74d65d832137e20e193c960802afba73b5d38sm /* We know none of the subclasses define EGL_RENDERABLE_TYPE. 809cfd74d65d832137e20e193c960802afba73b5d38sm * And we know the configSpec is well formed. 810cfd74d65d832137e20e193c960802afba73b5d38sm */ 811cfd74d65d832137e20e193c960802afba73b5d38sm int len = configSpec.length; 812cfd74d65d832137e20e193c960802afba73b5d38sm int[] newConfigSpec = new int[len + 2]; 813cfd74d65d832137e20e193c960802afba73b5d38sm System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); 814cfd74d65d832137e20e193c960802afba73b5d38sm newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; 815cfd74d65d832137e20e193c960802afba73b5d38sm newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ 816cfd74d65d832137e20e193c960802afba73b5d38sm newConfigSpec[len+1] = EGL10.EGL_NONE; 817cfd74d65d832137e20e193c960802afba73b5d38sm return newConfigSpec; 818cfd74d65d832137e20e193c960802afba73b5d38sm } 819cfd74d65d832137e20e193c960802afba73b5d38sm } 820cfd74d65d832137e20e193c960802afba73b5d38sm 821cfd74d65d832137e20e193c960802afba73b5d38sm private class ComponentSizeChooser extends BaseConfigChooser { 822cfd74d65d832137e20e193c960802afba73b5d38sm public ComponentSizeChooser(int redSize, int greenSize, int blueSize, 823cfd74d65d832137e20e193c960802afba73b5d38sm int alphaSize, int depthSize, int stencilSize) { 824cfd74d65d832137e20e193c960802afba73b5d38sm super(new int[] { 825cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_RED_SIZE, redSize, 826cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_GREEN_SIZE, greenSize, 827cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_BLUE_SIZE, blueSize, 828cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_ALPHA_SIZE, alphaSize, 829cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_DEPTH_SIZE, depthSize, 830cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_STENCIL_SIZE, stencilSize, 831cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_NONE}); 832cfd74d65d832137e20e193c960802afba73b5d38sm mValue = new int[1]; 833cfd74d65d832137e20e193c960802afba73b5d38sm mRedSize = redSize; 834cfd74d65d832137e20e193c960802afba73b5d38sm mGreenSize = greenSize; 835cfd74d65d832137e20e193c960802afba73b5d38sm mBlueSize = blueSize; 836cfd74d65d832137e20e193c960802afba73b5d38sm mAlphaSize = alphaSize; 837cfd74d65d832137e20e193c960802afba73b5d38sm mDepthSize = depthSize; 838cfd74d65d832137e20e193c960802afba73b5d38sm mStencilSize = stencilSize; 839cfd74d65d832137e20e193c960802afba73b5d38sm } 840cfd74d65d832137e20e193c960802afba73b5d38sm 841cfd74d65d832137e20e193c960802afba73b5d38sm @Override 842cfd74d65d832137e20e193c960802afba73b5d38sm public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 843cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig[] configs) { 844cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig closestConfig = null; 845cfd74d65d832137e20e193c960802afba73b5d38sm int closestDistance = 1000; 846cfd74d65d832137e20e193c960802afba73b5d38sm for(EGLConfig config : configs) { 847cfd74d65d832137e20e193c960802afba73b5d38sm int d = findConfigAttrib(egl, display, config, 848cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_DEPTH_SIZE, 0); 849cfd74d65d832137e20e193c960802afba73b5d38sm int s = findConfigAttrib(egl, display, config, 850cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_STENCIL_SIZE, 0); 851cfd74d65d832137e20e193c960802afba73b5d38sm if (d >= mDepthSize && s>= mStencilSize) { 852cfd74d65d832137e20e193c960802afba73b5d38sm int r = findConfigAttrib(egl, display, config, 853cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_RED_SIZE, 0); 854cfd74d65d832137e20e193c960802afba73b5d38sm int g = findConfigAttrib(egl, display, config, 855cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_GREEN_SIZE, 0); 856cfd74d65d832137e20e193c960802afba73b5d38sm int b = findConfigAttrib(egl, display, config, 857cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_BLUE_SIZE, 0); 858cfd74d65d832137e20e193c960802afba73b5d38sm int a = findConfigAttrib(egl, display, config, 859cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_ALPHA_SIZE, 0); 860cfd74d65d832137e20e193c960802afba73b5d38sm int distance = Math.abs(r - mRedSize) 861cfd74d65d832137e20e193c960802afba73b5d38sm + Math.abs(g - mGreenSize) 862cfd74d65d832137e20e193c960802afba73b5d38sm + Math.abs(b - mBlueSize) 863cfd74d65d832137e20e193c960802afba73b5d38sm + Math.abs(a - mAlphaSize); 864cfd74d65d832137e20e193c960802afba73b5d38sm if (distance < closestDistance) { 865cfd74d65d832137e20e193c960802afba73b5d38sm closestDistance = distance; 866cfd74d65d832137e20e193c960802afba73b5d38sm closestConfig = config; 867cfd74d65d832137e20e193c960802afba73b5d38sm } 868cfd74d65d832137e20e193c960802afba73b5d38sm } 869cfd74d65d832137e20e193c960802afba73b5d38sm } 870cfd74d65d832137e20e193c960802afba73b5d38sm return closestConfig; 871cfd74d65d832137e20e193c960802afba73b5d38sm } 872cfd74d65d832137e20e193c960802afba73b5d38sm 873cfd74d65d832137e20e193c960802afba73b5d38sm private int findConfigAttrib(EGL10 egl, EGLDisplay display, 874cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig config, int attribute, int defaultValue) { 875cfd74d65d832137e20e193c960802afba73b5d38sm 876cfd74d65d832137e20e193c960802afba73b5d38sm if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 877cfd74d65d832137e20e193c960802afba73b5d38sm return mValue[0]; 878cfd74d65d832137e20e193c960802afba73b5d38sm } 879cfd74d65d832137e20e193c960802afba73b5d38sm return defaultValue; 880cfd74d65d832137e20e193c960802afba73b5d38sm } 881cfd74d65d832137e20e193c960802afba73b5d38sm 882cfd74d65d832137e20e193c960802afba73b5d38sm private int[] mValue; 883cfd74d65d832137e20e193c960802afba73b5d38sm // Subclasses can adjust these values: 884cfd74d65d832137e20e193c960802afba73b5d38sm protected int mRedSize; 885cfd74d65d832137e20e193c960802afba73b5d38sm protected int mGreenSize; 886cfd74d65d832137e20e193c960802afba73b5d38sm protected int mBlueSize; 887cfd74d65d832137e20e193c960802afba73b5d38sm protected int mAlphaSize; 888cfd74d65d832137e20e193c960802afba73b5d38sm protected int mDepthSize; 889cfd74d65d832137e20e193c960802afba73b5d38sm protected int mStencilSize; 890cfd74d65d832137e20e193c960802afba73b5d38sm } 891cfd74d65d832137e20e193c960802afba73b5d38sm 892cfd74d65d832137e20e193c960802afba73b5d38sm /** 893cfd74d65d832137e20e193c960802afba73b5d38sm * This class will choose a supported surface as close to 894cfd74d65d832137e20e193c960802afba73b5d38sm * RGB565 as possible, with or without a depth buffer. 895cfd74d65d832137e20e193c960802afba73b5d38sm * 896cfd74d65d832137e20e193c960802afba73b5d38sm */ 897cfd74d65d832137e20e193c960802afba73b5d38sm private class SimpleEGLConfigChooser extends ComponentSizeChooser { 898cfd74d65d832137e20e193c960802afba73b5d38sm public SimpleEGLConfigChooser(boolean withDepthBuffer) { 899cfd74d65d832137e20e193c960802afba73b5d38sm super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0); 900cfd74d65d832137e20e193c960802afba73b5d38sm // Adjust target values. This way we'll accept a 4444 or 901cfd74d65d832137e20e193c960802afba73b5d38sm // 555 buffer if there's no 565 buffer available. 902cfd74d65d832137e20e193c960802afba73b5d38sm mRedSize = 5; 903cfd74d65d832137e20e193c960802afba73b5d38sm mGreenSize = 6; 904cfd74d65d832137e20e193c960802afba73b5d38sm mBlueSize = 5; 905cfd74d65d832137e20e193c960802afba73b5d38sm } 906cfd74d65d832137e20e193c960802afba73b5d38sm } 907cfd74d65d832137e20e193c960802afba73b5d38sm 908cfd74d65d832137e20e193c960802afba73b5d38sm /** 909cfd74d65d832137e20e193c960802afba73b5d38sm * An EGL helper class. 910cfd74d65d832137e20e193c960802afba73b5d38sm */ 911cfd74d65d832137e20e193c960802afba73b5d38sm 912cfd74d65d832137e20e193c960802afba73b5d38sm private class EglHelper { 913cfd74d65d832137e20e193c960802afba73b5d38sm public EglHelper() { 914cfd74d65d832137e20e193c960802afba73b5d38sm 915cfd74d65d832137e20e193c960802afba73b5d38sm } 916cfd74d65d832137e20e193c960802afba73b5d38sm 917cfd74d65d832137e20e193c960802afba73b5d38sm /** 918cfd74d65d832137e20e193c960802afba73b5d38sm * Initialize EGL for a given configuration spec. 919cfd74d65d832137e20e193c960802afba73b5d38sm * @param configSpec 920cfd74d65d832137e20e193c960802afba73b5d38sm */ 921cfd74d65d832137e20e193c960802afba73b5d38sm public void start(){ 922cfd74d65d832137e20e193c960802afba73b5d38sm /* 923cfd74d65d832137e20e193c960802afba73b5d38sm * Get an EGL instance 924cfd74d65d832137e20e193c960802afba73b5d38sm */ 925cfd74d65d832137e20e193c960802afba73b5d38sm mEgl = (EGL10) EGLContext.getEGL(); 926cfd74d65d832137e20e193c960802afba73b5d38sm 927cfd74d65d832137e20e193c960802afba73b5d38sm /* 928cfd74d65d832137e20e193c960802afba73b5d38sm * Get to the default display. 929cfd74d65d832137e20e193c960802afba73b5d38sm */ 930cfd74d65d832137e20e193c960802afba73b5d38sm mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 931cfd74d65d832137e20e193c960802afba73b5d38sm 932cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 933cfd74d65d832137e20e193c960802afba73b5d38sm throw new RuntimeException("eglGetDisplay failed"); 934cfd74d65d832137e20e193c960802afba73b5d38sm } 935cfd74d65d832137e20e193c960802afba73b5d38sm 936cfd74d65d832137e20e193c960802afba73b5d38sm /* 937cfd74d65d832137e20e193c960802afba73b5d38sm * We can now initialize EGL for that display 938cfd74d65d832137e20e193c960802afba73b5d38sm */ 939cfd74d65d832137e20e193c960802afba73b5d38sm int[] version = new int[2]; 940cfd74d65d832137e20e193c960802afba73b5d38sm if(!mEgl.eglInitialize(mEglDisplay, version)) { 941cfd74d65d832137e20e193c960802afba73b5d38sm throw new RuntimeException("eglInitialize failed"); 942cfd74d65d832137e20e193c960802afba73b5d38sm } 943cfd74d65d832137e20e193c960802afba73b5d38sm mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 944cfd74d65d832137e20e193c960802afba73b5d38sm 945cfd74d65d832137e20e193c960802afba73b5d38sm /* 946cfd74d65d832137e20e193c960802afba73b5d38sm * Create an OpenGL ES context. This must be done only once, an 947cfd74d65d832137e20e193c960802afba73b5d38sm * OpenGL context is a somewhat heavy object. 948cfd74d65d832137e20e193c960802afba73b5d38sm */ 949cfd74d65d832137e20e193c960802afba73b5d38sm mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 950cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { 951cfd74d65d832137e20e193c960802afba73b5d38sm throwEglException("createContext"); 952cfd74d65d832137e20e193c960802afba73b5d38sm } 953cfd74d65d832137e20e193c960802afba73b5d38sm 954cfd74d65d832137e20e193c960802afba73b5d38sm mEglSurface = null; 955cfd74d65d832137e20e193c960802afba73b5d38sm } 956cfd74d65d832137e20e193c960802afba73b5d38sm 957cfd74d65d832137e20e193c960802afba73b5d38sm /* 958cfd74d65d832137e20e193c960802afba73b5d38sm * React to the creation of a new surface by creating and returning an 959cfd74d65d832137e20e193c960802afba73b5d38sm * OpenGL interface that renders to that surface. 960cfd74d65d832137e20e193c960802afba73b5d38sm */ 961cfd74d65d832137e20e193c960802afba73b5d38sm public GL createSurface(SurfaceHolder holder) { 962cfd74d65d832137e20e193c960802afba73b5d38sm /* 963cfd74d65d832137e20e193c960802afba73b5d38sm * The window size has changed, so we need to create a new 964cfd74d65d832137e20e193c960802afba73b5d38sm * surface. 965cfd74d65d832137e20e193c960802afba73b5d38sm */ 966cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 967cfd74d65d832137e20e193c960802afba73b5d38sm 968cfd74d65d832137e20e193c960802afba73b5d38sm /* 969cfd74d65d832137e20e193c960802afba73b5d38sm * Unbind and destroy the old EGL surface, if 970cfd74d65d832137e20e193c960802afba73b5d38sm * there is one. 971cfd74d65d832137e20e193c960802afba73b5d38sm */ 972cfd74d65d832137e20e193c960802afba73b5d38sm mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 973cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 974cfd74d65d832137e20e193c960802afba73b5d38sm mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 975cfd74d65d832137e20e193c960802afba73b5d38sm } 976cfd74d65d832137e20e193c960802afba73b5d38sm 977cfd74d65d832137e20e193c960802afba73b5d38sm /* 978cfd74d65d832137e20e193c960802afba73b5d38sm * Create an EGL surface we can render into. 979cfd74d65d832137e20e193c960802afba73b5d38sm */ 980cfd74d65d832137e20e193c960802afba73b5d38sm mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, 981cfd74d65d832137e20e193c960802afba73b5d38sm mEglDisplay, mEglConfig, holder); 982cfd74d65d832137e20e193c960802afba73b5d38sm 983cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 984cfd74d65d832137e20e193c960802afba73b5d38sm throwEglException("createWindowSurface"); 985cfd74d65d832137e20e193c960802afba73b5d38sm } 986cfd74d65d832137e20e193c960802afba73b5d38sm 987cfd74d65d832137e20e193c960802afba73b5d38sm /* 988cfd74d65d832137e20e193c960802afba73b5d38sm * Before we can issue GL commands, we need to make sure 989cfd74d65d832137e20e193c960802afba73b5d38sm * the context is current and bound to a surface. 990cfd74d65d832137e20e193c960802afba73b5d38sm */ 991cfd74d65d832137e20e193c960802afba73b5d38sm if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 992cfd74d65d832137e20e193c960802afba73b5d38sm throwEglException("eglMakeCurrent"); 993cfd74d65d832137e20e193c960802afba73b5d38sm } 994cfd74d65d832137e20e193c960802afba73b5d38sm 995cfd74d65d832137e20e193c960802afba73b5d38sm GL gl = mEglContext.getGL(); 996cfd74d65d832137e20e193c960802afba73b5d38sm if (mGLWrapper != null) { 997cfd74d65d832137e20e193c960802afba73b5d38sm gl = mGLWrapper.wrap(gl); 998cfd74d65d832137e20e193c960802afba73b5d38sm } 999cfd74d65d832137e20e193c960802afba73b5d38sm 1000cfd74d65d832137e20e193c960802afba73b5d38sm if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { 1001cfd74d65d832137e20e193c960802afba73b5d38sm int configFlags = 0; 1002cfd74d65d832137e20e193c960802afba73b5d38sm Writer log = null; 1003cfd74d65d832137e20e193c960802afba73b5d38sm if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { 1004cfd74d65d832137e20e193c960802afba73b5d38sm configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; 1005cfd74d65d832137e20e193c960802afba73b5d38sm } 1006cfd74d65d832137e20e193c960802afba73b5d38sm if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { 1007cfd74d65d832137e20e193c960802afba73b5d38sm log = new LogWriter(); 1008cfd74d65d832137e20e193c960802afba73b5d38sm } 1009cfd74d65d832137e20e193c960802afba73b5d38sm gl = GLDebugHelper.wrap(gl, configFlags, log); 1010cfd74d65d832137e20e193c960802afba73b5d38sm } 1011cfd74d65d832137e20e193c960802afba73b5d38sm return gl; 1012cfd74d65d832137e20e193c960802afba73b5d38sm } 1013cfd74d65d832137e20e193c960802afba73b5d38sm 1014cfd74d65d832137e20e193c960802afba73b5d38sm /** 1015cfd74d65d832137e20e193c960802afba73b5d38sm * Display the current render surface. 1016cfd74d65d832137e20e193c960802afba73b5d38sm * @return false if the context has been lost. 1017cfd74d65d832137e20e193c960802afba73b5d38sm */ 1018cfd74d65d832137e20e193c960802afba73b5d38sm public boolean swap() { 1019cfd74d65d832137e20e193c960802afba73b5d38sm mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); 1020cfd74d65d832137e20e193c960802afba73b5d38sm 1021cfd74d65d832137e20e193c960802afba73b5d38sm /* 1022cfd74d65d832137e20e193c960802afba73b5d38sm * Always check for EGL_CONTEXT_LOST, which means the context 1023cfd74d65d832137e20e193c960802afba73b5d38sm * and all associated data were lost (For instance because 1024cfd74d65d832137e20e193c960802afba73b5d38sm * the device went to sleep). We need to sleep until we 1025cfd74d65d832137e20e193c960802afba73b5d38sm * get a new surface. 1026cfd74d65d832137e20e193c960802afba73b5d38sm */ 1027cfd74d65d832137e20e193c960802afba73b5d38sm return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; 1028cfd74d65d832137e20e193c960802afba73b5d38sm } 1029cfd74d65d832137e20e193c960802afba73b5d38sm 1030cfd74d65d832137e20e193c960802afba73b5d38sm public void destroySurface() { 1031cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 1032cfd74d65d832137e20e193c960802afba73b5d38sm mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 1033cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_NO_SURFACE, 1034cfd74d65d832137e20e193c960802afba73b5d38sm EGL10.EGL_NO_CONTEXT); 1035cfd74d65d832137e20e193c960802afba73b5d38sm mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 1036cfd74d65d832137e20e193c960802afba73b5d38sm mEglSurface = null; 1037cfd74d65d832137e20e193c960802afba73b5d38sm } 1038cfd74d65d832137e20e193c960802afba73b5d38sm } 1039cfd74d65d832137e20e193c960802afba73b5d38sm 1040cfd74d65d832137e20e193c960802afba73b5d38sm public void finish() { 1041cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglContext != null) { 1042cfd74d65d832137e20e193c960802afba73b5d38sm mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); 1043cfd74d65d832137e20e193c960802afba73b5d38sm mEglContext = null; 1044cfd74d65d832137e20e193c960802afba73b5d38sm } 1045cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglDisplay != null) { 1046cfd74d65d832137e20e193c960802afba73b5d38sm mEgl.eglTerminate(mEglDisplay); 1047cfd74d65d832137e20e193c960802afba73b5d38sm mEglDisplay = null; 1048cfd74d65d832137e20e193c960802afba73b5d38sm } 1049cfd74d65d832137e20e193c960802afba73b5d38sm } 1050cfd74d65d832137e20e193c960802afba73b5d38sm 1051cfd74d65d832137e20e193c960802afba73b5d38sm private void throwEglException(String function) { 1052cfd74d65d832137e20e193c960802afba73b5d38sm throw new RuntimeException(function + " failed: " + mEgl.eglGetError()); 1053cfd74d65d832137e20e193c960802afba73b5d38sm } 1054cfd74d65d832137e20e193c960802afba73b5d38sm 1055cfd74d65d832137e20e193c960802afba73b5d38sm /** Checks to see if the current context is valid. **/ 1056cfd74d65d832137e20e193c960802afba73b5d38sm public boolean verifyContext() { 1057cfd74d65d832137e20e193c960802afba73b5d38sm EGLContext currentContext = mEgl.eglGetCurrentContext(); 1058cfd74d65d832137e20e193c960802afba73b5d38sm return currentContext != EGL10.EGL_NO_CONTEXT && mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; 1059cfd74d65d832137e20e193c960802afba73b5d38sm } 1060cfd74d65d832137e20e193c960802afba73b5d38sm 1061cfd74d65d832137e20e193c960802afba73b5d38sm EGL10 mEgl; 1062cfd74d65d832137e20e193c960802afba73b5d38sm EGLDisplay mEglDisplay; 1063cfd74d65d832137e20e193c960802afba73b5d38sm EGLSurface mEglSurface; 1064cfd74d65d832137e20e193c960802afba73b5d38sm EGLConfig mEglConfig; 1065cfd74d65d832137e20e193c960802afba73b5d38sm EGLContext mEglContext; 1066cfd74d65d832137e20e193c960802afba73b5d38sm 1067cfd74d65d832137e20e193c960802afba73b5d38sm } 1068cfd74d65d832137e20e193c960802afba73b5d38sm 1069cfd74d65d832137e20e193c960802afba73b5d38sm /** 1070cfd74d65d832137e20e193c960802afba73b5d38sm * A generic GL Thread. Takes care of initializing EGL and GL. Delegates 1071cfd74d65d832137e20e193c960802afba73b5d38sm * to a Renderer instance to do the actual drawing. Can be configured to 1072cfd74d65d832137e20e193c960802afba73b5d38sm * render continuously or on request. 1073cfd74d65d832137e20e193c960802afba73b5d38sm * 1074cfd74d65d832137e20e193c960802afba73b5d38sm * All potentially blocking synchronization is done through the 1075cfd74d65d832137e20e193c960802afba73b5d38sm * sGLThreadManager object. This avoids multiple-lock ordering issues. 1076cfd74d65d832137e20e193c960802afba73b5d38sm * 1077cfd74d65d832137e20e193c960802afba73b5d38sm */ 1078cfd74d65d832137e20e193c960802afba73b5d38sm private class GLThread extends Thread { 1079cfd74d65d832137e20e193c960802afba73b5d38sm public GLThread(Renderer renderer) { 1080cfd74d65d832137e20e193c960802afba73b5d38sm super(); 1081cfd74d65d832137e20e193c960802afba73b5d38sm mWidth = 0; 1082cfd74d65d832137e20e193c960802afba73b5d38sm mHeight = 0; 1083cfd74d65d832137e20e193c960802afba73b5d38sm mRequestRender = true; 1084cfd74d65d832137e20e193c960802afba73b5d38sm mRenderMode = RENDERMODE_CONTINUOUSLY; 1085cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer = renderer; 1086cfd74d65d832137e20e193c960802afba73b5d38sm } 1087cfd74d65d832137e20e193c960802afba73b5d38sm 1088cfd74d65d832137e20e193c960802afba73b5d38sm 1089cfd74d65d832137e20e193c960802afba73b5d38sm @Override 1090cfd74d65d832137e20e193c960802afba73b5d38sm public void run() { 1091cfd74d65d832137e20e193c960802afba73b5d38sm setName("GLThread " + getId()); 1092cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_THREADS) { 1093cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "starting tid=" + getId()); 1094cfd74d65d832137e20e193c960802afba73b5d38sm } 1095cfd74d65d832137e20e193c960802afba73b5d38sm 1096cfd74d65d832137e20e193c960802afba73b5d38sm try { 1097cfd74d65d832137e20e193c960802afba73b5d38sm guardedRun(); 1098cfd74d65d832137e20e193c960802afba73b5d38sm } catch (InterruptedException e) { 1099cfd74d65d832137e20e193c960802afba73b5d38sm // fall thru and exit normally 1100cfd74d65d832137e20e193c960802afba73b5d38sm } finally { 1101cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.threadExiting(this); 1102cfd74d65d832137e20e193c960802afba73b5d38sm } 1103cfd74d65d832137e20e193c960802afba73b5d38sm } 1104cfd74d65d832137e20e193c960802afba73b5d38sm 1105cfd74d65d832137e20e193c960802afba73b5d38sm /* 1106cfd74d65d832137e20e193c960802afba73b5d38sm * This private method should only be called inside a 1107cfd74d65d832137e20e193c960802afba73b5d38sm * synchronized(sGLThreadManager) block. 1108cfd74d65d832137e20e193c960802afba73b5d38sm */ 1109cfd74d65d832137e20e193c960802afba73b5d38sm private void stopEglLocked() { 1110cfd74d65d832137e20e193c960802afba73b5d38sm if (mHaveEglSurface) { 1111cfd74d65d832137e20e193c960802afba73b5d38sm mHaveEglSurface = false; 1112cfd74d65d832137e20e193c960802afba73b5d38sm mEglHelper.destroySurface(); 1113cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.releaseEglSurfaceLocked(this); 1114cfd74d65d832137e20e193c960802afba73b5d38sm } 1115cfd74d65d832137e20e193c960802afba73b5d38sm } 1116cfd74d65d832137e20e193c960802afba73b5d38sm 1117cfd74d65d832137e20e193c960802afba73b5d38sm private void guardedRun() throws InterruptedException { 1118cfd74d65d832137e20e193c960802afba73b5d38sm mEglHelper = new EglHelper(); 1119cfd74d65d832137e20e193c960802afba73b5d38sm mHaveEglContext = false; 1120cfd74d65d832137e20e193c960802afba73b5d38sm mHaveEglSurface = false; 1121cfd74d65d832137e20e193c960802afba73b5d38sm try { 1122cfd74d65d832137e20e193c960802afba73b5d38sm GL10 gl = null; 1123cfd74d65d832137e20e193c960802afba73b5d38sm boolean createEglSurface = false; 1124cfd74d65d832137e20e193c960802afba73b5d38sm boolean sizeChanged = false; 1125cfd74d65d832137e20e193c960802afba73b5d38sm boolean wantRenderNotification = false; 1126cfd74d65d832137e20e193c960802afba73b5d38sm boolean doRenderNotification = false; 1127cfd74d65d832137e20e193c960802afba73b5d38sm int w = 0; 1128cfd74d65d832137e20e193c960802afba73b5d38sm int h = 0; 1129cfd74d65d832137e20e193c960802afba73b5d38sm Runnable event = null; 11309d4cc2572d37983607df38b0f4216ed76ac51814sm int framesSinceResetHack = 0; 1131cfd74d65d832137e20e193c960802afba73b5d38sm while (true) { 1132cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (sGLThreadManager) { 1133cfd74d65d832137e20e193c960802afba73b5d38sm while (true) { 1134cfd74d65d832137e20e193c960802afba73b5d38sm if (mShouldExit) { 1135cfd74d65d832137e20e193c960802afba73b5d38sm return; 1136cfd74d65d832137e20e193c960802afba73b5d38sm } 1137cfd74d65d832137e20e193c960802afba73b5d38sm 1138cfd74d65d832137e20e193c960802afba73b5d38sm if (! mEventQueue.isEmpty()) { 1139cfd74d65d832137e20e193c960802afba73b5d38sm event = mEventQueue.remove(0); 1140cfd74d65d832137e20e193c960802afba73b5d38sm break; 1141cfd74d65d832137e20e193c960802afba73b5d38sm } 1142cfd74d65d832137e20e193c960802afba73b5d38sm 1143cfd74d65d832137e20e193c960802afba73b5d38sm // Do we need to release the EGL surface? 1144cfd74d65d832137e20e193c960802afba73b5d38sm if (mHaveEglSurface && mPaused) { 1145cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_SURFACE) { 1146cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "releasing EGL surface because paused tid=" + getId()); 1147cfd74d65d832137e20e193c960802afba73b5d38sm } 1148cfd74d65d832137e20e193c960802afba73b5d38sm stopEglLocked(); 1149cfd74d65d832137e20e193c960802afba73b5d38sm } 1150cfd74d65d832137e20e193c960802afba73b5d38sm 1151cfd74d65d832137e20e193c960802afba73b5d38sm // Have we lost the surface view surface? 1152cfd74d65d832137e20e193c960802afba73b5d38sm if ((! mHasSurface) && (! mWaitingForSurface)) { 1153cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_SURFACE) { 1154cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); 1155cfd74d65d832137e20e193c960802afba73b5d38sm } 1156cfd74d65d832137e20e193c960802afba73b5d38sm if (mHaveEglSurface) { 1157cfd74d65d832137e20e193c960802afba73b5d38sm stopEglLocked(); 1158cfd74d65d832137e20e193c960802afba73b5d38sm } 1159cfd74d65d832137e20e193c960802afba73b5d38sm mWaitingForSurface = true; 1160cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1161cfd74d65d832137e20e193c960802afba73b5d38sm } 1162cfd74d65d832137e20e193c960802afba73b5d38sm 1163cfd74d65d832137e20e193c960802afba73b5d38sm // Have we acquired the surface view surface? 1164cfd74d65d832137e20e193c960802afba73b5d38sm if (mHasSurface && mWaitingForSurface) { 1165cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_SURFACE) { 1166cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); 1167cfd74d65d832137e20e193c960802afba73b5d38sm } 1168cfd74d65d832137e20e193c960802afba73b5d38sm mWaitingForSurface = false; 1169cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1170cfd74d65d832137e20e193c960802afba73b5d38sm } 1171cfd74d65d832137e20e193c960802afba73b5d38sm 1172cfd74d65d832137e20e193c960802afba73b5d38sm if (doRenderNotification) { 1173cfd74d65d832137e20e193c960802afba73b5d38sm wantRenderNotification = false; 1174cfd74d65d832137e20e193c960802afba73b5d38sm doRenderNotification = false; 1175cfd74d65d832137e20e193c960802afba73b5d38sm mRenderComplete = true; 1176cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1177cfd74d65d832137e20e193c960802afba73b5d38sm } 1178cfd74d65d832137e20e193c960802afba73b5d38sm 1179cfd74d65d832137e20e193c960802afba73b5d38sm // Ready to draw? 1180cfd74d65d832137e20e193c960802afba73b5d38sm if ((!mPaused) && mHasSurface 1181cfd74d65d832137e20e193c960802afba73b5d38sm && (mWidth > 0) && (mHeight > 0) 1182cfd74d65d832137e20e193c960802afba73b5d38sm && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { 1183cfd74d65d832137e20e193c960802afba73b5d38sm 1184cfd74d65d832137e20e193c960802afba73b5d38sm if (mHaveEglContext && !mHaveEglSurface) { 1185cfd74d65d832137e20e193c960802afba73b5d38sm // Let's make sure the context hasn't been lost. 1186cfd74d65d832137e20e193c960802afba73b5d38sm if (!mEglHelper.verifyContext()) { 1187cfd74d65d832137e20e193c960802afba73b5d38sm mEglHelper.finish(); 1188cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.onSurfaceLost(); 1189cfd74d65d832137e20e193c960802afba73b5d38sm mHaveEglContext = false; 1190cfd74d65d832137e20e193c960802afba73b5d38sm } 1191cfd74d65d832137e20e193c960802afba73b5d38sm } 1192cfd74d65d832137e20e193c960802afba73b5d38sm // If we don't have an egl surface, try to acquire one. 1193cfd74d65d832137e20e193c960802afba73b5d38sm if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglSurfaceLocked(this)) { 1194cfd74d65d832137e20e193c960802afba73b5d38sm mHaveEglContext = true; 1195cfd74d65d832137e20e193c960802afba73b5d38sm mEglHelper.start(); 1196cfd74d65d832137e20e193c960802afba73b5d38sm 1197cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1198cfd74d65d832137e20e193c960802afba73b5d38sm } 1199cfd74d65d832137e20e193c960802afba73b5d38sm 1200cfd74d65d832137e20e193c960802afba73b5d38sm if (mHaveEglContext && !mHaveEglSurface) { 1201cfd74d65d832137e20e193c960802afba73b5d38sm mHaveEglSurface = true; 1202cfd74d65d832137e20e193c960802afba73b5d38sm createEglSurface = true; 1203cfd74d65d832137e20e193c960802afba73b5d38sm sizeChanged = true; 1204cfd74d65d832137e20e193c960802afba73b5d38sm } 1205cfd74d65d832137e20e193c960802afba73b5d38sm 1206cfd74d65d832137e20e193c960802afba73b5d38sm if (mHaveEglSurface) { 1207cfd74d65d832137e20e193c960802afba73b5d38sm if (mSizeChanged) { 1208cfd74d65d832137e20e193c960802afba73b5d38sm sizeChanged = true; 1209cfd74d65d832137e20e193c960802afba73b5d38sm w = mWidth; 1210cfd74d65d832137e20e193c960802afba73b5d38sm h = mHeight; 1211cfd74d65d832137e20e193c960802afba73b5d38sm wantRenderNotification = true; 1212cfd74d65d832137e20e193c960802afba73b5d38sm 1213cfd74d65d832137e20e193c960802afba73b5d38sm if (DRAW_TWICE_AFTER_SIZE_CHANGED) { 1214cfd74d65d832137e20e193c960802afba73b5d38sm // We keep mRequestRender true so that we draw twice after the size changes. 1215cfd74d65d832137e20e193c960802afba73b5d38sm // (Once because of mSizeChanged, the second time because of mRequestRender.) 1216cfd74d65d832137e20e193c960802afba73b5d38sm // This forces the updated graphics onto the screen. 1217cfd74d65d832137e20e193c960802afba73b5d38sm } else { 1218cfd74d65d832137e20e193c960802afba73b5d38sm mRequestRender = false; 1219cfd74d65d832137e20e193c960802afba73b5d38sm } 1220cfd74d65d832137e20e193c960802afba73b5d38sm mSizeChanged = false; 1221cfd74d65d832137e20e193c960802afba73b5d38sm } else { 1222cfd74d65d832137e20e193c960802afba73b5d38sm mRequestRender = false; 1223cfd74d65d832137e20e193c960802afba73b5d38sm } 1224cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1225cfd74d65d832137e20e193c960802afba73b5d38sm break; 1226cfd74d65d832137e20e193c960802afba73b5d38sm } 1227cfd74d65d832137e20e193c960802afba73b5d38sm } 1228cfd74d65d832137e20e193c960802afba73b5d38sm 1229cfd74d65d832137e20e193c960802afba73b5d38sm // By design, this is the only place in a GLThread thread where we wait(). 1230cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_THREADS) { 1231cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "waiting tid=" + getId()); 1232cfd74d65d832137e20e193c960802afba73b5d38sm } 1233cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.wait(); 1234cfd74d65d832137e20e193c960802afba73b5d38sm } 1235cfd74d65d832137e20e193c960802afba73b5d38sm } // end of synchronized(sGLThreadManager) 1236cfd74d65d832137e20e193c960802afba73b5d38sm 1237cfd74d65d832137e20e193c960802afba73b5d38sm if (event != null) { 1238cfd74d65d832137e20e193c960802afba73b5d38sm event.run(); 1239cfd74d65d832137e20e193c960802afba73b5d38sm event = null; 1240cfd74d65d832137e20e193c960802afba73b5d38sm continue; 1241cfd74d65d832137e20e193c960802afba73b5d38sm } 1242cfd74d65d832137e20e193c960802afba73b5d38sm 1243cfd74d65d832137e20e193c960802afba73b5d38sm if (mHasFocus) { 1244cfd74d65d832137e20e193c960802afba73b5d38sm if (createEglSurface) { 1245cfd74d65d832137e20e193c960802afba73b5d38sm gl = (GL10) mEglHelper.createSurface(getHolder()); 1246cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.checkGLDriver(gl); 1247cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_RENDERER) { 1248cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.w("GLThread", "onSurfaceCreated"); 1249cfd74d65d832137e20e193c960802afba73b5d38sm } 1250cfd74d65d832137e20e193c960802afba73b5d38sm mGL = gl; 1251cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); 1252cfd74d65d832137e20e193c960802afba73b5d38sm createEglSurface = false; 12539d4cc2572d37983607df38b0f4216ed76ac51814sm framesSinceResetHack = 0; 1254cfd74d65d832137e20e193c960802afba73b5d38sm } 1255cfd74d65d832137e20e193c960802afba73b5d38sm 1256cfd74d65d832137e20e193c960802afba73b5d38sm 1257cfd74d65d832137e20e193c960802afba73b5d38sm if (sizeChanged) { 1258cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_RENDERER) { 1259cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); 1260cfd74d65d832137e20e193c960802afba73b5d38sm } 1261cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.onSurfaceChanged(gl, w, h); 1262cfd74d65d832137e20e193c960802afba73b5d38sm sizeChanged = false; 1263cfd74d65d832137e20e193c960802afba73b5d38sm } 1264cfd74d65d832137e20e193c960802afba73b5d38sm 1265cfd74d65d832137e20e193c960802afba73b5d38sm 1266cfd74d65d832137e20e193c960802afba73b5d38sm 1267cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_RENDERER) { 1268cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.w("GLThread", "onDrawFrame"); 1269cfd74d65d832137e20e193c960802afba73b5d38sm } 12709d4cc2572d37983607df38b0f4216ed76ac51814sm 12719d4cc2572d37983607df38b0f4216ed76ac51814sm // Some phones (Motorola Cliq, Backflip; also the 12729d4cc2572d37983607df38b0f4216ed76ac51814sm // Huawei Pulse, and maybe the Samsung Behold II), use a 12739d4cc2572d37983607df38b0f4216ed76ac51814sm // broken graphics driver from Qualcomm. It fails in a 12749d4cc2572d37983607df38b0f4216ed76ac51814sm // very specific case: when the EGL context is lost due to 12759d4cc2572d37983607df38b0f4216ed76ac51814sm // resource constraints, and then recreated, if GL commands 12769d4cc2572d37983607df38b0f4216ed76ac51814sm // are sent within two frames of the surface being created 12779d4cc2572d37983607df38b0f4216ed76ac51814sm // then eglSwapBuffers() will hang. Normally, applications using 12789d4cc2572d37983607df38b0f4216ed76ac51814sm // the stock GLSurfaceView never run into this problem because it 12799d4cc2572d37983607df38b0f4216ed76ac51814sm // discards the EGL context explicitly on every pause. But 12809d4cc2572d37983607df38b0f4216ed76ac51814sm // I've modified this class to not do that--I only want to reload 12819d4cc2572d37983607df38b0f4216ed76ac51814sm // textures when the context is actually lost--so this bug 12829d4cc2572d37983607df38b0f4216ed76ac51814sm // revealed itself as black screens on devices like the Cliq. 12839d4cc2572d37983607df38b0f4216ed76ac51814sm // Thus, in "safe mode," I force two swaps to occur before 12849d4cc2572d37983607df38b0f4216ed76ac51814sm // issuing any GL commands. Don't ask me how long it took 12859d4cc2572d37983607df38b0f4216ed76ac51814sm // to figure this out. 12866cb78e547641bcab6f18ec34badca0840e000992Keun young Park // CTS: do not use safe mode. 12876cb78e547641bcab6f18ec34badca0840e000992Keun young Park mWatchDog.reset(); 12886cb78e547641bcab6f18ec34badca0840e000992Keun young Park mRenderer.onDrawFrame(gl); 12899d4cc2572d37983607df38b0f4216ed76ac51814sm 12909d4cc2572d37983607df38b0f4216ed76ac51814sm framesSinceResetHack++; 12919d4cc2572d37983607df38b0f4216ed76ac51814sm 1292cfd74d65d832137e20e193c960802afba73b5d38sm if(!mEglHelper.swap()) { 1293cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_SURFACE) { 1294cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "egl surface lost tid=" + getId()); 1295cfd74d65d832137e20e193c960802afba73b5d38sm } 12969d4cc2572d37983607df38b0f4216ed76ac51814sm 12979d4cc2572d37983607df38b0f4216ed76ac51814sm stopEglLocked(); 1298cfd74d65d832137e20e193c960802afba73b5d38sm } 1299cfd74d65d832137e20e193c960802afba73b5d38sm 1300cfd74d65d832137e20e193c960802afba73b5d38sm } 1301cfd74d65d832137e20e193c960802afba73b5d38sm if (wantRenderNotification) { 1302cfd74d65d832137e20e193c960802afba73b5d38sm doRenderNotification = true; 1303cfd74d65d832137e20e193c960802afba73b5d38sm } 1304cfd74d65d832137e20e193c960802afba73b5d38sm } 1305cfd74d65d832137e20e193c960802afba73b5d38sm 1306cfd74d65d832137e20e193c960802afba73b5d38sm } finally { 1307cfd74d65d832137e20e193c960802afba73b5d38sm mGL = null; 1308cfd74d65d832137e20e193c960802afba73b5d38sm /* 1309cfd74d65d832137e20e193c960802afba73b5d38sm * clean-up everything... 1310cfd74d65d832137e20e193c960802afba73b5d38sm */ 1311cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (sGLThreadManager) { 1312cfd74d65d832137e20e193c960802afba73b5d38sm stopEglLocked(); 1313cfd74d65d832137e20e193c960802afba73b5d38sm mEglHelper.finish(); 1314cfd74d65d832137e20e193c960802afba73b5d38sm } 1315cfd74d65d832137e20e193c960802afba73b5d38sm } 1316cfd74d65d832137e20e193c960802afba73b5d38sm } 1317cfd74d65d832137e20e193c960802afba73b5d38sm 1318cfd74d65d832137e20e193c960802afba73b5d38sm public void setRenderMode(int renderMode) { 1319cfd74d65d832137e20e193c960802afba73b5d38sm if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { 1320cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalArgumentException("renderMode"); 1321cfd74d65d832137e20e193c960802afba73b5d38sm } 1322cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1323cfd74d65d832137e20e193c960802afba73b5d38sm mRenderMode = renderMode; 1324cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1325cfd74d65d832137e20e193c960802afba73b5d38sm } 1326cfd74d65d832137e20e193c960802afba73b5d38sm } 1327cfd74d65d832137e20e193c960802afba73b5d38sm 1328cfd74d65d832137e20e193c960802afba73b5d38sm public int getRenderMode() { 1329cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1330cfd74d65d832137e20e193c960802afba73b5d38sm return mRenderMode; 1331cfd74d65d832137e20e193c960802afba73b5d38sm } 1332cfd74d65d832137e20e193c960802afba73b5d38sm } 1333cfd74d65d832137e20e193c960802afba73b5d38sm 1334cfd74d65d832137e20e193c960802afba73b5d38sm public void requestRender() { 1335cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1336cfd74d65d832137e20e193c960802afba73b5d38sm mRequestRender = true; 1337cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1338cfd74d65d832137e20e193c960802afba73b5d38sm } 1339cfd74d65d832137e20e193c960802afba73b5d38sm } 1340cfd74d65d832137e20e193c960802afba73b5d38sm 1341cfd74d65d832137e20e193c960802afba73b5d38sm public void surfaceCreated() { 1342cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1343cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_THREADS) { 1344cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "surfaceCreated tid=" + getId()); 1345cfd74d65d832137e20e193c960802afba73b5d38sm } 1346cfd74d65d832137e20e193c960802afba73b5d38sm mHasSurface = true; 1347cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1348cfd74d65d832137e20e193c960802afba73b5d38sm } 1349cfd74d65d832137e20e193c960802afba73b5d38sm } 1350cfd74d65d832137e20e193c960802afba73b5d38sm 1351cfd74d65d832137e20e193c960802afba73b5d38sm public void surfaceDestroyed() { 1352cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1353cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_THREADS) { 1354cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "surfaceDestroyed tid=" + getId()); 1355cfd74d65d832137e20e193c960802afba73b5d38sm } 1356cfd74d65d832137e20e193c960802afba73b5d38sm mHasSurface = false; 1357cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1358cfd74d65d832137e20e193c960802afba73b5d38sm while((!mWaitingForSurface) && (!mExited)) { 1359cfd74d65d832137e20e193c960802afba73b5d38sm try { 1360cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.wait(); 1361cfd74d65d832137e20e193c960802afba73b5d38sm } catch (InterruptedException e) { 1362cfd74d65d832137e20e193c960802afba73b5d38sm Thread.currentThread().interrupt(); 1363cfd74d65d832137e20e193c960802afba73b5d38sm } 1364cfd74d65d832137e20e193c960802afba73b5d38sm } 1365cfd74d65d832137e20e193c960802afba73b5d38sm } 1366cfd74d65d832137e20e193c960802afba73b5d38sm } 1367cfd74d65d832137e20e193c960802afba73b5d38sm 1368cfd74d65d832137e20e193c960802afba73b5d38sm public void onPause() { 1369cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (sGLThreadManager) { 1370cfd74d65d832137e20e193c960802afba73b5d38sm mPaused = true; 1371cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1372cfd74d65d832137e20e193c960802afba73b5d38sm } 1373cfd74d65d832137e20e193c960802afba73b5d38sm } 1374cfd74d65d832137e20e193c960802afba73b5d38sm 1375cfd74d65d832137e20e193c960802afba73b5d38sm public void onResume() { 1376cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (sGLThreadManager) { 1377cfd74d65d832137e20e193c960802afba73b5d38sm mPaused = false; 1378cfd74d65d832137e20e193c960802afba73b5d38sm mRequestRender = true; 1379cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1380cfd74d65d832137e20e193c960802afba73b5d38sm } 1381cfd74d65d832137e20e193c960802afba73b5d38sm } 1382cfd74d65d832137e20e193c960802afba73b5d38sm 1383cfd74d65d832137e20e193c960802afba73b5d38sm public void onWindowResize(int w, int h) { 1384cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (sGLThreadManager) { 1385cfd74d65d832137e20e193c960802afba73b5d38sm mWidth = w; 1386cfd74d65d832137e20e193c960802afba73b5d38sm mHeight = h; 1387cfd74d65d832137e20e193c960802afba73b5d38sm mSizeChanged = true; 1388cfd74d65d832137e20e193c960802afba73b5d38sm mRequestRender = true; 1389cfd74d65d832137e20e193c960802afba73b5d38sm mRenderComplete = false; 1390cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1391cfd74d65d832137e20e193c960802afba73b5d38sm 1392cfd74d65d832137e20e193c960802afba73b5d38sm // Wait for thread to react to resize and render a frame 1393cfd74d65d832137e20e193c960802afba73b5d38sm while (! mExited && !mPaused && !mRenderComplete ) { 1394cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_SURFACE) { 1395cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("Main thread", "onWindowResize waiting for render complete."); 1396cfd74d65d832137e20e193c960802afba73b5d38sm } 1397cfd74d65d832137e20e193c960802afba73b5d38sm try { 1398cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.wait(); 1399cfd74d65d832137e20e193c960802afba73b5d38sm } catch (InterruptedException ex) { 1400cfd74d65d832137e20e193c960802afba73b5d38sm Thread.currentThread().interrupt(); 1401cfd74d65d832137e20e193c960802afba73b5d38sm } 1402cfd74d65d832137e20e193c960802afba73b5d38sm } 1403cfd74d65d832137e20e193c960802afba73b5d38sm } 1404cfd74d65d832137e20e193c960802afba73b5d38sm } 1405cfd74d65d832137e20e193c960802afba73b5d38sm 1406cfd74d65d832137e20e193c960802afba73b5d38sm public void loadTextures(TextureLibrary library) { 1407cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (this) { 1408cfd74d65d832137e20e193c960802afba73b5d38sm assert mGL != null; 1409cfd74d65d832137e20e193c960802afba73b5d38sm if (mGL != null && mHasSurface) { 1410cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.loadTextures(mGL, library); 1411cfd74d65d832137e20e193c960802afba73b5d38sm } 1412cfd74d65d832137e20e193c960802afba73b5d38sm } 1413cfd74d65d832137e20e193c960802afba73b5d38sm } 1414cfd74d65d832137e20e193c960802afba73b5d38sm 1415cfd74d65d832137e20e193c960802afba73b5d38sm public void flushTextures(TextureLibrary library) { 1416cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (this) { 1417cfd74d65d832137e20e193c960802afba73b5d38sm assert mGL != null; 1418cfd74d65d832137e20e193c960802afba73b5d38sm if (mGL != null) { 1419cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.flushTextures(mGL, library); 1420cfd74d65d832137e20e193c960802afba73b5d38sm } 1421cfd74d65d832137e20e193c960802afba73b5d38sm } 1422cfd74d65d832137e20e193c960802afba73b5d38sm } 1423cfd74d65d832137e20e193c960802afba73b5d38sm 1424cfd74d65d832137e20e193c960802afba73b5d38sm public void loadBuffers(BufferLibrary library) { 1425cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (this) { 1426cfd74d65d832137e20e193c960802afba73b5d38sm assert mGL != null; 1427cfd74d65d832137e20e193c960802afba73b5d38sm if (mGL != null) { 1428cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.loadBuffers(mGL, library); 1429cfd74d65d832137e20e193c960802afba73b5d38sm } 1430cfd74d65d832137e20e193c960802afba73b5d38sm } 1431cfd74d65d832137e20e193c960802afba73b5d38sm } 1432cfd74d65d832137e20e193c960802afba73b5d38sm 1433cfd74d65d832137e20e193c960802afba73b5d38sm public void flushBuffers(BufferLibrary library) { 1434cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (this) { 1435cfd74d65d832137e20e193c960802afba73b5d38sm assert mGL != null; 1436cfd74d65d832137e20e193c960802afba73b5d38sm if (mGL != null) { 1437cfd74d65d832137e20e193c960802afba73b5d38sm mRenderer.flushBuffers(mGL, library); 1438cfd74d65d832137e20e193c960802afba73b5d38sm } 1439cfd74d65d832137e20e193c960802afba73b5d38sm } 1440cfd74d65d832137e20e193c960802afba73b5d38sm } 1441cfd74d65d832137e20e193c960802afba73b5d38sm 1442cfd74d65d832137e20e193c960802afba73b5d38sm // On some Qualcomm devices (such as the HTC Magic running Android 1.6), 1443cfd74d65d832137e20e193c960802afba73b5d38sm // there's a bug in the graphics driver that will cause glViewport() to 1444cfd74d65d832137e20e193c960802afba73b5d38sm // do the wrong thing in a very specific situation. When the screen is 1445cfd74d65d832137e20e193c960802afba73b5d38sm // rotated, if a surface is created in one layout (say, portrait view) 1446cfd74d65d832137e20e193c960802afba73b5d38sm // and then rotated to another, subsequent calls to glViewport are clipped. 1447cfd74d65d832137e20e193c960802afba73b5d38sm // So, if the window is, say, 320x480 when the surface is created, and 1448cfd74d65d832137e20e193c960802afba73b5d38sm // then the rotation occurs and glViewport() is called with the new 1449cfd74d65d832137e20e193c960802afba73b5d38sm // size of 480x320, devices with the buggy driver will clip the viewport 1450cfd74d65d832137e20e193c960802afba73b5d38sm // to the old width (which means 320x320...ugh!). This is fixed in 1451cfd74d65d832137e20e193c960802afba73b5d38sm // Android 2.1 Qualcomm devices (like Nexus One) and doesn't affect 1452cfd74d65d832137e20e193c960802afba73b5d38sm // non-Qualcomm devices (like the Motorola DROID). 1453cfd74d65d832137e20e193c960802afba73b5d38sm // 1454cfd74d65d832137e20e193c960802afba73b5d38sm // Unfortunately, under Android 1.6 this exact case occurs when the 1455cfd74d65d832137e20e193c960802afba73b5d38sm // screen is put to sleep and then wakes up again. The lock screen 1456cfd74d65d832137e20e193c960802afba73b5d38sm // comes up in portrait mode, but at the same time the window surface 1457cfd74d65d832137e20e193c960802afba73b5d38sm // is also created in the backgrounded game. When the lock screen is closed 1458cfd74d65d832137e20e193c960802afba73b5d38sm // and the game comes forward, the window is fixed to the correct size 1459cfd74d65d832137e20e193c960802afba73b5d38sm // which causes the bug to occur. 1460cfd74d65d832137e20e193c960802afba73b5d38sm 1461cfd74d65d832137e20e193c960802afba73b5d38sm // The solution used here is to simply never render when the window surface 1462cfd74d65d832137e20e193c960802afba73b5d38sm // does not have the focus. When the lock screen (or menu) is up, rendering 1463cfd74d65d832137e20e193c960802afba73b5d38sm // will stop. This resolves the driver bug (as the egl surface won't be created 1464cfd74d65d832137e20e193c960802afba73b5d38sm // until after the screen size has been fixed), and is generally good practice 1465cfd74d65d832137e20e193c960802afba73b5d38sm // since you don't want to be doing a lot of CPU intensive work when the lock 1466cfd74d65d832137e20e193c960802afba73b5d38sm // screen is up (to preserve battery life). 1467cfd74d65d832137e20e193c960802afba73b5d38sm 1468cfd74d65d832137e20e193c960802afba73b5d38sm public void onWindowFocusChanged(boolean hasFocus) { 1469cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1470cfd74d65d832137e20e193c960802afba73b5d38sm mHasFocus = hasFocus; 1471cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1472cfd74d65d832137e20e193c960802afba73b5d38sm } 1473cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_SURFACE) { 1474cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("Main thread", "Focus " + (mHasFocus ? "gained" : "lost")); 1475cfd74d65d832137e20e193c960802afba73b5d38sm } 1476cfd74d65d832137e20e193c960802afba73b5d38sm 1477cfd74d65d832137e20e193c960802afba73b5d38sm } 1478cfd74d65d832137e20e193c960802afba73b5d38sm 1479cfd74d65d832137e20e193c960802afba73b5d38sm public void requestExitAndWait() { 1480cfd74d65d832137e20e193c960802afba73b5d38sm // don't call this from GLThread thread or it is a guaranteed 1481cfd74d65d832137e20e193c960802afba73b5d38sm // deadlock! 1482cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1483cfd74d65d832137e20e193c960802afba73b5d38sm mShouldExit = true; 1484cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1485cfd74d65d832137e20e193c960802afba73b5d38sm while (! mExited) { 1486cfd74d65d832137e20e193c960802afba73b5d38sm try { 1487cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.wait(); 1488cfd74d65d832137e20e193c960802afba73b5d38sm } catch (InterruptedException ex) { 1489cfd74d65d832137e20e193c960802afba73b5d38sm Thread.currentThread().interrupt(); 1490cfd74d65d832137e20e193c960802afba73b5d38sm } 1491cfd74d65d832137e20e193c960802afba73b5d38sm } 1492cfd74d65d832137e20e193c960802afba73b5d38sm } 1493cfd74d65d832137e20e193c960802afba73b5d38sm } 1494cfd74d65d832137e20e193c960802afba73b5d38sm 1495cfd74d65d832137e20e193c960802afba73b5d38sm /** 1496cfd74d65d832137e20e193c960802afba73b5d38sm * Queue an "event" to be run on the GL rendering thread. 1497cfd74d65d832137e20e193c960802afba73b5d38sm * @param r the runnable to be run on the GL rendering thread. 1498cfd74d65d832137e20e193c960802afba73b5d38sm */ 1499cfd74d65d832137e20e193c960802afba73b5d38sm public void queueEvent(Runnable r) { 1500cfd74d65d832137e20e193c960802afba73b5d38sm if (r == null) { 1501cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalArgumentException("r must not be null"); 1502cfd74d65d832137e20e193c960802afba73b5d38sm } 1503cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(sGLThreadManager) { 1504cfd74d65d832137e20e193c960802afba73b5d38sm mEventQueue.add(r); 1505cfd74d65d832137e20e193c960802afba73b5d38sm sGLThreadManager.notifyAll(); 1506cfd74d65d832137e20e193c960802afba73b5d38sm } 1507cfd74d65d832137e20e193c960802afba73b5d38sm } 15089d4cc2572d37983607df38b0f4216ed76ac51814sm 15099d4cc2572d37983607df38b0f4216ed76ac51814sm public void setSafeMode(boolean on) { 15109d4cc2572d37983607df38b0f4216ed76ac51814sm mSafeMode = on; 15119d4cc2572d37983607df38b0f4216ed76ac51814sm } 1512cfd74d65d832137e20e193c960802afba73b5d38sm 1513cfd74d65d832137e20e193c960802afba73b5d38sm // Once the thread is started, all accesses to the following member 1514cfd74d65d832137e20e193c960802afba73b5d38sm // variables are protected by the sGLThreadManager monitor 1515cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mShouldExit; 1516cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mExited; 1517cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mPaused; 1518cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mHasSurface; 1519cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mWaitingForSurface; 1520cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mHaveEglContext; 1521cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mHaveEglSurface; 1522cfd74d65d832137e20e193c960802afba73b5d38sm private int mWidth; 1523cfd74d65d832137e20e193c960802afba73b5d38sm private int mHeight; 1524cfd74d65d832137e20e193c960802afba73b5d38sm private int mRenderMode; 1525cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mRequestRender; 1526cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mRenderComplete; 1527cfd74d65d832137e20e193c960802afba73b5d38sm private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); 1528cfd74d65d832137e20e193c960802afba73b5d38sm private GL10 mGL; 1529cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mHasFocus; 15309d4cc2572d37983607df38b0f4216ed76ac51814sm private boolean mSafeMode = false; 1531cfd74d65d832137e20e193c960802afba73b5d38sm 1532cfd74d65d832137e20e193c960802afba73b5d38sm // End of member variables protected by the sGLThreadManager monitor. 1533cfd74d65d832137e20e193c960802afba73b5d38sm 1534cfd74d65d832137e20e193c960802afba73b5d38sm private Renderer mRenderer; 1535cfd74d65d832137e20e193c960802afba73b5d38sm private EglHelper mEglHelper; 1536cfd74d65d832137e20e193c960802afba73b5d38sm } 1537cfd74d65d832137e20e193c960802afba73b5d38sm 1538cfd74d65d832137e20e193c960802afba73b5d38sm static class LogWriter extends Writer { 1539cfd74d65d832137e20e193c960802afba73b5d38sm 1540cfd74d65d832137e20e193c960802afba73b5d38sm @Override public void close() { 1541cfd74d65d832137e20e193c960802afba73b5d38sm flushBuilder(); 1542cfd74d65d832137e20e193c960802afba73b5d38sm } 1543cfd74d65d832137e20e193c960802afba73b5d38sm 1544cfd74d65d832137e20e193c960802afba73b5d38sm @Override public void flush() { 1545cfd74d65d832137e20e193c960802afba73b5d38sm flushBuilder(); 1546cfd74d65d832137e20e193c960802afba73b5d38sm } 1547cfd74d65d832137e20e193c960802afba73b5d38sm 1548cfd74d65d832137e20e193c960802afba73b5d38sm @Override public void write(char[] buf, int offset, int count) { 1549cfd74d65d832137e20e193c960802afba73b5d38sm for(int i = 0; i < count; i++) { 1550cfd74d65d832137e20e193c960802afba73b5d38sm char c = buf[offset + i]; 1551cfd74d65d832137e20e193c960802afba73b5d38sm if ( c == '\n') { 1552cfd74d65d832137e20e193c960802afba73b5d38sm flushBuilder(); 1553cfd74d65d832137e20e193c960802afba73b5d38sm } 1554cfd74d65d832137e20e193c960802afba73b5d38sm else { 1555cfd74d65d832137e20e193c960802afba73b5d38sm mBuilder.append(c); 1556cfd74d65d832137e20e193c960802afba73b5d38sm } 1557cfd74d65d832137e20e193c960802afba73b5d38sm } 1558cfd74d65d832137e20e193c960802afba73b5d38sm } 1559cfd74d65d832137e20e193c960802afba73b5d38sm 1560cfd74d65d832137e20e193c960802afba73b5d38sm private void flushBuilder() { 1561cfd74d65d832137e20e193c960802afba73b5d38sm if (mBuilder.length() > 0) { 1562cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.v("GLSurfaceView", mBuilder.toString()); 1563cfd74d65d832137e20e193c960802afba73b5d38sm mBuilder.delete(0, mBuilder.length()); 1564cfd74d65d832137e20e193c960802afba73b5d38sm } 1565cfd74d65d832137e20e193c960802afba73b5d38sm } 1566cfd74d65d832137e20e193c960802afba73b5d38sm 1567cfd74d65d832137e20e193c960802afba73b5d38sm private StringBuilder mBuilder = new StringBuilder(); 1568cfd74d65d832137e20e193c960802afba73b5d38sm } 1569cfd74d65d832137e20e193c960802afba73b5d38sm 1570cfd74d65d832137e20e193c960802afba73b5d38sm 1571cfd74d65d832137e20e193c960802afba73b5d38sm private void checkRenderThreadState() { 1572cfd74d65d832137e20e193c960802afba73b5d38sm if (mGLThread != null) { 1573cfd74d65d832137e20e193c960802afba73b5d38sm throw new IllegalStateException( 1574cfd74d65d832137e20e193c960802afba73b5d38sm "setRenderer has already been called for this instance."); 1575cfd74d65d832137e20e193c960802afba73b5d38sm } 1576cfd74d65d832137e20e193c960802afba73b5d38sm } 1577cfd74d65d832137e20e193c960802afba73b5d38sm 1578cfd74d65d832137e20e193c960802afba73b5d38sm private static class GLThreadManager { 1579cfd74d65d832137e20e193c960802afba73b5d38sm 1580cfd74d65d832137e20e193c960802afba73b5d38sm public synchronized void threadExiting(GLThread thread) { 1581cfd74d65d832137e20e193c960802afba73b5d38sm if (LOG_THREADS) { 1582cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.i("GLThread", "exiting tid=" + thread.getId()); 1583cfd74d65d832137e20e193c960802afba73b5d38sm } 1584cfd74d65d832137e20e193c960802afba73b5d38sm thread.mExited = true; 1585cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglOwner == thread) { 1586cfd74d65d832137e20e193c960802afba73b5d38sm mEglOwner = null; 1587cfd74d65d832137e20e193c960802afba73b5d38sm } 1588cfd74d65d832137e20e193c960802afba73b5d38sm notifyAll(); 1589cfd74d65d832137e20e193c960802afba73b5d38sm } 1590cfd74d65d832137e20e193c960802afba73b5d38sm 1591cfd74d65d832137e20e193c960802afba73b5d38sm /* 1592cfd74d65d832137e20e193c960802afba73b5d38sm * Tries once to acquire the right to use an EGL 1593cfd74d65d832137e20e193c960802afba73b5d38sm * surface. Does not block. Requires that we are already 1594cfd74d65d832137e20e193c960802afba73b5d38sm * in the sGLThreadManager monitor when this is called. 1595cfd74d65d832137e20e193c960802afba73b5d38sm * 1596cfd74d65d832137e20e193c960802afba73b5d38sm * @return true if the right to use an EGL surface was acquired. 1597cfd74d65d832137e20e193c960802afba73b5d38sm */ 1598cfd74d65d832137e20e193c960802afba73b5d38sm public boolean tryAcquireEglSurfaceLocked(GLThread thread) { 1599cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglOwner == thread || mEglOwner == null) { 1600cfd74d65d832137e20e193c960802afba73b5d38sm mEglOwner = thread; 1601cfd74d65d832137e20e193c960802afba73b5d38sm notifyAll(); 1602cfd74d65d832137e20e193c960802afba73b5d38sm return true; 1603cfd74d65d832137e20e193c960802afba73b5d38sm } 1604cfd74d65d832137e20e193c960802afba73b5d38sm checkGLESVersion(); 1605cfd74d65d832137e20e193c960802afba73b5d38sm if (mMultipleGLESContextsAllowed) { 1606cfd74d65d832137e20e193c960802afba73b5d38sm return true; 1607cfd74d65d832137e20e193c960802afba73b5d38sm } 1608cfd74d65d832137e20e193c960802afba73b5d38sm return false; 1609cfd74d65d832137e20e193c960802afba73b5d38sm } 1610cfd74d65d832137e20e193c960802afba73b5d38sm /* 1611cfd74d65d832137e20e193c960802afba73b5d38sm * Releases the EGL surface. Requires that we are already in the 1612cfd74d65d832137e20e193c960802afba73b5d38sm * sGLThreadManager monitor when this is called. 1613cfd74d65d832137e20e193c960802afba73b5d38sm */ 1614cfd74d65d832137e20e193c960802afba73b5d38sm public void releaseEglSurfaceLocked(GLThread thread) { 1615cfd74d65d832137e20e193c960802afba73b5d38sm if (mEglOwner == thread) { 1616cfd74d65d832137e20e193c960802afba73b5d38sm mEglOwner = null; 1617cfd74d65d832137e20e193c960802afba73b5d38sm } 1618cfd74d65d832137e20e193c960802afba73b5d38sm notifyAll(); 1619cfd74d65d832137e20e193c960802afba73b5d38sm } 1620cfd74d65d832137e20e193c960802afba73b5d38sm 1621cfd74d65d832137e20e193c960802afba73b5d38sm public synchronized void checkGLDriver(GL10 gl) { 1622cfd74d65d832137e20e193c960802afba73b5d38sm if (! mGLESDriverCheckComplete) { 1623cfd74d65d832137e20e193c960802afba73b5d38sm checkGLESVersion(); 1624cfd74d65d832137e20e193c960802afba73b5d38sm if (mGLESVersion < kGLES_20) { 1625cfd74d65d832137e20e193c960802afba73b5d38sm String renderer = gl.glGetString(GL10.GL_RENDERER); 1626cfd74d65d832137e20e193c960802afba73b5d38sm mMultipleGLESContextsAllowed = false; 1627cfd74d65d832137e20e193c960802afba73b5d38sm notifyAll(); 1628cfd74d65d832137e20e193c960802afba73b5d38sm } 1629cfd74d65d832137e20e193c960802afba73b5d38sm mGLESDriverCheckComplete = true; 1630cfd74d65d832137e20e193c960802afba73b5d38sm } 1631cfd74d65d832137e20e193c960802afba73b5d38sm } 1632cfd74d65d832137e20e193c960802afba73b5d38sm 1633cfd74d65d832137e20e193c960802afba73b5d38sm private void checkGLESVersion() { 1634cfd74d65d832137e20e193c960802afba73b5d38sm if (! mGLESVersionCheckComplete) { 1635cfd74d65d832137e20e193c960802afba73b5d38sm mGLESVersion = ConfigurationInfo.GL_ES_VERSION_UNDEFINED; 1636cfd74d65d832137e20e193c960802afba73b5d38sm if (mGLESVersion >= kGLES_20) { 1637cfd74d65d832137e20e193c960802afba73b5d38sm mMultipleGLESContextsAllowed = true; 1638cfd74d65d832137e20e193c960802afba73b5d38sm } 1639cfd74d65d832137e20e193c960802afba73b5d38sm mGLESVersionCheckComplete = true; 1640cfd74d65d832137e20e193c960802afba73b5d38sm } 1641cfd74d65d832137e20e193c960802afba73b5d38sm 1642cfd74d65d832137e20e193c960802afba73b5d38sm } 1643cfd74d65d832137e20e193c960802afba73b5d38sm 1644cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mGLESVersionCheckComplete; 1645cfd74d65d832137e20e193c960802afba73b5d38sm private int mGLESVersion; 1646cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mGLESDriverCheckComplete; 1647cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mMultipleGLESContextsAllowed; 1648cfd74d65d832137e20e193c960802afba73b5d38sm private int mGLContextCount; 1649cfd74d65d832137e20e193c960802afba73b5d38sm private static final int kGLES_20 = 0x20000; 1650cfd74d65d832137e20e193c960802afba73b5d38sm private GLThread mEglOwner; 1651cfd74d65d832137e20e193c960802afba73b5d38sm 1652cfd74d65d832137e20e193c960802afba73b5d38sm } 1653cfd74d65d832137e20e193c960802afba73b5d38sm 1654cfd74d65d832137e20e193c960802afba73b5d38sm private static final GLThreadManager sGLThreadManager = new GLThreadManager(); 1655cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mSizeChanged = true; 1656cfd74d65d832137e20e193c960802afba73b5d38sm 1657cfd74d65d832137e20e193c960802afba73b5d38sm private GLThread mGLThread; 1658cfd74d65d832137e20e193c960802afba73b5d38sm private EGLConfigChooser mEGLConfigChooser; 1659cfd74d65d832137e20e193c960802afba73b5d38sm private EGLContextFactory mEGLContextFactory; 1660cfd74d65d832137e20e193c960802afba73b5d38sm private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; 1661cfd74d65d832137e20e193c960802afba73b5d38sm private GLWrapper mGLWrapper; 1662cfd74d65d832137e20e193c960802afba73b5d38sm private int mDebugFlags; 1663cfd74d65d832137e20e193c960802afba73b5d38sm private int mEGLContextClientVersion; 16646cb78e547641bcab6f18ec34badca0840e000992Keun young Park private final RenderingWatchDog mWatchDog = new RenderingWatchDog(); 1665cfd74d65d832137e20e193c960802afba73b5d38sm 1666cfd74d65d832137e20e193c960802afba73b5d38sm} 1667