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; 2080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevichimport java.lang.ref.WeakReference; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL10; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL11; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLConfig; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLContext; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLDisplay; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLSurface; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL10; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 33c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevichimport android.content.pm.ConfigurationInfo; 34c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevichimport android.os.SystemProperties; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceView; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An implementation of SurfaceView that uses the dedicated surface for 42b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * displaying OpenGL rendering. 43b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 44b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView provides the following features: 45b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 46b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 47b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages a surface, which is a special piece of memory that can be 48b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * composited into the Android view system. 49b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages an EGL display, which enables OpenGL to render into a surface. 50b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Accepts a user-provided Renderer object that does the actual rendering. 51b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Renders on a dedicated thread to decouple rendering performance from the 52b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * UI thread. 53b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Supports both on-demand and continuous rendering. 54b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls. 55b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 56b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 5761fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <div class="special reference"> 5861fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <h3>Developer Guides</h3> 5961fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <p>For more information about how to use OpenGL, read the 6061fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a> developer guide.</p> 6161fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * </div> 6261fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * 63b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Using GLSurfaceView</h3> 64b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 65b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you use GLSurfaceView by subclassing it and overriding one or more of the 66b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * View system input event methods. If your application does not need to override event 67b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * methods then GLSurfaceView can be used as-is. For the most part 68b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. 69b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * For example, unlike a regular View, drawing is delegated to a separate Renderer object which 70b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is registered with the GLSurfaceView 71b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * using the {@link #setRenderer(Renderer)} call. 72b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 73b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Initializing GLSurfaceView</h3> 74b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. 75b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or 76b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * more of these methods before calling setRenderer: 77b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 78b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setDebugFlags(int)} 79b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 80b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 81b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 82b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setGLWrapper(GLWrapper)} 83b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 84b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 8583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <h4>Specifying the android.view.Surface</h4> 8629e0bd2f5a80fdfe0e5b482a1df86363afcecbfaMathias Agopian * By default GLSurfaceView will create a PixelFormat.RGB_888 format surface. If a translucent 8783835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). 8883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The exact format of a TRANSLUCENT surface is device dependent, but it will be 8983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * a 32-bit-per-pixel surface with 8 bits per component. 9083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 91b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Choosing an EGL Configuration</h4> 9283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * A given Android device may support multiple EGLConfig rendering configurations. 9383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * The available configurations may differ in how may channels of data are present, as 94b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * well as how many bits are allocated to each channel. Therefore, the first thing 9583835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * GLSurfaceView has to do when starting to render is choose what EGLConfig to use. 9683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * <p> 9729e0bd2f5a80fdfe0e5b482a1df86363afcecbfaMathias Agopian * By default GLSurfaceView chooses a EGLConfig that has an RGB_888 pixel format, 9883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least a 16-bit depth buffer and no stencil. 99b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 10083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If you would prefer a different EGLConfig 10183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * you can override the default behavior by calling one of the 102b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setEGLConfigChooser methods. 103b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 104b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Debug Behavior</h4> 105b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * You can optionally modify the behavior of GLSurfaceView by calling 106b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one or more of the debugging methods {@link #setDebugFlags(int)}, 107b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but 108b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically they are called before setRenderer so that they take effect immediately. 109b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 110b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Setting a Renderer</h4> 111b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. 112b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is 113b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * responsible for doing the actual OpenGL rendering. 114b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 115b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Rendering Mode</h3> 116b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Once the renderer is set, you can control whether the renderer draws 117b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously or on-demand by calling 118b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #setRenderMode}. The default is continuous rendering. 119b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 120b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Activity Life-cycle</h3> 121b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients 122b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * are required to call {@link #onPause()} when the activity pauses and 123b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to 124b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate 125b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL display. 126b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 127b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Handling events</h3> 128b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 129b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * To handle an event you will typically subclass GLSurfaceView and override the 130b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * appropriate method, just as you would with any other View. However, when handling 131b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the event, you may need to communicate with the Renderer object 132b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that's running in the rendering thread. You can do this using any 133b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java cross-thread communication mechanism. In addition, 134b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one relatively easy way to communicate with your renderer is 135b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to call 136b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #queueEvent(Runnable)}. For example: 137b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 138b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLSurfaceView extends GLSurfaceView { 139b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 140b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * private MyRenderer mMyRenderer; 141b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 142b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void start() { 143b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer = ...; 144b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer(mMyRenderer); 145b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 146b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 147b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public boolean onKeyDown(int keyCode, KeyEvent event) { 148b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 149b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * queueEvent(new Runnable() { 150b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // This method will be called on the rendering 151b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // thread: 152b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * public void run() { 153b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * mMyRenderer.handleDpadCenter(); 154b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * }}); 155b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return true; 156b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 157b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return super.onKeyDown(keyCode, event); 158b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 159b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 160b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 1642ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private final static String TAG = "GLSurfaceView"; 1652ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private final static boolean LOG_ATTACH_DETACH = false; 16657c6a46bd0c84c4b349d49f8df12f30a8cfcdaa2Jack Palevich private final static boolean LOG_THREADS = false; 1674a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_PAUSE_RESUME = false; 1684a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_SURFACE = false; 1694a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_RENDERER = false; 1704a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private final static boolean LOG_RENDERER_DRAW_FRAME = false; 1714a65900cd69b79e6e47d275575eaeb5bb2487f9fJack Palevich private final static boolean LOG_EGL = false; 172b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 173b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer only renders 174b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * when the surface is created, or when {@link #requestRender} is called. 175b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 176b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 177b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 178840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * @see #requestRender() 179b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int RENDERMODE_WHEN_DIRTY = 0; 181b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 182b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is called 183b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously to re-render the scene. 184b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 185b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getRenderMode() 186b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderMode(int) 187b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 1883e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich public final static int RENDERMODE_CONTINUOUSLY = 1; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 191b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Check glError() after every GL call and throw an exception if glError indicates 192b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that an error has occurred. This can be used to help track down which OpenGL ES call 193b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is causing an error. 194b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 195b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getDebugFlags 196b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setDebugFlags 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int DEBUG_CHECK_GL_ERROR = 1; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". 202b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 203b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #getDebugFlags 204b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setDebugFlags 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static int DEBUG_LOG_GL_CALLS = 2; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 208b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 209b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Standard View constructor. In order to render something, you 210b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * must call {@link #setRenderer} to register a renderer. 211b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GLSurfaceView(Context context) { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 217b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 218b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Standard View constructor. In order to render something, you 219b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * must call {@link #setRenderer} to register a renderer. 220b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GLSurfaceView(Context context, AttributeSet attrs) { 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich @Override 22780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich protected void finalize() throws Throwable { 22880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich try { 22980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (mGLThread != null) { 23080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich // GLThread may still be running if this view was never 23180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich // attached to a window. 23280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mGLThread.requestExitAndWait(); 23380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 23480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } finally { 23580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich super.finalize(); 23680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 23780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 23880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init() { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Install a SurfaceHolder.Callback so we get notified when the 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // underlying surface is created and destroyed 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SurfaceHolder holder = getHolder(); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project holder.addCallback(this); 2441b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // setFormat is done by SurfaceView in SDK 2.3 and newer. Uncomment 2451b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // this statement if back-porting to 2.2 or older: 2461b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // holder.setFormat(PixelFormat.RGB_565); 2471b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // 248840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // setType is not needed for SDK 2.0 or newer. Uncomment this 249840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // statement if back-porting this code to older SDKs. 250840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 254b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the glWrapper. If the glWrapper is not null, its 255b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLWrapper#wrap(GL)} method is called 256b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * whenever a surface is created. A GLWrapper can be used to wrap 257b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the GL object that's passed to the renderer. Wrapping a GL 258b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * object enables examining and modifying the behavior of the 259b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL calls made by the renderer. 260b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 261b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wrapping is typically used for debugging purposes. 262b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 263b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The default value is null. 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param glWrapper the new GLWrapper 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGLWrapper(GLWrapper glWrapper) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLWrapper = glWrapper; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 271b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the debug flags to a new value. The value is 272b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * constructed by OR-together zero or more 273b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * of the DEBUG_CHECK_* constants. The debug flags take effect 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whenever a surface is created. The default value is zero. 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param debugFlags the new debug flags 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_CHECK_GL_ERROR 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #DEBUG_LOG_GL_CALLS 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDebugFlags(int debugFlags) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDebugFlags = debugFlags; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 283b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 284b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Get the current value of the debug flags. 285b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return the current value of the debug flags. 286b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getDebugFlags() { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDebugFlags; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2928432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * Control whether the EGL context is preserved when the GLSurfaceView is paused and 2938432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * resumed. 2948432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 2958432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * If set to true, then the EGL context may be preserved when the GLSurfaceView is paused. 2968432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * Whether the EGL context is actually preserved or not depends upon whether the 2978432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * Android device that the program is running on can support an arbitrary number of EGL 2988432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * contexts or not. Devices that can only support a limited number of EGL contexts must 2998432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * release the EGL context in order to allow multiple applications to share the GPU. 3008432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 3018432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * If set to false, the EGL context will be released when the GLSurfaceView is paused, 3028432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * and recreated when the GLSurfaceView is resumed. 3038432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * <p> 3048432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * 3058432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * The default is false. 3068432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * 3078432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * @param preserveOnPause preserve the EGL context when paused 3088432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich */ 3098432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich public void setPreserveEGLContextOnPause(boolean preserveOnPause) { 3108432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich mPreserveEGLContextOnPause = preserveOnPause; 3118432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 3128432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich 3138432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich /** 3148432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich * @return true if the EGL context will be preserved when paused 3158432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich */ 3168432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich public boolean getPreserveEGLContextOnPause() { 3178432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich return mPreserveEGLContextOnPause; 3188432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 3198432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich 3208432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich /** 321b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the renderer associated with this view. Also starts the thread that 322b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * will call the renderer, which in turn causes the rendering to start. 323b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>This method should be called once and only once in the life-cycle of 324b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * a GLSurfaceView. 325b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>The following GLSurfaceView methods can only be called <em>before</em> 326b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer is called: 327b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 328b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)} 329b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)} 330b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)} 331b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 332b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 333b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The following GLSurfaceView methods can only be called <em>after</em> 334b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setRenderer is called: 335b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul> 336b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #getRenderMode()} 337b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #onPause()} 338b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #onResume()} 339b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #queueEvent(Runnable)} 340b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #requestRender()} 341b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setRenderMode(int)} 342b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul> 343b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 344b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param renderer the renderer to use to perform OpenGL drawing. 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderer(Renderer renderer) { 34715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 348a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (mEGLConfigChooser == null) { 349a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLConfigChooser = new SimpleEGLConfigChooser(true); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLContextFactory == null) { 35215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory = new DefaultContextFactory(); 35315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 35415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mEGLWindowSurfaceFactory == null) { 35515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); 35615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 3572ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mRenderer = renderer; 35880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mGLThread = new GLThread(mThisWeakRef); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.start(); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 36315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLContextFactory. 36415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 36515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 36615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 36715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 36815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If this method is not called, then by default 36915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * a context will be created with no shared context and 37015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * with a null attribute list. 37115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 372a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich public void setEGLContextFactory(EGLContextFactory factory) { 37315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 37415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLContextFactory = factory; 37515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 37615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 37715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 37815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * Install a custom EGLWindowSurfaceFactory. 37915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p>If this method is 38015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 38115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * is called. 38215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 38315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * If this method is not called, then by default 38415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * a window surface will be created with a null attribute list. 38515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 386a8fecb87c5eaaefc9ca6272e3b59ef88d293dd6dJack Palevich public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { 38715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 38815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich mEGLWindowSurfaceFactory = factory; 38915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 39015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 39115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 392b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a custom EGLConfigChooser. 393b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 394b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 395a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 396a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 397b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If no setEGLConfigChooser method is called, then by default the 39883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * view will choose an EGLConfig that is compatible with the current 39983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * android.view.Surface, with a depth buffer depth of 40083835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 401a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param configChooser 402a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 403a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(EGLConfigChooser configChooser) { 40415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich checkRenderThreadState(); 405a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mEGLConfigChooser = configChooser; 406a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 407a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 408a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 409b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a config chooser which will choose a config 410a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * as close to 16-bit RGB as possible, with or without an optional depth 411a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * buffer as close to 16-bits as possible. 412b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 413b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 414b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is called. 415a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 41683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * If no setEGLConfigChooser method is called, then by default the 41729e0bd2f5a80fdfe0e5b482a1df86363afcecbfaMathias Agopian * view will choose an RGB_888 surface with a depth buffer depth of 41883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 419a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 420a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param needDepth 421a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 422a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(boolean needDepth) { 423a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); 424a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 425a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 426a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 427b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Install a config chooser which will choose a config 42883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * with at least the specified depthSize and stencilSize, 42983835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * and exactly the specified redSize, greenSize, blueSize and alphaSize. 430b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>If this method is 431a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * called, it must be called before {@link #setRenderer(Renderer)} 432a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * is called. 433a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * <p> 434b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * If no setEGLConfigChooser method is called, then by default the 43529e0bd2f5a80fdfe0e5b482a1df86363afcecbfaMathias Agopian * view will choose an RGB_888 surface with a depth buffer depth of 43683835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * at least 16 bits. 437a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 438a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 439a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, 440a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 441a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, 442a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich blueSize, alphaSize, depthSize, stencilSize)); 443a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 4446ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 4456ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /** 4466ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Inform the default EGLContextFactory and default EGLConfigChooser 4476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * which EGLContext client version to pick. 4486ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>Use this method to create an OpenGL ES 2.0-compatible context. 4496ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * Example: 4506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <pre class="prettyprint"> 4516ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * public MyView(Context context) { 4526ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * super(context); 4536ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context. 4546ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setRenderer(new MyRenderer()); 4556ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * } 4566ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * </pre> 4576ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>Note: Activities which require OpenGL ES 2.0 should indicate this by 4586ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's 4596ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * AndroidManifest.xml file. 4606ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>If this method is called, it must be called before {@link #setRenderer(Renderer)} 4616ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * is called. 4626ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * <p>This method only affects the behavior of the default EGLContexFactory and the 4636ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * default EGLConfigChooser. If 4646ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied 4656ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. 4666ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * If 4676ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied 4686ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. 4696ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 4706ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 4716ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich public void setEGLContextClientVersion(int version) { 4726ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich checkRenderThreadState(); 4736ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mEGLContextClientVersion = version; 4746ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 4756ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 476a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 477b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Set the rendering mode. When renderMode is 4783e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * RENDERMODE_CONTINUOUSLY, the renderer is called 479b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * repeatedly to re-render the scene. When renderMode 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface 4813e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. 482b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 483b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance 484b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * by allowing the GPU and CPU to idle when the view does not need to be updated. 485b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 486b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method can only be called after {@link #setRenderer(Renderer)} 487b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param renderMode one of the RENDERMODE_X constants 4893e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * @see #RENDERMODE_CONTINUOUSLY 490b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #RENDERMODE_WHEN_DIRTY 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderMode(int renderMode) { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.setRenderMode(renderMode); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the current rendering mode. May be called 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from any thread. Must not be called before a renderer has been set. 499b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return the current rendering mode. 5003e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich * @see #RENDERMODE_CONTINUOUSLY 501b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #RENDERMODE_WHEN_DIRTY 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRenderMode() { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGLThread.getRenderMode(); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 508b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Request that the renderer render a frame. 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method is typically used when the render mode has been set to 510b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. 511b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * May be called 512b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * from any thread. Must not be called before a renderer has been set. 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestRender() { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.requestRender(); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 518b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 519b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 520b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 521b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated(SurfaceHolder holder) { 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceCreated(); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 526b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 527b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 528b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 529b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Surface will be destroyed when we return 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.surfaceDestroyed(); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 535b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 536b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is part of the SurfaceHolder.Callback interface, and is 537b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * not normally called or subclassed by clients of GLSurfaceView. 538b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onWindowResize(w, h); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is paused. The owner of this view must 545b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * call this method when the activity is paused. Calling this method will 546b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause the rendering thread. 547b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPause() { 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onPause(); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Inform the view that the activity is resumed. The owner of this view must 555b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * call this method when the activity is resumed. Calling this method will 556b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * recreate the OpenGL display and resume the rendering 557b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * thread. 558b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onResume() { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.onResume(); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 565b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Queue a runnable to be run on the GL rendering thread. This can be used 566b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to communicate with the Renderer on the rendering thread. 567b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param r the runnable to be run on the GL rendering thread. 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGLThread.queueEvent(r); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 574b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 575b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is used as part of the View class and is not normally 576b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * called or subclassed by clients of GLSurfaceView. 5772ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich */ 5782ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich @Override 5792ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich protected void onAttachedToWindow() { 5802ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich super.onAttachedToWindow(); 5812ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (LOG_ATTACH_DETACH) { 5822ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich Log.d(TAG, "onAttachedToWindow reattach =" + mDetached); 5832ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5842ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (mDetached && (mRenderer != null)) { 5851396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich int renderMode = RENDERMODE_CONTINUOUSLY; 5861396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich if (mGLThread != null) { 5871396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich renderMode = mGLThread.getRenderMode(); 5881396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich } 58980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mGLThread = new GLThread(mThisWeakRef); 5901396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich if (renderMode != RENDERMODE_CONTINUOUSLY) { 5911396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich mGLThread.setRenderMode(renderMode); 5921396afb73047c402db5af98e8f6b442ecbfa98d4Jack Palevich } 5932ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mGLThread.start(); 5942ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5952ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mDetached = false; 5962ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 5972ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich 5982ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich /** 5992ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * This method is used as part of the View class and is not normally 6002ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich * called or subclassed by clients of GLSurfaceView. 601b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Must not be called before a renderer has been set. 602b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDetachedFromWindow() { 6052ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (LOG_ATTACH_DETACH) { 6062ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich Log.d(TAG, "onDetachedFromWindow"); 6072ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 6082ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich if (mGLThread != null) { 6092ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mGLThread.requestExitAndWait(); 6102ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich } 6112ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich mDetached = true; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onDetachedFromWindow(); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ---------------------------------------------------------------------- 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 617b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 618b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface used to wrap a GL interface. 619b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>Typically 620b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * used for implementing debugging and tracing on top of the default 621b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL interface. You would typically use this by creating your own class 622b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that implemented all the GL methods by delegating to another GL instance. 623b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Then you could add your own behavior before or after calling the 624b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * delegate. All the GLWrapper would do was instantiate and return the 625b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * wrapper GL instance: 626b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 627b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLWrapper implements GLWrapper { 628b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GL wrap(GL gl) { 629b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * return new MyGLImplementation(gl); 630b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 631b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * static class MyGLImplementation implements GL,GL10,GL11,... { 632b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * ... 633b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 634b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 635b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 636b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setGLWrapper(GLWrapper) 637b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface GLWrapper { 639b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich /** 640b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Wraps a gl interface in another gl interface. 641b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @param gl a GL interface that is to be wrapped. 642b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @return either the input argument or another GL object that wraps the input argument. 643b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich */ 644b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich GL wrap(GL gl); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic renderer interface. 649b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 650b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is responsible for making OpenGL calls to render a frame. 651b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 652b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView clients typically create their own classes that implement 653b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * this interface, and then call {@link GLSurfaceView#setRenderer} to 654b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * register the renderer with the GLSurfaceView. 655b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 65661fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * 65761fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <div class="special reference"> 65861fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <h3>Developer Guides</h3> 65961fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <p>For more information about how to use OpenGL, read the 66061fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a> developer guide.</p> 66161fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * </div> 66261fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * 663b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Threading</h3> 664b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer will be called on a separate thread, so that rendering 665b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * performance is decoupled from the UI thread. Clients typically need to 666b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * communicate with the renderer from the UI thread, because that's where 667b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * input events are received. Clients can communicate using any of the 668b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java techniques for cross-thread communication, or they can 669b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. 670b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 671b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>EGL Context Lost</h3> 672b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * There are situations where the EGL rendering context will be lost. This 673b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically happens when device wakes up after going to sleep. When 674b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the EGL context is lost, all OpenGL resources (such as textures) that are 675b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * associated with that context will be automatically deleted. In order to 676b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * keep rendering correctly, a renderer must recreate any lost resources 677b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method 678b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is a convenient place to do this. 679b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 680b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * 681b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * @see #setRenderer(Renderer) 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface Renderer { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 685b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface is created or recreated. 686b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 687b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the rendering thread 688840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * starts and whenever the EGL context is lost. The EGL context will typically 689b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * be lost when the Android device awakes after going to sleep. 690b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 691b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Since this method is called at the beginning of rendering, as well as 692b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * every time the EGL context is lost, this method is a convenient place to put 693b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * code to create resources that need to be created when the rendering 694b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * starts, and that need to be recreated when the EGL context is lost. 695b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Textures are an example of a resource that you might want to create 696b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * here. 697b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 698b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Note that when the EGL context is lost, all OpenGL resources associated 699b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * with that context will be automatically deleted. You do not need to call 700b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the corresponding "glDelete" methods such as glDeleteTextures to 701b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * manually delete these lost resources. 702b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param config the EGLConfig of the created surface. Can be used 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to create matching pbuffers. 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSurfaceCreated(GL10 gl, EGLConfig config); 709b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 711b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called when the surface changed size. 712b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called after the surface is created and whenever 714b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL ES surface size changes. 715b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 716b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you will set your viewport here. If your camera 717b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is fixed then you could also set your projection matrix here: 718b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 719b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onSurfaceChanged(GL10 gl, int width, int height) { 720b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glViewport(0, 0, width, height); 721b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * // for a fixed camera, set the projection too 722b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * float ratio = (float) width / height; 723b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glMatrixMode(GL10.GL_PROJECTION); 724b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glLoadIdentity(); 725b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 726b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 727b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param width 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param height 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSurfaceChanged(GL10 gl, int width, int height); 734b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 736b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Called to draw the current frame. 737b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 738b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This method is responsible for drawing the current frame. 739b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 740b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The implementation of this method typically looks like this: 741b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint"> 742b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * void onDrawFrame(GL10 gl) { 743b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 744b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * //... other gl calls to render the scene ... 745b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * } 746b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre> 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gl the GL interface. Use <code>instanceof</code> to 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test if the interface supports GL11 or higher interfaces. 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onDrawFrame(GL10 gl); 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 75415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * An interface for customizing the eglCreateContext and eglDestroyContext calls. 75515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 75615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * This interface must be implemented by clients wishing to call 75715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)} 75815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 75915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public interface EGLContextFactory { 76015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); 76115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); 76215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 76315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 7646ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class DefaultContextFactory implements EGLContextFactory { 7656ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 76615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 76715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { 7686ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, 7696ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich EGL10.EGL_NONE }; 7706ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 7716ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, 7726ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mEGLContextClientVersion != 0 ? attrib_list : null); 77315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 77415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 77515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void destroyContext(EGL10 egl, EGLDisplay display, 77615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLContext context) { 77707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (!egl.eglDestroyContext(display, context)) { 77807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.e("DefaultContextFactory", "display:" + display + " context: " + context); 77907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_THREADS) { 78007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId()); 78107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 7827d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich EglHelper.throwEglException("eglDestroyContex", egl.eglGetError()); 78307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 78415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 78515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 78615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 78715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 78815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. 78915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * <p> 79015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * This interface must be implemented by clients wishing to call 791d40dfbbbff81219258ca36b762a89ff503154345Jack Palevich * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} 79215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 79315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public interface EGLWindowSurfaceFactory { 794a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich /** 795a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich * @return null if the surface cannot be constructed. 796a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich */ 79715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, 79815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich Object nativeWindow); 79915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); 80015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 80115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 80215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { 80315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 80415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, 80515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLConfig config, Object nativeWindow) { 806a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich EGLSurface result = null; 807a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich try { 808a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich result = egl.eglCreateWindowSurface(display, config, nativeWindow, null); 809a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich } catch (IllegalArgumentException e) { 810a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich // This exception indicates that the surface flinger surface 811a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich // is not valid. This can happen if the surface flinger surface has 812a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich // been torn down, but the application has not yet been 813a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich // notified via SurfaceHolder.Callback.surfaceDestroyed. 814a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich // In theory the application should be notified first, 815a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich // but in practice sometimes it is not. See b/4588890 816a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich Log.e(TAG, "eglCreateWindowSurface", e); 817a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich } 818a35c120d8fafa7dded606a25bc100b13f48ab9e3Jack Palevich return result; 81915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 82015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 82115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich public void destroySurface(EGL10 egl, EGLDisplay display, 82215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich EGLSurface surface) { 82315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich egl.eglDestroySurface(display, surface); 82415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 82515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 82615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 82715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /** 828b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * An interface for choosing an EGLConfig configuration from a list of 829a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * potential configurations. 830b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p> 831b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * This interface must be implemented by clients wishing to call 832b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} 833a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 834a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public interface EGLConfigChooser { 835a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 836a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * Choose a configuration from the list. Implementors typically 837a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * implement this method by calling 838b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the 839b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. 840a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param egl the EGL10 for the current display. 841a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @param display the current display. 842a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * @return the chosen configuration. 843a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 844a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); 845a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 846a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 8476ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private abstract class BaseConfigChooser 848a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich implements EGLConfigChooser { 849a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public BaseConfigChooser(int[] configSpec) { 8506ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich mConfigSpec = filterConfigSpec(configSpec); 851a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 8526ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 853a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 854a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int[] num_config = new int[1]; 85528023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, 85628023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich num_config)) { 85728023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new IllegalArgumentException("eglChooseConfig failed"); 85828023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 859a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 860a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int numConfigs = num_config[0]; 861a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 862a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (numConfigs <= 0) { 863a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new IllegalArgumentException( 864a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich "No configs match configSpec"); 865a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 866a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 867a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs = new EGLConfig[numConfigs]; 86828023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, 86928023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich num_config)) { 87028023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new IllegalArgumentException("eglChooseConfig#2 failed"); 87128023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 872a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config = chooseConfig(egl, display, configs); 873a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (config == null) { 874a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich throw new IllegalArgumentException("No config chosen"); 875a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 876a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return config; 877a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 878a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 879a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 880a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs); 881a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 882a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int[] mConfigSpec; 8836ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich 8846ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int[] filterConfigSpec(int[] configSpec) { 8856ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich if (mEGLContextClientVersion != 2) { 8866ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return configSpec; 8876ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 8886ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich /* We know none of the subclasses define EGL_RENDERABLE_TYPE. 8896ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich * And we know the configSpec is well formed. 8906ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich */ 8916ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int len = configSpec.length; 8926ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich int[] newConfigSpec = new int[len + 2]; 8936ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); 8946ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; 8956ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ 8966ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich newConfigSpec[len+1] = EGL10.EGL_NONE; 8976ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich return newConfigSpec; 8986ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich } 899a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 900a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 90183835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich /** 90283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * Choose a configuration with exactly the specified r,g,b,a sizes, 90383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * and at least the specified depth and stencil sizes. 90483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich */ 9056ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class ComponentSizeChooser extends BaseConfigChooser { 906a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public ComponentSizeChooser(int redSize, int greenSize, int blueSize, 907a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int alphaSize, int depthSize, int stencilSize) { 908a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich super(new int[] { 909a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_RED_SIZE, redSize, 910a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_GREEN_SIZE, greenSize, 911a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_BLUE_SIZE, blueSize, 912a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_ALPHA_SIZE, alphaSize, 913a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, depthSize, 914a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_STENCIL_SIZE, stencilSize, 915a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_NONE}); 916a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mValue = new int[1]; 917a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mRedSize = redSize; 918a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mGreenSize = greenSize; 919a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mBlueSize = blueSize; 920a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mAlphaSize = alphaSize; 921a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mDepthSize = depthSize; 922a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich mStencilSize = stencilSize; 923a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 924a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 925a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich @Override 926a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 927a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig[] configs) { 92883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich for (EGLConfig config : configs) { 929a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int d = findConfigAttrib(egl, display, config, 930a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_DEPTH_SIZE, 0); 931a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich int s = findConfigAttrib(egl, display, config, 932a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGL10.EGL_STENCIL_SIZE, 0); 93383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich if ((d >= mDepthSize) && (s >= mStencilSize)) { 93482fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int r = findConfigAttrib(egl, display, config, 93582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_RED_SIZE, 0); 93682fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int g = findConfigAttrib(egl, display, config, 93782fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_GREEN_SIZE, 0); 93882fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int b = findConfigAttrib(egl, display, config, 93982fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_BLUE_SIZE, 0); 94082fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian int a = findConfigAttrib(egl, display, config, 94182fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian EGL10.EGL_ALPHA_SIZE, 0); 94283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich if ((r == mRedSize) && (g == mGreenSize) 94383835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich && (b == mBlueSize) && (a == mAlphaSize)) { 94483835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich return config; 94582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian } 946a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 947a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 94883835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich return null; 949a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 950a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 951a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int findConfigAttrib(EGL10 egl, EGLDisplay display, 952a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich EGLConfig config, int attribute, int defaultValue) { 953a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 954a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 955a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return mValue[0]; 956a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 957a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich return defaultValue; 958a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 959a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 960a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private int[] mValue; 961a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich // Subclasses can adjust these values: 962a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mRedSize; 963a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mGreenSize; 964a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mBlueSize; 965a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mAlphaSize; 966a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mDepthSize; 967a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich protected int mStencilSize; 968a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 969a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 970a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 97129e0bd2f5a80fdfe0e5b482a1df86363afcecbfaMathias Agopian * This class will choose a RGB_888 surface with 97283835359e51ddb8be37cea9bf4bb32f9390d82b7Jack Palevich * or without a depth buffer. 973a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich * 974a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich */ 9756ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private class SimpleEGLConfigChooser extends ComponentSizeChooser { 976a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich public SimpleEGLConfigChooser(boolean withDepthBuffer) { 97729e0bd2f5a80fdfe0e5b482a1df86363afcecbfaMathias Agopian super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0); 978a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 979a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich } 980a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich 981a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich /** 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An EGL helper class. 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 98580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich private static class EglHelper { 98680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich public EglHelper(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) { 98780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mGLSurfaceViewWeakRef = glSurfaceViewWeakRef; 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Initialize EGL for a given configuration spec. 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param configSpec 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 994840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void start() { 99507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 99607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId()); 99707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get an EGL instance 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl = (EGL10) EGLContext.getEGL(); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get to the default display. 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 100828023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 100928023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new RuntimeException("eglGetDisplay failed"); 101028023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 101128023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can now initialize EGL for that display 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] version = new int[2]; 101628023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich if(!mEgl.eglInitialize(mEglDisplay, version)) { 101728023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich throw new RuntimeException("eglInitialize failed"); 101828023911a4b572f0ca640e7a3e3f9a0dd6f535e9Jack Palevich } 101980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 102080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view == null) { 102180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglConfig = null; 102280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglContext = null; 102380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } else { 102480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 102680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich /* 102780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich * Create an EGL context. We want to do this as rarely as we can, because an 102880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich * EGL context is a somewhat heavy object. 102980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich */ 103080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); 103180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 10322e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { 103307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich mEglContext = null; 10349bb4dbae91df0971038e955ef49c5d9a64d4a428Jack Palevich throwEglException("createContext"); 10352e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 103607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 103707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); 103807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1043b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich /** 1044b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich * Create an egl surface for the current SurfaceHolder surface. If a surface 1045b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich * already exists, destroy it before creating the new surface. 1046b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich * 1047b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich * @return true if the surface was created successfully. 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 104980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich public boolean createSurface() { 105007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 105107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); 105207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 105307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich /* 105407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich * Check preconditions. 105507353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich */ 105607353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEgl == null) { 105707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("egl not initialized"); 105807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 105907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglDisplay == null) { 106007353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("eglDisplay not initialized"); 106107353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 106207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (mEglConfig == null) { 106307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException("mEglConfig not initialized"); 106407353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 106580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The window size has changed, so we need to create a new 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * surface. 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 107080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich destroySurfaceImp(); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create an EGL surface we can render into. 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 107580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 107680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 107780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, 107880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglDisplay, mEglConfig, view.getHolder()); 107980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } else { 108080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglSurface = null; 108180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10832e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 10840e4aa37872810e46775374596e0beb11f7123727Jack Palevich int error = mEgl.eglGetError(); 10850e4aa37872810e46775374596e0beb11f7123727Jack Palevich if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 10860e4aa37872810e46775374596e0beb11f7123727Jack Palevich Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 10870e4aa37872810e46775374596e0beb11f7123727Jack Palevich } 1088b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich return false; 10892e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 10902e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before we can issue GL commands, we need to make sure 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the context is current and bound to a surface. 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10952e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 10967d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich /* 10977d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich * Could not make the context current, probably because the underlying 10987d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich * SurfaceView surface has been destroyed. 10997d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich */ 11007d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError()); 11017d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich return false; 11022e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich } 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1104b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich return true; 1105b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich } 1106b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich 1107b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich /** 1108b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich * Create a GL object for the current EGL context. 1109b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich * @return 1110b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich */ 1111b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich GL createGL() { 1112b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL gl = mEglContext.getGL(); 111480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 111580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 111680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view.mGLWrapper != null) { 111780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich gl = view.mGLWrapper.wrap(gl); 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 111980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich 112080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if ((view.mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { 112180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich int configFlags = 0; 112280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich Writer log = null; 112380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if ((view.mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { 112480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; 112580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 112680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if ((view.mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { 112780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich log = new LogWriter(); 112880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 112980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich gl = GLDebugHelper.wrap(gl, configFlags, log); 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return gl; 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Display the current render surface. 1137db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich * @return the EGL error code from eglSwapBuffers. 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1139db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich public int swap() { 114004b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 11417d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich return mEgl.eglGetError(); 114204b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 1143db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich return EGL10.EGL_SUCCESS; 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11461bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public void destroySurface() { 114707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 114807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId()); 114907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 115080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich destroySurfaceImp(); 115180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 115280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich 115380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich private void destroySurfaceImp() { 11542e26fc08aa1939c19e939d983bd608cdec050024Jack Palevich if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_SURFACE, 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10.EGL_NO_CONTEXT); 115880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 115980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 116080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich view.mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); 116180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglSurface = null; 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11641bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 11651bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich 11661bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich public void finish() { 116707353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_EGL) { 116807353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId()); 116907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglContext != null) { 117180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 117280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 117380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich view.mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); 117480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglContext = null; 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEglDisplay != null) { 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEgl.eglTerminate(mEglDisplay); 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEglDisplay = null; 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11835aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich private void throwEglException(String function) { 118404b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich throwEglException(function, mEgl.eglGetError()); 118504b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich } 118604b17ab7b4a17a28f541f746c3d55046c5b87596Jack Palevich 11877d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich public static void throwEglException(String function, int error) { 11887d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich String message = formatEglError(function, error); 118907353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich if (LOG_THREADS) { 11907d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " 11917d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich + message); 119207353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich } 119307353a1e8598b1e2993b8b6763f630379ae6e8bbJack Palevich throw new RuntimeException(message); 11945aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich } 11955aa3adcf304ec3767b3c22128acb23240d8d0babJack Palevich 11967d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich public static void logEglErrorAsWarning(String tag, String function, int error) { 11977d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich Log.w(tag, formatEglError(function, error)); 11987d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich } 11997d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich 12007d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich public static String formatEglError(String function, int error) { 12017d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich return function + " failed: " + EGLLogWrapper.getErrorString(error); 12027d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich } 12037d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich 120480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef; 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGL10 mEgl; 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLDisplay mEglDisplay; 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface mEglSurface; 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLConfig mEglConfig; 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext mEglContext; 1210840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A generic GL Thread. Takes care of initializing EGL and GL. Delegates 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to a Renderer instance to do the actual drawing. Can be configured to 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * render continuously or on request. 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 121867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * All potentially blocking synchronization is done through the 121967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * sGLThreadManager object. This avoids multiple-lock ordering issues. 122067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 122280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich static class GLThread extends Thread { 122380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) { 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = 0; 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = 0; 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestRender = true; 12283e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich mRenderMode = RENDERMODE_CONTINUOUSLY; 122980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mGLSurfaceViewWeakRef = glSurfaceViewWeakRef; 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 12348b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich setName("GLThread " + getId()); 12358b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 12368b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "starting tid=" + getId()); 12378b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 12388b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guardedRun(); 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fall thru and exit normally 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 124467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.threadExiting(this); 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 124867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich /* 124967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * This private method should only be called inside a 125067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * synchronized(sGLThreadManager) block. 125167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich */ 1252840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private void stopEglSurfaceLocked() { 1253840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1254840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = false; 125532d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich mEglHelper.destroySurface(); 125632d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 125732d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 125832d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich 1259840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich /* 1260840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * This private method should only be called inside a 1261840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * synchronized(sGLThreadManager) block. 1262840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich */ 1263840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private void stopEglContextLocked() { 1264840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglContext) { 1265840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mEglHelper.finish(); 1266840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = false; 1267840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich sGLThreadManager.releaseEglContextLocked(this); 1268840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1269840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void guardedRun() throws InterruptedException { 127180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich mEglHelper = new EglHelper(mGLSurfaceViewWeakRef); 1272840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglContext = false; 1273840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = false; 127415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich try { 127515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich GL10 gl = null; 1276840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich boolean createEglContext = false; 1277a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich boolean createEglSurface = false; 1278b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich boolean createGlInterface = false; 1279840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich boolean lostEglContext = false; 1280a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich boolean sizeChanged = false; 128121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich boolean wantRenderNotification = false; 128221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich boolean doRenderNotification = false; 12831b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich boolean askedToReleaseEglContext = false; 1284a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich int w = 0; 1285a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich int h = 0; 1286a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Runnable event = null; 128767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1288a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while (true) { 128967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 129067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich while (true) { 1291a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mShouldExit) { 1292a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich return; 1293a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1294a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1295a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (! mEventQueue.isEmpty()) { 1296a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event = mEventQueue.remove(0); 1297a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich break; 1298a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1299a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1300451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich // Update the pause state. 1301cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich boolean pausing = false; 1302451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (mPaused != mRequestPaused) { 1303cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich pausing = mRequestPaused; 1304451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mPaused = mRequestPaused; 1305451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.notifyAll(); 1306451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1307451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId()); 1308451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1309451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1310451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich 13111b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // Do we need to give up the EGL context? 13121b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (mShouldReleaseEglContext) { 13131b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 13141b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "releasing EGL context because asked to tid=" + getId()); 13151b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13161b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich stopEglSurfaceLocked(); 13171b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich stopEglContextLocked(); 13181b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mShouldReleaseEglContext = false; 13191b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich askedToReleaseEglContext = true; 13201b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 13211b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 1322840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // Have we lost the EGL context? 1323840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (lostEglContext) { 1324840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1325840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 1326840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich lostEglContext = false; 1327840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1328840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1329cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich // When pausing, release the EGL surface: 1330cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich if (pausing && mHaveEglSurface) { 1331a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1332a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); 1333a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1334840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1335cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich } 1336cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich 1337cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich // When pausing, optionally release the EGL Context: 1338cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich if (pausing && mHaveEglContext) { 133980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 134080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich boolean preserveEglContextOnPause = view == null ? 134180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich false : view.mPreserveEGLContextOnPause; 134280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { 1343840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 1344840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (LOG_SURFACE) { 1345840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); 1346840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1347840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1348cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich } 1349cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich 1350cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich // When pausing, optionally terminate EGL: 1351cee059dc764a57860da6b1574952089680b5ddc6Jack Palevich if (pausing) { 1352b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if (sGLThreadManager.shouldTerminateEGLWhenPausing()) { 1353b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich mEglHelper.finish(); 1354b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich if (LOG_SURFACE) { 1355b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich Log.i("GLThread", "terminating EGL because paused tid=" + getId()); 1356b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1357b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 135867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1359a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 13607d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich // Have we lost the SurfaceView surface? 1361a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if ((! mHasSurface) && (! mWaitingForSurface)) { 1362a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1363a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); 136415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1365840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1366840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 136732d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 1368a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mWaitingForSurface = true; 1369db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich mSurfaceIsBad = false; 1370a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 137132d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 137267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1373a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Have we acquired the surface view surface? 1374a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mHasSurface && mWaitingForSurface) { 1375a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_SURFACE) { 1376a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); 1377a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1378a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mWaitingForSurface = false; 1379a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 138067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 138167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 138221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (doRenderNotification) { 13831b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 13841b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "sending render notification tid=" + getId()); 13851b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 138621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich wantRenderNotification = false; 138721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich doRenderNotification = false; 138821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mRenderComplete = true; 138921799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.notifyAll(); 139021799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 139121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 1392a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // Ready to draw? 13931b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (readyToDraw()) { 1394a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1395840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich // If we don't have an EGL context, try to acquire one. 13961b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (! mHaveEglContext) { 13971b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (askedToReleaseEglContext) { 13981b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich askedToReleaseEglContext = false; 13991b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) { 14001b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich try { 14011b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mEglHelper.start(); 14021b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } catch (RuntimeException t) { 14031b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.releaseEglContextLocked(this); 14041b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich throw t; 14051b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 14061b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mHaveEglContext = true; 14071b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich createEglContext = true; 1408840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 14091b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.notifyAll(); 14101b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 1411840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1412840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1413840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglContext && !mHaveEglSurface) { 1414840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich mHaveEglSurface = true; 1415a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = true; 1416b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich createGlInterface = true; 1417a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = true; 1418a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 141967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1420840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (mHaveEglSurface) { 1421a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (mSizeChanged) { 1422a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = true; 1423a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich w = mWidth; 1424a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich h = mHeight; 142521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich wantRenderNotification = true; 14261b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (LOG_SURFACE) { 1427db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich Log.i("GLThread", 1428db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich "noticing that we want render notification tid=" 1429db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich + getId()); 14301b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 143121799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 1432b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich // Destroy and recreate the EGL surface. 1433b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich createEglSurface = true; 1434b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich 1435a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mSizeChanged = false; 1436a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1437b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich mRequestRender = false; 143867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1439a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich break; 144067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 144132d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich } 144267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1443a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich // By design, this is the only place in a GLThread thread where we wait(). 144432d416518473f3bf5323d660e5910ca5633ffed6Jack Palevich if (LOG_THREADS) { 14451b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.i("GLThread", "waiting tid=" + getId() 14461b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHaveEglContext: " + mHaveEglContext 14471b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHaveEglSurface: " + mHaveEglSurface 14481b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mPaused: " + mPaused 14491b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHasSurface: " + mHasSurface 1450db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich + " mSurfaceIsBad: " + mSurfaceIsBad 14511b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mWaitingForSurface: " + mWaitingForSurface 14521b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mWidth: " + mWidth 14531b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mHeight: " + mHeight 14541b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mRequestRender: " + mRequestRender 14551b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich + " mRenderMode: " + mRenderMode); 14561bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 145767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.wait(); 145815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 145967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } // end of synchronized(sGLThreadManager) 146067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1461a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (event != null) { 1462a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event.run(); 1463a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich event = null; 146467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich continue; 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 146667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 1467a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (createEglSurface) { 14684a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 14694a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w("GLThread", "egl createSurface"); 14704a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 147180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (!mEglHelper.createSurface()) { 14727dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich synchronized(sGLThreadManager) { 14737dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich mSurfaceIsBad = true; 14747dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich sGLThreadManager.notifyAll(); 14757dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich } 14767d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich continue; 14770e4aa37872810e46775374596e0beb11f7123727Jack Palevich } 1478a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich createEglSurface = false; 147915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1480a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 1481b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich if (createGlInterface) { 1482b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich gl = (GL10) mEglHelper.createGL(); 1483b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich 1484b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich sGLThreadManager.checkGLDriver(gl); 1485b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich createGlInterface = false; 1486b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich } 1487b50e2afd6782e9b877f52844bec106c12ff9a9efJack Palevich 1488840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich if (createEglContext) { 14894a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_RENDERER) { 14904a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w("GLThread", "onSurfaceCreated"); 14914a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 149280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 149380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 149480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); 149580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 1496840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich createEglContext = false; 1497840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1498840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1499a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (sizeChanged) { 1500a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (LOG_RENDERER) { 1501a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); 1502a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 150380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 150480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 150580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich view.mRenderer.onSurfaceChanged(gl, w, h); 150680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 1507a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sizeChanged = false; 150815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 1509a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich 15104a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_RENDERER_DRAW_FRAME) { 15111b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich Log.w("GLThread", "onDrawFrame tid=" + getId()); 1512a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 151380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich { 151480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich GLSurfaceView view = mGLSurfaceViewWeakRef.get(); 151580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich if (view != null) { 151680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich view.mRenderer.onDrawFrame(gl); 151780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 151880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich } 1519db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich int swapError = mEglHelper.swap(); 1520db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich switch (swapError) { 1521db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich case EGL10.EGL_SUCCESS: 1522db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich break; 1523db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich case EGL11.EGL_CONTEXT_LOST: 1524db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich if (LOG_SURFACE) { 1525db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich Log.i("GLThread", "egl context lost tid=" + getId()); 1526db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich } 1527db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich lostEglContext = true; 1528db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich break; 1529db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich default: 1530db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich // Other errors typically mean that the current surface is bad, 15317d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich // probably because the SurfaceView surface has been destroyed, 1532db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich // but we haven't been notified yet. 1533db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich // Log the error to help developers understand why rendering stopped. 15347d73df83f9a28950f404e957eb2e4ea1e8525c55Jack Palevich EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError); 15357dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich 15367dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich synchronized(sGLThreadManager) { 15377dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich mSurfaceIsBad = true; 15387dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich sGLThreadManager.notifyAll(); 15397dee7a38baafcbdd26ff116eeec862ec661dedecJack Palevich } 1540db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich break; 154115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 154221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 154321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (wantRenderNotification) { 154421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich doRenderNotification = true; 154521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 1546a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1547840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 154815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } finally { 154915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich /* 155015e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich * clean-up everything... 155115e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich */ 155267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1553840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglSurfaceLocked(); 1554840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich stopEglContextLocked(); 155567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 155615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15591b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public boolean ableToDraw() { 15601b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich return mHaveEglContext && mHaveEglSurface && readyToDraw(); 15611b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 15621b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 15631b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private boolean readyToDraw() { 1564db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich return (!mPaused) && mHasSurface && (!mSurfaceIsBad) 15651b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich && (mWidth > 0) && (mHeight > 0) 15661b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); 15671b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 15681b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRenderMode(int renderMode) { 15703e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { 15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("renderMode"); 15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 157367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRenderMode = renderMode; 1575a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRenderMode() { 158067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mRenderMode; 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestRender() { 158667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestRender = true; 158867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated() { 159367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 15948b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 15958b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "surfaceCreated tid=" + getId()); 15968b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasSurface = true; 159867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1599451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while((mWaitingForSurface) && (!mExited)) { 1600451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1601451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1602451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException e) { 1603451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1604451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1605451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed() { 161067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 16118b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich if (LOG_THREADS) { 16128b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich Log.i("GLThread", "surfaceDestroyed tid=" + getId()); 16138b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasSurface = false; 161567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1616a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while((!mWaitingForSurface) && (!mExited)) { 16171bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich try { 161867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.wait(); 16191bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } catch (InterruptedException e) { 16201bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich Thread.currentThread().interrupt(); 16211bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 16221bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich } 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPause() { 162767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1628e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich if (LOG_PAUSE_RESUME) { 1629e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich Log.i("GLThread", "onPause tid=" + getId()); 1630e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1631451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRequestPaused = true; 163267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1633451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while ((! mExited) && (! mPaused)) { 1634451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1635451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("Main thread", "onPause waiting for mPaused."); 1636451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1637451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1638451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1639451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException ex) { 1640451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1641451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1642451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onResume() { 164767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 1648e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich if (LOG_PAUSE_RESUME) { 1649e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich Log.i("GLThread", "onResume tid=" + getId()); 1650e6c9448eb3228887c49f6ba9c4be2345443286e9Jack Palevich } 1651451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRequestPaused = false; 16528b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich mRequestRender = true; 1653451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich mRenderComplete = false; 165467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1655451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich while ((! mExited) && mPaused && (!mRenderComplete)) { 1656451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich if (LOG_PAUSE_RESUME) { 1657451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Log.i("Main thread", "onResume waiting for !mPaused."); 1658451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1659451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich try { 1660451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich sGLThreadManager.wait(); 1661451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } catch (InterruptedException ex) { 1662451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich Thread.currentThread().interrupt(); 1663451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 1664451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich } 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onWindowResize(int w, int h) { 166967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized (sGLThreadManager) { 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = w; 16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = h; 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSizeChanged = true; 1673a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mRequestRender = true; 167421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich mRenderComplete = false; 167567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 167621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich 167721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich // Wait for thread to react to resize and render a frame 16781b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich while (! mExited && !mPaused && !mRenderComplete 167980b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich && ableToDraw()) { 168021799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich if (LOG_SURFACE) { 168180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + getId()); 168221799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 168321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich try { 168421799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich sGLThreadManager.wait(); 168521799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } catch (InterruptedException ex) { 168621799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich Thread.currentThread().interrupt(); 168721799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 168821799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich } 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestExitAndWait() { 16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't call this from GLThread thread or it is a guaranteed 16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // deadlock! 169567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich synchronized(sGLThreadManager) { 1696a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mShouldExit = true; 169767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich sGLThreadManager.notifyAll(); 1698a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich while (! mExited) { 1699a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich try { 1700a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.wait(); 1701a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } catch (InterruptedException ex) { 1702a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich Thread.currentThread().interrupt(); 1703a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 1704a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich } 17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17081b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich public void requestReleaseEglContextLocked() { 17091b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mShouldReleaseEglContext = true; 17101b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich sGLThreadManager.notifyAll(); 17111b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 17121b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich 17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Queue an "event" to be run on the GL rendering thread. 17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param r the runnable to be run on the GL rendering thread. 17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void queueEvent(Runnable r) { 1718a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich if (r == null) { 1719a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich throw new IllegalArgumentException("r must not be null"); 17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1721a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich synchronized(sGLThreadManager) { 1722a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich mEventQueue.add(r); 1723a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich sGLThreadManager.notifyAll(); 17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // Once the thread is started, all accesses to the following member 172867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // variables are protected by the sGLThreadManager monitor 1729a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mShouldExit; 1730a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private boolean mExited; 1731451a224c46c297bd6b25e3570b45f5053b4788beJack Palevich private boolean mRequestPaused; 17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mPaused; 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mHasSurface; 1734db6c78b5bdf264abe8f6de97f67ca5e90fb6a05aJack Palevich private boolean mSurfaceIsBad; 17351bd888ba2e0976a179258cfa65ef07be31602a0aJack Palevich private boolean mWaitingForSurface; 1736840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private boolean mHaveEglContext; 1737840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich private boolean mHaveEglSurface; 17381b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich private boolean mShouldReleaseEglContext; 17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mWidth; 17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mHeight; 17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRenderMode; 17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mRequestRender; 174321799450ec751fd3c41c7e66e69fefb094b3050bJack Palevich private boolean mRenderComplete; 1744a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); 174580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich private boolean mSizeChanged = true; 1746840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 174767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich // End of member variables protected by the sGLThreadManager monitor. 174867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich 17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EglHelper mEglHelper; 175080b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich 175180b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich /** 175280b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich * Set once at thread construction time, nulled out when the parent view is garbage 175380b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich * called. This weak reference allows the GLSurfaceView to be garbage collected while 175480b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich * the GLThread is still alive. 175580b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich */ 175680b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef; 175780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class LogWriter extends Writer { 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void close() { 17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void flush() { 17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void write(char[] buf, int offset, int count) { 17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < count; i++) { 17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = buf[offset + i]; 17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ( c == '\n') { 17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flushBuilder(); 17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuilder.append(c); 17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void flushBuilder() { 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBuilder.length() > 0) { 17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v("GLSurfaceView", mBuilder.toString()); 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBuilder.delete(0, mBuilder.length()); 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private StringBuilder mBuilder = new StringBuilder(); 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179215e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 179315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private void checkRenderThreadState() { 179415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich if (mGLThread != null) { 179515e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich throw new IllegalStateException( 179615e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich "setRenderer has already been called for this instance."); 179715e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 179815e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich } 179915e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich 180079447b2087c8c820d742185dda7305101f9656f0Jack Palevich private static class GLThreadManager { 18014a2221ec4a929976be570ad096252c8dea326e19Jack Palevich private static String TAG = "GLThreadManager"; 18028da3ac92a6a6247ef06de4d4b684f8635d8fc003Jack Palevich 180367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich public synchronized void threadExiting(GLThread thread) { 180467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (LOG_THREADS) { 180567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich Log.i("GLThread", "exiting tid=" + thread.getId()); 18068b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 1807a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich thread.mExited = true; 180867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread) { 180967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = null; 18108b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 181167dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 181267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich } 1813c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 181467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich /* 181567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich * Tries once to acquire the right to use an EGL 1816840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * context. Does not block. Requires that we are already 1817a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * in the sGLThreadManager monitor when this is called. 181866a4a6e45f59f72f24d710221c27db1bd233e154Jack Palevich * 1819840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * @return true if the right to use an EGL context was acquired. 182067dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich */ 1821840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public boolean tryAcquireEglContextLocked(GLThread thread) { 182267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread || mEglOwner == null) { 182367dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = thread; 182467dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 182567dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return true; 18268b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 18271179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich checkGLESVersion(); 18281179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (mMultipleGLESContextsAllowed) { 18291179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich return true; 18308b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 18311b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // Notify the owning thread that it should release the context. 18321b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // TODO: implement a fairness policy. Currently 18331b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // if the owning thread is drawing continuously it will just 18341b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich // reacquire the EGL context. 18351b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich if (mEglOwner != null) { 18361b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich mEglOwner.requestReleaseEglContextLocked(); 18371b4ecc63c4eceb7c125d4e749fd5f747d99d6ec6Jack Palevich } 183867dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich return false; 1839c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1840840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1841a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich /* 1842840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich * Releases the EGL context. Requires that we are already in the 1843a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich * sGLThreadManager monitor when this is called. 1844a08d46d8aaabb53eef4d5dc47272565d50f23c19Jack Palevich */ 1845840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public void releaseEglContextLocked(GLThread thread) { 184667dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich if (mEglOwner == thread) { 184767dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich mEglOwner = null; 184879447b2087c8c820d742185dda7305101f9656f0Jack Palevich } 184967dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich notifyAll(); 1850c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1851c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 1852840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich public synchronized boolean shouldReleaseEGLContextWhenPausing() { 1853b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // Release the EGL context when pausing even if 1854b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // the hardware supports multiple EGL contexts. 1855b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich // Otherwise the device could run out of EGL contexts. 18568432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich return mLimitedGLESContexts; 1857b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich } 1858b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich 1859b1768998f14e03bd69cf049783d6cbeccf6d5839Jack Palevich public synchronized boolean shouldTerminateEGLWhenPausing() { 1860840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich checkGLESVersion(); 18614a2221ec4a929976be570ad096252c8dea326e19Jack Palevich return !mMultipleGLESContextsAllowed; 1862840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich } 1863840e958847f31f835dbf17ce539c9f8317251cc9Jack Palevich 1864c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich public synchronized void checkGLDriver(GL10 gl) { 1865c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich if (! mGLESDriverCheckComplete) { 18661179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich checkGLESVersion(); 18678432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich String renderer = gl.glGetString(GL10.GL_RENDERER); 1868c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich if (mGLESVersion < kGLES_20) { 1869c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich mMultipleGLESContextsAllowed = 1870c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); 1871c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich notifyAll(); 1872c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 18738b854cd74bd29b6bb0b4c681490a3a97b1739289Jack Palevich mLimitedGLESContexts = !mMultipleGLESContextsAllowed; 18748432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich if (LOG_SURFACE) { 18758432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " 18768432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich + mMultipleGLESContextsAllowed 18778432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich + " mLimitedGLESContexts = " + mLimitedGLESContexts); 18788432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich } 1879c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich mGLESDriverCheckComplete = true; 1880c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1881c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich } 1882c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 18831179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich private void checkGLESVersion() { 18841179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (! mGLESVersionCheckComplete) { 18851179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mGLESVersion = SystemProperties.getInt( 18861179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich "ro.opengles.version", 18871179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich ConfigurationInfo.GL_ES_VERSION_UNDEFINED); 18881179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich if (mGLESVersion >= kGLES_20) { 18891179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mMultipleGLESContextsAllowed = true; 18901179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 18914a2221ec4a929976be570ad096252c8dea326e19Jack Palevich if (LOG_SURFACE) { 18924a2221ec4a929976be570ad096252c8dea326e19Jack Palevich Log.w(TAG, "checkGLESVersion mGLESVersion =" + 18934a2221ec4a929976be570ad096252c8dea326e19Jack Palevich " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); 18944a2221ec4a929976be570ad096252c8dea326e19Jack Palevich } 18951179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich mGLESVersionCheckComplete = true; 18961179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 18971179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich } 18981179efbb3b8856eb8160e2dd67a300a5d64e8e98Jack Palevich 18998b854cd74bd29b6bb0b4c681490a3a97b1739289Jack Palevich /** 19008b854cd74bd29b6bb0b4c681490a3a97b1739289Jack Palevich * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides 19018b854cd74bd29b6bb0b4c681490a3a97b1739289Jack Palevich * support for hardware-accelerated views, therefore multiple EGL contexts are 19028b854cd74bd29b6bb0b4c681490a3a97b1739289Jack Palevich * supported on all Android 3.0+ EGL drivers. 19038b854cd74bd29b6bb0b4c681490a3a97b1739289Jack Palevich */ 1904c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mGLESVersionCheckComplete; 1905c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private int mGLESVersion; 1906c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mGLESDriverCheckComplete; 1907c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private boolean mMultipleGLESContextsAllowed; 19088432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich private boolean mLimitedGLESContexts; 1909c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private static final int kGLES_20 = 0x20000; 1910c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich private static final String kMSM7K_RENDERER_PREFIX = 1911c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich "Q3Dimension MSM7500 "; 191267dcd6c2392caf3ff98f35a3d1ec550d229c167bJack Palevich private GLThread mEglOwner; 19138b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich } 1914c52ba78cab001ff68b4823f4769c129b8acfddeeJack Palevich 19158b2c9c9ecb08d25244fa97fb42c2c315ae3cf03dJack Palevich private static final GLThreadManager sGLThreadManager = new GLThreadManager(); 19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 191780b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich private final WeakReference<GLSurfaceView> mThisWeakRef = 191880b3cd6bc608c5929096e3407de2b157be925d3eJack Palevich new WeakReference<GLSurfaceView>(this); 19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLThread mGLThread; 19202ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private Renderer mRenderer; 19212ff6a824619ac6849ba9f36d97590acf74f62518Jack Palevich private boolean mDetached; 1922a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich private EGLConfigChooser mEGLConfigChooser; 192315e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private EGLContextFactory mEGLContextFactory; 192415e1c6dc7a778590068b1cad55beea2bc6159509Jack Palevich private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; 19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GLWrapper mGLWrapper; 19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDebugFlags; 19276ae4da75422bbb31c3e0a09f616cdaee1d465946Jack Palevich private int mEGLContextClientVersion; 19288432b3f98a22d5cdfcc0183d134770597e44d412Jack Palevich private boolean mPreserveEGLContextOnPause; 19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1930