GLSurfaceView.java revision 61fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ec
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 * 5761fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <div class="special reference"> 5861fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <h3>Developer Guides</h3> 5961fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <p>For more information about how to use OpenGL, read the 6061fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a> developer guide.</p> 6161fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * </div> 6261fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * 63b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Using GLSurfaceView</h3> 64b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 65b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you use GLSurfaceView by subclassing it and overriding one or more of the 66b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * View system input event methods. If your application does not need to override event 67b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * methods then GLSurfaceView can be used as-is. For the most part 68b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. 69b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * For example, unlike a regular View, drawing is delegated to a separate Renderer object which 70b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is registered with the GLSurfaceView 71b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * using the {@link #setRenderer(Renderer)} call. 72b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 73b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Initializing GLSurfaceView</h3> 74b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. 75b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or 76b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * more of these methods before calling setRenderer: 77b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 78b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setDebugFlags(int)} 79b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 80b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 81b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 82b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setGLWrapper(GLWrapper)} 83b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 84b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 8583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <h4>Specifying the android.view.Surface</h4> 8683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * By default GLSurfaceView will create a PixelFormat.RGB_565 format surface. If a translucent 8783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). 8883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The exact format of a TRANSLUCENT surface is device dependent, but it will be 8983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * a 32-bit-per-pixel surface with 8 bits per component. 9083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 91b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Choosing an EGL Configuration</h4> 9283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * A given Android device may support multiple EGLConfig rendering configurations. 9383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The available configurations may differ in how may channels of data are present, as 94b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * well as how many bits are allocated to each channel. Therefore, the first thing 9583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * GLSurfaceView has to do when starting to render is choose what EGLConfig to use. 9683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 9743dd61e08a726fbc3695b1cbfdef6bdd4ddd34beMathias Agopian * By default GLSurfaceView chooses a EGLConfig that has an RGB_565 pixel format, 9883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least a 16-bit depth buffer and no stencil. 99b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 10083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If you would prefer a different EGLConfig 10183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * you can override the default behavior by calling one of the 102b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setEGLConfigChooser methods. 103b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 104b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Debug Behavior</h4> 105b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * You can optionally modify the behavior of GLSurfaceView by calling 106b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one or more of the debugging methods {@link #setDebugFlags(int)}, 107b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but 108b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically they are called before setRenderer so that they take effect immediately. 109b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 110b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Setting a Renderer</h4> 111b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. 112b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is 113b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * responsible for doing the actual OpenGL rendering. 114b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 115b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Rendering Mode</h3> 116b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Once the renderer is set, you can control whether the renderer draws 117b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously or on-demand by calling 118b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #setRenderMode}. The default is continuous rendering. 119b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 120b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Activity Life-cycle</h3> 121b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients 122b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * are required to call {@link #onPause()} when the activity pauses and 123b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to 124b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate 125b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL display. 126b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 127b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Handling events</h3> 128b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 129b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * To handle an event you will typically subclass GLSurfaceView and override the 130b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * appropriate method, just as you would with any other View. However, when handling 131b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the event, you may need to communicate with the Renderer object 132b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that's running in the rendering thread. You can do this using any 133b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java cross-thread communication mechanism. In addition, 134b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one relatively easy way to communicate with your renderer is 135b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to call 136b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #queueEvent(Runnable)}. For example: 137b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 138b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLSurfaceView extends GLSurfaceView { 139b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 140b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * private MyRenderer mMyRenderer; 141b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 142b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void start() { 143b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer = ...; 144b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer(mMyRenderer); 145b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 146b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 147b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public boolean onKeyDown(int keyCode, KeyEvent event) { 148b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 149b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * queueEvent(new Runnable() { 150b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // This method will be called on the rendering 151b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // thread: 152b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void run() { 153b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer.handleDpadCenter(); 154b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * }}); 155b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return true; 156b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 157b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return super.onKeyDown(keyCode, event); 158b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 159b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 160b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 1642ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private final static String TAG = "GLSurfaceView"; 1652ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private final static boolean LOG_ATTACH_DETACH = false; 16657c6a46bd0c84c4b349d49f8df12f30a8cfcdaa2Jack Palevich private final static boolean LOG_THREADS = false; 1674a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_PAUSE_RESUME = false; 1684a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_SURFACE = false; 1694a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_RENDERER = false; 1704a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private final static boolean LOG_RENDERER_DRAW_FRAME = false; 1714a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_EGL = false; 172a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Work-around for bug 2263168 173a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true; 174b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 175b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer only renders 176b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * when the surface is created, or when {@link #requestRender} is called. 177b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 178b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 179b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 180840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * @see #requestRender() 181b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int RENDERMODE_WHEN_DIRTY = 0; 183b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 184b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is called 185b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously to re-render the scene. 186b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 187b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 188b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 189b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 1903e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich public final static int RENDERMODE_CONTINUOUSLY = 1; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 193b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Check glError() after every GL call and throw an exception if glError indicates 194b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that an error has occurred. This can be used to help track down which OpenGL ES call 195b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is causing an error. 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_CHECK_GL_ERROR = 1; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". 204b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 205b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getDebugFlags 206b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setDebugFlags 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int DEBUG_LOG_GL_CALLS = 2; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 210b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 211b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Standard View constructor. In order to render something, you 212b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * must call {@link #setRenderer} to register a renderer. 213b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GLSurfaceView(Context context) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 220b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Standard View constructor. In order to render something, you 221b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * must call {@link #setRenderer} to register a renderer. 222b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GLSurfaceView(Context context, AttributeSet attrs) { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init() { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Install a SurfaceHolder.Callback so we get notified when the 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // underlying surface is created and destroyed 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SurfaceHolder holder = getHolder(); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project holder.addCallback(this); 2331b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // setFormat is done by SurfaceView in SDK 2.3 and newer. Uncomment 2341b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // this statement if back-porting to 2.2 or older: 2351b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // holder.setFormat(PixelFormat.RGB_565); 2361b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // 237840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // setType is not needed for SDK 2.0 or newer. Uncomment this 238840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // statement if back-porting this code to older SDKs. 239840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 243b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the glWrapper. If the glWrapper is not null, its 244b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLWrapper#wrap(GL)} method is called 245b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * whenever a surface is created. A GLWrapper can be used to wrap 246b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the GL object that's passed to the renderer. Wrapping a GL 247b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * object enables examining and modifying the behavior of the 248b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL calls made by the renderer. 249b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 250b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wrapping is typically used for debugging purposes. 251b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 252b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The default value is null. 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param glWrapper the new GLWrapper 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGLWrapper(GLWrapper glWrapper) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLWrapper = glWrapper; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 260b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the debug flags to a new value. The value is 261b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * constructed by OR-together zero or more 262b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * of the DEBUG_CHECK_* constants. The debug flags take effect 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whenever a surface is created. The default value is zero. 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param debugFlags the new debug flags 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_CHECK_GL_ERROR 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_LOG_GL_CALLS 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDebugFlags(int debugFlags) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDebugFlags = debugFlags; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 272b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 273b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Get the current value of the debug flags. 274b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return the current value of the debug flags. 275b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getDebugFlags() { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDebugFlags; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2818432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * Control whether the EGL context is preserved when the GLSurfaceView is paused and 2828432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * resumed. 2838432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 2848432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * If set to true, then the EGL context may be preserved when the GLSurfaceView is paused. 2858432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * Whether the EGL context is actually preserved or not depends upon whether the 2868432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * Android device that the program is running on can support an arbitrary number of EGL 2878432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * contexts or not. Devices that can only support a limited number of EGL contexts must 2888432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * release the EGL context in order to allow multiple applications to share the GPU. 2898432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 2908432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * If set to false, the EGL context will be released when the GLSurfaceView is paused, 2918432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * and recreated when the GLSurfaceView is resumed. 2928432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 2938432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * 2948432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * The default is false. 2958432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * 2968432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * @param preserveOnPause preserve the EGL context when paused 2978432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich */ 2988432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich public void setPreserveEGLContextOnPause(boolean preserveOnPause) { 2998432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mPreserveEGLContextOnPause = preserveOnPause; 3008432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 3018432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich 3028432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich /** 3038432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * @return true if the EGL context will be preserved when paused 3048432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich */ 3058432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich public boolean getPreserveEGLContextOnPause() { 3068432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich return mPreserveEGLContextOnPause; 3078432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 3088432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich 3098432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich /** 310b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the renderer associated with this view. Also starts the thread that 311b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * will call the renderer, which in turn causes the rendering to start. 312b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>This method should be called once and only once in the life-cycle of 313b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * a GLSurfaceView. 314b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>The following GLSurfaceView methods can only be called <em>before</em> 315b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer is called: 316b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 317b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 318b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 319b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 320b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 321b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 322b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The following GLSurfaceView methods can only be called <em>after</em> 323b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer is called: 324b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 325b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #getRenderMode()} 326b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #onPause()} 327b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #onResume()} 328b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #queueEvent(Runnable)} 329b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #requestRender()} 330b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setRenderMode(int)} 331b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 332b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 333b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param renderer the renderer to use to perform OpenGL drawing. 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderer(Renderer renderer) { 33615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 337a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEGLConfigChooser == null) { 338a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLConfigChooser = new SimpleEGLConfigChooser(true); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLContextFactory == null) { 34115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory = new DefaultContextFactory(); 34215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 34315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLWindowSurfaceFactory == null) { 34415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); 34515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 3462ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mRenderer = renderer; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread = new GLThread(renderer); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.start(); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 35215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLContextFactory. 35315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 35415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 35515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 35615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 35715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If this method is not called, then by default 35815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * a context will be created with no shared context and 35915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * with a null attribute list. 36015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 361a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich public void setEGLContextFactory(EGLContextFactory factory) { 36215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 36315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory = factory; 36415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 36515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 36615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 36715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLWindowSurfaceFactory. 36815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 36915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 37015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 37115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 37215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If this method is not called, then by default 37315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * a window surface will be created with a null attribute list. 37415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 375a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { 37615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 37715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory = factory; 37815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 37915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 38015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 381b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a custom EGLConfigChooser. 382b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 383b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 384a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 385a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 386b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If no setEGLConfigChooser method is called, then by default the 38783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an EGLConfig that is compatible with the current 38883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * android.view.Surface, with a depth buffer depth of 38983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 390a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param configChooser 391a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 392a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(EGLConfigChooser configChooser) { 39315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 394a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLConfigChooser = configChooser; 395a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 396a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 397a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 398b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a config chooser which will choose a config 399a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * as close to 16-bit RGB as possible, with or without an optional depth 400a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * buffer as close to 16-bits as possible. 401b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 402b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 403b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is called. 404a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 40583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If no setEGLConfigChooser method is called, then by default the 40683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an RGB_565 surface with a depth buffer depth of 40783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 408a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 409a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param needDepth 410a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 411a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(boolean needDepth) { 412a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); 413a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 414a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 415a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 416b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a config chooser which will choose a config 41783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least the specified depthSize and stencilSize, 41883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * and exactly the specified redSize, greenSize, blueSize and alphaSize. 419b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 420a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 421a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 422a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 423b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If no setEGLConfigChooser method is called, then by default the 42483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an RGB_565 surface with a depth buffer depth of 42583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 426a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 427a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 428a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, 429a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 430a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, 431a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich blueSize, alphaSize, depthSize, stencilSize)); 432a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 4336ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 4346ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 4356ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Inform the default EGLContextFactory and default EGLConfigChooser 4366ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * which EGLContext client version to pick. 4376ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>Use this method to create an OpenGL ES 2.0-compatible context. 4386ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Example: 4396ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <pre class="prettyprint"> 4406ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * public MyView(Context context) { 4416ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * super(context); 4426ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context. 4436ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setRenderer(new MyRenderer()); 4446ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * } 4456ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * </pre> 4466ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>Note: Activities which require OpenGL ES 2.0 should indicate this by 4476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's 4486ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * AndroidManifest.xml file. 4496ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>If this method is called, it must be called before {@link #setRenderer(Renderer)} 4506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * is called. 4516ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>This method only affects the behavior of the default EGLContexFactory and the 4526ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * default EGLConfigChooser. If 4536ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied 4546ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. 4556ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * If 4566ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied 4576ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. 4586ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 4596ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 4606ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public void setEGLContextClientVersion(int version) { 4616ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich checkRenderThreadState(); 4626ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mEGLContextClientVersion = version; 4636ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 4646ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 465a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 466b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the rendering mode. When renderMode is 4673e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * RENDERMODE_CONTINUOUSLY, the renderer is called 468b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * repeatedly to re-render the scene. When renderMode 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface 4703e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. 471b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 472b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance 473b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * by allowing the GPU and CPU to idle when the view does not need to be updated. 474b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 475b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method can only be called after {@link #setRenderer(Renderer)} 476b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param renderMode one of the RENDERMODE_X constants 4783e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * @see #RENDERMODE_CONTINUOUSLY 479b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #RENDERMODE_WHEN_DIRTY 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderMode(int renderMode) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.setRenderMode(renderMode); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the current rendering mode. May be called 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from any thread. Must not be called before a renderer has been set. 488b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return the current rendering mode. 4893e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * @see #RENDERMODE_CONTINUOUSLY 490b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #RENDERMODE_WHEN_DIRTY 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRenderMode() { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGLThread.getRenderMode(); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 497b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Request that the renderer render a frame. 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method is typically used when the render mode has been set to 499b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. 500b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * May be called 501b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * from any thread. Must not be called before a renderer has been set. 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestRender() { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.requestRender(); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 507b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 508b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 509b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 510b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated(SurfaceHolder holder) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceCreated(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 515b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 516b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 517b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 518b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Surface will be destroyed when we return 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceDestroyed(); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 524b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 525b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 526b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 527b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onWindowResize(w, h); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is paused. The owner of this view must 534b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * call this method when the activity is paused. Calling this method will 535b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause the rendering thread. 536b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPause() { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onPause(); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is resumed. The owner of this view must 544b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * call this method when the activity is resumed. Calling this method will 545b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * recreate the OpenGL display and resume the rendering 546b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * thread. 547b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onResume() { 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onResume(); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 554b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Queue a runnable to be run on the GL rendering thread. This can be used 555b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to communicate with the Renderer on the rendering thread. 556b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param r the runnable to be run on the GL rendering thread. 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.queueEvent(r); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 563b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 564b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is used as part of the View class and is not normally 565b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called or subclassed by clients of GLSurfaceView. 5662ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich */ 5672ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich @Override 5682ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich protected void onAttachedToWindow() { 5692ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich super.onAttachedToWindow(); 5702ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (LOG_ATTACH_DETACH) { 5712ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich Log.d(TAG, "onAttachedToWindow reattach =" + mDetached); 5722ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5732ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (mDetached && (mRenderer != null)) { 5741396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich int renderMode = RENDERMODE_CONTINUOUSLY; 5751396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich if (mGLThread != null) { 5761396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich renderMode = mGLThread.getRenderMode(); 5771396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich } 5782ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mGLThread = new GLThread(mRenderer); 5791396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich if (renderMode != RENDERMODE_CONTINUOUSLY) { 5801396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich mGLThread.setRenderMode(renderMode); 5811396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich } 5822ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mGLThread.start(); 5832ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5842ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mDetached = false; 5852ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5862ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich 5872ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich /** 5882ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * This method is used as part of the View class and is not normally 5892ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * called or subclassed by clients of GLSurfaceView. 590b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 591b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDetachedFromWindow() { 5942ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (LOG_ATTACH_DETACH) { 5952ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich Log.d(TAG, "onDetachedFromWindow"); 5962ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5972ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (mGLThread != null) { 5982ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mGLThread.requestExitAndWait(); 5992ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 6002ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mDetached = true; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onDetachedFromWindow(); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ---------------------------------------------------------------------- 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 606b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 607b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface used to wrap a GL interface. 608b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>Typically 609b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * used for implementing debugging and tracing on top of the default 610b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL interface. You would typically use this by creating your own class 611b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that implemented all the GL methods by delegating to another GL instance. 612b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Then you could add your own behavior before or after calling the 613b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * delegate. All the GLWrapper would do was instantiate and return the 614b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * wrapper GL instance: 615b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 616b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLWrapper implements GLWrapper { 617b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL wrap(GL gl) { 618b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return new MyGLImplementation(gl); 619b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 620b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * static class MyGLImplementation implements GL,GL10,GL11,... { 621b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * ... 622b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 623b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 624b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 625b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setGLWrapper(GLWrapper) 626b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface GLWrapper { 628b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 629b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wraps a gl interface in another gl interface. 630b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param gl a GL interface that is to be wrapped. 631b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return either the input argument or another GL object that wraps the input argument. 632b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 633b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich GL wrap(GL gl); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic renderer interface. 638b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 639b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is responsible for making OpenGL calls to render a frame. 640b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 641b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView clients typically create their own classes that implement 642b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * this interface, and then call {@link GLSurfaceView#setRenderer} to 643b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * register the renderer with the GLSurfaceView. 644b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 64561fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * 64661fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <div class="special reference"> 64761fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <h3>Developer Guides</h3> 64861fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <p>For more information about how to use OpenGL, read the 64961fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a> developer guide.</p> 65061fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * </div> 65161fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * 652b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Threading</h3> 653b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer will be called on a separate thread, so that rendering 654b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * performance is decoupled from the UI thread. Clients typically need to 655b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * communicate with the renderer from the UI thread, because that's where 656b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * input events are received. Clients can communicate using any of the 657b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java techniques for cross-thread communication, or they can 658b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. 659b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 660b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>EGL Context Lost</h3> 661b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * There are situations where the EGL rendering context will be lost. This 662b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically happens when device wakes up after going to sleep. When 663b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the EGL context is lost, all OpenGL resources (such as textures) that are 664b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * associated with that context will be automatically deleted. In order to 665b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * keep rendering correctly, a renderer must recreate any lost resources 666b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method 667b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is a convenient place to do this. 668b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 669b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 670b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderer(Renderer) 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface Renderer { 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 674b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface is created or recreated. 675b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 676b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the rendering thread 677840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * starts and whenever the EGL context is lost. The EGL context will typically 678b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * be lost when the Android device awakes after going to sleep. 679b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 680b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Since this method is called at the beginning of rendering, as well as 681b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * every time the EGL context is lost, this method is a convenient place to put 682b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * code to create resources that need to be created when the rendering 683b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * starts, and that need to be recreated when the EGL context is lost. 684b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Textures are an example of a resource that you might want to create 685b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * here. 686b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 687b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Note that when the EGL context is lost, all OpenGL resources associated 688b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * with that context will be automatically deleted. You do not need to call 689b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the corresponding "glDelete" methods such as glDeleteTextures to 690b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * manually delete these lost resources. 691b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param config the EGLConfig of the created surface. Can be used 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to create matching pbuffers. 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSurfaceCreated(GL10 gl, EGLConfig config); 698b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 700b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface changed size. 701b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called after the surface is created and whenever 703b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL ES surface size changes. 704b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 705b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you will set your viewport here. If your camera 706b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is fixed then you could also set your projection matrix here: 707b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 708b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onSurfaceChanged(GL10 gl, int width, int height) { 709b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glViewport(0, 0, width, height); 710b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // for a fixed camera, set the projection too 711b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * float ratio = (float) width / height; 712b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glMatrixMode(GL10.GL_PROJECTION); 713b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glLoadIdentity(); 714b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 715b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 716b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param width 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param height 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSurfaceChanged(GL10 gl, int width, int height); 723b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 725b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called to draw the current frame. 726b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 727b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is responsible for drawing the current frame. 728b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 729b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The implementation of this method typically looks like this: 730b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 731b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onDrawFrame(GL10 gl) { 732b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 733b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * //... other gl calls to render the scene ... 734b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 735b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onDrawFrame(GL10 gl); 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 74315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * An interface for customizing the eglCreateContext and eglDestroyContext calls. 74415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 74515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * This interface must be implemented by clients wishing to call 74615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)} 74715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 74815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public interface EGLContextFactory { 74915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); 75015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); 75115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 75215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 7536ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class DefaultContextFactory implements EGLContextFactory { 7546ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 75515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 75615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { 7576ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, 7586ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich EGL10.EGL_NONE }; 7596ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 7606ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, 7616ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mEGLContextClientVersion != 0 ? attrib_list : null); 76215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 76315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 76415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void destroyContext(EGL10 egl, EGLDisplay display, 76515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLContext context) { 76607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (!egl.eglDestroyContext(display, context)) { 76707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.e("DefaultContextFactory", "display:" + display + " context: " + context); 76807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_THREADS) { 76907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId()); 77007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 77107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("eglDestroyContext failed: " 77207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich + EGLLogWrapper.getErrorString(egl.eglGetError())); 77307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 77415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 77515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 77615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 77715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 77815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. 77915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 78015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * This interface must be implemented by clients wishing to call 781d40dfbbbff81219258ca36b762a89ff503154345Jack Palevich * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} 78215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 78315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public interface EGLWindowSurfaceFactory { 78415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, 78515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich Object nativeWindow); 78615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); 78715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 78815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 78915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { 79015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 79115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, 79215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLConfig config, Object nativeWindow) { 79315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich return egl.eglCreateWindowSurface(display, config, nativeWindow, null); 79415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 79515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 79615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void destroySurface(EGL10 egl, EGLDisplay display, 79715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLSurface surface) { 79815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich egl.eglDestroySurface(display, surface); 79915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 80015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 80115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 80215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 803b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface for choosing an EGLConfig configuration from a list of 804a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * potential configurations. 805b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 806b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This interface must be implemented by clients wishing to call 807b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} 808a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 809a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public interface EGLConfigChooser { 810a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 811a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Choose a configuration from the list. Implementors typically 812a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * implement this method by calling 813b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the 814b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. 815a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param egl the EGL10 for the current display. 816a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param display the current display. 817a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @return the chosen configuration. 818a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 819a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); 820a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 821a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 8226ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private abstract class BaseConfigChooser 823a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich implements EGLConfigChooser { 824a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public BaseConfigChooser(int[] configSpec) { 8256ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mConfigSpec = filterConfigSpec(configSpec); 826a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 8276ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 828a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 829a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int[] num_config = new int[1]; 83028023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, 83128023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich num_config)) { 83228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new IllegalArgumentException("eglChooseConfig failed"); 83328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 834a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 835a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int numConfigs = num_config[0]; 836a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 837a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (numConfigs <= 0) { 838a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new IllegalArgumentException( 839a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich "No configs match configSpec"); 840a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 841a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 842a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs = new EGLConfig[numConfigs]; 84328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, 84428023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich num_config)) { 84528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new IllegalArgumentException("eglChooseConfig#2 failed"); 84628023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 847a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config = chooseConfig(egl, display, configs); 848a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (config == null) { 849a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new IllegalArgumentException("No config chosen"); 850a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 851a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return config; 852a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 853a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 854a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 855a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs); 856a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 857a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int[] mConfigSpec; 8586ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 8596ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int[] filterConfigSpec(int[] configSpec) { 8606ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich if (mEGLContextClientVersion != 2) { 8616ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return configSpec; 8626ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 8636ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /* We know none of the subclasses define EGL_RENDERABLE_TYPE. 8646ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * And we know the configSpec is well formed. 8656ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 8666ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int len = configSpec.length; 8676ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] newConfigSpec = new int[len + 2]; 8686ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); 8696ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; 8706ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ 8716ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len+1] = EGL10.EGL_NONE; 8726ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return newConfigSpec; 8736ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 874a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 875a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 87683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich /** 87783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * Choose a configuration with exactly the specified r,g,b,a sizes, 87883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * and at least the specified depth and stencil sizes. 87983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich */ 8806ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class ComponentSizeChooser extends BaseConfigChooser { 881a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public ComponentSizeChooser(int redSize, int greenSize, int blueSize, 882a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 883a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich super(new int[] { 884a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_RED_SIZE, redSize, 885a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_GREEN_SIZE, greenSize, 886a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_BLUE_SIZE, blueSize, 887a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_ALPHA_SIZE, alphaSize, 888a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, depthSize, 889a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_STENCIL_SIZE, stencilSize, 890a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_NONE}); 891a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mValue = new int[1]; 892a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mRedSize = redSize; 893a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mGreenSize = greenSize; 894a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mBlueSize = blueSize; 895a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mAlphaSize = alphaSize; 896a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mDepthSize = depthSize; 897a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mStencilSize = stencilSize; 898a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 899a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 900a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich @Override 901a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 902a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs) { 90383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich for (EGLConfig config : configs) { 904a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int d = findConfigAttrib(egl, display, config, 905a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, 0); 906a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int s = findConfigAttrib(egl, display, config, 907a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_STENCIL_SIZE, 0); 90883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich if ((d >= mDepthSize) && (s >= mStencilSize)) { 90982fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int r = findConfigAttrib(egl, display, config, 91082fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_RED_SIZE, 0); 91182fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int g = findConfigAttrib(egl, display, config, 91282fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_GREEN_SIZE, 0); 91382fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int b = findConfigAttrib(egl, display, config, 91482fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_BLUE_SIZE, 0); 91582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int a = findConfigAttrib(egl, display, config, 91682fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_ALPHA_SIZE, 0); 91783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich if ((r == mRedSize) && (g == mGreenSize) 91883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich && (b == mBlueSize) && (a == mAlphaSize)) { 91983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich return config; 92082fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian } 921a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 922a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 92383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich return null; 924a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 925a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 926a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int findConfigAttrib(EGL10 egl, EGLDisplay display, 927a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config, int attribute, int defaultValue) { 928a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 929a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 930a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return mValue[0]; 931a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 932a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return defaultValue; 933a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 934a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 935a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int[] mValue; 936a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich // Subclasses can adjust these values: 937a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mRedSize; 938a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mGreenSize; 939a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mBlueSize; 940a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mAlphaSize; 941a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mDepthSize; 942a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mStencilSize; 943a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 944a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 945a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 94683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * This class will choose a RGB_565 surface with 94783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * or without a depth buffer. 948a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 949a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 9506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class SimpleEGLConfigChooser extends ComponentSizeChooser { 951a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public SimpleEGLConfigChooser(boolean withDepthBuffer) { 95283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich super(5, 6, 5, 0, withDepthBuffer ? 16 : 0, 0); 953a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 954a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 955a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 956a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An EGL helper class. 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class EglHelper { 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public EglHelper() { 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Initialize EGL for a given configuration spec. 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param configSpec 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 969840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void start() { 97007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 97107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId()); 97207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get an EGL instance 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl = (EGL10) EGLContext.getEGL(); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get to the default display. 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 98328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 98428023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new RuntimeException("eglGetDisplay failed"); 98528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 98628023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can now initialize EGL for that display 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] version = new int[2]; 99128023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if(!mEgl.eglInitialize(mEglDisplay, version)) { 99228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new RuntimeException("eglInitialize failed"); 99328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 994a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 997840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * Create an EGL context. We want to do this as rarely as we can, because an 998840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * EGL context is a somewhat heavy object. 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 100015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 10012e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { 100207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEglContext = null; 10039bb4dbae91df0971038e955ef49c5d9a64d4a428Jack Palevich throwEglException("createContext"); 10042e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 100507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 100607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); 100707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * React to the creation of a new surface by creating and returning an 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * OpenGL interface that renders to that surface. 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GL createSurface(SurfaceHolder holder) { 101707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 101807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); 101907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 102007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich /* 102107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich * Check preconditions. 102207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich */ 102307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEgl == null) { 102407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("egl not initialized"); 102507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 102607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglDisplay == null) { 102707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("eglDisplay not initialized"); 102807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 102907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglConfig == null) { 103007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("mEglConfig not initialized"); 103107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The window size has changed, so we need to create a new 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * surface. 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10362e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unbind and destroy the old EGL surface, if 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is one. 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 104415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create an EGL surface we can render into. 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 105015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, 105115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEglDisplay, mEglConfig, holder); 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10532e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 10540e4aa37872810e46775374596e0beb11f7123727Jack Palevich int error = mEgl.eglGetError(); 10550e4aa37872810e46775374596e0beb11f7123727Jack Palevich if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 10560e4aa37872810e46775374596e0beb11f7123727Jack Palevich Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 10570e4aa37872810e46775374596e0beb11f7123727Jack Palevich return null; 10580e4aa37872810e46775374596e0beb11f7123727Jack Palevich } 10590e4aa37872810e46775374596e0beb11f7123727Jack Palevich throwEglException("createWindowSurface", error); 10602e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 10612e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before we can issue GL commands, we need to make sure 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the context is current and bound to a surface. 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10662e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 10675aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich throwEglException("eglMakeCurrent"); 10682e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL gl = mEglContext.getGL(); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGLWrapper != null) { 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gl = mGLWrapper.wrap(gl); 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1075a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int configFlags = 0; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Writer log = null; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log = new LogWriter(); 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gl = GLDebugHelper.wrap(gl, configFlags, log); 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return gl; 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10893ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian public void purgeBuffers() { 10903ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian mEgl.eglMakeCurrent(mEglDisplay, 10913ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, 10923ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian EGL10.EGL_NO_CONTEXT); 10933ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian mEgl.eglMakeCurrent(mEglDisplay, 10943ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian mEglSurface, mEglSurface, 10953ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian mEglContext); 10963ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian } 10973ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Display the current render surface. 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return false if the context has been lost. 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean swap() { 110304b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 110504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich /* 110604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * Check for EGL_CONTEXT_LOST, which means the context 110704b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * and all associated data were lost (For instance because 110804b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * the device went to sleep). We need to sleep until we 110904b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * get a new surface. 111004b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich */ 111104b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich int error = mEgl.eglGetError(); 11120e4aa37872810e46775374596e0beb11f7123727Jack Palevich switch(error) { 11130e4aa37872810e46775374596e0beb11f7123727Jack Palevich case EGL11.EGL_CONTEXT_LOST: 111404b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich return false; 11150e4aa37872810e46775374596e0beb11f7123727Jack Palevich case EGL10.EGL_BAD_NATIVE_WINDOW: 11160e4aa37872810e46775374596e0beb11f7123727Jack Palevich // The native window is bad, probably because the 11170e4aa37872810e46775374596e0beb11f7123727Jack Palevich // window manager has closed it. Ignore this error, 11180e4aa37872810e46775374596e0beb11f7123727Jack Palevich // on the expectation that the application will be closed soon. 11190e4aa37872810e46775374596e0beb11f7123727Jack Palevich Log.e("EglHelper", "eglSwapBuffers returned EGL_BAD_NATIVE_WINDOW. tid=" + Thread.currentThread().getId()); 11200e4aa37872810e46775374596e0beb11f7123727Jack Palevich break; 11210e4aa37872810e46775374596e0beb11f7123727Jack Palevich default: 112204b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich throwEglException("eglSwapBuffers", error); 112304b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 112404b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 112504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich return true; 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11281bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public void destroySurface() { 112907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 113007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId()); 113107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 11322e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_SURFACE, 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_CONTEXT); 113615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11391bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 11401bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich 11411bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public void finish() { 114207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 114307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId()); 114407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglContext != null) { 114615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglContext = null; 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglDisplay != null) { 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglTerminate(mEglDisplay); 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglDisplay = null; 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11555aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich private void throwEglException(String function) { 115604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich throwEglException(function, mEgl.eglGetError()); 115704b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 115804b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich 115904b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich private void throwEglException(String function, int error) { 116007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich String message = function + " failed: " + EGLLogWrapper.getErrorString(error); 116107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_THREADS) { 116207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " + message); 116307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 116407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException(message); 11655aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich } 11665aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10 mEgl; 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLDisplay mEglDisplay; 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface mEglSurface; 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLConfig mEglConfig; 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext mEglContext; 1172840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic GL Thread. Takes care of initializing EGL and GL. Delegates 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to a Renderer instance to do the actual drawing. Can be configured to 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * render continuously or on request. 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 118067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * All potentially blocking synchronization is done through the 118167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * sGLThreadManager object. This avoids multiple-lock ordering issues. 118267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class GLThread extends Thread { 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GLThread(Renderer renderer) { 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = 0; 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = 0; 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestRender = true; 11903e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich mRenderMode = RENDERMODE_CONTINUOUSLY; 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderer = renderer; 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 11968b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich setName("GLThread " + getId()); 11978b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 11988b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "starting tid=" + getId()); 11998b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 12008b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guardedRun(); 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fall thru and exit normally 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 120667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.threadExiting(this); 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 121067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich /* 121167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * This private method should only be called inside a 121267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * synchronized(sGLThreadManager) block. 121367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich */ 1214840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private void stopEglSurfaceLocked() { 1215840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1216840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = false; 121732d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich mEglHelper.destroySurface(); 121832d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 121932d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 122032d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich 1221840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich /* 1222840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * This private method should only be called inside a 1223840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * synchronized(sGLThreadManager) block. 1224840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich */ 1225840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private void stopEglContextLocked() { 1226840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglContext) { 1227840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mEglHelper.finish(); 1228840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = false; 1229840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich sGLThreadManager.releaseEglContextLocked(this); 1230840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1231840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void guardedRun() throws InterruptedException { 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglHelper = new EglHelper(); 1234840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = false; 1235840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = false; 123615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich try { 123715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich GL10 gl = null; 1238840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich boolean createEglContext = false; 1239a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich boolean createEglSurface = false; 1240840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich boolean lostEglContext = false; 1241a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich boolean sizeChanged = false; 124221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich boolean wantRenderNotification = false; 124321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich boolean doRenderNotification = false; 12441b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich boolean askedToReleaseEglContext = false; 1245a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich int w = 0; 1246a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich int h = 0; 1247a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Runnable event = null; 124867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1249a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while (true) { 125067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 125167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich while (true) { 1252a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mShouldExit) { 1253a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich return; 1254a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1255a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1256a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (! mEventQueue.isEmpty()) { 1257a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event = mEventQueue.remove(0); 1258a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich break; 1259a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1260a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1261451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich // Update the pause state. 1262451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (mPaused != mRequestPaused) { 1263451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mPaused = mRequestPaused; 1264451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.notifyAll(); 1265451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1266451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId()); 1267451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1268451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1269451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 12701b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // Do we need to give up the EGL context? 12711b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (mShouldReleaseEglContext) { 12721b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 12731b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "releasing EGL context because asked to tid=" + getId()); 12741b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 12751b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich stopEglSurfaceLocked(); 12761b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich stopEglContextLocked(); 12771b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mShouldReleaseEglContext = false; 12781b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich askedToReleaseEglContext = true; 12791b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 12801b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 1281840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // Have we lost the EGL context? 1282840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (lostEglContext) { 1283840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1284840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 1285840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich lostEglContext = false; 1286840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1287840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1288a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Do we need to release the EGL surface? 1289840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface && mPaused) { 1290a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1291a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); 1292a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1293840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 12948432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich if (!mPreserveEGLContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { 1295840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 1296840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (LOG_SURFACE) { 1297840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); 1298840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1299840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1300b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if (sGLThreadManager.shouldTerminateEGLWhenPausing()) { 1301b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich mEglHelper.finish(); 1302b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if (LOG_SURFACE) { 1303b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich Log.i("GLThread", "terminating EGL because paused tid=" + getId()); 1304b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1305b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 130667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1307a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1308a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Have we lost the surface view surface? 1309a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if ((! mHasSurface) && (! mWaitingForSurface)) { 1310a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1311a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); 131215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1313840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1314840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 131532d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 1316a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mWaitingForSurface = true; 1317a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 131832d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 131967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1320a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Have we acquired the surface view surface? 1321a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mHasSurface && mWaitingForSurface) { 1322a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1323a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); 1324a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1325a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mWaitingForSurface = false; 1326a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 132767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 132867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 132921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (doRenderNotification) { 13301b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 13311b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "sending render notification tid=" + getId()); 13321b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 133321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich wantRenderNotification = false; 133421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich doRenderNotification = false; 133521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mRenderComplete = true; 133621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.notifyAll(); 133721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 133821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 1339a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Ready to draw? 13401b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (readyToDraw()) { 1341a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1342840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // If we don't have an EGL context, try to acquire one. 13431b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (! mHaveEglContext) { 13441b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (askedToReleaseEglContext) { 13451b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich askedToReleaseEglContext = false; 13461b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) { 13471b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich try { 13481b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mEglHelper.start(); 13491b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } catch (RuntimeException t) { 13501b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.releaseEglContextLocked(this); 13511b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich throw t; 13521b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13531b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mHaveEglContext = true; 13541b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich createEglContext = true; 1355840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 13561b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.notifyAll(); 13571b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 1358840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1359840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1360840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglContext && !mHaveEglSurface) { 1361840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = true; 1362a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = true; 1363a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = true; 1364a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 136567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1366840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1367a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mSizeChanged) { 1368a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = true; 1369a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich w = mWidth; 1370a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich h = mHeight; 137121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich wantRenderNotification = true; 13721b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 13731b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "noticing that we want render notification tid=" + getId()); 13741b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 137521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 1376a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (DRAW_TWICE_AFTER_SIZE_CHANGED) { 1377a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // We keep mRequestRender true so that we draw twice after the size changes. 1378a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // (Once because of mSizeChanged, the second time because of mRequestRender.) 1379a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // This forces the updated graphics onto the screen. 1380a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } else { 1381a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = false; 1382a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1383a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mSizeChanged = false; 1384a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } else { 1385a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = false; 1386a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 138767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1388a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich break; 138967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 139032d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 139167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1392a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // By design, this is the only place in a GLThread thread where we wait(). 139332d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich if (LOG_THREADS) { 13941b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "waiting tid=" + getId() 13951b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHaveEglContext: " + mHaveEglContext 13961b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHaveEglSurface: " + mHaveEglSurface 13971b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mPaused: " + mPaused 13981b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHasSurface: " + mHasSurface 13991b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mWaitingForSurface: " + mWaitingForSurface 14001b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mWidth: " + mWidth 14011b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHeight: " + mHeight 14021b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mRequestRender: " + mRequestRender 14031b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mRenderMode: " + mRenderMode); 14041bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 140567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.wait(); 140615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 140767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } // end of synchronized(sGLThreadManager) 140867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1409a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (event != null) { 1410a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event.run(); 1411a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event = null; 141267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich continue; 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 141467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1415a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (createEglSurface) { 14164a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 14174a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w("GLThread", "egl createSurface"); 14184a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 141915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich gl = (GL10) mEglHelper.createSurface(getHolder()); 14200e4aa37872810e46775374596e0beb11f7123727Jack Palevich if (gl == null) { 14210e4aa37872810e46775374596e0beb11f7123727Jack Palevich // Couldn't create a surface. Quit quietly. 14220e4aa37872810e46775374596e0beb11f7123727Jack Palevich break; 14230e4aa37872810e46775374596e0beb11f7123727Jack Palevich } 142479447b2087c8c820d742185dda7305101f9656f0Jack Palevich sGLThreadManager.checkGLDriver(gl); 1425a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = false; 142615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1427a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1428840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (createEglContext) { 14294a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_RENDERER) { 14304a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w("GLThread", "onSurfaceCreated"); 14314a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 1432840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); 1433840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich createEglContext = false; 1434840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1435840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1436a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (sizeChanged) { 1437a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_RENDERER) { 1438a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); 1439a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 14403ab88557947d708cc36d60ce6566509ceff944e4Mathias Agopian mEglHelper.purgeBuffers(); 144115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mRenderer.onSurfaceChanged(gl, w, h); 1442a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = false; 144315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1444a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 14454a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_RENDERER_DRAW_FRAME) { 14461b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.w("GLThread", "onDrawFrame tid=" + getId()); 1447a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1448a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRenderer.onDrawFrame(gl); 1449840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (!mEglHelper.swap()) { 1450a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1451840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich Log.i("GLThread", "egl context lost tid=" + getId()); 1452a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1453840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich lostEglContext = true; 145415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 145521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 145621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (wantRenderNotification) { 145721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich doRenderNotification = true; 145821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 1459a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1460840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 146115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } finally { 146215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /* 146315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * clean-up everything... 146415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 146567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1466840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1467840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 146867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 146915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14721b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public boolean ableToDraw() { 14731b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich return mHaveEglContext && mHaveEglSurface && readyToDraw(); 14741b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 14751b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 14761b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private boolean readyToDraw() { 14771b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich return (!mPaused) && mHasSurface 14781b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich && (mWidth > 0) && (mHeight > 0) 14791b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); 14801b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 14811b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderMode(int renderMode) { 14833e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("renderMode"); 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 148667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderMode = renderMode; 1488a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRenderMode() { 149367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mRenderMode; 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestRender() { 149967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestRender = true; 150167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated() { 150667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15078b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 15088b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "surfaceCreated tid=" + getId()); 15098b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasSurface = true; 151167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1512451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while((mWaitingForSurface) && (!mExited)) { 1513451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1514451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1515451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException e) { 1516451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1517451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1518451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed() { 152367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15248b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 15258b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "surfaceDestroyed tid=" + getId()); 15268b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasSurface = false; 152867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1529a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while((!mWaitingForSurface) && (!mExited)) { 15301bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich try { 153167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.wait(); 15321bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } catch (InterruptedException e) { 15331bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich Thread.currentThread().interrupt(); 15341bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 15351bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPause() { 154067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1541e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich if (LOG_PAUSE_RESUME) { 1542e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich Log.i("GLThread", "onPause tid=" + getId()); 1543e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1544451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRequestPaused = true; 154567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1546451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while ((! mExited) && (! mPaused)) { 1547451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1548451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("Main thread", "onPause waiting for mPaused."); 1549451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1550451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1551451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1552451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException ex) { 1553451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1554451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1555451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onResume() { 156067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1561e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich if (LOG_PAUSE_RESUME) { 1562e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich Log.i("GLThread", "onResume tid=" + getId()); 1563e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1564451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRequestPaused = false; 15658b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich mRequestRender = true; 1566451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRenderComplete = false; 156767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1568451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while ((! mExited) && mPaused && (!mRenderComplete)) { 1569451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1570451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("Main thread", "onResume waiting for !mPaused."); 1571451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1572451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1573451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1574451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException ex) { 1575451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1576451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1577451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onWindowResize(int w, int h) { 158267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = w; 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = h; 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSizeChanged = true; 1586a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = true; 158721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mRenderComplete = false; 158867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 158921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 159021799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich // Wait for thread to react to resize and render a frame 15911b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich while (! mExited && !mPaused && !mRenderComplete 15921b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich && (mGLThread != null && mGLThread.ableToDraw())) { 159321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (LOG_SURFACE) { 15941b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + mGLThread.getId()); 159521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 159621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich try { 159721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.wait(); 159821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } catch (InterruptedException ex) { 159921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich Thread.currentThread().interrupt(); 160021799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 160121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestExitAndWait() { 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't call this from GLThread thread or it is a guaranteed 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // deadlock! 160867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 1609a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mShouldExit = true; 161067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1611a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while (! mExited) { 1612a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich try { 1613a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.wait(); 1614a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } catch (InterruptedException ex) { 1615a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Thread.currentThread().interrupt(); 1616a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1617a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16211b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public void requestReleaseEglContextLocked() { 16221b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mShouldReleaseEglContext = true; 16231b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.notifyAll(); 16241b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 16251b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Queue an "event" to be run on the GL rendering thread. 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param r the runnable to be run on the GL rendering thread. 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 1631a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (r == null) { 1632a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich throw new IllegalArgumentException("r must not be null"); 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1634a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 1635a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mEventQueue.add(r); 1636a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 164067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // Once the thread is started, all accesses to the following member 164167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // variables are protected by the sGLThreadManager monitor 1642a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mShouldExit; 1643a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mExited; 1644451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private boolean mRequestPaused; 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mPaused; 16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mHasSurface; 16471bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich private boolean mWaitingForSurface; 1648840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private boolean mHaveEglContext; 1649840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private boolean mHaveEglSurface; 16501b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private boolean mShouldReleaseEglContext; 16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mWidth; 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mHeight; 16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRenderMode; 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mRequestRender; 165521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich private boolean mRenderComplete; 1656a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); 1657840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 165867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // End of member variables protected by the sGLThreadManager monitor. 165967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Renderer mRenderer; 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EglHelper mEglHelper; 16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class LogWriter extends Writer { 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void close() { 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void flush() { 16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void write(char[] buf, int offset, int count) { 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < count; i++) { 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = buf[offset + i]; 16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ( c == '\n') { 16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuilder.append(c); 16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void flushBuilder() { 16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBuilder.length() > 0) { 16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v("GLSurfaceView", mBuilder.toString()); 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuilder.delete(0, mBuilder.length()); 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private StringBuilder mBuilder = new StringBuilder(); 16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 169615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 169715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private void checkRenderThreadState() { 169815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mGLThread != null) { 169915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich throw new IllegalStateException( 170015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich "setRenderer has already been called for this instance."); 170115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 170215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 170315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 170479447b2087c8c820d742185dda7305101f9656f0Jack Palevich private static class GLThreadManager { 17054a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private static String TAG = "GLThreadManager"; 17068da3ac92a6a6247ef06de4d4b684f8635d8fc003Jack Palevich 170767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich public synchronized void threadExiting(GLThread thread) { 170867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (LOG_THREADS) { 170967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich Log.i("GLThread", "exiting tid=" + thread.getId()); 17108b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 1711a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich thread.mExited = true; 171267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread) { 171367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = null; 17148b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 171567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 171667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1717c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 171867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich /* 171967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * Tries once to acquire the right to use an EGL 1720840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * context. Does not block. Requires that we are already 1721a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * in the sGLThreadManager monitor when this is called. 172266a4a6e45f59f72f24d710221c27db1bd233e154Jack Palevich * 1723840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * @return true if the right to use an EGL context was acquired. 172467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich */ 1725840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public boolean tryAcquireEglContextLocked(GLThread thread) { 172667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread || mEglOwner == null) { 172767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = thread; 172867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 172967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return true; 17308b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 17311179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich checkGLESVersion(); 17321179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (mMultipleGLESContextsAllowed) { 17331179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich return true; 17348b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 17351b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // Notify the owning thread that it should release the context. 17361b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // TODO: implement a fairness policy. Currently 17371b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // if the owning thread is drawing continuously it will just 17381b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // reacquire the EGL context. 17391b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (mEglOwner != null) { 17401b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mEglOwner.requestReleaseEglContextLocked(); 17411b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 174267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return false; 1743c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1744840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1745a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich /* 1746840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * Releases the EGL context. Requires that we are already in the 1747a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * sGLThreadManager monitor when this is called. 1748a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich */ 1749840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void releaseEglContextLocked(GLThread thread) { 175067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread) { 175167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = null; 175279447b2087c8c820d742185dda7305101f9656f0Jack Palevich } 175367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 1754c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1755c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 1756840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public synchronized boolean shouldReleaseEGLContextWhenPausing() { 1757b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // Release the EGL context when pausing even if 1758b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // the hardware supports multiple EGL contexts. 1759b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // Otherwise the device could run out of EGL contexts. 17608432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich return mLimitedGLESContexts; 1761b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1762b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich 1763b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich public synchronized boolean shouldTerminateEGLWhenPausing() { 1764840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich checkGLESVersion(); 17654a2221ec4a929976be570ad096252c8dea326e19Jack Palevich return !mMultipleGLESContextsAllowed; 1766840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1767840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1768c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich public synchronized void checkGLDriver(GL10 gl) { 1769c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich if (! mGLESDriverCheckComplete) { 17701179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich checkGLESVersion(); 17718432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich String renderer = gl.glGetString(GL10.GL_RENDERER); 1772c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich if (mGLESVersion < kGLES_20) { 1773c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich mMultipleGLESContextsAllowed = 1774c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); 1775c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich notifyAll(); 1776c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 17778432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mLimitedGLESContexts = !mMultipleGLESContextsAllowed || renderer.startsWith(kADRENO); 17788432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich if (LOG_SURFACE) { 17798432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " 17808432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich + mMultipleGLESContextsAllowed 17818432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich + " mLimitedGLESContexts = " + mLimitedGLESContexts); 17828432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 1783c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich mGLESDriverCheckComplete = true; 1784c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1785c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1786c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 17871179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich private void checkGLESVersion() { 17881179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (! mGLESVersionCheckComplete) { 17891179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mGLESVersion = SystemProperties.getInt( 17901179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich "ro.opengles.version", 17911179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich ConfigurationInfo.GL_ES_VERSION_UNDEFINED); 17921179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (mGLESVersion >= kGLES_20) { 17931179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mMultipleGLESContextsAllowed = true; 17941179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 17954a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 17964a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w(TAG, "checkGLESVersion mGLESVersion =" + 17974a2221ec4a929976be570ad096252c8dea326e19Jack Palevich " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); 17984a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 17991179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mGLESVersionCheckComplete = true; 18001179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 18011179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 18021179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich 1803c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mGLESVersionCheckComplete; 1804c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private int mGLESVersion; 1805c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mGLESDriverCheckComplete; 1806c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mMultipleGLESContextsAllowed; 18078432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich private boolean mLimitedGLESContexts; 1808c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private static final int kGLES_20 = 0x20000; 1809c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private static final String kMSM7K_RENDERER_PREFIX = 1810c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich "Q3Dimension MSM7500 "; 18118432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich private static final String kADRENO = "Adreno"; 181267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich private GLThread mEglOwner; 18138b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 1814c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 18158b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich private static final GLThreadManager sGLThreadManager = new GLThreadManager(); 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mSizeChanged = true; 18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLThread mGLThread; 18192ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private Renderer mRenderer; 18202ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private boolean mDetached; 1821a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private EGLConfigChooser mEGLConfigChooser; 182215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private EGLContextFactory mEGLContextFactory; 182315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; 18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLWrapper mGLWrapper; 18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDebugFlags; 18266ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int mEGLContextClientVersion; 18278432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich private boolean mPreserveEGLContextOnPause; 18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1829