GLSurfaceView.java revision 82fd4fce16b9bbde25d044acc86ddf7306ebdd10
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.opengl;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.Writer;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.Semaphore;
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;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceView;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An implementation of SurfaceView that uses the dedicated surface for
40b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * displaying OpenGL rendering.
41b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
42b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView provides the following features:
43b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
44b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul>
45b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages a surface, which is a special piece of memory that can be
46b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * composited into the Android view system.
47b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Manages an EGL display, which enables OpenGL to render into a surface.
48b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Accepts a user-provided Renderer object that does the actual rendering.
49b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Renders on a dedicated thread to decouple rendering performance from the
50b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * UI thread.
51b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Supports both on-demand and continuous rendering.
52b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.
53b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul>
54b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *
55b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Using GLSurfaceView</h3>
56b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
57b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Typically you use GLSurfaceView by subclassing it and overriding one or more of the
58b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * View system input event methods. If your application does not need to override event
59b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * methods then GLSurfaceView can be used as-is. For the most part
60b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing.
61b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * For example, unlike a regular View, drawing is delegated to a separate Renderer object which
62b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * is registered with the GLSurfaceView
63b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * using the {@link #setRenderer(Renderer)} call.
64b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
65b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Initializing GLSurfaceView</h3>
66b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}.
67b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or
68b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * more of these methods before calling setRenderer:
69b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <ul>
70b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setDebugFlags(int)}
71b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(boolean)}
72b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
73b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
74b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <li>{@link #setGLWrapper(GLWrapper)}
75b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </ul>
76b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
77b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Choosing an EGL Configuration</h4>
78b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A given Android device may support multiple possible types of drawing surfaces.
79b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The available surfaces may differ in how may channels of data are present, as
80b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * well as how many bits are allocated to each channel. Therefore, the first thing
81b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * GLSurfaceView has to do when starting to render is choose what type of surface to use.
82b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
83b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * By default GLSurfaceView chooses an available surface that's closest to a 16-bit R5G6B5 surface
84b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * with a 16-bit depth buffer and no stencil. If you would prefer a different surface (for example,
85b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * if you do not need a depth buffer) you can override the default behavior by calling one of the
86b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * setEGLConfigChooser methods.
87b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
88b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Debug Behavior</h4>
89b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * You can optionally modify the behavior of GLSurfaceView by calling
90b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one or more of the debugging methods {@link #setDebugFlags(int)},
91b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but
92b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * typically they are called before setRenderer so that they take effect immediately.
93b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
94b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h4>Setting a Renderer</h4>
95b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Finally, you must call {@link #setRenderer} to register a {@link Renderer}.
96b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * The renderer is
97b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * responsible for doing the actual OpenGL rendering.
98b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
99b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Rendering Mode</h3>
100b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * Once the renderer is set, you can control whether the renderer draws
101b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * continuously or on-demand by calling
102b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #setRenderMode}. The default is continuous rendering.
103b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
104b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Activity Life-cycle</h3>
105b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients
106b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * are required to call {@link #onPause()} when the activity pauses and
107b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to
108b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
109b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the OpenGL display.
110b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
111b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <h3>Handling events</h3>
112b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <p>
113b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * To handle an event you will typically subclass GLSurfaceView and override the
114b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * appropriate method, just as you would with any other View. However, when handling
115b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * the event, you may need to communicate with the Renderer object
116b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * that's running in the rendering thread. You can do this using any
117b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * standard Java cross-thread communication mechanism. In addition,
118b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * one relatively easy way to communicate with your renderer is
119b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * to call
120b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * {@link #queueEvent(Runnable)}. For example:
121b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * <pre class="prettyprint">
122b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * class MyGLSurfaceView extends GLSurfaceView {
123b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *
124b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *     private MyRenderer mMyRenderer;
125b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *
126b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *     public void start() {
127b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *         mMyRenderer = ...;
128b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *         setRenderer(mMyRenderer);
129b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *     }
130b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *
131b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *     public boolean onKeyDown(int keyCode, KeyEvent event) {
132b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
133b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *             queueEvent(new Runnable() {
134b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *                 // This method will be called on the rendering
135b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *                 // thread:
136b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *                 public void run() {
137b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *                     mMyRenderer.handleDpadCenter();
138b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *                 }});
139b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *             return true;
140b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *         }
141b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *         return super.onKeyDown(keyCode, event);
142b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich *     }
143b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * }
144b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich * </pre>
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
148b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
149b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * The renderer only renders
150b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * when the surface is created, or when {@link #requestRender} is called.
151b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
152b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #getRenderMode()
153b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #setRenderMode(int)
154b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int RENDERMODE_WHEN_DIRTY = 0;
156b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
157b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * The renderer is called
158b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * continuously to re-render the scene.
159b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
160b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #getRenderMode()
161b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #setRenderMode(int)
162b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #requestRender()
163b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
1643e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich    public final static int RENDERMODE_CONTINUOUSLY = 1;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
167b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Check glError() after every GL call and throw an exception if glError indicates
168b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * that an error has occurred. This can be used to help track down which OpenGL ES call
169b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * is causing an error.
170b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
171b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #getDebugFlags
172b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #setDebugFlags
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int DEBUG_CHECK_GL_ERROR = 1;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView".
178b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
179b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #getDebugFlags
180b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #setDebugFlags
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int DEBUG_LOG_GL_CALLS = 2;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
184b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
185b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Standard View constructor. In order to render something, you
186b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * must call {@link #setRenderer} to register a renderer.
187b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GLSurfaceView(Context context) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        init();
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
193b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
194b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Standard View constructor. In order to render something, you
195b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * must call {@link #setRenderer} to register a renderer.
196b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GLSurfaceView(Context context, AttributeSet attrs) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        init();
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void init() {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Install a SurfaceHolder.Callback so we get notified when the
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // underlying surface is created and destroyed
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SurfaceHolder holder = getHolder();
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        holder.addCallback(this);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
210b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Set the glWrapper. If the glWrapper is not null, its
211b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * {@link GLWrapper#wrap(GL)} method is called
212b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * whenever a surface is created. A GLWrapper can be used to wrap
213b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * the GL object that's passed to the renderer. Wrapping a GL
214b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * object enables examining and modifying the behavior of the
215b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * GL calls made by the renderer.
216b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
217b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Wrapping is typically used for debugging purposes.
218b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
219b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * The default value is null.
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param glWrapper the new GLWrapper
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGLWrapper(GLWrapper glWrapper) {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLWrapper = glWrapper;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
227b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Set the debug flags to a new value. The value is
228b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * constructed by OR-together zero or more
229b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * of the DEBUG_CHECK_* constants. The debug flags take effect
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * whenever a surface is created. The default value is zero.
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param debugFlags the new debug flags
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #DEBUG_CHECK_GL_ERROR
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #DEBUG_LOG_GL_CALLS
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDebugFlags(int debugFlags) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDebugFlags = debugFlags;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
240b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Get the current value of the debug flags.
241b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @return the current value of the debug flags.
242b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDebugFlags() {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDebugFlags;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
248b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Set the renderer associated with this view. Also starts the thread that
249b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * will call the renderer, which in turn causes the rendering to start.
250b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>This method should be called once and only once in the life-cycle of
251b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * a GLSurfaceView.
252b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>The following GLSurfaceView methods can only be called <em>before</em>
253b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * setRenderer is called:
254b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <ul>
255b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #setEGLConfigChooser(boolean)}
256b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
257b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
258b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * </ul>
259b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
260b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * The following GLSurfaceView methods can only be called <em>after</em>
261b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * setRenderer is called:
262b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <ul>
263b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #getRenderMode()}
264b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #onPause()}
265b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #onResume()}
266b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #queueEvent(Runnable)}
267b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #requestRender()}
268b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <li>{@link #setRenderMode(int)}
269b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * </ul>
270b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
271b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @param renderer the renderer to use to perform OpenGL drawing.
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setRenderer(Renderer renderer) {
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mGLThread != null) {
275a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            throw new IllegalStateException(
276a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    "setRenderer has already been called for this instance.");
277a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
278a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        if (mEGLConfigChooser == null) {
279a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mEGLConfigChooser = new SimpleEGLConfigChooser(true);
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread = new GLThread(renderer);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.start();
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
286b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Install a custom EGLConfigChooser.
287b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>If this method is
288b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * called, it must be called before {@link #setRenderer(Renderer)}
289a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * is called.
290a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
291b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * If no setEGLConfigChooser method is called, then by default the
292b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * view will choose a config as close to 16-bit RGB as possible, with
293b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * a depth buffer as close to 16 bits as possible.
294a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * @param configChooser
295a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
296a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public void setEGLConfigChooser(EGLConfigChooser configChooser) {
297a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        if (mGLThread != null) {
298a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            throw new IllegalStateException(
299a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    "setRenderer has already been called for this instance.");
300a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
301a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        mEGLConfigChooser = configChooser;
302a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
303a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
304a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
305b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Install a config chooser which will choose a config
306a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * as close to 16-bit RGB as possible, with or without an optional depth
307a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * buffer as close to 16-bits as possible.
308b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>If this method is
309b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * called, it must be called before {@link #setRenderer(Renderer)}
310b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * is called.
311a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
312b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich      * If no setEGLConfigChooser method is called, then by default the
313a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * view will choose a config as close to 16-bit RGB as possible, with
314b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * a depth buffer as close to 16 bits as possible.
315a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
316a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * @param needDepth
317a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
318a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public void setEGLConfigChooser(boolean needDepth) {
319a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
320a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
321a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
322a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
323b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Install a config chooser which will choose a config
324b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * with at least the specified component sizes, and as close
325b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * to the specified component sizes as possible.
326b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>If this method is
327a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * called, it must be called before {@link #setRenderer(Renderer)}
328a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * is called.
329a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
330b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * If no setEGLConfigChooser method is called, then by default the
331b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * view will choose a config as close to 16-bit RGB as possible, with
332b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * a depth buffer as close to 16 bits as possible.
333a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
334a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
335a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
336a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int alphaSize, int depthSize, int stencilSize) {
337a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
338a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                blueSize, alphaSize, depthSize, stencilSize));
339a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
340a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
341b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Set the rendering mode. When renderMode is
3423e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich     * RENDERMODE_CONTINUOUSLY, the renderer is called
343b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * repeatedly to re-render the scene. When renderMode
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
3453e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich     * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
346b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
347b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance
348b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * by allowing the GPU and CPU to idle when the view does not need to be updated.
349b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
350b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * This method can only be called after {@link #setRenderer(Renderer)}
351b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param renderMode one of the RENDERMODE_X constants
3533e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich     * @see #RENDERMODE_CONTINUOUSLY
354b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #RENDERMODE_WHEN_DIRTY
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setRenderMode(int renderMode) {
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.setRenderMode(renderMode);
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the current rendering mode. May be called
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from any thread. Must not be called before a renderer has been set.
363b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @return the current rendering mode.
3643e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich     * @see #RENDERMODE_CONTINUOUSLY
365b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #RENDERMODE_WHEN_DIRTY
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getRenderMode() {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGLThread.getRenderMode();
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
372b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Request that the renderer render a frame.
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This method is typically used when the render mode has been set to
374b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand.
375b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * May be called
376b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * from any thread. Must not be called before a renderer has been set.
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestRender() {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.requestRender();
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
382b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
383b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * This method is part of the SurfaceHolder.Callback interface, and is
384b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * not normally called or subclassed by clients of GLSurfaceView.
385b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.surfaceCreated();
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
390b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
391b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * This method is part of the SurfaceHolder.Callback interface, and is
392b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * not normally called or subclassed by clients of GLSurfaceView.
393b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Surface will be destroyed when we return
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.surfaceDestroyed();
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
400b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * This method is part of the SurfaceHolder.Callback interface, and is
401b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * not normally called or subclassed by clients of GLSurfaceView.
402b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.onWindowResize(w, h);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inform the view that the activity is paused. The owner of this view must
409b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * call this method when the activity is paused. Calling this method will
410b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * pause the rendering thread.
411b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Must not be called before a renderer has been set.
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onPause() {
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.onPause();
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inform the view that the activity is resumed. The owner of this view must
419b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * call this method when the activity is resumed. Calling this method will
420b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * recreate the OpenGL display and resume the rendering
421b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * thread.
422b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Must not be called before a renderer has been set.
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onResume() {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.onResume();
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
429b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Queue a runnable to be run on the GL rendering thread. This can be used
430b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * to communicate with the Renderer on the rendering thread.
431b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Must not be called before a renderer has been set.
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param r the runnable to be run on the GL rendering thread.
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void queueEvent(Runnable r) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.queueEvent(r);
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
438b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
439b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * This method is used as part of the View class and is not normally
440b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * called or subclassed by clients of GLSurfaceView.
441b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Must not be called before a renderer has been set.
442b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onDetachedFromWindow() {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onDetachedFromWindow();
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.requestExitAndWait();
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
451b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich    /**
452b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * An interface used to wrap a GL interface.
453b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>Typically
454b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * used for implementing debugging and tracing on top of the default
455b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * GL interface. You would typically use this by creating your own class
456b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * that implemented all the GL methods by delegating to another GL instance.
457b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * Then you could add your own behavior before or after calling the
458b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * delegate. All the GLWrapper would do was instantiate and return the
459b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * wrapper GL instance:
460b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <pre class="prettyprint">
461b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * class MyGLWrapper implements GLWrapper {
462b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *     GL wrap(GL gl) {
463b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *         return new MyGLImplementation(gl);
464b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *     }
465b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *     static class MyGLImplementation implements GL,GL10,GL11,... {
466b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *         ...
467b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *     }
468b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * }
469b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * </pre>
470b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #setGLWrapper(GLWrapper)
471b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     */
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface GLWrapper {
473b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich        /**
474b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Wraps a gl interface in another gl interface.
475b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * @param gl a GL interface that is to be wrapped.
476b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * @return either the input argument or another GL object that wraps the input argument.
477b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         */
478b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich        GL wrap(GL gl);
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A generic renderer interface.
483b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
484b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * The renderer is responsible for making OpenGL calls to render a frame.
485b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
486b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * GLSurfaceView clients typically create their own classes that implement
487b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * this interface, and then call {@link GLSurfaceView#setRenderer} to
488b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * register the renderer with the GLSurfaceView.
489b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
490b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <h3>Threading</h3>
491b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * The renderer will be called on a separate thread, so that rendering
492b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * performance is decoupled from the UI thread. Clients typically need to
493b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * communicate with the renderer from the UI thread, because that's where
494b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * input events are received. Clients can communicate using any of the
495b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * standard Java techniques for cross-thread communication, or they can
496b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method.
497b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
498b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <h3>EGL Context Lost</h3>
499b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * There are situations where the EGL rendering context will be lost. This
500b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * typically happens when device wakes up after going to sleep. When
501b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * the EGL context is lost, all OpenGL resources (such as textures) that are
502b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * associated with that context will be automatically deleted. In order to
503b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * keep rendering correctly, a renderer must recreate any lost resources
504b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method
505b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * is a convenient place to do this.
506b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
507b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     *
508b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * @see #setRenderer(Renderer)
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Renderer {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
512b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Called when the surface is created or recreated.
513b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
514b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Called when the rendering thread
515b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * starts and whenever the EGL context is lost. The context will typically
516b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * be lost when the Android device awakes after going to sleep.
517b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
518b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Since this method is called at the beginning of rendering, as well as
519b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * every time the EGL context is lost, this method is a convenient place to put
520b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * code to create resources that need to be created when the rendering
521b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * starts, and that need to be recreated when the EGL context is lost.
522b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Textures are an example of a resource that you might want to create
523b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * here.
524b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
525b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Note that when the EGL context is lost, all OpenGL resources associated
526b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * with that context will be automatically deleted. You do not need to call
527b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * the corresponding "glDelete" methods such as glDeleteTextures to
528b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * manually delete these lost resources.
529b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param gl the GL interface. Use <code>instanceof</code> to
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * test if the interface supports GL11 or higher interfaces.
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param config the EGLConfig of the created surface. Can be used
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to create matching pbuffers.
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSurfaceCreated(GL10 gl, EGLConfig config);
536b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
538b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Called when the surface changed size.
539b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called after the surface is created and whenever
541b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * the OpenGL ES surface size changes.
542b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
543b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Typically you will set your viewport here. If your camera
544b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * is fixed then you could also set your projection matrix here:
545b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <pre class="prettyprint">
546b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * void onSurfaceChanged(GL10 gl, int width, int height) {
547b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     gl.glViewport(0, 0, width, height);
548b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     // for a fixed camera, set the projection too
549b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     float ratio = (float) width / height;
550b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     gl.glMatrixMode(GL10.GL_PROJECTION);
551b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     gl.glLoadIdentity();
552b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
553b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * }
554b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * </pre>
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param gl the GL interface. Use <code>instanceof</code> to
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * test if the interface supports GL11 or higher interfaces.
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param width
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param height
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSurfaceChanged(GL10 gl, int width, int height);
561b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
563b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * Called to draw the current frame.
564b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
565b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * This method is responsible for drawing the current frame.
566b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <p>
567b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * The implementation of this method typically looks like this:
568b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * <pre class="prettyprint">
569b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * void onDrawFrame(GL10 gl) {
570b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
571b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         *     //... other gl calls to render the scene ...
572b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * }
573b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * </pre>
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param gl the GL interface. Use <code>instanceof</code> to
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * test if the interface supports GL11 or higher interfaces.
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onDrawFrame(GL10 gl);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
581b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * An interface for choosing an EGLConfig configuration from a list of
582a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * potential configurations.
583b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * <p>
584b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * This interface must be implemented by clients wishing to call
585b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich     * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)}
586a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
587a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public interface EGLConfigChooser {
588a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        /**
589a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * Choose a configuration from the list. Implementors typically
590a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * implement this method by calling
591b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the
592b47c641fe8330fc68dbed91163ff07015068d0ceJack Palevich         * EGL specification available from The Khronos Group to learn how to call eglChooseConfig.
593a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * @param egl the EGL10 for the current display.
594a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * @param display the current display.
595a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * @return the chosen configuration.
596a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         */
597a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
598a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
599a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
600a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private static abstract class BaseConfigChooser
601a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            implements EGLConfigChooser {
602a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public BaseConfigChooser(int[] configSpec) {
603a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mConfigSpec = configSpec;
604a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
605a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
606a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int[] num_config = new int[1];
607a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config);
608a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
609a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int numConfigs = num_config[0];
610a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
611a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            if (numConfigs <= 0) {
612a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                throw new IllegalArgumentException(
613a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        "No configs match configSpec");
614a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
615a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
616a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            EGLConfig[] configs = new EGLConfig[numConfigs];
617a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
618a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    num_config);
619a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            EGLConfig config = chooseConfig(egl, display, configs);
620a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            if (config == null) {
621a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                throw new IllegalArgumentException("No config chosen");
622a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
623a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            return config;
624a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
625a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
626a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
627a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                EGLConfig[] configs);
628a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
629a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int[] mConfigSpec;
630a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
631a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
632a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private static class ComponentSizeChooser extends BaseConfigChooser {
633a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
634a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int alphaSize, int depthSize, int stencilSize) {
635a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            super(new int[] {
636a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_RED_SIZE, redSize,
637a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_GREEN_SIZE, greenSize,
638a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_BLUE_SIZE, blueSize,
639a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_ALPHA_SIZE, alphaSize,
640a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_DEPTH_SIZE, depthSize,
641a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_STENCIL_SIZE, stencilSize,
642a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_NONE});
643a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mValue = new int[1];
644a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mRedSize = redSize;
645a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mGreenSize = greenSize;
646a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mBlueSize = blueSize;
647a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mAlphaSize = alphaSize;
648a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mDepthSize = depthSize;
649a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mStencilSize = stencilSize;
650a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich       }
651a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
652a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        @Override
653a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
654a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                EGLConfig[] configs) {
655a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            EGLConfig closestConfig = null;
656a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int closestDistance = 1000;
657a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            for(EGLConfig config : configs) {
658a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int d = findConfigAttrib(egl, display, config,
659a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        EGL10.EGL_DEPTH_SIZE, 0);
660a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int s = findConfigAttrib(egl, display, config,
661a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        EGL10.EGL_STENCIL_SIZE, 0);
66282fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                if (d >= mDepthSize && s>= mStencilSize) {
66382fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    int r = findConfigAttrib(egl, display, config,
66482fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                            EGL10.EGL_RED_SIZE, 0);
66582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    int g = findConfigAttrib(egl, display, config,
66682fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                             EGL10.EGL_GREEN_SIZE, 0);
66782fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    int b = findConfigAttrib(egl, display, config,
66882fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                              EGL10.EGL_BLUE_SIZE, 0);
66982fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    int a = findConfigAttrib(egl, display, config,
67082fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                            EGL10.EGL_ALPHA_SIZE, 0);
67182fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    int distance = Math.abs(r - mRedSize)
67282fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                                + Math.abs(g - mGreenSize)
67382fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                                + Math.abs(b - mBlueSize)
67482fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                                + Math.abs(a - mAlphaSize);
67582fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    if (distance < closestDistance) {
67682fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                        closestDistance = distance;
67782fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                        closestConfig = config;
67882fd4fce16b9bbde25d044acc86ddf7306ebdd10Mathias Agopian                    }
679a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                }
680a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
681a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            return closestConfig;
682a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
683a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
684a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        private int findConfigAttrib(EGL10 egl, EGLDisplay display,
685a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                EGLConfig config, int attribute, int defaultValue) {
686a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
687a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
688a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                return mValue[0];
689a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
690a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            return defaultValue;
691a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
692a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
693a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        private int[] mValue;
694a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        // Subclasses can adjust these values:
695a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mRedSize;
696a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mGreenSize;
697a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mBlueSize;
698a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mAlphaSize;
699a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mDepthSize;
700a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mStencilSize;
701a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
702a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
703a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
704a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * This class will choose a supported surface as close to
705a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * RGB565 as possible, with or without a depth buffer.
706a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
707a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
708a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private static class SimpleEGLConfigChooser extends ComponentSizeChooser {
709a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public SimpleEGLConfigChooser(boolean withDepthBuffer) {
710a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
711a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            // Adjust target values. This way we'll accept a 4444 or
712a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            // 555 buffer if there's no 565 buffer available.
713a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mRedSize = 5;
714a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mGreenSize = 6;
715a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mBlueSize = 5;
716a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
717a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
718a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
719a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An EGL helper class.
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class EglHelper {
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public EglHelper() {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Initialize EGL for a given configuration spec.
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param configSpec
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
732a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public void start(){
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Get an EGL instance
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl = (EGL10) EGLContext.getEGL();
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Get to the default display.
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * We can now initialize EGL for that display
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] version = new int[2];
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl.eglInitialize(mEglDisplay, version);
748a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            * Create an OpenGL ES context. This must be done only once, an
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            * OpenGL context is a somewhat heavy object.
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    EGL10.EGL_NO_CONTEXT, null);
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglSurface = null;
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * React to the creation of a new surface by creating and returning an
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * OpenGL interface that renders to that surface.
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GL createSurface(SurfaceHolder holder) {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *  The window size has changed, so we need to create a new
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *  surface.
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglSurface != null) {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /*
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * Unbind and destroy the old EGL surface, if
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * there is one.
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 */
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Create an EGL surface we can render into.
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEglConfig, holder, null);
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Before we can issue GL commands, we need to make sure
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * the context is current and bound to a surface.
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEglContext);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GL gl = mEglContext.getGL();
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mGLWrapper != null) {
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                gl = mGLWrapper.wrap(gl);
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS))!= 0) {
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int configFlags = 0;
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Writer log = null;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log = new LogWriter();
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                gl = GLDebugHelper.wrap(gl, configFlags, log);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return gl;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Display the current render surface.
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return false if the context has been lost.
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean swap() {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Always check for EGL_CONTEXT_LOST, which means the context
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * and all associated data were lost (For instance because
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * the device went to sleep). We need to sleep until we
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * get a new surface.
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void finish() {
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglSurface != null) {
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EGL10.EGL_NO_SURFACE,
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EGL10.EGL_NO_CONTEXT);
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEglSurface = null;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglContext != null) {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEglContext = null;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglDisplay != null) {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglTerminate(mEglDisplay);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEglDisplay = null;
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGL10 mEgl;
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLDisplay mEglDisplay;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLSurface mEglSurface;
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLConfig mEglConfig;
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLContext mEglContext;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A generic GL Thread. Takes care of initializing EGL and GL. Delegates
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to a Renderer instance to do the actual drawing. Can be configured to
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * render continuously or on request.
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class GLThread extends Thread {
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        GLThread(Renderer renderer) {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super();
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDone = false;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWidth = 0;
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeight = 0;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRequestRender = true;
8673e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich            mRenderMode = RENDERMODE_CONTINUOUSLY;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRenderer = renderer;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setName("GLThread");
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * When the android framework launches a second instance of
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * an activity, the new instance's onCreate() method may be
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * called before the first instance returns from onDestroy().
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * This semaphore ensures that only one instance at a time
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * accesses EGL.
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sEglSemaphore.acquire();
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (InterruptedException e) {
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                guardedRun();
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException e) {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // fall thru and exit normally
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sEglSemaphore.release();
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void guardedRun() throws InterruptedException {
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglHelper = new EglHelper();
898a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mEglHelper.start();
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GL10 gl = null;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean tellRendererSurfaceCreated = true;
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean tellRendererSurfaceChanged = true;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * This is our main activity thread's loop, we go until
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * asked to quit.
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (!mDone) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /*
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 *  Update the asynchronous state (window size)
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 */
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int w, h;
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed;
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean needStart = false;
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (this) {
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Runnable r;
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((r = getEvent()) != null) {
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        r.run();
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mPaused) {
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mEglHelper.finish();
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        needStart = true;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while (needToWait()) {
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        wait();
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mDone) {
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    changed = mSizeChanged;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    w = mWidth;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    h = mHeight;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSizeChanged = false;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRequestRender = false;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (needStart) {
938a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    mEglHelper.start();
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceCreated = true;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    changed = true;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (changed) {
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    gl = (GL10) mEglHelper.createSurface(getHolder());
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceChanged = true;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (tellRendererSurfaceCreated) {
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceCreated = false;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (tellRendererSurfaceChanged) {
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRenderer.onSurfaceChanged(gl, w, h);
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceChanged = false;
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((w > 0) && (h > 0)) {
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* draw a frame here */
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRenderer.onDrawFrame(gl);
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /*
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     * Once we're done with GL, we need to call swapBuffers()
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     * to instruct the system to display the rendered frame
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     */
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEglHelper.swap();
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             }
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * clean-up everything...
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglHelper.finish();
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean needToWait() {
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDone) {
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPaused || (! mHasSurface)) {
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9813e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich            if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setRenderMode(int renderMode) {
9893e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich            if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("renderMode");
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRenderMode = renderMode;
9943e832dbe966c2ca0fde2f4bd87ad9c974a93a7cfJack Palevich                if (renderMode == RENDERMODE_CONTINUOUSLY) {
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    notify();
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getRenderMode() {
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mRenderMode;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void requestRender() {
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRequestRender = true;
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void surfaceCreated() {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHasSurface = true;
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void surfaceDestroyed() {
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHasSurface = false;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onPause() {
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPaused = true;
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onResume() {
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPaused = false;
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onWindowResize(int w, int h) {
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWidth = w;
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeight = h;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSizeChanged = true;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void requestExitAndWait() {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't call this from GLThread thread or it is a guaranteed
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // deadlock!
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDone = true;
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                join();
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException ex) {
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Thread.currentThread().interrupt();
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Queue an "event" to be run on the GL rendering thread.
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param r the runnable to be run on the GL rendering thread.
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void queueEvent(Runnable r) {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEventQueue.add(r);
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Runnable getEvent() {
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mEventQueue.size() > 0) {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return mEventQueue.remove(0);
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mDone;
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mPaused;
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mHasSurface;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mWidth;
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mHeight;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mRenderMode;
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mRequestRender;
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Renderer mRenderer;
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private EglHelper mEglHelper;
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static class LogWriter extends Writer {
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void close() {
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flushBuilder();
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void flush() {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flushBuilder();
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void write(char[] buf, int offset, int count) {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for(int i = 0; i < count; i++) {
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                char c = buf[offset + i];
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ( c == '\n') {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    flushBuilder();
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                else {
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mBuilder.append(c);
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void flushBuilder() {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBuilder.length() > 0) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.v("GLSurfaceView", mBuilder.toString());
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBuilder.delete(0, mBuilder.length());
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private StringBuilder mBuilder = new StringBuilder();
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Semaphore sEglSemaphore = new Semaphore(1);
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mSizeChanged = true;
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GLThread mGLThread;
1131a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private EGLConfigChooser mEGLConfigChooser;
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GLWrapper mGLWrapper;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mDebugFlags;
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1135