GLSurfaceView.java revision 04b17ab7b4a17a28f541f746c3d55046c5b87596
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.opengl; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.Writer; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL10; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL11; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLConfig; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLContext; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLDisplay; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLSurface; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL10; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 32c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevichimport android.content.pm.ConfigurationInfo; 3383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevichimport android.graphics.PixelFormat; 34c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevichimport android.os.SystemProperties; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceView; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An implementation of SurfaceView that uses the dedicated surface for 42b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * displaying OpenGL rendering. 43b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 44b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView provides the following features: 45b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 46b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 47b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages a surface, which is a special piece of memory that can be 48b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * composited into the Android view system. 49b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages an EGL display, which enables OpenGL to render into a surface. 50b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Accepts a user-provided Renderer object that does the actual rendering. 51b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Renders on a dedicated thread to decouple rendering performance from the 52b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * UI thread. 53b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Supports both on-demand and continuous rendering. 54b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls. 55b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 56b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 57b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Using GLSurfaceView</h3> 58b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 59b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you use GLSurfaceView by subclassing it and overriding one or more of the 60b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * View system input event methods. If your application does not need to override event 61b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * methods then GLSurfaceView can be used as-is. For the most part 62b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. 63b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * For example, unlike a regular View, drawing is delegated to a separate Renderer object which 64b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is registered with the GLSurfaceView 65b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * using the {@link #setRenderer(Renderer)} call. 66b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 67b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Initializing GLSurfaceView</h3> 68b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. 69b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or 70b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * more of these methods before calling setRenderer: 71b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 72b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setDebugFlags(int)} 73b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 74b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 75b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 76b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setGLWrapper(GLWrapper)} 77b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 78b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 7983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <h4>Specifying the android.view.Surface</h4> 8083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * By default GLSurfaceView will create a PixelFormat.RGB_565 format surface. If a translucent 8183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). 8283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The exact format of a TRANSLUCENT surface is device dependent, but it will be 8383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * a 32-bit-per-pixel surface with 8 bits per component. 8483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 85b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Choosing an EGL Configuration</h4> 8683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * A given Android device may support multiple EGLConfig rendering configurations. 8783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The available configurations may differ in how may channels of data are present, as 88b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * well as how many bits are allocated to each channel. Therefore, the first thing 8983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * GLSurfaceView has to do when starting to render is choose what EGLConfig to use. 9083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 9183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * By default GLSurfaceView chooses a EGLConfig that has an RGB_656 pixel format, 9283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least a 16-bit depth buffer and no stencil. 93b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 9483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If you would prefer a different EGLConfig 9583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * you can override the default behavior by calling one of the 96b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setEGLConfigChooser methods. 97b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 98b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Debug Behavior</h4> 99b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * You can optionally modify the behavior of GLSurfaceView by calling 100b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one or more of the debugging methods {@link #setDebugFlags(int)}, 101b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but 102b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically they are called before setRenderer so that they take effect immediately. 103b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 104b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Setting a Renderer</h4> 105b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. 106b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is 107b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * responsible for doing the actual OpenGL rendering. 108b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 109b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Rendering Mode</h3> 110b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Once the renderer is set, you can control whether the renderer draws 111b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously or on-demand by calling 112b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #setRenderMode}. The default is continuous rendering. 113b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 114b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Activity Life-cycle</h3> 115b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients 116b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * are required to call {@link #onPause()} when the activity pauses and 117b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to 118b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate 119b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL display. 120b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 121b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Handling events</h3> 122b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 123b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * To handle an event you will typically subclass GLSurfaceView and override the 124b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * appropriate method, just as you would with any other View. However, when handling 125b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the event, you may need to communicate with the Renderer object 126b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that's running in the rendering thread. You can do this using any 127b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java cross-thread communication mechanism. In addition, 128b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one relatively easy way to communicate with your renderer is 129b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to call 130b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #queueEvent(Runnable)}. For example: 131b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 132b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLSurfaceView extends GLSurfaceView { 133b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 134b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * private MyRenderer mMyRenderer; 135b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 136b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void start() { 137b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer = ...; 138b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer(mMyRenderer); 139b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 140b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 141b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public boolean onKeyDown(int keyCode, KeyEvent event) { 142b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 143b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * queueEvent(new Runnable() { 144b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // This method will be called on the rendering 145b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // thread: 146b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void run() { 147b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer.handleDpadCenter(); 148b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * }}); 149b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return true; 150b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 151b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return super.onKeyDown(keyCode, event); 152b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 153b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 154b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 1582ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private final static boolean LOG_THREADS = false; 1592ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private final static boolean LOG_SURFACE = false; 16057c6a46bd0c84c4b349d49f8df12f30a8cfcdaa2Jack Palevich private final static boolean LOG_RENDERER = false; 1614a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_RENDERER_DRAW_FRAME = false; 1624a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich // Work-around for bug 2263168 1634a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true; 1644a2221ec4a929976be570ad096252c8dea326e19Jack Palevich /** 1654a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich * The renderer only renders 166a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * when the surface is created, or when {@link #requestRender} is called. 167a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * 168b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 169b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 170b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #requestRender() 171b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 172b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public final static int RENDERMODE_WHEN_DIRTY = 0; 173b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 174840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * The renderer is called 175b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously to re-render the scene. 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 177b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 178b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 179b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 180b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public final static int RENDERMODE_CONTINUOUSLY = 1; 181b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 182b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 183b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Check glError() after every GL call and throw an exception if glError indicates 1843e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * that an error has occurred. This can be used to help track down which OpenGL ES call 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is causing an error. 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 187b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getDebugFlags 188b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setDebugFlags 189b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 190b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public final static int DEBUG_CHECK_GL_ERROR = 1; 191b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 192b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #getDebugFlags 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setDebugFlags 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 198b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public final static int DEBUG_LOG_GL_CALLS = 2; 199b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 200b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Standard View constructor. In order to render something, you 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * must call {@link #setRenderer} to register a renderer. 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 204b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public GLSurfaceView(Context context) { 205b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich super(context); 206b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich init(); 207b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Standard View constructor. In order to render something, you 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * must call {@link #setRenderer} to register a renderer. 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 213b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public GLSurfaceView(Context context, AttributeSet attrs) { 214b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich super(context, attrs); 215b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich init(); 216b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init() { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Install a SurfaceHolder.Callback so we get notified when the 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // underlying surface is created and destroyed 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SurfaceHolder holder = getHolder(); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project holder.addCallback(this); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project holder.setFormat(PixelFormat.RGB_565); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // setType is not needed for SDK 2.0 or newer. Uncomment this 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // statement if back-porting this code to older SDKs. 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); 2271b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 2281b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 2291b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich /** 2301b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich * Set the glWrapper. If the glWrapper is not null, its 231840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * {@link GLWrapper#wrap(GL)} method is called 232840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * whenever a surface is created. A GLWrapper can be used to wrap 233840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * the GL object that's passed to the renderer. Wrapping a GL 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * object enables examining and modifying the behavior of the 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GL calls made by the renderer. 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 237b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wrapping is typically used for debugging purposes. 238b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 239b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The default value is null. 240b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param glWrapper the new GLWrapper 241b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 242b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public void setGLWrapper(GLWrapper glWrapper) { 243b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mGLWrapper = glWrapper; 244b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 245b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 246b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the debug flags to a new value. The value is 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * constructed by OR-together zero or more 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the DEBUG_CHECK_* constants. The debug flags take effect 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whenever a surface is created. The default value is zero. 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param debugFlags the new debug flags 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_CHECK_GL_ERROR 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_LOG_GL_CALLS 254b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 255b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public void setDebugFlags(int debugFlags) { 256b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mDebugFlags = debugFlags; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the current value of the debug flags. 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the current value of the debug flags. 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getDebugFlags() { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDebugFlags; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 266b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 267b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 268b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the renderer associated with this view. Also starts the thread that 269b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * will call the renderer, which in turn causes the rendering to start. 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This method should be called once and only once in the life-cycle of 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a GLSurfaceView. 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The following GLSurfaceView methods can only be called <em>before</em> 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * setRenderer is called: 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul> 2758432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 2768432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 2778432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 2788432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * </ul> 2798432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 2808432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * The following GLSurfaceView methods can only be called <em>after</em> 2818432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * setRenderer is called: 2828432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <ul> 2838432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #getRenderMode()} 2848432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #onPause()} 2858432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #onResume()} 2868432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #queueEvent(Runnable)} 2878432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #requestRender()} 2888432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <li>{@link #setRenderMode(int)} 2898432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * </ul> 2908432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * 2918432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * @param renderer the renderer to use to perform OpenGL drawing. 2928432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich */ 2938432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich public void setRenderer(Renderer renderer) { 2948432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich checkRenderThreadState(); 2958432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich if (mEGLConfigChooser == null) { 2968432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mEGLConfigChooser = new SimpleEGLConfigChooser(true); 2978432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 2988432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich if (mEGLContextFactory == null) { 2998432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mEGLContextFactory = new DefaultContextFactory(); 3008432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 3018432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich if (mEGLWindowSurfaceFactory == null) { 3028432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); 3038432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 3048432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mGLThread = new GLThread(renderer); 3058432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mGLThread.start(); 306b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 307b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 308b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 309b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a custom EGLContextFactory. 310b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 311b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 312b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is called. 313b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 314b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If this method is not called, then by default 315b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * a context will be created with no shared context and 316b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * with a null attribute list. 317b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 318b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public void setEGLContextFactory(EGLContextFactory factory) { 319b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich checkRenderThreadState(); 320b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mEGLContextFactory = factory; 321b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 322b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 323b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 324b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a custom EGLWindowSurfaceFactory. 325b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 326b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 327b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is called. 328b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 329b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If this method is not called, then by default 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a window surface will be created with a null attribute list. 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { 333a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich checkRenderThreadState(); 334a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLWindowSurfaceFactory = factory; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 33715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 33815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLConfigChooser. 33915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 34015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 34115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 3422ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * <p> 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If no setEGLConfigChooser method is called, then by default the 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view will choose an EGLConfig that is compatible with the current 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.view.Surface, with a depth buffer depth of 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at least 16 bits. 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param configChooser 34815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 34915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void setEGLConfigChooser(EGLConfigChooser configChooser) { 35015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 35115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLConfigChooser = configChooser; 35215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 35315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 35415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 35515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a config chooser which will choose a config 35615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * as close to 16-bit RGB as possible, with or without an optional depth 357a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich * buffer as close to 16-bits as possible. 35815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 35915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 36015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 36115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 36215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If no setEGLConfigChooser method is called, then by default the 36315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * view will choose an RGB_565 surface with a depth buffer depth of 36415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * at least 16 bits. 36515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * 36615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * @param needDepth 36715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 36815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void setEGLConfigChooser(boolean needDepth) { 36915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); 37015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 371a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich 37215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 37315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a config chooser which will choose a config 37415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * with at least the specified depthSize and stencilSize, 37515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * and exactly the specified redSize, greenSize, blueSize and alphaSize. 37615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 377b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 378b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is called. 379b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 380a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * If no setEGLConfigChooser method is called, then by default the 381a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * view will choose an RGB_565 surface with a depth buffer depth of 382b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * at least 16 bits. 38383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * 38483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich */ 38583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, 386a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 387a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, 388a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich blueSize, alphaSize, depthSize, stencilSize)); 38915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 390a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 391a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 392a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Inform the default EGLContextFactory and default EGLConfigChooser 393a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * which EGLContext client version to pick. 394b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>Use this method to create an OpenGL ES 2.0-compatible context. 395a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Example: 396a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <pre class="prettyprint"> 397b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public MyView(Context context) { 398b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * super(context); 399b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context. 400a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * setRenderer(new MyRenderer()); 40183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * } 40283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * </pre> 40383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p>Note: Activities which require OpenGL ES 2.0 should indicate this by 404a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's 405a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * AndroidManifest.xml file. 406a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p>If this method is called, it must be called before {@link #setRenderer(Renderer)} 407a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 408a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p>This method only affects the behavior of the default EGLContexFactory and the 409a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * default EGLConfigChooser. If 410a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied 411a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. 412b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If 41383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied 41483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. 415b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 416a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 417a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLContextClientVersion(int version) { 418a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich checkRenderThreadState(); 419b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mEGLContextClientVersion = version; 42083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich } 42183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich 422a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 423a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Set the rendering mode. When renderMode is 424a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * RENDERMODE_CONTINUOUSLY, the renderer is called 425a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * repeatedly to re-render the scene. When renderMode 426a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface 427a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. 428a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 4296ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance 4306ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * by allowing the GPU and CPU to idle when the view does not need to be updated. 4316ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p> 4326ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * This method can only be called after {@link #setRenderer(Renderer)} 4336ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * 4346ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @param renderMode one of the RENDERMODE_X constants 4356ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @see #RENDERMODE_CONTINUOUSLY 4366ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @see #RENDERMODE_WHEN_DIRTY 4376ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 4386ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public void setRenderMode(int renderMode) { 4396ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mGLThread.setRenderMode(renderMode); 4406ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 4416ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 4426ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 4436ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Get the current rendering mode. May be called 4446ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * from any thread. Must not be called before a renderer has been set. 4456ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @return the current rendering mode. 4466ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @see #RENDERMODE_CONTINUOUSLY 4476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @see #RENDERMODE_WHEN_DIRTY 4486ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 4496ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public int getRenderMode() { 4506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return mGLThread.getRenderMode(); 4516ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 4526ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 4536ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 4546ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Request that the renderer render a frame. 4556ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * This method is typically used when the render mode has been set to 4566ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. 4576ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * May be called 4586ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * from any thread. Must not be called before a renderer has been set. 4596ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 4606ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public void requestRender() { 461a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mGLThread.requestRender(); 462b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 4633e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich 464b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method is part of the SurfaceHolder.Callback interface, and is 4663e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 467b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 468b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public void surfaceCreated(SurfaceHolder holder) { 469b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mGLThread.surfaceCreated(); 470b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 471b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 472b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method is part of the SurfaceHolder.Callback interface, and is 4743e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 475b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) { 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Surface will be destroyed when we return 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceDestroyed(); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method is part of the SurfaceHolder.Callback interface, and is 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not normally called or subclassed by clients of GLSurfaceView. 484b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 4853e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 486b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mGLThread.onWindowResize(w, h); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is paused. The owner of this view must 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call this method when the activity is paused. Calling this method will 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pause the rendering thread. 493b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 495b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public void onPause() { 496b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich mGLThread.onPause(); 497b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is resumed. The owner of this view must 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call this method when the activity is resumed. Calling this method will 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * recreate the OpenGL display and resume the rendering 503b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * thread. 504b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 505b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 506b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public void onResume() { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onResume(); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 511b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Queue a runnable to be run on the GL rendering thread. This can be used 512b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to communicate with the Renderer on the rendering thread. 513b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 514b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param r the runnable to be run on the GL rendering thread. 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.queueEvent(r); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 520b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 521b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is used as part of the View class and is not normally 522b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called or subclassed by clients of GLSurfaceView. 523b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDetachedFromWindow() { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onDetachedFromWindow(); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.requestExitAndWait(); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 530b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 531b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich // ---------------------------------------------------------------------- 532b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An interface used to wrap a GL interface. 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Typically 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * used for implementing debugging and tracing on top of the default 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GL interface. You would typically use this by creating your own class 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that implemented all the GL methods by delegating to another GL instance. 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Then you could add your own behavior before or after calling the 540b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * delegate. All the GLWrapper would do was instantiate and return the 541b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * wrapper GL instance: 542b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 543b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLWrapper implements GLWrapper { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * GL wrap(GL gl) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return new MyGLImplementation(gl); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * static class MyGLImplementation implements GL,GL10,GL11,... { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ... 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 550b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 551b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 552b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setGLWrapper(GLWrapper) 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface GLWrapper { 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Wraps a gl interface in another gl interface. 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl a GL interface that is to be wrapped. 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return either the input argument or another GL object that wraps the input argument. 559b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 560b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich GL wrap(GL gl); 561b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 5622ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich 5632ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich /** 5642ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * A generic renderer interface. 5652ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * <p> 5662ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * The renderer is responsible for making OpenGL calls to render a frame. 5672ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * <p> 5682ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * GLSurfaceView clients typically create their own classes that implement 5692ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * this interface, and then call {@link GLSurfaceView#setRenderer} to 5701396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * register the renderer with the GLSurfaceView. 5711396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * <p> 5721396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * <h3>Threading</h3> 5731396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * The renderer will be called on a separate thread, so that rendering 5742ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * performance is decoupled from the UI thread. Clients typically need to 5751396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * communicate with the renderer from the UI thread, because that's where 5761396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * input events are received. Clients can communicate using any of the 5771396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich * standard Java techniques for cross-thread communication, or they can 5782ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. 5792ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * <p> 5802ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * <h3>EGL Context Lost</h3> 5812ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * There are situations where the EGL rendering context will be lost. This 5822ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * typically happens when device wakes up after going to sleep. When 5832ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * the EGL context is lost, all OpenGL resources (such as textures) that are 5842ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * associated with that context will be automatically deleted. In order to 5852ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * keep rendering correctly, a renderer must recreate any lost resources 586b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method 587b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is a convenient place to do this. 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5902ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * @see #setRenderer(Renderer) 5912ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich */ 5922ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich public interface Renderer { 5932ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich /** 5942ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * Called when the surface is created or recreated. 5952ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * <p> 5962ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * Called when the rendering thread 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starts and whenever the EGL context is lost. The EGL context will typically 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be lost when the Android device awakes after going to sleep. 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Since this method is called at the beginning of rendering, as well as 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * every time the EGL context is lost, this method is a convenient place to put 602b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * code to create resources that need to be created when the rendering 603b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * starts, and that need to be recreated when the EGL context is lost. 604b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Textures are an example of a resource that you might want to create 605b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * here. 606b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 607b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Note that when the EGL context is lost, all OpenGL resources associated 608b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * with that context will be automatically deleted. You do not need to call 609b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the corresponding "glDelete" methods such as glDeleteTextures to 610b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * manually delete these lost resources. 611b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 612b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param gl the GL interface. Use <code>instanceof</code> to 613b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * test if the interface supports GL11 or higher interfaces. 614b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param config the EGLConfig of the created surface. Can be used 615b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to create matching pbuffers. 616b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 617b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich void onSurfaceCreated(GL10 gl, EGLConfig config); 618b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 619b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 620b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface changed size. 621b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 622b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called after the surface is created and whenever 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the OpenGL ES surface size changes. 624b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 625b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you will set your viewport here. If your camera 626b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is fixed then you could also set your projection matrix here: 627b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 628b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onSurfaceChanged(GL10 gl, int width, int height) { 629b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glViewport(0, 0, width, height); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // for a fixed camera, set the projection too 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * float ratio = (float) width / height; 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gl.glMatrixMode(GL10.GL_PROJECTION); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gl.glLoadIdentity(); 634b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 635b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 636b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 637b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param gl the GL interface. Use <code>instanceof</code> to 638b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * test if the interface supports GL11 or higher interfaces. 639b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param width 640b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param height 641b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 642b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich void onSurfaceChanged(GL10 gl, int width, int height); 643b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 644b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 645b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called to draw the current frame. 646b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 647b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is responsible for drawing the current frame. 648b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 649b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The implementation of this method typically looks like this: 650b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 651b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onDrawFrame(GL10 gl) { 652b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 653b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * //... other gl calls to render the scene ... 654b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 655b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 656b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param gl the GL interface. Use <code>instanceof</code> to 657b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * test if the interface supports GL11 or higher interfaces. 658b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 659b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich void onDrawFrame(GL10 gl); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 663b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface for customizing the eglCreateContext and eglDestroyContext calls. 664b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 665b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This interface must be implemented by clients wishing to call 666840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)} 667b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 668b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public interface EGLContextFactory { 669b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); 670b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); 671b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 672b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 673b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich private class DefaultContextFactory implements EGLContextFactory { 674b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 675b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 676b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { 677b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, 678b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich EGL10.EGL_NONE }; 679b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 680b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEGLContextClientVersion != 0 ? attrib_list : null); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void destroyContext(EGL10 egl, EGLDisplay display, 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext context) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project egl.eglDestroyContext(display, context); 687b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 690b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. 692b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 693b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This interface must be implemented by clients wishing to call 694b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} 695b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 696b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public interface EGLWindowSurfaceFactory { 697b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, 698b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich Object nativeWindow); 699b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); 700b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 701b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 702b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { 703b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 704b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, 705b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich EGLConfig config, Object nativeWindow) { 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return egl.eglCreateWindowSurface(display, config, nativeWindow, null); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void destroySurface(EGL10 egl, EGLDisplay display, 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface surface) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project egl.eglDestroySurface(display, surface); 712b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 714b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 715b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 716b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface for choosing an EGLConfig configuration from a list of 717b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * potential configurations. 718b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 719b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This interface must be implemented by clients wishing to call 720b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} 721b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 722b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public interface EGLConfigChooser { 723b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 724b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Choose a configuration from the list. Implementors typically 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implement this method by calling 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param egl the EGL10 for the current display. 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param display the current display. 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the chosen configuration. 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 73215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); 73315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 73415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 73515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private abstract class BaseConfigChooser 73615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich implements EGLConfigChooser { 73715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public BaseConfigChooser(int[] configSpec) { 73815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mConfigSpec = filterConfigSpec(configSpec); 73915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 74015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 74115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 7426ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] num_config = new int[1]; 7436ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, 74415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich num_config)) { 74515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich throw new IllegalArgumentException("eglChooseConfig failed"); 7466ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 7476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 7486ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int numConfigs = num_config[0]; 7496ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 7506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich if (numConfigs <= 0) { 75115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich throw new IllegalArgumentException( 75215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich "No configs match configSpec"); 75315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 75415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 75507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich EGLConfig[] configs = new EGLConfig[numConfigs]; 75607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, 75707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich num_config)) { 75807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new IllegalArgumentException("eglChooseConfig#2 failed"); 75907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 76007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich EGLConfig config = chooseConfig(egl, display, configs); 76107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (config == null) { 76207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new IllegalArgumentException("No config chosen"); 76315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 76415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich return config; 76515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 76615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 76715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 76815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLConfig[] configs); 76915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 770d40dfbbbff81219258ca36b762a89ff503154345Jack Palevich protected int[] mConfigSpec; 77115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 77215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private int[] filterConfigSpec(int[] configSpec) { 77315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLContextClientVersion != 2) { 77415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich return configSpec; 77515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 77615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /* We know none of the subclasses define EGL_RENDERABLE_TYPE. 77715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * And we know the configSpec is well formed. 77815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 77915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich int len = configSpec.length; 78015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich int[] newConfigSpec = new int[len + 2]; 78115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); 78215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; 78315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ 78415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich newConfigSpec[len+1] = EGL10.EGL_NONE; 78515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich return newConfigSpec; 78615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 78715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 78815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 78915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 79015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Choose a configuration with exactly the specified r,g,b,a sizes, 79115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * and at least the specified depth and stencil sizes. 792b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 793a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private class ComponentSizeChooser extends BaseConfigChooser { 794b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich public ComponentSizeChooser(int redSize, int greenSize, int blueSize, 795b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich int alphaSize, int depthSize, int stencilSize) { 796b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich super(new int[] { 797a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_RED_SIZE, redSize, 798a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_GREEN_SIZE, greenSize, 799a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_BLUE_SIZE, blueSize, 800a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_ALPHA_SIZE, alphaSize, 801a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, depthSize, 802b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich EGL10.EGL_STENCIL_SIZE, stencilSize, 803b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich EGL10.EGL_NONE}); 804a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mValue = new int[1]; 805a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mRedSize = redSize; 806a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mGreenSize = greenSize; 807a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mBlueSize = blueSize; 808a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mAlphaSize = alphaSize; 809a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mDepthSize = depthSize; 810a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mStencilSize = stencilSize; 8116ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 812a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 813a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich @Override 8146ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 815a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs) { 8166ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich for (EGLConfig config : configs) { 817a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int d = findConfigAttrib(egl, display, config, 818a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, 0); 81928023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich int s = findConfigAttrib(egl, display, config, 82028023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich EGL10.EGL_STENCIL_SIZE, 0); 82128023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if ((d >= mDepthSize) && (s >= mStencilSize)) { 82228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich int r = findConfigAttrib(egl, display, config, 823a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_RED_SIZE, 0); 824a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int g = findConfigAttrib(egl, display, config, 825a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_GREEN_SIZE, 0); 826a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int b = findConfigAttrib(egl, display, config, 827a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_BLUE_SIZE, 0); 828a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int a = findConfigAttrib(egl, display, config, 829a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_ALPHA_SIZE, 0); 830a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if ((r == mRedSize) && (g == mGreenSize) 831a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich && (b == mBlueSize) && (a == mAlphaSize)) { 83228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich return config; 83328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 83428023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 83528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 836a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return null; 837a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 838a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 839a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int findConfigAttrib(EGL10 egl, EGLDisplay display, 840a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config, int attribute, int defaultValue) { 841a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 842a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 843a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return mValue[0]; 844a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 845a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return defaultValue; 846a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 8476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 8486ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int[] mValue; 8496ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich // Subclasses can adjust these values: 8506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich protected int mRedSize; 8516ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich protected int mGreenSize; 8526ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich protected int mBlueSize; 8536ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich protected int mAlphaSize; 8546ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich protected int mDepthSize; 8556ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich protected int mStencilSize; 8566ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 8576ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 8586ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 8596ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * This class will choose a RGB_565 surface with 8606ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * or without a depth buffer. 8616ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * 8626ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 863a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private class SimpleEGLConfigChooser extends ComponentSizeChooser { 864a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public SimpleEGLConfigChooser(boolean withDepthBuffer) { 86583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich super(5, 6, 5, 0, withDepthBuffer ? 16 : 0, 0); 86683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich } 86783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich } 86883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich 8696ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 870a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * An EGL helper class. 871a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 872a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 873a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private class EglHelper { 874a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EglHelper() { 875a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 876a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 877a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 878a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 879a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Initialize EGL for a given configuration spec. 880a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param configSpec 881a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 882a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void start() { 883a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /* 884a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Get an EGL instance 885a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 886a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEgl = (EGL10) EGLContext.getEGL(); 887a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 888a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /* 889a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Get to the default display. 890a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 891a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 89283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich 893a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 894a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new RuntimeException("eglGetDisplay failed"); 895a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 896a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 89783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich /* 89882fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian * We can now initialize EGL for that display 89982fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian */ 90082fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int[] version = new int[2]; 90182fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian if(!mEgl.eglInitialize(mEglDisplay, version)) { 90282fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian throw new RuntimeException("eglInitialize failed"); 90382fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian } 90482fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 90582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian 90683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich /* 90783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * Create an EGL context. We want to do this as rarely as we can, because an 90883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * EGL context is a somewhat heavy object. 90982fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian */ 910a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 911a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { 91283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich throwEglException("createContext"); 913a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 914a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 915a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEglSurface = null; 916a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 917a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 918a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /* 919a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * React to the creation of a new surface by creating and returning an 920a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * OpenGL interface that renders to that surface. 921a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 922a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public GL createSurface(SurfaceHolder holder) { 923a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /* 924a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * The window size has changed, so we need to create a new 925a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * surface. 926a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 927a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 928a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 929a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /* 930a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Unbind and destroy the old EGL surface, if 931a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * there is one. 932a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 933a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 934a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 93583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 93683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich } 937a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 938a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /* 9396ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Create an EGL surface we can render into. 940a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 94183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, 942a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEglDisplay, mEglConfig, holder); 943a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 944a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 945a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throwEglException("createWindowSurface"); 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before we can issue GL commands, we need to make sure 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the context is current and bound to a surface. 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throwEglException("eglMakeCurrent"); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL gl = mEglContext.getGL(); 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGLWrapper != null) { 958840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich gl = mGLWrapper.wrap(gl); 95907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 96007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich 96107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int configFlags = 0; 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Writer log = null; 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log = new LogWriter(); 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gl = GLDebugHelper.wrap(gl, configFlags, log); 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 97228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich return gl; 97328023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 97428023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich 97528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich /** 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Display the current render surface. 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return false if the context has been lost. 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean swap() { 98028023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 98128023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich 98228023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich /* 983a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Check for EGL_CONTEXT_LOST, which means the context 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and all associated data were lost (For instance because 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the device went to sleep). We need to sleep until we 986840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * get a new surface. 987840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich */ 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int error = mEgl.eglGetError(); 98915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (error == EGL11.EGL_CONTEXT_LOST) { 9902e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich return false; 99107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } else { 9929bb4dbae91df0971038e955ef49c5d9a64d4a428Jack Palevich throwEglException("eglSwapBuffers", error); 9932e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 99407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 99507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich return true; 99607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void destroySurface() { 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_SURFACE, 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_CONTEXT); 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 100607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 100707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich 100807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich public void finish() { 100907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglContext != null) { 101007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); 101107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEglContext = null; 101207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 101307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglDisplay != null) { 101407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEgl.eglTerminate(mEglDisplay); 101507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEglDisplay = null; 101607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 101707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 101807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich 101907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich private void throwEglException(String function) { 102007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throwEglException(function, mEgl.eglGetError()); 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void throwEglException(String function, int error) { 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException(function + " failed: " + error); 10252e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10 mEgl; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLDisplay mEglDisplay; 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface mEglSurface; 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLConfig mEglConfig; 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext mEglContext; 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 103315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic GL Thread. Takes care of initializing EGL and GL. Delegates 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to a Renderer instance to do the actual drawing. Can be configured to 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * render continuously or on request. 103915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * 104015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * All potentially blocking synchronization is done through the 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sGLThreadManager object. This avoids multiple-lock ordering issues. 10422e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich * 10430e4aa37872810e46775374596e0beb11f7123727Jack Palevich */ 10440e4aa37872810e46775374596e0beb11f7123727Jack Palevich class GLThread extends Thread { 10450e4aa37872810e46775374596e0beb11f7123727Jack Palevich GLThread(Renderer renderer) { 10460e4aa37872810e46775374596e0beb11f7123727Jack Palevich super(); 10470e4aa37872810e46775374596e0beb11f7123727Jack Palevich mWidth = 0; 10480e4aa37872810e46775374596e0beb11f7123727Jack Palevich mHeight = 0; 10492e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich mRequestRender = true; 10502e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich mRenderMode = RENDERMODE_CONTINUOUSLY; 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderer = renderer; 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10552e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich @Override 10565aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich public void run() { 10572e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich setName("GLThread " + getId()); 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOG_THREADS) { 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.i("GLThread", "starting tid=" + getId()); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guardedRun(); 1064a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } catch (InterruptedException e) { 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fall thru and exit normally 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sGLThreadManager.threadExiting(this); 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This private method should only be called inside a 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * synchronized(sGLThreadManager) block. 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void stopEglSurfaceLocked() { 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHaveEglSurface) { 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHaveEglSurface = false; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglHelper.destroySurface(); 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 108304b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich * This private method should only be called inside a 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * synchronized(sGLThreadManager) block. 108504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich */ 108604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich private void stopEglContextLocked() { 108704b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich if (mHaveEglContext) { 108804b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich mEglHelper.finish(); 108904b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich mHaveEglContext = false; 109004b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich sGLThreadManager.releaseEglContextLocked(this); 109104b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 10920e4aa37872810e46775374596e0beb11f7123727Jack Palevich } 10930e4aa37872810e46775374596e0beb11f7123727Jack Palevich private void guardedRun() throws InterruptedException { 109404b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich mEglHelper = new EglHelper(); 10950e4aa37872810e46775374596e0beb11f7123727Jack Palevich mHaveEglContext = false; 10960e4aa37872810e46775374596e0beb11f7123727Jack Palevich mHaveEglSurface = false; 10970e4aa37872810e46775374596e0beb11f7123727Jack Palevich try { 10980e4aa37872810e46775374596e0beb11f7123727Jack Palevich GL10 gl = null; 10990e4aa37872810e46775374596e0beb11f7123727Jack Palevich boolean createEglContext = false; 11000e4aa37872810e46775374596e0beb11f7123727Jack Palevich boolean createEglSurface = false; 11010e4aa37872810e46775374596e0beb11f7123727Jack Palevich boolean lostEglContext = false; 110204b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich boolean sizeChanged = false; 110304b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich boolean wantRenderNotification = false; 110404b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich boolean doRenderNotification = false; 110504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich int w = 0; 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int h = 0; 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Runnable event = null; 11081bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich 110907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich while (true) { 111007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich synchronized (sGLThreadManager) { 111107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich while (true) { 11122e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mShouldExit) { 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 111615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (! mEventQueue.isEmpty()) { 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = mEventQueue.remove(0); 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11191bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 11201bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich 11211bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich // Have we lost the EGL context? 112207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (lostEglContext) { 112307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich stopEglSurfaceLocked(); 112407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich stopEglContextLocked(); 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lostEglContext = false; 112615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Do we need to release the EGL surface? 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHaveEglSurface && mPaused) { 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOG_SURFACE) { 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopEglSurfaceLocked(); 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { 11355aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich stopEglContextLocked(); 113604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich if (LOG_SURFACE) { 113704b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); 113804b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 113904b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 114007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 114107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich 114207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich // Have we lost the surface view surface? 114307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if ((! mHasSurface) && (! mWaitingForSurface)) { 114407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_SURFACE) { 11455aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); 11465aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich } 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHaveEglSurface) { 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopEglSurfaceLocked(); 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWaitingForSurface = true; 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sGLThreadManager.notifyAll(); 1152840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Have we acquired the surface view surface? 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHasSurface && mWaitingForSurface) { 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOG_SURFACE) { 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWaitingForSurface = false; 116067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 116167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 116267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (doRenderNotification) { 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wantRenderNotification = false; 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project doRenderNotification = false; 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderComplete = true; 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sGLThreadManager.notifyAll(); 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11703e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich // Ready to draw? 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((!mPaused) && mHasSurface 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mWidth > 0) && (mHeight > 0) 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we don't have an EGL context, try to acquire one. 11768b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglContextLocked(this)) { 11778b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich mHaveEglContext = true; 11788b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich createEglContext = true; 11798b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich mEglHelper.start(); 11808b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sGLThreadManager.notifyAll(); 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHaveEglContext && !mHaveEglSurface) { 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHaveEglSurface = true; 118667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich createEglSurface = true; 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sizeChanged = true; 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mHaveEglSurface) { 119167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mSizeChanged) { 119267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sizeChanged = true; 119367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich w = mWidth; 1194840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich h = mHeight; 1195840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich wantRenderNotification = true; 1196840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 119732d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich if (DRAW_TWICE_AFTER_SIZE_CHANGED) { 119832d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich // We keep mRequestRender true so that we draw twice after the size changes. 119932d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich // (Once because of mSizeChanged, the second time because of mRequestRender.) 120032d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich // This forces the updated graphics onto the screen. 1201840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } else { 1202840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mRequestRender = false; 1203840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1204840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mSizeChanged = false; 1205840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } else { 1206840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mRequestRender = false; 1207840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1208840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich sGLThreadManager.notifyAll(); 1209840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich break; 1210840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1211840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // By design, this is the only place in a GLThread thread where we wait(). 1214840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (LOG_THREADS) { 1215840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich Log.i("GLThread", "waiting tid=" + getId()); 121615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 121715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich sGLThreadManager.wait(); 1218840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1219a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } // end of synchronized(sGLThreadManager) 1220840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1221a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (event != null) { 122221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich event.run(); 122321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich event = null; 12241b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich continue; 1225a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1226a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1227a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (createEglSurface) { 122867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (LOG_SURFACE) { 1229a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.w("GLThread", "egl createSurface"); 123067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 123167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich gl = (GL10) mEglHelper.createSurface(getHolder()); 1232a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.checkGLDriver(gl); 1233a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = false; 1234a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1235a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1236a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (createEglContext) { 1237a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_RENDERER) { 1238a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.w("GLThread", "onSurfaceCreated"); 1239a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1240a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); 1241451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich createEglContext = false; 1242451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1243451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 1244451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (sizeChanged) { 1245451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_RENDERER) { 1246451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); 1247451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1248451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRenderer.onSurfaceChanged(gl, w, h); 1249451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sizeChanged = false; 12501b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 12511b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 12521b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_RENDERER_DRAW_FRAME) { 12531b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.w("GLThread", "onDrawFrame"); 12541b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 12551b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mRenderer.onDrawFrame(gl); 12561b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (!mEglHelper.swap()) { 12571b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 12581b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "egl context lost tid=" + getId()); 12591b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 12601b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich lostEglContext = true; 1261840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1262840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1263840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (wantRenderNotification) { 1264840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich doRenderNotification = true; 1265840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1266840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1267840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1268a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } finally { 1269840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich /* 1270a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * clean-up everything... 1271a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich */ 1272a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized (sGLThreadManager) { 1273840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 12748432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich stopEglContextLocked(); 1275840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1276840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1277840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1278840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1279840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void setRenderMode(int renderMode) { 1280b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { 1281b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich throw new IllegalArgumentException("renderMode"); 1282b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1283b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich synchronized(sGLThreadManager) { 1284b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich mRenderMode = renderMode; 1285b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich sGLThreadManager.notifyAll(); 128667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1287a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1288a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1289a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich public int getRenderMode() { 1290a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 1291a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich return mRenderMode; 129215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1293840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1294840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 129532d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich public void requestRender() { 1296a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 1297a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = true; 129832d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich sGLThreadManager.notifyAll(); 129967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1300a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1301a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1302a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich public void surfaceCreated() { 1303a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 1304a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_THREADS) { 1305a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "surfaceCreated tid=" + getId()); 1306a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 130767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mHasSurface = true; 130867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 130921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 13101b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13111b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 13121b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public void surfaceDestroyed() { 131321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich synchronized(sGLThreadManager) { 131421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (LOG_THREADS) { 131521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich Log.i("GLThread", "surfaceDestroyed tid=" + getId()); 131621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 131721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mHasSurface = false; 131821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.notifyAll(); 1319a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while((!mWaitingForSurface) && (!mExited)) { 13201b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich try { 1321a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.wait(); 1322840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } catch (InterruptedException e) { 13231b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Thread.currentThread().interrupt(); 13241b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13251b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13261b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13271b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13281b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 13291b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public void onPause() { 13301b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich synchronized (sGLThreadManager) { 13311b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mPaused = true; 13321b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.notifyAll(); 13331b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13341b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 1335840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 13361b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public void onResume() { 13371b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich synchronized (sGLThreadManager) { 1338840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mPaused = false; 1339840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mRequestRender = true; 1340840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich sGLThreadManager.notifyAll(); 1341840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1342a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1343a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1344a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich public void onWindowResize(int w, int h) { 134567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1346840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mWidth = w; 1347a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mHeight = h; 1348a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mSizeChanged = true; 1349a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = true; 1350a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRenderComplete = false; 135121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.notifyAll(); 13521b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 13531b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // Wait for thread to react to resize and render a frame 13541b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich while (! mExited && !mPaused && !mRenderComplete ) { 135521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (LOG_SURFACE) { 1356a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("Main thread", "onWindowResize waiting for render complete."); 1357a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1358a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich try { 1359a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.wait(); 1360a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } catch (InterruptedException ex) { 1361a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Thread.currentThread().interrupt(); 1362a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1363a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1364a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1365a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1366a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 136767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich public void requestExitAndWait() { 1368a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // don't call this from GLThread thread or it is a guaranteed 136967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // deadlock! 137032d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich synchronized(sGLThreadManager) { 137167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mShouldExit = true; 1372a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 137332d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich while (! mExited) { 13741b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich try { 13751b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.wait(); 13761b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } catch (InterruptedException ex) { 13771b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Thread.currentThread().interrupt(); 13781b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13791b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13801b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13811b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13821b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 13831b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich /** 13841bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich * Queue an "event" to be run on the GL rendering thread. 138567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * @param r the runnable to be run on the GL rendering thread. 138615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 138767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich public void queueEvent(Runnable r) { 138867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (r == null) { 1389a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich throw new IllegalArgumentException("r must not be null"); 1390a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1391a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 139267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEventQueue.add(r); 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sGLThreadManager.notifyAll(); 139467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1395a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 13964a2221ec4a929976be570ad096252c8dea326e19Jack Palevich 13974a2221ec4a929976be570ad096252c8dea326e19Jack Palevich // Once the thread is started, all accesses to the following member 13984a2221ec4a929976be570ad096252c8dea326e19Jack Palevich // variables are protected by the sGLThreadManager monitor 139915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private boolean mShouldExit; 14000e4aa37872810e46775374596e0beb11f7123727Jack Palevich private boolean mExited; 14010e4aa37872810e46775374596e0beb11f7123727Jack Palevich private boolean mPaused; 14020e4aa37872810e46775374596e0beb11f7123727Jack Palevich private boolean mHasSurface; 14030e4aa37872810e46775374596e0beb11f7123727Jack Palevich private boolean mWaitingForSurface; 140479447b2087c8c820d742185dda7305101f9656f0Jack Palevich private boolean mHaveEglContext; 1405a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mHaveEglSurface; 140615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private int mWidth; 1407a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private int mHeight; 1408840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private int mRenderMode; 14094a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private boolean mRequestRender; 14104a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private boolean mRenderComplete; 14114a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); 1412840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1413840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // End of member variables protected by the sGLThreadManager monitor. 1414840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1415840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private Renderer mRenderer; 1416a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private EglHelper mEglHelper; 1417a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1418a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1419a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich static class LogWriter extends Writer { 142015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 1421a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich @Override public void close() { 142215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich flushBuilder(); 1423a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 14244a2221ec4a929976be570ad096252c8dea326e19Jack Palevich 14251b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich @Override public void flush() { 1426a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich flushBuilder(); 1427a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1428840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1429a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich @Override public void write(char[] buf, int offset, int count) { 1430840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich for(int i = 0; i < count; i++) { 1431a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich char c = buf[offset + i]; 1432840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if ( c == '\n') { 143315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich flushBuilder(); 143421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 143521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich else { 143621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mBuilder.append(c); 143721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 1438a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1439840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 144015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 144115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private void flushBuilder() { 144215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mBuilder.length() > 0) { 144315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich Log.v("GLSurfaceView", mBuilder.toString()); 144467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mBuilder.delete(0, mBuilder.length()); 1445840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1446840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 144767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 144815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private StringBuilder mBuilder = new StringBuilder(); 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14511b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 14521b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private void checkRenderThreadState() { 14531b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (mGLThread != null) { 14541b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich throw new IllegalStateException( 14551b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich "setRenderer has already been called for this instance."); 14561b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 14571b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 14581b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 14591b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private static class GLThreadManager { 14601b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private static String TAG = "GLThreadManager"; 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14623e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich public synchronized void threadExiting(GLThread thread) { 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOG_THREADS) { 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.i("GLThread", "exiting tid=" + thread.getId()); 146567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thread.mExited = true; 1467a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mEglOwner == thread) { 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglOwner = null; 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyAll(); 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 147267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Tries once to acquire the right to use an EGL 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * context. Does not block. Requires that we are already 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the sGLThreadManager monitor when this is called. 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 147867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * @return true if the right to use an EGL context was acquired. 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 148067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich public boolean tryAcquireEglContextLocked(GLThread thread) { 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglOwner == thread || mEglOwner == null) { 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglOwner = thread; 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyAll(); 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 148567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 14868b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich checkGLESVersion(); 14878b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (mMultipleGLESContextsAllowed) { 14888b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich return true; 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 149067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return false; 1491451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1492451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 1493451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich /* 1494451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich * Releases the EGL context. Requires that we are already in the 1495451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich * sGLThreadManager monitor when this is called. 1496451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich */ 1497451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich public void releaseEglContextLocked(GLThread thread) { 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglOwner == thread) { 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglOwner = null; 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notifyAll(); 150267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 15038b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich 15048b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich public synchronized boolean shouldReleaseEGLContextWhenPausing() { 15058b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich checkGLESVersion(); 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !mMultipleGLESContextsAllowed; 150767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1508a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 15091bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public synchronized void checkGLDriver(GL10 gl) { 151067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (! mGLESDriverCheckComplete) { 15111bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich checkGLESVersion(); 15121bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich if (mGLESVersion < kGLES_20) { 15131bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich String renderer = gl.glGetString(GL10.GL_RENDERER); 15141bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich mMultipleGLESContextsAllowed = 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOG_SURFACE) { 15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + mMultipleGLESContextsAllowed); 151967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1520e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich notifyAll(); 1521e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1522e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich mGLESDriverCheckComplete = true; 1523451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 152467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1525451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 1526451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private void checkGLESVersion() { 1527451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (! mGLESVersionCheckComplete) { 1528451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mGLESVersion = SystemProperties.getInt( 1529451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich "ro.opengles.version", 1530451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich ConfigurationInfo.GL_ES_VERSION_UNDEFINED); 1531451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (mGLESVersion >= kGLES_20) { 1532451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mMultipleGLESContextsAllowed = true; 1533451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1534451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_SURFACE) { 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "checkGLESVersion mGLESVersion =" + 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLESVersionCheckComplete = true; 153967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1540e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1541e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich 1542e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich private boolean mGLESVersionCheckComplete; 1543451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private int mGLESVersion; 15448b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich private boolean mGLESDriverCheckComplete; 1545451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private boolean mMultipleGLESContextsAllowed; 154667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich private static final int kGLES_20 = 0x20000; 1547451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private static final String kMSM7K_RENDERER_PREFIX = 1548451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich "Q3Dimension MSM7500 "; 1549451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private GLThread mEglOwner; 1550451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1551451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 1552451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private static final GLThreadManager sGLThreadManager = new GLThreadManager(); 1553451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private boolean mSizeChanged = true; 1554451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 1555451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private GLThread mGLThread; 1556451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private EGLConfigChooser mEGLConfigChooser; 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EGLContextFactory mEGLContextFactory; 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLWrapper mGLWrapper; 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDebugFlags; 156167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich private int mEGLContextClientVersion; 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project