GLSurfaceView.java revision 451a224c46c297bd6b25e3570b45f5053b4788be
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.opengl; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.Writer; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL10; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL11; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLConfig; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLContext; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLDisplay; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLSurface; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL10; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 32c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevichimport android.content.pm.ConfigurationInfo; 3383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevichimport android.graphics.PixelFormat; 34c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevichimport android.os.SystemProperties; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceView; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An implementation of SurfaceView that uses the dedicated surface for 42b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * displaying OpenGL rendering. 43b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 44b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView provides the following features: 45b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 46b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 47b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages a surface, which is a special piece of memory that can be 48b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * composited into the Android view system. 49b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages an EGL display, which enables OpenGL to render into a surface. 50b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Accepts a user-provided Renderer object that does the actual rendering. 51b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Renders on a dedicated thread to decouple rendering performance from the 52b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * UI thread. 53b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Supports both on-demand and continuous rendering. 54b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls. 55b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 56b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 57b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Using GLSurfaceView</h3> 58b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 59b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you use GLSurfaceView by subclassing it and overriding one or more of the 60b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * View system input event methods. If your application does not need to override event 61b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * methods then GLSurfaceView can be used as-is. For the most part 62b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. 63b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * For example, unlike a regular View, drawing is delegated to a separate Renderer object which 64b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is registered with the GLSurfaceView 65b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * using the {@link #setRenderer(Renderer)} call. 66b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 67b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Initializing GLSurfaceView</h3> 68b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. 69b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or 70b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * more of these methods before calling setRenderer: 71b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 72b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setDebugFlags(int)} 73b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 74b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 75b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 76b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setGLWrapper(GLWrapper)} 77b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 78b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 7983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <h4>Specifying the android.view.Surface</h4> 8083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * By default GLSurfaceView will create a PixelFormat.RGB_565 format surface. If a translucent 8183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). 8283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The exact format of a TRANSLUCENT surface is device dependent, but it will be 8383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * a 32-bit-per-pixel surface with 8 bits per component. 8483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 85b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Choosing an EGL Configuration</h4> 8683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * A given Android device may support multiple EGLConfig rendering configurations. 8783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The available configurations may differ in how may channels of data are present, as 88b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * well as how many bits are allocated to each channel. Therefore, the first thing 8983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * GLSurfaceView has to do when starting to render is choose what EGLConfig to use. 9083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 9183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * By default GLSurfaceView chooses a EGLConfig that has an RGB_656 pixel format, 9283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least a 16-bit depth buffer and no stencil. 93b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 9483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If you would prefer a different EGLConfig 9583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * you can override the default behavior by calling one of the 96b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setEGLConfigChooser methods. 97b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 98b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Debug Behavior</h4> 99b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * You can optionally modify the behavior of GLSurfaceView by calling 100b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one or more of the debugging methods {@link #setDebugFlags(int)}, 101b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but 102b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically they are called before setRenderer so that they take effect immediately. 103b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 104b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Setting a Renderer</h4> 105b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. 106b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is 107b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * responsible for doing the actual OpenGL rendering. 108b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 109b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Rendering Mode</h3> 110b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Once the renderer is set, you can control whether the renderer draws 111b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously or on-demand by calling 112b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #setRenderMode}. The default is continuous rendering. 113b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 114b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Activity Life-cycle</h3> 115b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients 116b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * are required to call {@link #onPause()} when the activity pauses and 117b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to 118b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate 119b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL display. 120b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 121b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Handling events</h3> 122b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 123b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * To handle an event you will typically subclass GLSurfaceView and override the 124b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * appropriate method, just as you would with any other View. However, when handling 125b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the event, you may need to communicate with the Renderer object 126b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that's running in the rendering thread. You can do this using any 127b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java cross-thread communication mechanism. In addition, 128b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one relatively easy way to communicate with your renderer is 129b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to call 130b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #queueEvent(Runnable)}. For example: 131b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 132b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLSurfaceView extends GLSurfaceView { 133b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 134b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * private MyRenderer mMyRenderer; 135b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 136b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void start() { 137b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer = ...; 138b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer(mMyRenderer); 139b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 140b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 141b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public boolean onKeyDown(int keyCode, KeyEvent event) { 142b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 143b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * queueEvent(new Runnable() { 144b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // This method will be called on the rendering 145b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // thread: 146b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void run() { 147b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer.handleDpadCenter(); 148b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * }}); 149b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return true; 150b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 151b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return super.onKeyDown(keyCode, event); 152b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 153b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 154b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 15857c6a46bd0c84c4b349d49f8df12f30a8cfcdaa2Jack Palevich private final static boolean LOG_THREADS = false; 159e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich private final static boolean LOG_PAUSE_RESUME = true; 160e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich private final static boolean LOG_SURFACE = true; 161451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private final static boolean LOG_RENDERER = true; 1624a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private final static boolean LOG_RENDERER_DRAW_FRAME = false; 163e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich private final static boolean LOG_EGL = true; 164a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Work-around for bug 2263168 165a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true; 166b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 167b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer only renders 168b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * when the surface is created, or when {@link #requestRender} is called. 169b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 170b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 171b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 172840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * @see #requestRender() 173b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int RENDERMODE_WHEN_DIRTY = 0; 175b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 176b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is called 177b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously to re-render the scene. 178b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 179b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 180b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 181b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 1823e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich public final static int RENDERMODE_CONTINUOUSLY = 1; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 185b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Check glError() after every GL call and throw an exception if glError indicates 186b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that an error has occurred. This can be used to help track down which OpenGL ES call 187b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is causing an error. 188b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 189b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getDebugFlags 190b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setDebugFlags 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int DEBUG_CHECK_GL_ERROR = 1; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". 196b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 197b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getDebugFlags 198b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setDebugFlags 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int DEBUG_LOG_GL_CALLS = 2; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 202b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 203b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Standard View constructor. In order to render something, you 204b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * must call {@link #setRenderer} to register a renderer. 205b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GLSurfaceView(Context context) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 211b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 212b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Standard View constructor. In order to render something, you 213b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * must call {@link #setRenderer} to register a renderer. 214b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GLSurfaceView(Context context, AttributeSet attrs) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init() { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Install a SurfaceHolder.Callback so we get notified when the 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // underlying surface is created and destroyed 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SurfaceHolder holder = getHolder(); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project holder.addCallback(this); 22583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich holder.setFormat(PixelFormat.RGB_565); 226840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // setType is not needed for SDK 2.0 or newer. Uncomment this 227840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // statement if back-porting this code to older SDKs. 228840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 232b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the glWrapper. If the glWrapper is not null, its 233b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLWrapper#wrap(GL)} method is called 234b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * whenever a surface is created. A GLWrapper can be used to wrap 235b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the GL object that's passed to the renderer. Wrapping a GL 236b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * object enables examining and modifying the behavior of the 237b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL calls made by the renderer. 238b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 239b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wrapping is typically used for debugging purposes. 240b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 241b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The default value is null. 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param glWrapper the new GLWrapper 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGLWrapper(GLWrapper glWrapper) { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLWrapper = glWrapper; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 249b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the debug flags to a new value. The value is 250b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * constructed by OR-together zero or more 251b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * of the DEBUG_CHECK_* constants. The debug flags take effect 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whenever a surface is created. The default value is zero. 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param debugFlags the new debug flags 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_CHECK_GL_ERROR 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_LOG_GL_CALLS 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDebugFlags(int debugFlags) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDebugFlags = debugFlags; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 261b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 262b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Get the current value of the debug flags. 263b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return the current value of the debug flags. 264b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getDebugFlags() { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDebugFlags; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 270b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the renderer associated with this view. Also starts the thread that 271b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * will call the renderer, which in turn causes the rendering to start. 272b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>This method should be called once and only once in the life-cycle of 273b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * a GLSurfaceView. 274b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>The following GLSurfaceView methods can only be called <em>before</em> 275b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer is called: 276b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 277b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 278b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 279b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 280b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 281b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 282b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The following GLSurfaceView methods can only be called <em>after</em> 283b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer is called: 284b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 285b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #getRenderMode()} 286b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #onPause()} 287b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #onResume()} 288b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #queueEvent(Runnable)} 289b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #requestRender()} 290b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setRenderMode(int)} 291b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 292b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 293b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param renderer the renderer to use to perform OpenGL drawing. 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderer(Renderer renderer) { 29615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 297a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEGLConfigChooser == null) { 298a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLConfigChooser = new SimpleEGLConfigChooser(true); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLContextFactory == null) { 30115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory = new DefaultContextFactory(); 30215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 30315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLWindowSurfaceFactory == null) { 30415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); 30515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread = new GLThread(renderer); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.start(); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 31115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLContextFactory. 31215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 31315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 31415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 31515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 31615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If this method is not called, then by default 31715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * a context will be created with no shared context and 31815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * with a null attribute list. 31915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 320a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich public void setEGLContextFactory(EGLContextFactory factory) { 32115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 32215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory = factory; 32315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 32415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 32515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 32615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLWindowSurfaceFactory. 32715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 32815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 32915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 33015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 33115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If this method is not called, then by default 33215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * a window surface will be created with a null attribute list. 33315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 334a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { 33515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 33615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory = factory; 33715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 33815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 33915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 340b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a custom EGLConfigChooser. 341b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 342b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 343a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 344a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 345b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If no setEGLConfigChooser method is called, then by default the 34683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an EGLConfig that is compatible with the current 34783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * android.view.Surface, with a depth buffer depth of 34883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 349a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param configChooser 350a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 351a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(EGLConfigChooser configChooser) { 35215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 353a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLConfigChooser = configChooser; 354a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 355a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 356a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 357b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a config chooser which will choose a config 358a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * as close to 16-bit RGB as possible, with or without an optional depth 359a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * buffer as close to 16-bits as possible. 360b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 361b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 362b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is called. 363a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 36483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If no setEGLConfigChooser method is called, then by default the 36583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an RGB_565 surface with a depth buffer depth of 36683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 367a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 368a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param needDepth 369a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 370a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(boolean needDepth) { 371a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); 372a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 373a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 374a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 375b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a config chooser which will choose a config 37683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least the specified depthSize and stencilSize, 37783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * and exactly the specified redSize, greenSize, blueSize and alphaSize. 378b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 379a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 380a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 381a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 382b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If no setEGLConfigChooser method is called, then by default the 38383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an RGB_565 surface with a depth buffer depth of 38483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 385a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 386a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 387a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, 388a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 389a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, 390a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich blueSize, alphaSize, depthSize, stencilSize)); 391a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 3926ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 3936ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 3946ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Inform the default EGLContextFactory and default EGLConfigChooser 3956ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * which EGLContext client version to pick. 3966ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>Use this method to create an OpenGL ES 2.0-compatible context. 3976ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Example: 3986ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <pre class="prettyprint"> 3996ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * public MyView(Context context) { 4006ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * super(context); 4016ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context. 4026ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setRenderer(new MyRenderer()); 4036ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * } 4046ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * </pre> 4056ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>Note: Activities which require OpenGL ES 2.0 should indicate this by 4066ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's 4076ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * AndroidManifest.xml file. 4086ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>If this method is called, it must be called before {@link #setRenderer(Renderer)} 4096ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * is called. 4106ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>This method only affects the behavior of the default EGLContexFactory and the 4116ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * default EGLConfigChooser. If 4126ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied 4136ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. 4146ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * If 4156ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied 4166ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. 4176ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 4186ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 4196ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public void setEGLContextClientVersion(int version) { 4206ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich checkRenderThreadState(); 4216ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mEGLContextClientVersion = version; 4226ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 4236ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 424a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 425b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the rendering mode. When renderMode is 4263e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * RENDERMODE_CONTINUOUSLY, the renderer is called 427b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * repeatedly to re-render the scene. When renderMode 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface 4293e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. 430b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 431b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance 432b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * by allowing the GPU and CPU to idle when the view does not need to be updated. 433b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 434b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method can only be called after {@link #setRenderer(Renderer)} 435b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param renderMode one of the RENDERMODE_X constants 4373e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * @see #RENDERMODE_CONTINUOUSLY 438b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #RENDERMODE_WHEN_DIRTY 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderMode(int renderMode) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.setRenderMode(renderMode); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the current rendering mode. May be called 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from any thread. Must not be called before a renderer has been set. 447b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return the current rendering mode. 4483e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * @see #RENDERMODE_CONTINUOUSLY 449b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #RENDERMODE_WHEN_DIRTY 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRenderMode() { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGLThread.getRenderMode(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 456b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Request that the renderer render a frame. 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method is typically used when the render mode has been set to 458b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. 459b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * May be called 460b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * from any thread. Must not be called before a renderer has been set. 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestRender() { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.requestRender(); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 466b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 467b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 468b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 469b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated(SurfaceHolder holder) { 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceCreated(); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 474b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 475b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 476b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 477b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Surface will be destroyed when we return 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceDestroyed(); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 483b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 484b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 485b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 486b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onWindowResize(w, h); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is paused. The owner of this view must 493b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * call this method when the activity is paused. Calling this method will 494b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause the rendering thread. 495b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPause() { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onPause(); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is resumed. The owner of this view must 503b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * call this method when the activity is resumed. Calling this method will 504b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * recreate the OpenGL display and resume the rendering 505b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * thread. 506b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onResume() { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onResume(); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 513b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Queue a runnable to be run on the GL rendering thread. This can be used 514b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to communicate with the Renderer on the rendering thread. 515b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param r the runnable to be run on the GL rendering thread. 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.queueEvent(r); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 522b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 523b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is used as part of the View class and is not normally 524b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called or subclassed by clients of GLSurfaceView. 525b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 526b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDetachedFromWindow() { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onDetachedFromWindow(); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.requestExitAndWait(); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ---------------------------------------------------------------------- 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 535b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 536b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface used to wrap a GL interface. 537b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>Typically 538b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * used for implementing debugging and tracing on top of the default 539b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL interface. You would typically use this by creating your own class 540b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that implemented all the GL methods by delegating to another GL instance. 541b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Then you could add your own behavior before or after calling the 542b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * delegate. All the GLWrapper would do was instantiate and return the 543b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * wrapper GL instance: 544b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 545b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLWrapper implements GLWrapper { 546b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL wrap(GL gl) { 547b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return new MyGLImplementation(gl); 548b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 549b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * static class MyGLImplementation implements GL,GL10,GL11,... { 550b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * ... 551b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 552b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 553b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 554b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setGLWrapper(GLWrapper) 555b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface GLWrapper { 557b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 558b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wraps a gl interface in another gl interface. 559b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param gl a GL interface that is to be wrapped. 560b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return either the input argument or another GL object that wraps the input argument. 561b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 562b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich GL wrap(GL gl); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic renderer interface. 567b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 568b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is responsible for making OpenGL calls to render a frame. 569b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 570b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView clients typically create their own classes that implement 571b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * this interface, and then call {@link GLSurfaceView#setRenderer} to 572b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * register the renderer with the GLSurfaceView. 573b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 574b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Threading</h3> 575b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer will be called on a separate thread, so that rendering 576b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * performance is decoupled from the UI thread. Clients typically need to 577b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * communicate with the renderer from the UI thread, because that's where 578b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * input events are received. Clients can communicate using any of the 579b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java techniques for cross-thread communication, or they can 580b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. 581b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 582b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>EGL Context Lost</h3> 583b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * There are situations where the EGL rendering context will be lost. This 584b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically happens when device wakes up after going to sleep. When 585b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the EGL context is lost, all OpenGL resources (such as textures) that are 586b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * associated with that context will be automatically deleted. In order to 587b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * keep rendering correctly, a renderer must recreate any lost resources 588b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method 589b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is a convenient place to do this. 590b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 591b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 592b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderer(Renderer) 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface Renderer { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 596b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface is created or recreated. 597b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 598b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the rendering thread 599840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * starts and whenever the EGL context is lost. The EGL context will typically 600b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * be lost when the Android device awakes after going to sleep. 601b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 602b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Since this method is called at the beginning of rendering, as well as 603b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * every time the EGL context is lost, this method is a convenient place to put 604b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * code to create resources that need to be created when the rendering 605b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * starts, and that need to be recreated when the EGL context is lost. 606b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Textures are an example of a resource that you might want to create 607b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * here. 608b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 609b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Note that when the EGL context is lost, all OpenGL resources associated 610b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * with that context will be automatically deleted. You do not need to call 611b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the corresponding "glDelete" methods such as glDeleteTextures to 612b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * manually delete these lost resources. 613b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param config the EGLConfig of the created surface. Can be used 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to create matching pbuffers. 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSurfaceCreated(GL10 gl, EGLConfig config); 620b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 622b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface changed size. 623b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called after the surface is created and whenever 625b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL ES surface size changes. 626b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 627b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you will set your viewport here. If your camera 628b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is fixed then you could also set your projection matrix here: 629b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 630b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onSurfaceChanged(GL10 gl, int width, int height) { 631b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glViewport(0, 0, width, height); 632b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // for a fixed camera, set the projection too 633b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * float ratio = (float) width / height; 634b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glMatrixMode(GL10.GL_PROJECTION); 635b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glLoadIdentity(); 636b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 637b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 638b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param width 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param height 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSurfaceChanged(GL10 gl, int width, int height); 645b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 647b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called to draw the current frame. 648b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 649b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is responsible for drawing the current frame. 650b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 651b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The implementation of this method typically looks like this: 652b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 653b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onDrawFrame(GL10 gl) { 654b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 655b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * //... other gl calls to render the scene ... 656b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 657b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onDrawFrame(GL10 gl); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 66515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * An interface for customizing the eglCreateContext and eglDestroyContext calls. 66615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 66715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * This interface must be implemented by clients wishing to call 66815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)} 66915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 67015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public interface EGLContextFactory { 67115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); 67215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); 67315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 67415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 6756ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class DefaultContextFactory implements EGLContextFactory { 6766ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 67715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 67815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { 6796ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, 6806ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich EGL10.EGL_NONE }; 6816ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 6826ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, 6836ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mEGLContextClientVersion != 0 ? attrib_list : null); 68415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 68515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 68615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void destroyContext(EGL10 egl, EGLDisplay display, 68715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLContext context) { 68807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (!egl.eglDestroyContext(display, context)) { 68907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.e("DefaultContextFactory", "display:" + display + " context: " + context); 69007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_THREADS) { 69107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId()); 69207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 69307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("eglDestroyContext failed: " 69407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich + EGLLogWrapper.getErrorString(egl.eglGetError())); 69507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 69615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 69715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 69815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 69915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 70015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. 70115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 70215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * This interface must be implemented by clients wishing to call 703d40dfbbbff81219258ca36b762a89ff503154345Jack Palevich * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} 70415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 70515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public interface EGLWindowSurfaceFactory { 70615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, 70715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich Object nativeWindow); 70815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); 70915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 71015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 71115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { 71215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 71315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, 71415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLConfig config, Object nativeWindow) { 71515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich return egl.eglCreateWindowSurface(display, config, nativeWindow, null); 71615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 71715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 71815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void destroySurface(EGL10 egl, EGLDisplay display, 71915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLSurface surface) { 72015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich egl.eglDestroySurface(display, surface); 72115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 72215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 72315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 72415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 725b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface for choosing an EGLConfig configuration from a list of 726a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * potential configurations. 727b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 728b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This interface must be implemented by clients wishing to call 729b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} 730a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 731a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public interface EGLConfigChooser { 732a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 733a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Choose a configuration from the list. Implementors typically 734a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * implement this method by calling 735b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the 736b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. 737a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param egl the EGL10 for the current display. 738a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param display the current display. 739a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @return the chosen configuration. 740a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 741a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); 742a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 743a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 7446ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private abstract class BaseConfigChooser 745a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich implements EGLConfigChooser { 746a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public BaseConfigChooser(int[] configSpec) { 7476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mConfigSpec = filterConfigSpec(configSpec); 748a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 7496ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 750a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 751a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int[] num_config = new int[1]; 75228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, 75328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich num_config)) { 75428023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new IllegalArgumentException("eglChooseConfig failed"); 75528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 756a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 757a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int numConfigs = num_config[0]; 758a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 759a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (numConfigs <= 0) { 760a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new IllegalArgumentException( 761a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich "No configs match configSpec"); 762a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 763a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 764a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs = new EGLConfig[numConfigs]; 76528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, 76628023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich num_config)) { 76728023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new IllegalArgumentException("eglChooseConfig#2 failed"); 76828023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 769a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config = chooseConfig(egl, display, configs); 770a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (config == null) { 771a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new IllegalArgumentException("No config chosen"); 772a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 773a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return config; 774a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 775a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 776a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 777a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs); 778a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 779a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int[] mConfigSpec; 7806ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 7816ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int[] filterConfigSpec(int[] configSpec) { 7826ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich if (mEGLContextClientVersion != 2) { 7836ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return configSpec; 7846ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 7856ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /* We know none of the subclasses define EGL_RENDERABLE_TYPE. 7866ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * And we know the configSpec is well formed. 7876ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 7886ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int len = configSpec.length; 7896ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] newConfigSpec = new int[len + 2]; 7906ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); 7916ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; 7926ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ 7936ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len+1] = EGL10.EGL_NONE; 7946ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return newConfigSpec; 7956ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 796a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 797a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 79883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich /** 79983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * Choose a configuration with exactly the specified r,g,b,a sizes, 80083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * and at least the specified depth and stencil sizes. 80183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich */ 8026ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class ComponentSizeChooser extends BaseConfigChooser { 803a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public ComponentSizeChooser(int redSize, int greenSize, int blueSize, 804a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 805a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich super(new int[] { 806a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_RED_SIZE, redSize, 807a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_GREEN_SIZE, greenSize, 808a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_BLUE_SIZE, blueSize, 809a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_ALPHA_SIZE, alphaSize, 810a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, depthSize, 811a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_STENCIL_SIZE, stencilSize, 812a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_NONE}); 813a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mValue = new int[1]; 814a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mRedSize = redSize; 815a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mGreenSize = greenSize; 816a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mBlueSize = blueSize; 817a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mAlphaSize = alphaSize; 818a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mDepthSize = depthSize; 819a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mStencilSize = stencilSize; 820a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 821a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 822a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich @Override 823a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 824a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs) { 82583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich for (EGLConfig config : configs) { 826a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int d = findConfigAttrib(egl, display, config, 827a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, 0); 828a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int s = findConfigAttrib(egl, display, config, 829a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_STENCIL_SIZE, 0); 83083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich if ((d >= mDepthSize) && (s >= mStencilSize)) { 83182fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int r = findConfigAttrib(egl, display, config, 83282fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_RED_SIZE, 0); 83382fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int g = findConfigAttrib(egl, display, config, 83482fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_GREEN_SIZE, 0); 83582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int b = findConfigAttrib(egl, display, config, 83682fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_BLUE_SIZE, 0); 83782fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int a = findConfigAttrib(egl, display, config, 83882fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_ALPHA_SIZE, 0); 83983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich if ((r == mRedSize) && (g == mGreenSize) 84083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich && (b == mBlueSize) && (a == mAlphaSize)) { 84183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich return config; 84282fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian } 843a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 844a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 84583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich return null; 846a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 847a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 848a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int findConfigAttrib(EGL10 egl, EGLDisplay display, 849a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config, int attribute, int defaultValue) { 850a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 851a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 852a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return mValue[0]; 853a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 854a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return defaultValue; 855a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 856a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 857a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int[] mValue; 858a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich // Subclasses can adjust these values: 859a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mRedSize; 860a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mGreenSize; 861a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mBlueSize; 862a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mAlphaSize; 863a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mDepthSize; 864a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mStencilSize; 865a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 866a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 867a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 86883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * This class will choose a RGB_565 surface with 86983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * or without a depth buffer. 870a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 871a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 8726ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class SimpleEGLConfigChooser extends ComponentSizeChooser { 873a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public SimpleEGLConfigChooser(boolean withDepthBuffer) { 87483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich super(5, 6, 5, 0, withDepthBuffer ? 16 : 0, 0); 875a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 876a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 877a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 878a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An EGL helper class. 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class EglHelper { 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public EglHelper() { 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Initialize EGL for a given configuration spec. 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param configSpec 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 891840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void start() { 89207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 89307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId()); 89407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get an EGL instance 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl = (EGL10) EGLContext.getEGL(); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get to the default display. 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 90528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 90628023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new RuntimeException("eglGetDisplay failed"); 90728023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 90828023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can now initialize EGL for that display 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] version = new int[2]; 91328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if(!mEgl.eglInitialize(mEglDisplay, version)) { 91428023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new RuntimeException("eglInitialize failed"); 91528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 916a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 919840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * Create an EGL context. We want to do this as rarely as we can, because an 920840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * EGL context is a somewhat heavy object. 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 92215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 9232e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { 92407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEglContext = null; 9259bb4dbae91df0971038e955ef49c5d9a64d4a428Jack Palevich throwEglException("createContext"); 9262e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 92707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 92807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); 92907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * React to the creation of a new surface by creating and returning an 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * OpenGL interface that renders to that surface. 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GL createSurface(SurfaceHolder holder) { 93907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 94007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); 94107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 94207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich /* 94307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich * Check preconditions. 94407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich */ 94507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEgl == null) { 94607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("egl not initialized"); 94707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 94807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglDisplay == null) { 94907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("eglDisplay not initialized"); 95007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 95107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglConfig == null) { 95207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("mEglConfig not initialized"); 95307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The window size has changed, so we need to create a new 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * surface. 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9582e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unbind and destroy the old EGL surface, if 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is one. 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 96615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create an EGL surface we can render into. 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 97215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, 97315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEglDisplay, mEglConfig, holder); 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9752e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 97607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createWindowSurface failed. mEglDisplay: " + mEglDisplay + 97707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich " mEglConfig: " + mEglConfig + " holder: " + holder); 9785aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich throwEglException("createWindowSurface"); 9792e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 9802e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before we can issue GL commands, we need to make sure 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the context is current and bound to a surface. 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9852e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 9865aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich throwEglException("eglMakeCurrent"); 9872e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL gl = mEglContext.getGL(); 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGLWrapper != null) { 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gl = mGLWrapper.wrap(gl); 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 994a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int configFlags = 0; 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Writer log = null; 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log = new LogWriter(); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gl = GLDebugHelper.wrap(gl, configFlags, log); 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return gl; 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Display the current render surface. 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return false if the context has been lost. 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean swap() { 101304b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 101504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich /* 101604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * Check for EGL_CONTEXT_LOST, which means the context 101704b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * and all associated data were lost (For instance because 101804b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * the device went to sleep). We need to sleep until we 101904b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * get a new surface. 102004b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich */ 102104b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich int error = mEgl.eglGetError(); 102204b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich if (error == EGL11.EGL_CONTEXT_LOST) { 102304b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich return false; 102404b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } else { 102504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich throwEglException("eglSwapBuffers", error); 102604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 102704b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 102804b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich return true; 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10311bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public void destroySurface() { 103207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 103307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId()); 103407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 10352e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_SURFACE, 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_CONTEXT); 103915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10421bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 10431bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich 10441bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public void finish() { 104507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 104607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId()); 104707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglContext != null) { 104915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglContext = null; 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglDisplay != null) { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglTerminate(mEglDisplay); 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglDisplay = null; 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10585aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich private void throwEglException(String function) { 105904b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich throwEglException(function, mEgl.eglGetError()); 106004b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 106104b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich 106204b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich private void throwEglException(String function, int error) { 106307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich String message = function + " failed: " + EGLLogWrapper.getErrorString(error); 106407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_THREADS) { 106507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " + message); 106607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 106707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException(message); 10685aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich } 10695aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10 mEgl; 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLDisplay mEglDisplay; 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface mEglSurface; 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLConfig mEglConfig; 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext mEglContext; 1075840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic GL Thread. Takes care of initializing EGL and GL. Delegates 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to a Renderer instance to do the actual drawing. Can be configured to 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * render continuously or on request. 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 108367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * All potentially blocking synchronization is done through the 108467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * sGLThreadManager object. This avoids multiple-lock ordering issues. 108567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class GLThread extends Thread { 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GLThread(Renderer renderer) { 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = 0; 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = 0; 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestRender = true; 10933e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich mRenderMode = RENDERMODE_CONTINUOUSLY; 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderer = renderer; 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1097840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 11008b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich setName("GLThread " + getId()); 11018b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 11028b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "starting tid=" + getId()); 11038b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 11048b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guardedRun(); 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fall thru and exit normally 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 111067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.threadExiting(this); 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 111467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich /* 111567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * This private method should only be called inside a 111667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * synchronized(sGLThreadManager) block. 111767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich */ 1118840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private void stopEglSurfaceLocked() { 1119840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1120840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = false; 112132d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich mEglHelper.destroySurface(); 112232d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 112332d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 112432d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich 1125840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich /* 1126840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * This private method should only be called inside a 1127840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * synchronized(sGLThreadManager) block. 1128840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich */ 1129840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private void stopEglContextLocked() { 1130840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglContext) { 1131840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mEglHelper.finish(); 1132840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = false; 1133840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich sGLThreadManager.releaseEglContextLocked(this); 1134840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1135840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void guardedRun() throws InterruptedException { 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglHelper = new EglHelper(); 1138840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = false; 1139840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = false; 114015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich try { 114115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich GL10 gl = null; 1142840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich boolean createEglContext = false; 1143a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich boolean createEglSurface = false; 1144840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich boolean lostEglContext = false; 1145a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich boolean sizeChanged = false; 114621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich boolean wantRenderNotification = false; 114721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich boolean doRenderNotification = false; 1148a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich int w = 0; 1149a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich int h = 0; 1150a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Runnable event = null; 115167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1152a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while (true) { 115367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 115467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich while (true) { 1155a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mShouldExit) { 1156a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich return; 1157a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1158a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1159a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (! mEventQueue.isEmpty()) { 1160a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event = mEventQueue.remove(0); 1161a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich break; 1162a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1163a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1164451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich // Update the pause state. 1165451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (mPaused != mRequestPaused) { 1166451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mPaused = mRequestPaused; 1167451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.notifyAll(); 1168451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1169451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId()); 1170451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1171451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1172451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 1173840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // Have we lost the EGL context? 1174840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (lostEglContext) { 1175840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1176840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 1177840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich lostEglContext = false; 1178840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1179840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1180a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Do we need to release the EGL surface? 1181840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface && mPaused) { 1182a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1183a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); 1184a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1185840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1186840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { 1187840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 1188840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (LOG_SURFACE) { 1189840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); 1190840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1191840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1192b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if (sGLThreadManager.shouldTerminateEGLWhenPausing()) { 1193b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich mEglHelper.finish(); 1194b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if (LOG_SURFACE) { 1195b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich Log.i("GLThread", "terminating EGL because paused tid=" + getId()); 1196b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1197b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 119867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1199a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1200a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Have we lost the surface view surface? 1201a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if ((! mHasSurface) && (! mWaitingForSurface)) { 1202a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1203a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); 120415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1205840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1206840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 120732d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 1208a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mWaitingForSurface = true; 1209a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 121032d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 121167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1212a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Have we acquired the surface view surface? 1213a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mHasSurface && mWaitingForSurface) { 1214a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1215a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); 1216a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1217a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mWaitingForSurface = false; 1218a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 121967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 122067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 122121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (doRenderNotification) { 122221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich wantRenderNotification = false; 122321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich doRenderNotification = false; 122421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mRenderComplete = true; 122521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.notifyAll(); 122621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 122721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 1228a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Ready to draw? 1229a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if ((!mPaused) && mHasSurface 1230a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich && (mWidth > 0) && (mHeight > 0) 1231a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { 1232a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1233840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // If we don't have an EGL context, try to acquire one. 1234840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglContextLocked(this)) { 123507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich try { 123607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEglHelper.start(); 123707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } catch (RuntimeException t) { 123807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich sGLThreadManager.releaseEglContextLocked(this); 123907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw t; 124007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 1241840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = true; 1242840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich createEglContext = true; 1243840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1244840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich sGLThreadManager.notifyAll(); 1245840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1246840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1247840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglContext && !mHaveEglSurface) { 1248840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = true; 1249a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = true; 1250a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = true; 1251a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 125267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1253840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1254a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mSizeChanged) { 1255a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = true; 1256a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich w = mWidth; 1257a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich h = mHeight; 125821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich wantRenderNotification = true; 125921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 1260a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (DRAW_TWICE_AFTER_SIZE_CHANGED) { 1261a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // We keep mRequestRender true so that we draw twice after the size changes. 1262a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // (Once because of mSizeChanged, the second time because of mRequestRender.) 1263a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // This forces the updated graphics onto the screen. 1264a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } else { 1265a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = false; 1266a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1267a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mSizeChanged = false; 1268a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } else { 1269a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = false; 1270a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 127167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1272a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich break; 127367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 127432d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 127567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1276a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // By design, this is the only place in a GLThread thread where we wait(). 127732d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich if (LOG_THREADS) { 127867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich Log.i("GLThread", "waiting tid=" + getId()); 12791bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 128067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.wait(); 128115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 128267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } // end of synchronized(sGLThreadManager) 128367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1284a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (event != null) { 1285a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event.run(); 1286a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event = null; 128767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich continue; 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 128967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1290a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (createEglSurface) { 12914a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 12924a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w("GLThread", "egl createSurface"); 12934a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 129415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich gl = (GL10) mEglHelper.createSurface(getHolder()); 129579447b2087c8c820d742185dda7305101f9656f0Jack Palevich sGLThreadManager.checkGLDriver(gl); 1296a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = false; 129715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1298a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1299840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (createEglContext) { 13004a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_RENDERER) { 13014a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w("GLThread", "onSurfaceCreated"); 13024a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 1303840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); 1304840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich createEglContext = false; 1305840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1306840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1307a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (sizeChanged) { 1308a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_RENDERER) { 1309a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); 1310a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 131115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mRenderer.onSurfaceChanged(gl, w, h); 1312a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = false; 131315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1314a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 13154a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_RENDERER_DRAW_FRAME) { 1316a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.w("GLThread", "onDrawFrame"); 1317a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1318a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRenderer.onDrawFrame(gl); 1319840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (!mEglHelper.swap()) { 1320a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1321840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich Log.i("GLThread", "egl context lost tid=" + getId()); 1322a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1323840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich lostEglContext = true; 132415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 132521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 132621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (wantRenderNotification) { 132721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich doRenderNotification = true; 132821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 1329a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1330840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 133115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } finally { 133215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /* 133315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * clean-up everything... 133415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 133567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1336840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1337840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 133867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 133915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderMode(int renderMode) { 13433e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("renderMode"); 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 134667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderMode = renderMode; 1348a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRenderMode() { 135367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mRenderMode; 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestRender() { 135967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestRender = true; 136167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated() { 136667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 13678b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 13688b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "surfaceCreated tid=" + getId()); 13698b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasSurface = true; 137167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1372451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while((mWaitingForSurface) && (!mExited)) { 1373451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1374451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1375451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException e) { 1376451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1377451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1378451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed() { 138367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 13848b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 13858b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "surfaceDestroyed tid=" + getId()); 13868b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasSurface = false; 138867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1389a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while((!mWaitingForSurface) && (!mExited)) { 13901bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich try { 139167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.wait(); 13921bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } catch (InterruptedException e) { 13931bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich Thread.currentThread().interrupt(); 13941bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 13951bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPause() { 140067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1401e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich if (LOG_PAUSE_RESUME) { 1402e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich Log.i("GLThread", "onPause tid=" + getId()); 1403e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1404451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRequestPaused = true; 140567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1406451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while ((! mExited) && (! mPaused)) { 1407451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1408451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("Main thread", "onPause waiting for mPaused."); 1409451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1410451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1411451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1412451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException ex) { 1413451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1414451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1415451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onResume() { 142067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1421e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich if (LOG_PAUSE_RESUME) { 1422e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich Log.i("GLThread", "onResume tid=" + getId()); 1423e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1424451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRequestPaused = false; 14258b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich mRequestRender = true; 1426451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRenderComplete = false; 142767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1428451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while ((! mExited) && mPaused && (!mRenderComplete)) { 1429451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1430451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("Main thread", "onResume waiting for !mPaused."); 1431451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1432451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1433451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1434451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException ex) { 1435451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1436451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1437451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onWindowResize(int w, int h) { 144267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = w; 14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = h; 14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSizeChanged = true; 1446a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = true; 144721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mRenderComplete = false; 144867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 144921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 145021799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich // Wait for thread to react to resize and render a frame 145121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich while (! mExited && !mPaused && !mRenderComplete ) { 145221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (LOG_SURFACE) { 145321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich Log.i("Main thread", "onWindowResize waiting for render complete."); 145421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 145521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich try { 145621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.wait(); 145721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } catch (InterruptedException ex) { 145821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich Thread.currentThread().interrupt(); 145921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 146021799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestExitAndWait() { 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't call this from GLThread thread or it is a guaranteed 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // deadlock! 146767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 1468a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mShouldExit = true; 146967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1470a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while (! mExited) { 1471a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich try { 1472a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.wait(); 1473a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } catch (InterruptedException ex) { 1474a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Thread.currentThread().interrupt(); 1475a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1476a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Queue an "event" to be run on the GL rendering thread. 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param r the runnable to be run on the GL rendering thread. 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 1485a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (r == null) { 1486a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich throw new IllegalArgumentException("r must not be null"); 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1488a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 1489a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mEventQueue.add(r); 1490a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 149467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // Once the thread is started, all accesses to the following member 149567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // variables are protected by the sGLThreadManager monitor 1496a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mShouldExit; 1497a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mExited; 1498451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private boolean mRequestPaused; 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mPaused; 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mHasSurface; 15011bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich private boolean mWaitingForSurface; 1502840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private boolean mHaveEglContext; 1503840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private boolean mHaveEglSurface; 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mWidth; 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mHeight; 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRenderMode; 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mRequestRender; 150821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich private boolean mRenderComplete; 1509a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); 1510840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 151167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // End of member variables protected by the sGLThreadManager monitor. 151267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Renderer mRenderer; 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EglHelper mEglHelper; 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class LogWriter extends Writer { 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void close() { 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void flush() { 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void write(char[] buf, int offset, int count) { 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < count; i++) { 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = buf[offset + i]; 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ( c == '\n') { 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuilder.append(c); 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void flushBuilder() { 15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBuilder.length() > 0) { 15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v("GLSurfaceView", mBuilder.toString()); 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuilder.delete(0, mBuilder.length()); 15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private StringBuilder mBuilder = new StringBuilder(); 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 154915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 155015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private void checkRenderThreadState() { 155115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mGLThread != null) { 155215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich throw new IllegalStateException( 155315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich "setRenderer has already been called for this instance."); 155415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 155515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 155615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 155779447b2087c8c820d742185dda7305101f9656f0Jack Palevich private static class GLThreadManager { 15584a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private static String TAG = "GLThreadManager"; 15598da3ac92a6a6247ef06de4d4b684f8635d8fc003Jack Palevich 156067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich public synchronized void threadExiting(GLThread thread) { 156167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (LOG_THREADS) { 156267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich Log.i("GLThread", "exiting tid=" + thread.getId()); 15638b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 1564a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich thread.mExited = true; 156567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread) { 156667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = null; 15678b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 156867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 156967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1570c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 157167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich /* 157267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * Tries once to acquire the right to use an EGL 1573840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * context. Does not block. Requires that we are already 1574a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * in the sGLThreadManager monitor when this is called. 157566a4a6e45f59f72f24d710221c27db1bd233e154Jack Palevich * 1576840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * @return true if the right to use an EGL context was acquired. 157767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich */ 1578840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public boolean tryAcquireEglContextLocked(GLThread thread) { 157967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread || mEglOwner == null) { 158067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = thread; 158167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 158267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return true; 15838b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 15841179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich checkGLESVersion(); 15851179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (mMultipleGLESContextsAllowed) { 15861179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich return true; 15878b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 158867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return false; 1589c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1590840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1591a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich /* 1592840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * Releases the EGL context. Requires that we are already in the 1593a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * sGLThreadManager monitor when this is called. 1594a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich */ 1595840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void releaseEglContextLocked(GLThread thread) { 159667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread) { 159767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = null; 159879447b2087c8c820d742185dda7305101f9656f0Jack Palevich } 159967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 1600c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1601c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 1602840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public synchronized boolean shouldReleaseEGLContextWhenPausing() { 1603b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // Release the EGL context when pausing even if 1604b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // the hardware supports multiple EGL contexts. 1605b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // Otherwise the device could run out of EGL contexts. 1606b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich return true; 1607b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1608b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich 1609b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich public synchronized boolean shouldTerminateEGLWhenPausing() { 1610840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich checkGLESVersion(); 16114a2221ec4a929976be570ad096252c8dea326e19Jack Palevich return !mMultipleGLESContextsAllowed; 1612840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1613840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1614c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich public synchronized void checkGLDriver(GL10 gl) { 1615c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich if (! mGLESDriverCheckComplete) { 16161179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich checkGLESVersion(); 1617c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich if (mGLESVersion < kGLES_20) { 1618c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich String renderer = gl.glGetString(GL10.GL_RENDERER); 1619c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich mMultipleGLESContextsAllowed = 1620c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); 16214a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 16224a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " 16234a2221ec4a929976be570ad096252c8dea326e19Jack Palevich + mMultipleGLESContextsAllowed); 16244a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 1625c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich notifyAll(); 1626c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1627c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich mGLESDriverCheckComplete = true; 1628c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1629c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1630c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 16311179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich private void checkGLESVersion() { 16321179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (! mGLESVersionCheckComplete) { 16331179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mGLESVersion = SystemProperties.getInt( 16341179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich "ro.opengles.version", 16351179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich ConfigurationInfo.GL_ES_VERSION_UNDEFINED); 16361179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (mGLESVersion >= kGLES_20) { 16371179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mMultipleGLESContextsAllowed = true; 16381179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 16394a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 16404a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w(TAG, "checkGLESVersion mGLESVersion =" + 16414a2221ec4a929976be570ad096252c8dea326e19Jack Palevich " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); 16424a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 16431179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mGLESVersionCheckComplete = true; 16441179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 16451179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 16461179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich 1647c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mGLESVersionCheckComplete; 1648c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private int mGLESVersion; 1649c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mGLESDriverCheckComplete; 1650c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mMultipleGLESContextsAllowed; 1651c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private static final int kGLES_20 = 0x20000; 1652c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private static final String kMSM7K_RENDERER_PREFIX = 1653c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich "Q3Dimension MSM7500 "; 165467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich private GLThread mEglOwner; 16558b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 1656c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 16578b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich private static final GLThreadManager sGLThreadManager = new GLThreadManager(); 16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mSizeChanged = true; 16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLThread mGLThread; 1661a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private EGLConfigChooser mEGLConfigChooser; 166215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private EGLContextFactory mEGLContextFactory; 166315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLWrapper mGLWrapper; 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDebugFlags; 16666ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int mEGLContextClientVersion; 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1668