1cfd74d65d832137e20e193c960802afba73b5d38sm/*
23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project
3cfd74d65d832137e20e193c960802afba73b5d38sm *
4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License");
5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License.
6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at
7cfd74d65d832137e20e193c960802afba73b5d38sm *
8cfd74d65d832137e20e193c960802afba73b5d38sm *      http://www.apache.org/licenses/LICENSE-2.0
9cfd74d65d832137e20e193c960802afba73b5d38sm *
10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software
11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS,
12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and
14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License.
15cfd74d65d832137e20e193c960802afba73b5d38sm */
16cfd74d65d832137e20e193c960802afba73b5d38sm
17cfd74d65d832137e20e193c960802afba73b5d38smpackage com.replica.replicaisland;
18cfd74d65d832137e20e193c960802afba73b5d38sm
19cfd74d65d832137e20e193c960802afba73b5d38smimport java.io.Writer;
20cfd74d65d832137e20e193c960802afba73b5d38smimport java.util.ArrayList;
21cfd74d65d832137e20e193c960802afba73b5d38sm
22cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGL10;
23cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGL11;
24cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLConfig;
25cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLContext;
26cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLDisplay;
27cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLSurface;
28cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.opengles.GL;
29cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.opengles.GL10;
30cfd74d65d832137e20e193c960802afba73b5d38sm
31cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.Context;
32cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.pm.ConfigurationInfo;
33cfd74d65d832137e20e193c960802afba73b5d38smimport android.opengl.GLDebugHelper;
34cfd74d65d832137e20e193c960802afba73b5d38smimport android.util.AttributeSet;
35cfd74d65d832137e20e193c960802afba73b5d38smimport android.view.SurfaceHolder;
36cfd74d65d832137e20e193c960802afba73b5d38smimport android.view.SurfaceView;
37cfd74d65d832137e20e193c960802afba73b5d38sm
38cfd74d65d832137e20e193c960802afba73b5d38sm/**
39cfd74d65d832137e20e193c960802afba73b5d38sm * An implementation of SurfaceView that uses the dedicated surface for
40cfd74d65d832137e20e193c960802afba73b5d38sm * displaying OpenGL rendering.
41cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
42cfd74d65d832137e20e193c960802afba73b5d38sm * A GLSurfaceView provides the following features:
43cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
44cfd74d65d832137e20e193c960802afba73b5d38sm * <ul>
45cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Manages a surface, which is a special piece of memory that can be
46cfd74d65d832137e20e193c960802afba73b5d38sm * composited into the Android view system.
47cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Manages an EGL display, which enables OpenGL to render into a surface.
48cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Accepts a user-provided Renderer object that does the actual rendering.
49cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Renders on a dedicated thread to decouple rendering performance from the
50cfd74d65d832137e20e193c960802afba73b5d38sm * UI thread.
51cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Supports both on-demand and continuous rendering.
52cfd74d65d832137e20e193c960802afba73b5d38sm * <li>Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.
53cfd74d65d832137e20e193c960802afba73b5d38sm * </ul>
54cfd74d65d832137e20e193c960802afba73b5d38sm *
55cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Using GLSurfaceView</h3>
56cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
57cfd74d65d832137e20e193c960802afba73b5d38sm * Typically you use GLSurfaceView by subclassing it and overriding one or more of the
58cfd74d65d832137e20e193c960802afba73b5d38sm * View system input event methods. If your application does not need to override event
59cfd74d65d832137e20e193c960802afba73b5d38sm * methods then GLSurfaceView can be used as-is. For the most part
60cfd74d65d832137e20e193c960802afba73b5d38sm * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing.
61cfd74d65d832137e20e193c960802afba73b5d38sm * For example, unlike a regular View, drawing is delegated to a separate Renderer object which
62cfd74d65d832137e20e193c960802afba73b5d38sm * is registered with the GLSurfaceView
63cfd74d65d832137e20e193c960802afba73b5d38sm * using the {@link #setRenderer(Renderer)} call.
64cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
65cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Initializing GLSurfaceView</h3>
66cfd74d65d832137e20e193c960802afba73b5d38sm * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}.
67cfd74d65d832137e20e193c960802afba73b5d38sm * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or
68cfd74d65d832137e20e193c960802afba73b5d38sm * more of these methods before calling setRenderer:
69cfd74d65d832137e20e193c960802afba73b5d38sm * <ul>
70cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setDebugFlags(int)}
71cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(boolean)}
72cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
73cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
74cfd74d65d832137e20e193c960802afba73b5d38sm * <li>{@link #setGLWrapper(GLWrapper)}
75cfd74d65d832137e20e193c960802afba73b5d38sm * </ul>
76cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
77cfd74d65d832137e20e193c960802afba73b5d38sm * <h4>Choosing an EGL Configuration</h4>
78cfd74d65d832137e20e193c960802afba73b5d38sm * A given Android device may support multiple possible types of drawing surfaces.
79cfd74d65d832137e20e193c960802afba73b5d38sm * The available surfaces may differ in how may channels of data are present, as
80cfd74d65d832137e20e193c960802afba73b5d38sm * well as how many bits are allocated to each channel. Therefore, the first thing
81cfd74d65d832137e20e193c960802afba73b5d38sm * GLSurfaceView has to do when starting to render is choose what type of surface to use.
82cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
83cfd74d65d832137e20e193c960802afba73b5d38sm * By default GLSurfaceView chooses an available surface that's closest to a 16-bit R5G6B5 surface
84cfd74d65d832137e20e193c960802afba73b5d38sm * with a 16-bit depth buffer and no stencil. If you would prefer a different surface (for example,
85cfd74d65d832137e20e193c960802afba73b5d38sm * if you do not need a depth buffer) you can override the default behavior by calling one of the
86cfd74d65d832137e20e193c960802afba73b5d38sm * setEGLConfigChooser methods.
87cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
88cfd74d65d832137e20e193c960802afba73b5d38sm * <h4>Debug Behavior</h4>
89cfd74d65d832137e20e193c960802afba73b5d38sm * You can optionally modify the behavior of GLSurfaceView by calling
90cfd74d65d832137e20e193c960802afba73b5d38sm * one or more of the debugging methods {@link #setDebugFlags(int)},
91cfd74d65d832137e20e193c960802afba73b5d38sm * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but
92cfd74d65d832137e20e193c960802afba73b5d38sm * typically they are called before setRenderer so that they take effect immediately.
93cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
94cfd74d65d832137e20e193c960802afba73b5d38sm * <h4>Setting a Renderer</h4>
95cfd74d65d832137e20e193c960802afba73b5d38sm * Finally, you must call {@link #setRenderer} to register a {@link Renderer}.
96cfd74d65d832137e20e193c960802afba73b5d38sm * The renderer is
97cfd74d65d832137e20e193c960802afba73b5d38sm * responsible for doing the actual OpenGL rendering.
98cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
99cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Rendering Mode</h3>
100cfd74d65d832137e20e193c960802afba73b5d38sm * Once the renderer is set, you can control whether the renderer draws
101cfd74d65d832137e20e193c960802afba73b5d38sm * continuously or on-demand by calling
102cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #setRenderMode}. The default is continuous rendering.
103cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
104cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Activity Life-cycle</h3>
105cfd74d65d832137e20e193c960802afba73b5d38sm * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients
106cfd74d65d832137e20e193c960802afba73b5d38sm * are required to call {@link #onPause()} when the activity pauses and
107cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to
108cfd74d65d832137e20e193c960802afba73b5d38sm * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
109cfd74d65d832137e20e193c960802afba73b5d38sm * the OpenGL display.
110cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
111cfd74d65d832137e20e193c960802afba73b5d38sm * <h3>Handling events</h3>
112cfd74d65d832137e20e193c960802afba73b5d38sm * <p>
113cfd74d65d832137e20e193c960802afba73b5d38sm * To handle an event you will typically subclass GLSurfaceView and override the
114cfd74d65d832137e20e193c960802afba73b5d38sm * appropriate method, just as you would with any other View. However, when handling
115cfd74d65d832137e20e193c960802afba73b5d38sm * the event, you may need to communicate with the Renderer object
116cfd74d65d832137e20e193c960802afba73b5d38sm * that's running in the rendering thread. You can do this using any
117cfd74d65d832137e20e193c960802afba73b5d38sm * standard Java cross-thread communication mechanism. In addition,
118cfd74d65d832137e20e193c960802afba73b5d38sm * one relatively easy way to communicate with your renderer is
119cfd74d65d832137e20e193c960802afba73b5d38sm * to call
120cfd74d65d832137e20e193c960802afba73b5d38sm * {@link #queueEvent(Runnable)}. For example:
121cfd74d65d832137e20e193c960802afba73b5d38sm * <pre class="prettyprint">
122cfd74d65d832137e20e193c960802afba73b5d38sm * class MyGLSurfaceView extends GLSurfaceView {
123cfd74d65d832137e20e193c960802afba73b5d38sm *
124cfd74d65d832137e20e193c960802afba73b5d38sm *     private MyRenderer mMyRenderer;
125cfd74d65d832137e20e193c960802afba73b5d38sm *
126cfd74d65d832137e20e193c960802afba73b5d38sm *     public void start() {
127cfd74d65d832137e20e193c960802afba73b5d38sm *         mMyRenderer = ...;
128cfd74d65d832137e20e193c960802afba73b5d38sm *         setRenderer(mMyRenderer);
129cfd74d65d832137e20e193c960802afba73b5d38sm *     }
130cfd74d65d832137e20e193c960802afba73b5d38sm *
131cfd74d65d832137e20e193c960802afba73b5d38sm *     public boolean onKeyDown(int keyCode, KeyEvent event) {
132cfd74d65d832137e20e193c960802afba73b5d38sm *         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
133cfd74d65d832137e20e193c960802afba73b5d38sm *             queueEvent(new Runnable() {
134cfd74d65d832137e20e193c960802afba73b5d38sm *                 // This method will be called on the rendering
135cfd74d65d832137e20e193c960802afba73b5d38sm *                 // thread:
136cfd74d65d832137e20e193c960802afba73b5d38sm *                 public void run() {
137cfd74d65d832137e20e193c960802afba73b5d38sm *                     mMyRenderer.handleDpadCenter();
138cfd74d65d832137e20e193c960802afba73b5d38sm *                 }});
139cfd74d65d832137e20e193c960802afba73b5d38sm *             return true;
140cfd74d65d832137e20e193c960802afba73b5d38sm *         }
141cfd74d65d832137e20e193c960802afba73b5d38sm *         return super.onKeyDown(keyCode, event);
142cfd74d65d832137e20e193c960802afba73b5d38sm *     }
143cfd74d65d832137e20e193c960802afba73b5d38sm * }
144cfd74d65d832137e20e193c960802afba73b5d38sm * </pre>
145cfd74d65d832137e20e193c960802afba73b5d38sm *
146cfd74d65d832137e20e193c960802afba73b5d38sm */
147cfd74d65d832137e20e193c960802afba73b5d38smpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
148cfd74d65d832137e20e193c960802afba73b5d38sm    private final static boolean LOG_THREADS = false;
149cfd74d65d832137e20e193c960802afba73b5d38sm    private final static boolean LOG_SURFACE = true;
150cfd74d65d832137e20e193c960802afba73b5d38sm    private final static boolean LOG_RENDERER = false;
151cfd74d65d832137e20e193c960802afba73b5d38sm    // Work-around for bug 2263168
152cfd74d65d832137e20e193c960802afba73b5d38sm    private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true;
153cfd74d65d832137e20e193c960802afba73b5d38sm    /**
154cfd74d65d832137e20e193c960802afba73b5d38sm     * The renderer only renders
155cfd74d65d832137e20e193c960802afba73b5d38sm     * when the surface is created, or when {@link #requestRender} is called.
156cfd74d65d832137e20e193c960802afba73b5d38sm     *
157cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #getRenderMode()
158cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #setRenderMode(int)
159cfd74d65d832137e20e193c960802afba73b5d38sm     */
160cfd74d65d832137e20e193c960802afba73b5d38sm    public final static int RENDERMODE_WHEN_DIRTY = 0;
161cfd74d65d832137e20e193c960802afba73b5d38sm    /**
162cfd74d65d832137e20e193c960802afba73b5d38sm     * The renderer is called
163cfd74d65d832137e20e193c960802afba73b5d38sm     * continuously to re-render the scene.
164cfd74d65d832137e20e193c960802afba73b5d38sm     *
165cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #getRenderMode()
166cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #setRenderMode(int)
167cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #requestRender()
168cfd74d65d832137e20e193c960802afba73b5d38sm     */
169cfd74d65d832137e20e193c960802afba73b5d38sm    public final static int RENDERMODE_CONTINUOUSLY = 1;
170cfd74d65d832137e20e193c960802afba73b5d38sm
171cfd74d65d832137e20e193c960802afba73b5d38sm    /**
172cfd74d65d832137e20e193c960802afba73b5d38sm     * Check glError() after every GL call and throw an exception if glError indicates
173cfd74d65d832137e20e193c960802afba73b5d38sm     * that an error has occurred. This can be used to help track down which OpenGL ES call
174cfd74d65d832137e20e193c960802afba73b5d38sm     * is causing an error.
175cfd74d65d832137e20e193c960802afba73b5d38sm     *
176cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #getDebugFlags
177cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #setDebugFlags
178cfd74d65d832137e20e193c960802afba73b5d38sm     */
179cfd74d65d832137e20e193c960802afba73b5d38sm    public final static int DEBUG_CHECK_GL_ERROR = 1;
180cfd74d65d832137e20e193c960802afba73b5d38sm
181cfd74d65d832137e20e193c960802afba73b5d38sm    /**
182cfd74d65d832137e20e193c960802afba73b5d38sm     * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView".
183cfd74d65d832137e20e193c960802afba73b5d38sm     *
184cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #getDebugFlags
185cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #setDebugFlags
186cfd74d65d832137e20e193c960802afba73b5d38sm     */
187cfd74d65d832137e20e193c960802afba73b5d38sm    public final static int DEBUG_LOG_GL_CALLS = 2;
188cfd74d65d832137e20e193c960802afba73b5d38sm
189cfd74d65d832137e20e193c960802afba73b5d38sm    /**
190cfd74d65d832137e20e193c960802afba73b5d38sm     * Standard View constructor. In order to render something, you
191cfd74d65d832137e20e193c960802afba73b5d38sm     * must call {@link #setRenderer} to register a renderer.
192cfd74d65d832137e20e193c960802afba73b5d38sm     */
193cfd74d65d832137e20e193c960802afba73b5d38sm    public GLSurfaceView(Context context) {
194cfd74d65d832137e20e193c960802afba73b5d38sm        super(context);
195cfd74d65d832137e20e193c960802afba73b5d38sm        init();
196cfd74d65d832137e20e193c960802afba73b5d38sm    }
197cfd74d65d832137e20e193c960802afba73b5d38sm
198cfd74d65d832137e20e193c960802afba73b5d38sm    /**
199cfd74d65d832137e20e193c960802afba73b5d38sm     * Standard View constructor. In order to render something, you
200cfd74d65d832137e20e193c960802afba73b5d38sm     * must call {@link #setRenderer} to register a renderer.
201cfd74d65d832137e20e193c960802afba73b5d38sm     */
202cfd74d65d832137e20e193c960802afba73b5d38sm    public GLSurfaceView(Context context, AttributeSet attrs) {
203cfd74d65d832137e20e193c960802afba73b5d38sm        super(context, attrs);
204cfd74d65d832137e20e193c960802afba73b5d38sm        init();
205cfd74d65d832137e20e193c960802afba73b5d38sm    }
206cfd74d65d832137e20e193c960802afba73b5d38sm
207cfd74d65d832137e20e193c960802afba73b5d38sm    private void init() {
208cfd74d65d832137e20e193c960802afba73b5d38sm        // Install a SurfaceHolder.Callback so we get notified when the
209cfd74d65d832137e20e193c960802afba73b5d38sm        // underlying surface is created and destroyed
210cfd74d65d832137e20e193c960802afba73b5d38sm        SurfaceHolder holder = getHolder();
211cfd74d65d832137e20e193c960802afba73b5d38sm        holder.addCallback(this);
212cfd74d65d832137e20e193c960802afba73b5d38sm        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
213cfd74d65d832137e20e193c960802afba73b5d38sm
214cfd74d65d832137e20e193c960802afba73b5d38sm    }
215cfd74d65d832137e20e193c960802afba73b5d38sm
216cfd74d65d832137e20e193c960802afba73b5d38sm    /**
217cfd74d65d832137e20e193c960802afba73b5d38sm     * Set the glWrapper. If the glWrapper is not null, its
218cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link GLWrapper#wrap(GL)} method is called
219cfd74d65d832137e20e193c960802afba73b5d38sm     * whenever a surface is created. A GLWrapper can be used to wrap
220cfd74d65d832137e20e193c960802afba73b5d38sm     * the GL object that's passed to the renderer. Wrapping a GL
221cfd74d65d832137e20e193c960802afba73b5d38sm     * object enables examining and modifying the behavior of the
222cfd74d65d832137e20e193c960802afba73b5d38sm     * GL calls made by the renderer.
223cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
224cfd74d65d832137e20e193c960802afba73b5d38sm     * Wrapping is typically used for debugging purposes.
225cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
226cfd74d65d832137e20e193c960802afba73b5d38sm     * The default value is null.
227cfd74d65d832137e20e193c960802afba73b5d38sm     * @param glWrapper the new GLWrapper
228cfd74d65d832137e20e193c960802afba73b5d38sm     */
229cfd74d65d832137e20e193c960802afba73b5d38sm    public void setGLWrapper(GLWrapper glWrapper) {
230cfd74d65d832137e20e193c960802afba73b5d38sm        mGLWrapper = glWrapper;
231cfd74d65d832137e20e193c960802afba73b5d38sm    }
232cfd74d65d832137e20e193c960802afba73b5d38sm
233cfd74d65d832137e20e193c960802afba73b5d38sm    /**
234cfd74d65d832137e20e193c960802afba73b5d38sm     * Set the debug flags to a new value. The value is
235cfd74d65d832137e20e193c960802afba73b5d38sm     * constructed by OR-together zero or more
236cfd74d65d832137e20e193c960802afba73b5d38sm     * of the DEBUG_CHECK_* constants. The debug flags take effect
237cfd74d65d832137e20e193c960802afba73b5d38sm     * whenever a surface is created. The default value is zero.
238cfd74d65d832137e20e193c960802afba73b5d38sm     * @param debugFlags the new debug flags
239cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #DEBUG_CHECK_GL_ERROR
240cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #DEBUG_LOG_GL_CALLS
241cfd74d65d832137e20e193c960802afba73b5d38sm     */
242cfd74d65d832137e20e193c960802afba73b5d38sm    public void setDebugFlags(int debugFlags) {
243cfd74d65d832137e20e193c960802afba73b5d38sm        mDebugFlags = debugFlags;
244cfd74d65d832137e20e193c960802afba73b5d38sm    }
245cfd74d65d832137e20e193c960802afba73b5d38sm
246cfd74d65d832137e20e193c960802afba73b5d38sm    /**
247cfd74d65d832137e20e193c960802afba73b5d38sm     * Get the current value of the debug flags.
248cfd74d65d832137e20e193c960802afba73b5d38sm     * @return the current value of the debug flags.
249cfd74d65d832137e20e193c960802afba73b5d38sm     */
250cfd74d65d832137e20e193c960802afba73b5d38sm    public int getDebugFlags() {
251cfd74d65d832137e20e193c960802afba73b5d38sm        return mDebugFlags;
252cfd74d65d832137e20e193c960802afba73b5d38sm    }
253cfd74d65d832137e20e193c960802afba73b5d38sm
254cfd74d65d832137e20e193c960802afba73b5d38sm    /**
255cfd74d65d832137e20e193c960802afba73b5d38sm     * Set the renderer associated with this view. Also starts the thread that
256cfd74d65d832137e20e193c960802afba73b5d38sm     * will call the renderer, which in turn causes the rendering to start.
257cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>This method should be called once and only once in the life-cycle of
258cfd74d65d832137e20e193c960802afba73b5d38sm     * a GLSurfaceView.
259cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>The following GLSurfaceView methods can only be called <em>before</em>
260cfd74d65d832137e20e193c960802afba73b5d38sm     * setRenderer is called:
261cfd74d65d832137e20e193c960802afba73b5d38sm     * <ul>
262cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #setEGLConfigChooser(boolean)}
263cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
264cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
265cfd74d65d832137e20e193c960802afba73b5d38sm     * </ul>
266cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
267cfd74d65d832137e20e193c960802afba73b5d38sm     * The following GLSurfaceView methods can only be called <em>after</em>
268cfd74d65d832137e20e193c960802afba73b5d38sm     * setRenderer is called:
269cfd74d65d832137e20e193c960802afba73b5d38sm     * <ul>
270cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #getRenderMode()}
271cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #onPause()}
272cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #onResume()}
273cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #queueEvent(Runnable)}
274cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #requestRender()}
275cfd74d65d832137e20e193c960802afba73b5d38sm     * <li>{@link #setRenderMode(int)}
276cfd74d65d832137e20e193c960802afba73b5d38sm     * </ul>
277cfd74d65d832137e20e193c960802afba73b5d38sm     *
278cfd74d65d832137e20e193c960802afba73b5d38sm     * @param renderer the renderer to use to perform OpenGL drawing.
279cfd74d65d832137e20e193c960802afba73b5d38sm     */
280cfd74d65d832137e20e193c960802afba73b5d38sm    public void setRenderer(Renderer renderer) {
281cfd74d65d832137e20e193c960802afba73b5d38sm        checkRenderThreadState();
282cfd74d65d832137e20e193c960802afba73b5d38sm        if (mEGLConfigChooser == null) {
283cfd74d65d832137e20e193c960802afba73b5d38sm            mEGLConfigChooser = new SimpleEGLConfigChooser(true);
284cfd74d65d832137e20e193c960802afba73b5d38sm        }
285cfd74d65d832137e20e193c960802afba73b5d38sm        if (mEGLContextFactory == null) {
286cfd74d65d832137e20e193c960802afba73b5d38sm            mEGLContextFactory = new DefaultContextFactory();
287cfd74d65d832137e20e193c960802afba73b5d38sm        }
288cfd74d65d832137e20e193c960802afba73b5d38sm        if (mEGLWindowSurfaceFactory == null) {
289cfd74d65d832137e20e193c960802afba73b5d38sm            mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
290cfd74d65d832137e20e193c960802afba73b5d38sm        }
291cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread = new GLThread(renderer);
292cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.start();
293cfd74d65d832137e20e193c960802afba73b5d38sm    }
294cfd74d65d832137e20e193c960802afba73b5d38sm
295cfd74d65d832137e20e193c960802afba73b5d38sm    /**
296cfd74d65d832137e20e193c960802afba73b5d38sm     * Install a custom EGLContextFactory.
297cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>If this method is
298cfd74d65d832137e20e193c960802afba73b5d38sm     * called, it must be called before {@link #setRenderer(Renderer)}
299cfd74d65d832137e20e193c960802afba73b5d38sm     * is called.
300cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
301cfd74d65d832137e20e193c960802afba73b5d38sm     * If this method is not called, then by default
302cfd74d65d832137e20e193c960802afba73b5d38sm     * a context will be created with no shared context and
303cfd74d65d832137e20e193c960802afba73b5d38sm     * with a null attribute list.
304cfd74d65d832137e20e193c960802afba73b5d38sm     */
305cfd74d65d832137e20e193c960802afba73b5d38sm    public void setEGLContextFactory(EGLContextFactory factory) {
306cfd74d65d832137e20e193c960802afba73b5d38sm        checkRenderThreadState();
307cfd74d65d832137e20e193c960802afba73b5d38sm        mEGLContextFactory = factory;
308cfd74d65d832137e20e193c960802afba73b5d38sm    }
309cfd74d65d832137e20e193c960802afba73b5d38sm
310cfd74d65d832137e20e193c960802afba73b5d38sm    /**
311cfd74d65d832137e20e193c960802afba73b5d38sm     * Install a custom EGLWindowSurfaceFactory.
312cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>If this method is
313cfd74d65d832137e20e193c960802afba73b5d38sm     * called, it must be called before {@link #setRenderer(Renderer)}
314cfd74d65d832137e20e193c960802afba73b5d38sm     * is called.
315cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
316cfd74d65d832137e20e193c960802afba73b5d38sm     * If this method is not called, then by default
317cfd74d65d832137e20e193c960802afba73b5d38sm     * a window surface will be created with a null attribute list.
318cfd74d65d832137e20e193c960802afba73b5d38sm     */
319cfd74d65d832137e20e193c960802afba73b5d38sm    public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
320cfd74d65d832137e20e193c960802afba73b5d38sm        checkRenderThreadState();
321cfd74d65d832137e20e193c960802afba73b5d38sm        mEGLWindowSurfaceFactory = factory;
322cfd74d65d832137e20e193c960802afba73b5d38sm    }
323cfd74d65d832137e20e193c960802afba73b5d38sm
324cfd74d65d832137e20e193c960802afba73b5d38sm    /**
325cfd74d65d832137e20e193c960802afba73b5d38sm     * Install a custom EGLConfigChooser.
326cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>If this method is
327cfd74d65d832137e20e193c960802afba73b5d38sm     * called, it must be called before {@link #setRenderer(Renderer)}
328cfd74d65d832137e20e193c960802afba73b5d38sm     * is called.
329cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
330cfd74d65d832137e20e193c960802afba73b5d38sm     * If no setEGLConfigChooser method is called, then by default the
331cfd74d65d832137e20e193c960802afba73b5d38sm     * view will choose a config as close to 16-bit RGB as possible, with
332cfd74d65d832137e20e193c960802afba73b5d38sm     * a depth buffer as close to 16 bits as possible.
333cfd74d65d832137e20e193c960802afba73b5d38sm     * @param configChooser
334cfd74d65d832137e20e193c960802afba73b5d38sm     */
335cfd74d65d832137e20e193c960802afba73b5d38sm    public void setEGLConfigChooser(EGLConfigChooser configChooser) {
336cfd74d65d832137e20e193c960802afba73b5d38sm        checkRenderThreadState();
337cfd74d65d832137e20e193c960802afba73b5d38sm        mEGLConfigChooser = configChooser;
338cfd74d65d832137e20e193c960802afba73b5d38sm    }
339cfd74d65d832137e20e193c960802afba73b5d38sm
340cfd74d65d832137e20e193c960802afba73b5d38sm    /**
341cfd74d65d832137e20e193c960802afba73b5d38sm     * Install a config chooser which will choose a config
342cfd74d65d832137e20e193c960802afba73b5d38sm     * as close to 16-bit RGB as possible, with or without an optional depth
343cfd74d65d832137e20e193c960802afba73b5d38sm     * buffer as close to 16-bits as possible.
344cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>If this method is
345cfd74d65d832137e20e193c960802afba73b5d38sm     * called, it must be called before {@link #setRenderer(Renderer)}
346cfd74d65d832137e20e193c960802afba73b5d38sm     * is called.
347cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
348cfd74d65d832137e20e193c960802afba73b5d38sm      * If no setEGLConfigChooser method is called, then by default the
349cfd74d65d832137e20e193c960802afba73b5d38sm     * view will choose a config as close to 16-bit RGB as possible, with
350cfd74d65d832137e20e193c960802afba73b5d38sm     * a depth buffer as close to 16 bits as possible.
351cfd74d65d832137e20e193c960802afba73b5d38sm     *
352cfd74d65d832137e20e193c960802afba73b5d38sm     * @param needDepth
353cfd74d65d832137e20e193c960802afba73b5d38sm     */
354cfd74d65d832137e20e193c960802afba73b5d38sm    public void setEGLConfigChooser(boolean needDepth) {
355cfd74d65d832137e20e193c960802afba73b5d38sm        setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
356cfd74d65d832137e20e193c960802afba73b5d38sm    }
357cfd74d65d832137e20e193c960802afba73b5d38sm
358cfd74d65d832137e20e193c960802afba73b5d38sm    /**
359cfd74d65d832137e20e193c960802afba73b5d38sm     * Install a config chooser which will choose a config
360cfd74d65d832137e20e193c960802afba73b5d38sm     * with at least the specified component sizes, and as close
361cfd74d65d832137e20e193c960802afba73b5d38sm     * to the specified component sizes as possible.
362cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>If this method is
363cfd74d65d832137e20e193c960802afba73b5d38sm     * called, it must be called before {@link #setRenderer(Renderer)}
364cfd74d65d832137e20e193c960802afba73b5d38sm     * is called.
365cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
366cfd74d65d832137e20e193c960802afba73b5d38sm     * If no setEGLConfigChooser method is called, then by default the
367cfd74d65d832137e20e193c960802afba73b5d38sm     * view will choose a config as close to 16-bit RGB as possible, with
368cfd74d65d832137e20e193c960802afba73b5d38sm     * a depth buffer as close to 16 bits as possible.
369cfd74d65d832137e20e193c960802afba73b5d38sm     *
370cfd74d65d832137e20e193c960802afba73b5d38sm     */
371cfd74d65d832137e20e193c960802afba73b5d38sm    public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
372cfd74d65d832137e20e193c960802afba73b5d38sm            int alphaSize, int depthSize, int stencilSize) {
373cfd74d65d832137e20e193c960802afba73b5d38sm        setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
374cfd74d65d832137e20e193c960802afba73b5d38sm                blueSize, alphaSize, depthSize, stencilSize));
375cfd74d65d832137e20e193c960802afba73b5d38sm    }
376cfd74d65d832137e20e193c960802afba73b5d38sm
377cfd74d65d832137e20e193c960802afba73b5d38sm    /**
378cfd74d65d832137e20e193c960802afba73b5d38sm     * Inform the default EGLContextFactory and default EGLConfigChooser
379cfd74d65d832137e20e193c960802afba73b5d38sm     * which EGLContext client version to pick.
380cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>Use this method to create an OpenGL ES 2.0-compatible context.
381cfd74d65d832137e20e193c960802afba73b5d38sm     * Example:
382cfd74d65d832137e20e193c960802afba73b5d38sm     * <pre class="prettyprint">
383cfd74d65d832137e20e193c960802afba73b5d38sm     *     public MyView(Context context) {
384cfd74d65d832137e20e193c960802afba73b5d38sm     *         super(context);
385cfd74d65d832137e20e193c960802afba73b5d38sm     *         setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
386cfd74d65d832137e20e193c960802afba73b5d38sm     *         setRenderer(new MyRenderer());
387cfd74d65d832137e20e193c960802afba73b5d38sm     *     }
388cfd74d65d832137e20e193c960802afba73b5d38sm     * </pre>
389cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>Note: Activities which require OpenGL ES 2.0 should indicate this by
390cfd74d65d832137e20e193c960802afba73b5d38sm     * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's
391cfd74d65d832137e20e193c960802afba73b5d38sm     * AndroidManifest.xml file.
392cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>If this method is called, it must be called before {@link #setRenderer(Renderer)}
393cfd74d65d832137e20e193c960802afba73b5d38sm     * is called.
394cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>This method only affects the behavior of the default EGLContexFactory and the
395cfd74d65d832137e20e193c960802afba73b5d38sm     * default EGLConfigChooser. If
396cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied
397cfd74d65d832137e20e193c960802afba73b5d38sm     * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context.
398cfd74d65d832137e20e193c960802afba73b5d38sm     * If
399cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied
400cfd74d65d832137e20e193c960802afba73b5d38sm     * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config.
401cfd74d65d832137e20e193c960802afba73b5d38sm     * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0
402cfd74d65d832137e20e193c960802afba73b5d38sm     */
403cfd74d65d832137e20e193c960802afba73b5d38sm    public void setEGLContextClientVersion(int version) {
404cfd74d65d832137e20e193c960802afba73b5d38sm        checkRenderThreadState();
405cfd74d65d832137e20e193c960802afba73b5d38sm        mEGLContextClientVersion = version;
406cfd74d65d832137e20e193c960802afba73b5d38sm    }
407cfd74d65d832137e20e193c960802afba73b5d38sm
408cfd74d65d832137e20e193c960802afba73b5d38sm    /**
409cfd74d65d832137e20e193c960802afba73b5d38sm     * Set the rendering mode. When renderMode is
410cfd74d65d832137e20e193c960802afba73b5d38sm     * RENDERMODE_CONTINUOUSLY, the renderer is called
411cfd74d65d832137e20e193c960802afba73b5d38sm     * repeatedly to re-render the scene. When renderMode
412cfd74d65d832137e20e193c960802afba73b5d38sm     * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
413cfd74d65d832137e20e193c960802afba73b5d38sm     * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
414cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
415cfd74d65d832137e20e193c960802afba73b5d38sm     * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance
416cfd74d65d832137e20e193c960802afba73b5d38sm     * by allowing the GPU and CPU to idle when the view does not need to be updated.
417cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
418cfd74d65d832137e20e193c960802afba73b5d38sm     * This method can only be called after {@link #setRenderer(Renderer)}
419cfd74d65d832137e20e193c960802afba73b5d38sm     *
420cfd74d65d832137e20e193c960802afba73b5d38sm     * @param renderMode one of the RENDERMODE_X constants
421cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #RENDERMODE_CONTINUOUSLY
422cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #RENDERMODE_WHEN_DIRTY
423cfd74d65d832137e20e193c960802afba73b5d38sm     */
424cfd74d65d832137e20e193c960802afba73b5d38sm    public void setRenderMode(int renderMode) {
425cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.setRenderMode(renderMode);
426cfd74d65d832137e20e193c960802afba73b5d38sm    }
427cfd74d65d832137e20e193c960802afba73b5d38sm
428cfd74d65d832137e20e193c960802afba73b5d38sm    /**
429cfd74d65d832137e20e193c960802afba73b5d38sm     * Get the current rendering mode. May be called
430cfd74d65d832137e20e193c960802afba73b5d38sm     * from any thread. Must not be called before a renderer has been set.
431cfd74d65d832137e20e193c960802afba73b5d38sm     * @return the current rendering mode.
432cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #RENDERMODE_CONTINUOUSLY
433cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #RENDERMODE_WHEN_DIRTY
434cfd74d65d832137e20e193c960802afba73b5d38sm     */
435cfd74d65d832137e20e193c960802afba73b5d38sm    public int getRenderMode() {
436cfd74d65d832137e20e193c960802afba73b5d38sm        return mGLThread.getRenderMode();
437cfd74d65d832137e20e193c960802afba73b5d38sm    }
438cfd74d65d832137e20e193c960802afba73b5d38sm
439cfd74d65d832137e20e193c960802afba73b5d38sm    /**
440cfd74d65d832137e20e193c960802afba73b5d38sm     * Request that the renderer render a frame.
441cfd74d65d832137e20e193c960802afba73b5d38sm     * This method is typically used when the render mode has been set to
442cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand.
443cfd74d65d832137e20e193c960802afba73b5d38sm     * May be called
444cfd74d65d832137e20e193c960802afba73b5d38sm     * from any thread. Must not be called before a renderer has been set.
445cfd74d65d832137e20e193c960802afba73b5d38sm     */
446cfd74d65d832137e20e193c960802afba73b5d38sm    public void requestRender() {
447cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.requestRender();
448cfd74d65d832137e20e193c960802afba73b5d38sm    }
449cfd74d65d832137e20e193c960802afba73b5d38sm
450cfd74d65d832137e20e193c960802afba73b5d38sm    /**
451cfd74d65d832137e20e193c960802afba73b5d38sm     * This method is part of the SurfaceHolder.Callback interface, and is
452cfd74d65d832137e20e193c960802afba73b5d38sm     * not normally called or subclassed by clients of GLSurfaceView.
453cfd74d65d832137e20e193c960802afba73b5d38sm     */
454cfd74d65d832137e20e193c960802afba73b5d38sm    public void surfaceCreated(SurfaceHolder holder) {
455cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.surfaceCreated();
456cfd74d65d832137e20e193c960802afba73b5d38sm    }
457cfd74d65d832137e20e193c960802afba73b5d38sm
458cfd74d65d832137e20e193c960802afba73b5d38sm    /**
459cfd74d65d832137e20e193c960802afba73b5d38sm     * This method is part of the SurfaceHolder.Callback interface, and is
460cfd74d65d832137e20e193c960802afba73b5d38sm     * not normally called or subclassed by clients of GLSurfaceView.
461cfd74d65d832137e20e193c960802afba73b5d38sm     */
462cfd74d65d832137e20e193c960802afba73b5d38sm    public void surfaceDestroyed(SurfaceHolder holder) {
463cfd74d65d832137e20e193c960802afba73b5d38sm        // Surface will be destroyed when we return
464cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.surfaceDestroyed();
465cfd74d65d832137e20e193c960802afba73b5d38sm    }
466cfd74d65d832137e20e193c960802afba73b5d38sm
467cfd74d65d832137e20e193c960802afba73b5d38sm    /**
468cfd74d65d832137e20e193c960802afba73b5d38sm     * This method is part of the SurfaceHolder.Callback interface, and is
469cfd74d65d832137e20e193c960802afba73b5d38sm     * not normally called or subclassed by clients of GLSurfaceView.
470cfd74d65d832137e20e193c960802afba73b5d38sm     */
471cfd74d65d832137e20e193c960802afba73b5d38sm    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
472cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.onWindowResize(w, h);
473cfd74d65d832137e20e193c960802afba73b5d38sm    }
474cfd74d65d832137e20e193c960802afba73b5d38sm
475cfd74d65d832137e20e193c960802afba73b5d38sm    /**
476cfd74d65d832137e20e193c960802afba73b5d38sm     * Inform the view that the activity is paused. The owner of this view must
477cfd74d65d832137e20e193c960802afba73b5d38sm     * call this method when the activity is paused. Calling this method will
478cfd74d65d832137e20e193c960802afba73b5d38sm     * pause the rendering thread.
479cfd74d65d832137e20e193c960802afba73b5d38sm     * Must not be called before a renderer has been set.
480cfd74d65d832137e20e193c960802afba73b5d38sm     */
481cfd74d65d832137e20e193c960802afba73b5d38sm    public void onPause() {
4826cb78e547641bcab6f18ec34badca0840e000992Keun young Park        mWatchDog.stop();
483cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.onPause();
484cfd74d65d832137e20e193c960802afba73b5d38sm    }
485cfd74d65d832137e20e193c960802afba73b5d38sm
486cfd74d65d832137e20e193c960802afba73b5d38sm    /**
487cfd74d65d832137e20e193c960802afba73b5d38sm     * Inform the view that the activity is resumed. The owner of this view must
488cfd74d65d832137e20e193c960802afba73b5d38sm     * call this method when the activity is resumed. Calling this method will
489cfd74d65d832137e20e193c960802afba73b5d38sm     * recreate the OpenGL display and resume the rendering
490cfd74d65d832137e20e193c960802afba73b5d38sm     * thread.
491cfd74d65d832137e20e193c960802afba73b5d38sm     * Must not be called before a renderer has been set.
492cfd74d65d832137e20e193c960802afba73b5d38sm     */
493cfd74d65d832137e20e193c960802afba73b5d38sm    public void onResume() {
4946cb78e547641bcab6f18ec34badca0840e000992Keun young Park        mWatchDog.start();
495cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.onResume();
496cfd74d65d832137e20e193c960802afba73b5d38sm    }
497cfd74d65d832137e20e193c960802afba73b5d38sm
498cfd74d65d832137e20e193c960802afba73b5d38sm    public void flushTextures(TextureLibrary library) {
499cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.flushTextures(library);
500cfd74d65d832137e20e193c960802afba73b5d38sm    }
501cfd74d65d832137e20e193c960802afba73b5d38sm
502cfd74d65d832137e20e193c960802afba73b5d38sm    public void loadTextures(TextureLibrary library) {
503cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.loadTextures(library);
504cfd74d65d832137e20e193c960802afba73b5d38sm    }
505cfd74d65d832137e20e193c960802afba73b5d38sm
506cfd74d65d832137e20e193c960802afba73b5d38sm    public void flushBuffers(BufferLibrary library) {
507cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.flushBuffers(library);
508cfd74d65d832137e20e193c960802afba73b5d38sm    }
509cfd74d65d832137e20e193c960802afba73b5d38sm
510cfd74d65d832137e20e193c960802afba73b5d38sm    public void loadBuffers(BufferLibrary library) {
511cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.loadBuffers(library);
512cfd74d65d832137e20e193c960802afba73b5d38sm    }
5139d4cc2572d37983607df38b0f4216ed76ac51814sm
5149d4cc2572d37983607df38b0f4216ed76ac51814sm    public void setSafeMode(boolean safeMode) {
5159d4cc2572d37983607df38b0f4216ed76ac51814sm    	mGLThread.setSafeMode(safeMode);
5169d4cc2572d37983607df38b0f4216ed76ac51814sm    }
517cfd74d65d832137e20e193c960802afba73b5d38sm
518cfd74d65d832137e20e193c960802afba73b5d38sm    /**
519cfd74d65d832137e20e193c960802afba73b5d38sm     * Queue a runnable to be run on the GL rendering thread. This can be used
520cfd74d65d832137e20e193c960802afba73b5d38sm     * to communicate with the Renderer on the rendering thread.
521cfd74d65d832137e20e193c960802afba73b5d38sm     * Must not be called before a renderer has been set.
522cfd74d65d832137e20e193c960802afba73b5d38sm     * @param r the runnable to be run on the GL rendering thread.
523cfd74d65d832137e20e193c960802afba73b5d38sm     */
524cfd74d65d832137e20e193c960802afba73b5d38sm    public void queueEvent(Runnable r) {
525cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.queueEvent(r);
526cfd74d65d832137e20e193c960802afba73b5d38sm    }
527cfd74d65d832137e20e193c960802afba73b5d38sm
528cfd74d65d832137e20e193c960802afba73b5d38sm    /**
529cfd74d65d832137e20e193c960802afba73b5d38sm     * Inform the view that the window focus has changed.
530cfd74d65d832137e20e193c960802afba73b5d38sm     */
531cfd74d65d832137e20e193c960802afba73b5d38sm    @Override
532cfd74d65d832137e20e193c960802afba73b5d38sm    public void onWindowFocusChanged(boolean hasFocus) {
533cfd74d65d832137e20e193c960802afba73b5d38sm        super.onWindowFocusChanged(hasFocus);
534cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.onWindowFocusChanged(hasFocus);
535cfd74d65d832137e20e193c960802afba73b5d38sm    }
536cfd74d65d832137e20e193c960802afba73b5d38sm
537cfd74d65d832137e20e193c960802afba73b5d38sm    /**
538cfd74d65d832137e20e193c960802afba73b5d38sm     * This method is used as part of the View class and is not normally
539cfd74d65d832137e20e193c960802afba73b5d38sm     * called or subclassed by clients of GLSurfaceView.
540cfd74d65d832137e20e193c960802afba73b5d38sm     * Must not be called before a renderer has been set.
541cfd74d65d832137e20e193c960802afba73b5d38sm     */
542cfd74d65d832137e20e193c960802afba73b5d38sm    @Override
543cfd74d65d832137e20e193c960802afba73b5d38sm    protected void onDetachedFromWindow() {
544cfd74d65d832137e20e193c960802afba73b5d38sm        super.onDetachedFromWindow();
545cfd74d65d832137e20e193c960802afba73b5d38sm        mGLThread.requestExitAndWait();
546cfd74d65d832137e20e193c960802afba73b5d38sm    }
547cfd74d65d832137e20e193c960802afba73b5d38sm
548cfd74d65d832137e20e193c960802afba73b5d38sm    // ----------------------------------------------------------------------
549cfd74d65d832137e20e193c960802afba73b5d38sm
550cfd74d65d832137e20e193c960802afba73b5d38sm    /**
551cfd74d65d832137e20e193c960802afba73b5d38sm     * An interface used to wrap a GL interface.
552cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>Typically
553cfd74d65d832137e20e193c960802afba73b5d38sm     * used for implementing debugging and tracing on top of the default
554cfd74d65d832137e20e193c960802afba73b5d38sm     * GL interface. You would typically use this by creating your own class
555cfd74d65d832137e20e193c960802afba73b5d38sm     * that implemented all the GL methods by delegating to another GL instance.
556cfd74d65d832137e20e193c960802afba73b5d38sm     * Then you could add your own behavior before or after calling the
557cfd74d65d832137e20e193c960802afba73b5d38sm     * delegate. All the GLWrapper would do was instantiate and return the
558cfd74d65d832137e20e193c960802afba73b5d38sm     * wrapper GL instance:
559cfd74d65d832137e20e193c960802afba73b5d38sm     * <pre class="prettyprint">
560cfd74d65d832137e20e193c960802afba73b5d38sm     * class MyGLWrapper implements GLWrapper {
561cfd74d65d832137e20e193c960802afba73b5d38sm     *     GL wrap(GL gl) {
562cfd74d65d832137e20e193c960802afba73b5d38sm     *         return new MyGLImplementation(gl);
563cfd74d65d832137e20e193c960802afba73b5d38sm     *     }
564cfd74d65d832137e20e193c960802afba73b5d38sm     *     static class MyGLImplementation implements GL,GL10,GL11,... {
565cfd74d65d832137e20e193c960802afba73b5d38sm     *         ...
566cfd74d65d832137e20e193c960802afba73b5d38sm     *     }
567cfd74d65d832137e20e193c960802afba73b5d38sm     * }
568cfd74d65d832137e20e193c960802afba73b5d38sm     * </pre>
569cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #setGLWrapper(GLWrapper)
570cfd74d65d832137e20e193c960802afba73b5d38sm     */
571cfd74d65d832137e20e193c960802afba73b5d38sm    public interface GLWrapper {
572cfd74d65d832137e20e193c960802afba73b5d38sm        /**
573cfd74d65d832137e20e193c960802afba73b5d38sm         * Wraps a gl interface in another gl interface.
574cfd74d65d832137e20e193c960802afba73b5d38sm         * @param gl a GL interface that is to be wrapped.
575cfd74d65d832137e20e193c960802afba73b5d38sm         * @return either the input argument or another GL object that wraps the input argument.
576cfd74d65d832137e20e193c960802afba73b5d38sm         */
577cfd74d65d832137e20e193c960802afba73b5d38sm        GL wrap(GL gl);
578cfd74d65d832137e20e193c960802afba73b5d38sm    }
579cfd74d65d832137e20e193c960802afba73b5d38sm
580cfd74d65d832137e20e193c960802afba73b5d38sm    /**
581cfd74d65d832137e20e193c960802afba73b5d38sm     * A generic renderer interface.
582cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
583cfd74d65d832137e20e193c960802afba73b5d38sm     * The renderer is responsible for making OpenGL calls to render a frame.
584cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
585cfd74d65d832137e20e193c960802afba73b5d38sm     * GLSurfaceView clients typically create their own classes that implement
586cfd74d65d832137e20e193c960802afba73b5d38sm     * this interface, and then call {@link GLSurfaceView#setRenderer} to
587cfd74d65d832137e20e193c960802afba73b5d38sm     * register the renderer with the GLSurfaceView.
588cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
589cfd74d65d832137e20e193c960802afba73b5d38sm     * <h3>Threading</h3>
590cfd74d65d832137e20e193c960802afba73b5d38sm     * The renderer will be called on a separate thread, so that rendering
591cfd74d65d832137e20e193c960802afba73b5d38sm     * performance is decoupled from the UI thread. Clients typically need to
592cfd74d65d832137e20e193c960802afba73b5d38sm     * communicate with the renderer from the UI thread, because that's where
593cfd74d65d832137e20e193c960802afba73b5d38sm     * input events are received. Clients can communicate using any of the
594cfd74d65d832137e20e193c960802afba73b5d38sm     * standard Java techniques for cross-thread communication, or they can
595cfd74d65d832137e20e193c960802afba73b5d38sm     * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method.
596cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
597cfd74d65d832137e20e193c960802afba73b5d38sm     * <h3>EGL Context Lost</h3>
598cfd74d65d832137e20e193c960802afba73b5d38sm     * There are situations where the EGL rendering context will be lost. This
599cfd74d65d832137e20e193c960802afba73b5d38sm     * typically happens when device wakes up after going to sleep. When
600cfd74d65d832137e20e193c960802afba73b5d38sm     * the EGL context is lost, all OpenGL resources (such as textures) that are
601cfd74d65d832137e20e193c960802afba73b5d38sm     * associated with that context will be automatically deleted. In order to
602cfd74d65d832137e20e193c960802afba73b5d38sm     * keep rendering correctly, a renderer must recreate any lost resources
603cfd74d65d832137e20e193c960802afba73b5d38sm     * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method
604cfd74d65d832137e20e193c960802afba73b5d38sm     * is a convenient place to do this.
605cfd74d65d832137e20e193c960802afba73b5d38sm     *
606cfd74d65d832137e20e193c960802afba73b5d38sm     *
607cfd74d65d832137e20e193c960802afba73b5d38sm     * @see #setRenderer(Renderer)
608cfd74d65d832137e20e193c960802afba73b5d38sm     */
609cfd74d65d832137e20e193c960802afba73b5d38sm    public interface Renderer {
610cfd74d65d832137e20e193c960802afba73b5d38sm        /**
611cfd74d65d832137e20e193c960802afba73b5d38sm         * Called when the surface is created or recreated.
612cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
613cfd74d65d832137e20e193c960802afba73b5d38sm         * Called when the rendering thread
614cfd74d65d832137e20e193c960802afba73b5d38sm         * starts and whenever the EGL context is lost. The context will typically
615cfd74d65d832137e20e193c960802afba73b5d38sm         * be lost when the Android device awakes after going to sleep.
616cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
617cfd74d65d832137e20e193c960802afba73b5d38sm         * Since this method is called at the beginning of rendering, as well as
618cfd74d65d832137e20e193c960802afba73b5d38sm         * every time the EGL context is lost, this method is a convenient place to put
619cfd74d65d832137e20e193c960802afba73b5d38sm         * code to create resources that need to be created when the rendering
620cfd74d65d832137e20e193c960802afba73b5d38sm         * starts, and that need to be recreated when the EGL context is lost.
621cfd74d65d832137e20e193c960802afba73b5d38sm         * Textures are an example of a resource that you might want to create
622cfd74d65d832137e20e193c960802afba73b5d38sm         * here.
623cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
624cfd74d65d832137e20e193c960802afba73b5d38sm         * Note that when the EGL context is lost, all OpenGL resources associated
625cfd74d65d832137e20e193c960802afba73b5d38sm         * with that context will be automatically deleted. You do not need to call
626cfd74d65d832137e20e193c960802afba73b5d38sm         * the corresponding "glDelete" methods such as glDeleteTextures to
627cfd74d65d832137e20e193c960802afba73b5d38sm         * manually delete these lost resources.
628cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
629cfd74d65d832137e20e193c960802afba73b5d38sm         * @param gl the GL interface. Use <code>instanceof</code> to
630cfd74d65d832137e20e193c960802afba73b5d38sm         * test if the interface supports GL11 or higher interfaces.
631cfd74d65d832137e20e193c960802afba73b5d38sm         * @param config the EGLConfig of the created surface. Can be used
632cfd74d65d832137e20e193c960802afba73b5d38sm         * to create matching pbuffers.
633cfd74d65d832137e20e193c960802afba73b5d38sm         */
634cfd74d65d832137e20e193c960802afba73b5d38sm        void onSurfaceCreated(GL10 gl, EGLConfig config);
635cfd74d65d832137e20e193c960802afba73b5d38sm
636cfd74d65d832137e20e193c960802afba73b5d38sm        /**
637cfd74d65d832137e20e193c960802afba73b5d38sm         * Called when the surface changed size.
638cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
639cfd74d65d832137e20e193c960802afba73b5d38sm         * Called after the surface is created and whenever
640cfd74d65d832137e20e193c960802afba73b5d38sm         * the OpenGL ES surface size changes.
641cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
642cfd74d65d832137e20e193c960802afba73b5d38sm         * Typically you will set your viewport here. If your camera
643cfd74d65d832137e20e193c960802afba73b5d38sm         * is fixed then you could also set your projection matrix here:
644cfd74d65d832137e20e193c960802afba73b5d38sm         * <pre class="prettyprint">
645cfd74d65d832137e20e193c960802afba73b5d38sm         * void onSurfaceChanged(GL10 gl, int width, int height) {
646cfd74d65d832137e20e193c960802afba73b5d38sm         *     gl.glViewport(0, 0, width, height);
647cfd74d65d832137e20e193c960802afba73b5d38sm         *     // for a fixed camera, set the projection too
648cfd74d65d832137e20e193c960802afba73b5d38sm         *     float ratio = (float) width / height;
649cfd74d65d832137e20e193c960802afba73b5d38sm         *     gl.glMatrixMode(GL10.GL_PROJECTION);
650cfd74d65d832137e20e193c960802afba73b5d38sm         *     gl.glLoadIdentity();
651cfd74d65d832137e20e193c960802afba73b5d38sm         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
652cfd74d65d832137e20e193c960802afba73b5d38sm         * }
653cfd74d65d832137e20e193c960802afba73b5d38sm         * </pre>
654cfd74d65d832137e20e193c960802afba73b5d38sm         * @param gl the GL interface. Use <code>instanceof</code> to
655cfd74d65d832137e20e193c960802afba73b5d38sm         * test if the interface supports GL11 or higher interfaces.
656cfd74d65d832137e20e193c960802afba73b5d38sm         * @param width
657cfd74d65d832137e20e193c960802afba73b5d38sm         * @param height
658cfd74d65d832137e20e193c960802afba73b5d38sm         */
659cfd74d65d832137e20e193c960802afba73b5d38sm        void onSurfaceChanged(GL10 gl, int width, int height);
660cfd74d65d832137e20e193c960802afba73b5d38sm
661cfd74d65d832137e20e193c960802afba73b5d38sm        /**
662cfd74d65d832137e20e193c960802afba73b5d38sm         * Called when the OpenGL context has been lost is about
663cfd74d65d832137e20e193c960802afba73b5d38sm         * to be recreated.  onSurfaceCreated() will be called after
664cfd74d65d832137e20e193c960802afba73b5d38sm         * onSurfaceLost().
665cfd74d65d832137e20e193c960802afba73b5d38sm         * */
666cfd74d65d832137e20e193c960802afba73b5d38sm        void onSurfaceLost();
667cfd74d65d832137e20e193c960802afba73b5d38sm
668cfd74d65d832137e20e193c960802afba73b5d38sm        /**
669cfd74d65d832137e20e193c960802afba73b5d38sm         * Called to draw the current frame.
670cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
671cfd74d65d832137e20e193c960802afba73b5d38sm         * This method is responsible for drawing the current frame.
672cfd74d65d832137e20e193c960802afba73b5d38sm         * <p>
673cfd74d65d832137e20e193c960802afba73b5d38sm         * The implementation of this method typically looks like this:
674cfd74d65d832137e20e193c960802afba73b5d38sm         * <pre class="prettyprint">
675cfd74d65d832137e20e193c960802afba73b5d38sm         * void onDrawFrame(GL10 gl) {
676cfd74d65d832137e20e193c960802afba73b5d38sm         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
677cfd74d65d832137e20e193c960802afba73b5d38sm         *     //... other gl calls to render the scene ...
678cfd74d65d832137e20e193c960802afba73b5d38sm         * }
679cfd74d65d832137e20e193c960802afba73b5d38sm         * </pre>
680cfd74d65d832137e20e193c960802afba73b5d38sm         * @param gl the GL interface. Use <code>instanceof</code> to
681cfd74d65d832137e20e193c960802afba73b5d38sm         * test if the interface supports GL11 or higher interfaces.
682cfd74d65d832137e20e193c960802afba73b5d38sm         */
683cfd74d65d832137e20e193c960802afba73b5d38sm        void onDrawFrame(GL10 gl);
684cfd74d65d832137e20e193c960802afba73b5d38sm
685cfd74d65d832137e20e193c960802afba73b5d38sm		void loadTextures(GL10 gl, TextureLibrary library);
686cfd74d65d832137e20e193c960802afba73b5d38sm        void flushTextures(GL10 gl, TextureLibrary library);
687cfd74d65d832137e20e193c960802afba73b5d38sm        void loadBuffers(GL10 gl, BufferLibrary library);
688cfd74d65d832137e20e193c960802afba73b5d38sm        void flushBuffers(GL10 gl, BufferLibrary library);
689cfd74d65d832137e20e193c960802afba73b5d38sm
690cfd74d65d832137e20e193c960802afba73b5d38sm
691cfd74d65d832137e20e193c960802afba73b5d38sm
692cfd74d65d832137e20e193c960802afba73b5d38sm    }
693cfd74d65d832137e20e193c960802afba73b5d38sm
694cfd74d65d832137e20e193c960802afba73b5d38sm    /**
695cfd74d65d832137e20e193c960802afba73b5d38sm     * An interface for customizing the eglCreateContext and eglDestroyContext calls.
696cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
697cfd74d65d832137e20e193c960802afba73b5d38sm     * This interface must be implemented by clients wishing to call
698cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)}
699cfd74d65d832137e20e193c960802afba73b5d38sm     */
700cfd74d65d832137e20e193c960802afba73b5d38sm    public interface EGLContextFactory {
701cfd74d65d832137e20e193c960802afba73b5d38sm        EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);
702cfd74d65d832137e20e193c960802afba73b5d38sm        void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
703cfd74d65d832137e20e193c960802afba73b5d38sm    }
704cfd74d65d832137e20e193c960802afba73b5d38sm
705cfd74d65d832137e20e193c960802afba73b5d38sm    private class DefaultContextFactory implements EGLContextFactory {
706cfd74d65d832137e20e193c960802afba73b5d38sm        private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
707cfd74d65d832137e20e193c960802afba73b5d38sm
708cfd74d65d832137e20e193c960802afba73b5d38sm        public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
709cfd74d65d832137e20e193c960802afba73b5d38sm            int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,
710cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_NONE };
711cfd74d65d832137e20e193c960802afba73b5d38sm
712cfd74d65d832137e20e193c960802afba73b5d38sm            return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,
713cfd74d65d832137e20e193c960802afba73b5d38sm                    mEGLContextClientVersion != 0 ? attrib_list : null);
714cfd74d65d832137e20e193c960802afba73b5d38sm        }
715cfd74d65d832137e20e193c960802afba73b5d38sm
716cfd74d65d832137e20e193c960802afba73b5d38sm        public void destroyContext(EGL10 egl, EGLDisplay display,
717cfd74d65d832137e20e193c960802afba73b5d38sm                EGLContext context) {
718cfd74d65d832137e20e193c960802afba73b5d38sm            egl.eglDestroyContext(display, context);
719cfd74d65d832137e20e193c960802afba73b5d38sm        }
720cfd74d65d832137e20e193c960802afba73b5d38sm    }
721cfd74d65d832137e20e193c960802afba73b5d38sm
722cfd74d65d832137e20e193c960802afba73b5d38sm    /**
723cfd74d65d832137e20e193c960802afba73b5d38sm     * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls.
724cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
725cfd74d65d832137e20e193c960802afba73b5d38sm     * This interface must be implemented by clients wishing to call
726cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)}
727cfd74d65d832137e20e193c960802afba73b5d38sm     */
728cfd74d65d832137e20e193c960802afba73b5d38sm    public interface EGLWindowSurfaceFactory {
729cfd74d65d832137e20e193c960802afba73b5d38sm        EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config,
730cfd74d65d832137e20e193c960802afba73b5d38sm                Object nativeWindow);
731cfd74d65d832137e20e193c960802afba73b5d38sm        void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);
732cfd74d65d832137e20e193c960802afba73b5d38sm    }
733cfd74d65d832137e20e193c960802afba73b5d38sm
734cfd74d65d832137e20e193c960802afba73b5d38sm    private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
735cfd74d65d832137e20e193c960802afba73b5d38sm
736cfd74d65d832137e20e193c960802afba73b5d38sm        public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
737cfd74d65d832137e20e193c960802afba73b5d38sm                EGLConfig config, Object nativeWindow) {
738cfd74d65d832137e20e193c960802afba73b5d38sm            return egl.eglCreateWindowSurface(display, config, nativeWindow, null);
739cfd74d65d832137e20e193c960802afba73b5d38sm        }
740cfd74d65d832137e20e193c960802afba73b5d38sm
741cfd74d65d832137e20e193c960802afba73b5d38sm        public void destroySurface(EGL10 egl, EGLDisplay display,
742cfd74d65d832137e20e193c960802afba73b5d38sm                EGLSurface surface) {
743cfd74d65d832137e20e193c960802afba73b5d38sm            egl.eglDestroySurface(display, surface);
744cfd74d65d832137e20e193c960802afba73b5d38sm        }
745cfd74d65d832137e20e193c960802afba73b5d38sm    }
746cfd74d65d832137e20e193c960802afba73b5d38sm
747cfd74d65d832137e20e193c960802afba73b5d38sm    /**
748cfd74d65d832137e20e193c960802afba73b5d38sm     * An interface for choosing an EGLConfig configuration from a list of
749cfd74d65d832137e20e193c960802afba73b5d38sm     * potential configurations.
750cfd74d65d832137e20e193c960802afba73b5d38sm     * <p>
751cfd74d65d832137e20e193c960802afba73b5d38sm     * This interface must be implemented by clients wishing to call
752cfd74d65d832137e20e193c960802afba73b5d38sm     * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)}
753cfd74d65d832137e20e193c960802afba73b5d38sm     */
754cfd74d65d832137e20e193c960802afba73b5d38sm    public interface EGLConfigChooser {
755cfd74d65d832137e20e193c960802afba73b5d38sm        /**
756cfd74d65d832137e20e193c960802afba73b5d38sm         * Choose a configuration from the list. Implementors typically
757cfd74d65d832137e20e193c960802afba73b5d38sm         * implement this method by calling
758cfd74d65d832137e20e193c960802afba73b5d38sm         * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the
759cfd74d65d832137e20e193c960802afba73b5d38sm         * EGL specification available from The Khronos Group to learn how to call eglChooseConfig.
760cfd74d65d832137e20e193c960802afba73b5d38sm         * @param egl the EGL10 for the current display.
761cfd74d65d832137e20e193c960802afba73b5d38sm         * @param display the current display.
762cfd74d65d832137e20e193c960802afba73b5d38sm         * @return the chosen configuration.
763cfd74d65d832137e20e193c960802afba73b5d38sm         */
764cfd74d65d832137e20e193c960802afba73b5d38sm        EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
765cfd74d65d832137e20e193c960802afba73b5d38sm    }
766cfd74d65d832137e20e193c960802afba73b5d38sm
767cfd74d65d832137e20e193c960802afba73b5d38sm    private abstract class BaseConfigChooser
768cfd74d65d832137e20e193c960802afba73b5d38sm            implements EGLConfigChooser {
769cfd74d65d832137e20e193c960802afba73b5d38sm        public BaseConfigChooser(int[] configSpec) {
770cfd74d65d832137e20e193c960802afba73b5d38sm            mConfigSpec = filterConfigSpec(configSpec);
771cfd74d65d832137e20e193c960802afba73b5d38sm        }
772cfd74d65d832137e20e193c960802afba73b5d38sm
773cfd74d65d832137e20e193c960802afba73b5d38sm        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
774cfd74d65d832137e20e193c960802afba73b5d38sm            int[] num_config = new int[1];
775cfd74d65d832137e20e193c960802afba73b5d38sm            if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
776cfd74d65d832137e20e193c960802afba73b5d38sm                    num_config)) {
777cfd74d65d832137e20e193c960802afba73b5d38sm                throw new IllegalArgumentException("eglChooseConfig failed");
778cfd74d65d832137e20e193c960802afba73b5d38sm            }
779cfd74d65d832137e20e193c960802afba73b5d38sm
780cfd74d65d832137e20e193c960802afba73b5d38sm            int numConfigs = num_config[0];
781cfd74d65d832137e20e193c960802afba73b5d38sm
782cfd74d65d832137e20e193c960802afba73b5d38sm            if (numConfigs <= 0) {
783cfd74d65d832137e20e193c960802afba73b5d38sm                throw new IllegalArgumentException(
784cfd74d65d832137e20e193c960802afba73b5d38sm                        "No configs match configSpec");
785cfd74d65d832137e20e193c960802afba73b5d38sm            }
786cfd74d65d832137e20e193c960802afba73b5d38sm
787cfd74d65d832137e20e193c960802afba73b5d38sm            EGLConfig[] configs = new EGLConfig[numConfigs];
788cfd74d65d832137e20e193c960802afba73b5d38sm            if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
789cfd74d65d832137e20e193c960802afba73b5d38sm                    num_config)) {
790cfd74d65d832137e20e193c960802afba73b5d38sm                throw new IllegalArgumentException("eglChooseConfig#2 failed");
791cfd74d65d832137e20e193c960802afba73b5d38sm            }
792cfd74d65d832137e20e193c960802afba73b5d38sm            EGLConfig config = chooseConfig(egl, display, configs);
793cfd74d65d832137e20e193c960802afba73b5d38sm            if (config == null) {
794cfd74d65d832137e20e193c960802afba73b5d38sm                throw new IllegalArgumentException("No config chosen");
795cfd74d65d832137e20e193c960802afba73b5d38sm            }
796cfd74d65d832137e20e193c960802afba73b5d38sm            return config;
797cfd74d65d832137e20e193c960802afba73b5d38sm        }
798cfd74d65d832137e20e193c960802afba73b5d38sm
799cfd74d65d832137e20e193c960802afba73b5d38sm        abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
800cfd74d65d832137e20e193c960802afba73b5d38sm                EGLConfig[] configs);
801cfd74d65d832137e20e193c960802afba73b5d38sm
802cfd74d65d832137e20e193c960802afba73b5d38sm        protected int[] mConfigSpec;
803cfd74d65d832137e20e193c960802afba73b5d38sm
804cfd74d65d832137e20e193c960802afba73b5d38sm        private int[] filterConfigSpec(int[] configSpec) {
805cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEGLContextClientVersion != 2) {
806cfd74d65d832137e20e193c960802afba73b5d38sm                return configSpec;
807cfd74d65d832137e20e193c960802afba73b5d38sm            }
808cfd74d65d832137e20e193c960802afba73b5d38sm            /* We know none of the subclasses define EGL_RENDERABLE_TYPE.
809cfd74d65d832137e20e193c960802afba73b5d38sm             * And we know the configSpec is well formed.
810cfd74d65d832137e20e193c960802afba73b5d38sm             */
811cfd74d65d832137e20e193c960802afba73b5d38sm            int len = configSpec.length;
812cfd74d65d832137e20e193c960802afba73b5d38sm            int[] newConfigSpec = new int[len + 2];
813cfd74d65d832137e20e193c960802afba73b5d38sm            System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
814cfd74d65d832137e20e193c960802afba73b5d38sm            newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
815cfd74d65d832137e20e193c960802afba73b5d38sm            newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
816cfd74d65d832137e20e193c960802afba73b5d38sm            newConfigSpec[len+1] = EGL10.EGL_NONE;
817cfd74d65d832137e20e193c960802afba73b5d38sm            return newConfigSpec;
818cfd74d65d832137e20e193c960802afba73b5d38sm        }
819cfd74d65d832137e20e193c960802afba73b5d38sm    }
820cfd74d65d832137e20e193c960802afba73b5d38sm
821cfd74d65d832137e20e193c960802afba73b5d38sm    private class ComponentSizeChooser extends BaseConfigChooser {
822cfd74d65d832137e20e193c960802afba73b5d38sm        public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
823cfd74d65d832137e20e193c960802afba73b5d38sm                int alphaSize, int depthSize, int stencilSize) {
824cfd74d65d832137e20e193c960802afba73b5d38sm            super(new int[] {
825cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_RED_SIZE, redSize,
826cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_GREEN_SIZE, greenSize,
827cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_BLUE_SIZE, blueSize,
828cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_ALPHA_SIZE, alphaSize,
829cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_DEPTH_SIZE, depthSize,
830cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_STENCIL_SIZE, stencilSize,
831cfd74d65d832137e20e193c960802afba73b5d38sm                    EGL10.EGL_NONE});
832cfd74d65d832137e20e193c960802afba73b5d38sm            mValue = new int[1];
833cfd74d65d832137e20e193c960802afba73b5d38sm            mRedSize = redSize;
834cfd74d65d832137e20e193c960802afba73b5d38sm            mGreenSize = greenSize;
835cfd74d65d832137e20e193c960802afba73b5d38sm            mBlueSize = blueSize;
836cfd74d65d832137e20e193c960802afba73b5d38sm            mAlphaSize = alphaSize;
837cfd74d65d832137e20e193c960802afba73b5d38sm            mDepthSize = depthSize;
838cfd74d65d832137e20e193c960802afba73b5d38sm            mStencilSize = stencilSize;
839cfd74d65d832137e20e193c960802afba73b5d38sm       }
840cfd74d65d832137e20e193c960802afba73b5d38sm
841cfd74d65d832137e20e193c960802afba73b5d38sm        @Override
842cfd74d65d832137e20e193c960802afba73b5d38sm        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
843cfd74d65d832137e20e193c960802afba73b5d38sm                EGLConfig[] configs) {
844cfd74d65d832137e20e193c960802afba73b5d38sm            EGLConfig closestConfig = null;
845cfd74d65d832137e20e193c960802afba73b5d38sm            int closestDistance = 1000;
846cfd74d65d832137e20e193c960802afba73b5d38sm            for(EGLConfig config : configs) {
847cfd74d65d832137e20e193c960802afba73b5d38sm                int d = findConfigAttrib(egl, display, config,
848cfd74d65d832137e20e193c960802afba73b5d38sm                        EGL10.EGL_DEPTH_SIZE, 0);
849cfd74d65d832137e20e193c960802afba73b5d38sm                int s = findConfigAttrib(egl, display, config,
850cfd74d65d832137e20e193c960802afba73b5d38sm                        EGL10.EGL_STENCIL_SIZE, 0);
851cfd74d65d832137e20e193c960802afba73b5d38sm                if (d >= mDepthSize && s>= mStencilSize) {
852cfd74d65d832137e20e193c960802afba73b5d38sm                    int r = findConfigAttrib(egl, display, config,
853cfd74d65d832137e20e193c960802afba73b5d38sm                            EGL10.EGL_RED_SIZE, 0);
854cfd74d65d832137e20e193c960802afba73b5d38sm                    int g = findConfigAttrib(egl, display, config,
855cfd74d65d832137e20e193c960802afba73b5d38sm                             EGL10.EGL_GREEN_SIZE, 0);
856cfd74d65d832137e20e193c960802afba73b5d38sm                    int b = findConfigAttrib(egl, display, config,
857cfd74d65d832137e20e193c960802afba73b5d38sm                              EGL10.EGL_BLUE_SIZE, 0);
858cfd74d65d832137e20e193c960802afba73b5d38sm                    int a = findConfigAttrib(egl, display, config,
859cfd74d65d832137e20e193c960802afba73b5d38sm                            EGL10.EGL_ALPHA_SIZE, 0);
860cfd74d65d832137e20e193c960802afba73b5d38sm                    int distance = Math.abs(r - mRedSize)
861cfd74d65d832137e20e193c960802afba73b5d38sm                                + Math.abs(g - mGreenSize)
862cfd74d65d832137e20e193c960802afba73b5d38sm                                + Math.abs(b - mBlueSize)
863cfd74d65d832137e20e193c960802afba73b5d38sm                                + Math.abs(a - mAlphaSize);
864cfd74d65d832137e20e193c960802afba73b5d38sm                    if (distance < closestDistance) {
865cfd74d65d832137e20e193c960802afba73b5d38sm                        closestDistance = distance;
866cfd74d65d832137e20e193c960802afba73b5d38sm                        closestConfig = config;
867cfd74d65d832137e20e193c960802afba73b5d38sm                    }
868cfd74d65d832137e20e193c960802afba73b5d38sm                }
869cfd74d65d832137e20e193c960802afba73b5d38sm            }
870cfd74d65d832137e20e193c960802afba73b5d38sm            return closestConfig;
871cfd74d65d832137e20e193c960802afba73b5d38sm        }
872cfd74d65d832137e20e193c960802afba73b5d38sm
873cfd74d65d832137e20e193c960802afba73b5d38sm        private int findConfigAttrib(EGL10 egl, EGLDisplay display,
874cfd74d65d832137e20e193c960802afba73b5d38sm                EGLConfig config, int attribute, int defaultValue) {
875cfd74d65d832137e20e193c960802afba73b5d38sm
876cfd74d65d832137e20e193c960802afba73b5d38sm            if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
877cfd74d65d832137e20e193c960802afba73b5d38sm                return mValue[0];
878cfd74d65d832137e20e193c960802afba73b5d38sm            }
879cfd74d65d832137e20e193c960802afba73b5d38sm            return defaultValue;
880cfd74d65d832137e20e193c960802afba73b5d38sm        }
881cfd74d65d832137e20e193c960802afba73b5d38sm
882cfd74d65d832137e20e193c960802afba73b5d38sm        private int[] mValue;
883cfd74d65d832137e20e193c960802afba73b5d38sm        // Subclasses can adjust these values:
884cfd74d65d832137e20e193c960802afba73b5d38sm        protected int mRedSize;
885cfd74d65d832137e20e193c960802afba73b5d38sm        protected int mGreenSize;
886cfd74d65d832137e20e193c960802afba73b5d38sm        protected int mBlueSize;
887cfd74d65d832137e20e193c960802afba73b5d38sm        protected int mAlphaSize;
888cfd74d65d832137e20e193c960802afba73b5d38sm        protected int mDepthSize;
889cfd74d65d832137e20e193c960802afba73b5d38sm        protected int mStencilSize;
890cfd74d65d832137e20e193c960802afba73b5d38sm        }
891cfd74d65d832137e20e193c960802afba73b5d38sm
892cfd74d65d832137e20e193c960802afba73b5d38sm    /**
893cfd74d65d832137e20e193c960802afba73b5d38sm     * This class will choose a supported surface as close to
894cfd74d65d832137e20e193c960802afba73b5d38sm     * RGB565 as possible, with or without a depth buffer.
895cfd74d65d832137e20e193c960802afba73b5d38sm     *
896cfd74d65d832137e20e193c960802afba73b5d38sm     */
897cfd74d65d832137e20e193c960802afba73b5d38sm    private class SimpleEGLConfigChooser extends ComponentSizeChooser {
898cfd74d65d832137e20e193c960802afba73b5d38sm        public SimpleEGLConfigChooser(boolean withDepthBuffer) {
899cfd74d65d832137e20e193c960802afba73b5d38sm            super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
900cfd74d65d832137e20e193c960802afba73b5d38sm            // Adjust target values. This way we'll accept a 4444 or
901cfd74d65d832137e20e193c960802afba73b5d38sm            // 555 buffer if there's no 565 buffer available.
902cfd74d65d832137e20e193c960802afba73b5d38sm            mRedSize = 5;
903cfd74d65d832137e20e193c960802afba73b5d38sm            mGreenSize = 6;
904cfd74d65d832137e20e193c960802afba73b5d38sm            mBlueSize = 5;
905cfd74d65d832137e20e193c960802afba73b5d38sm        }
906cfd74d65d832137e20e193c960802afba73b5d38sm    }
907cfd74d65d832137e20e193c960802afba73b5d38sm
908cfd74d65d832137e20e193c960802afba73b5d38sm    /**
909cfd74d65d832137e20e193c960802afba73b5d38sm     * An EGL helper class.
910cfd74d65d832137e20e193c960802afba73b5d38sm     */
911cfd74d65d832137e20e193c960802afba73b5d38sm
912cfd74d65d832137e20e193c960802afba73b5d38sm    private class EglHelper {
913cfd74d65d832137e20e193c960802afba73b5d38sm        public EglHelper() {
914cfd74d65d832137e20e193c960802afba73b5d38sm
915cfd74d65d832137e20e193c960802afba73b5d38sm        }
916cfd74d65d832137e20e193c960802afba73b5d38sm
917cfd74d65d832137e20e193c960802afba73b5d38sm        /**
918cfd74d65d832137e20e193c960802afba73b5d38sm         * Initialize EGL for a given configuration spec.
919cfd74d65d832137e20e193c960802afba73b5d38sm         * @param configSpec
920cfd74d65d832137e20e193c960802afba73b5d38sm         */
921cfd74d65d832137e20e193c960802afba73b5d38sm        public void start(){
922cfd74d65d832137e20e193c960802afba73b5d38sm            /*
923cfd74d65d832137e20e193c960802afba73b5d38sm             * Get an EGL instance
924cfd74d65d832137e20e193c960802afba73b5d38sm             */
925cfd74d65d832137e20e193c960802afba73b5d38sm            mEgl = (EGL10) EGLContext.getEGL();
926cfd74d65d832137e20e193c960802afba73b5d38sm
927cfd74d65d832137e20e193c960802afba73b5d38sm            /*
928cfd74d65d832137e20e193c960802afba73b5d38sm             * Get to the default display.
929cfd74d65d832137e20e193c960802afba73b5d38sm             */
930cfd74d65d832137e20e193c960802afba73b5d38sm            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
931cfd74d65d832137e20e193c960802afba73b5d38sm
932cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
933cfd74d65d832137e20e193c960802afba73b5d38sm                throw new RuntimeException("eglGetDisplay failed");
934cfd74d65d832137e20e193c960802afba73b5d38sm            }
935cfd74d65d832137e20e193c960802afba73b5d38sm
936cfd74d65d832137e20e193c960802afba73b5d38sm            /*
937cfd74d65d832137e20e193c960802afba73b5d38sm             * We can now initialize EGL for that display
938cfd74d65d832137e20e193c960802afba73b5d38sm             */
939cfd74d65d832137e20e193c960802afba73b5d38sm            int[] version = new int[2];
940cfd74d65d832137e20e193c960802afba73b5d38sm            if(!mEgl.eglInitialize(mEglDisplay, version)) {
941cfd74d65d832137e20e193c960802afba73b5d38sm                throw new RuntimeException("eglInitialize failed");
942cfd74d65d832137e20e193c960802afba73b5d38sm            }
943cfd74d65d832137e20e193c960802afba73b5d38sm            mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
944cfd74d65d832137e20e193c960802afba73b5d38sm
945cfd74d65d832137e20e193c960802afba73b5d38sm            /*
946cfd74d65d832137e20e193c960802afba73b5d38sm            * Create an OpenGL ES context. This must be done only once, an
947cfd74d65d832137e20e193c960802afba73b5d38sm            * OpenGL context is a somewhat heavy object.
948cfd74d65d832137e20e193c960802afba73b5d38sm            */
949cfd74d65d832137e20e193c960802afba73b5d38sm            mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
950cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
951cfd74d65d832137e20e193c960802afba73b5d38sm                throwEglException("createContext");
952cfd74d65d832137e20e193c960802afba73b5d38sm            }
953cfd74d65d832137e20e193c960802afba73b5d38sm
954cfd74d65d832137e20e193c960802afba73b5d38sm            mEglSurface = null;
955cfd74d65d832137e20e193c960802afba73b5d38sm        }
956cfd74d65d832137e20e193c960802afba73b5d38sm
957cfd74d65d832137e20e193c960802afba73b5d38sm        /*
958cfd74d65d832137e20e193c960802afba73b5d38sm         * React to the creation of a new surface by creating and returning an
959cfd74d65d832137e20e193c960802afba73b5d38sm         * OpenGL interface that renders to that surface.
960cfd74d65d832137e20e193c960802afba73b5d38sm         */
961cfd74d65d832137e20e193c960802afba73b5d38sm        public GL createSurface(SurfaceHolder holder) {
962cfd74d65d832137e20e193c960802afba73b5d38sm            /*
963cfd74d65d832137e20e193c960802afba73b5d38sm             *  The window size has changed, so we need to create a new
964cfd74d65d832137e20e193c960802afba73b5d38sm             *  surface.
965cfd74d65d832137e20e193c960802afba73b5d38sm             */
966cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
967cfd74d65d832137e20e193c960802afba73b5d38sm
968cfd74d65d832137e20e193c960802afba73b5d38sm                /*
969cfd74d65d832137e20e193c960802afba73b5d38sm                 * Unbind and destroy the old EGL surface, if
970cfd74d65d832137e20e193c960802afba73b5d38sm                 * there is one.
971cfd74d65d832137e20e193c960802afba73b5d38sm                 */
972cfd74d65d832137e20e193c960802afba73b5d38sm                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
973cfd74d65d832137e20e193c960802afba73b5d38sm                        EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
974cfd74d65d832137e20e193c960802afba73b5d38sm                mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
975cfd74d65d832137e20e193c960802afba73b5d38sm            }
976cfd74d65d832137e20e193c960802afba73b5d38sm
977cfd74d65d832137e20e193c960802afba73b5d38sm            /*
978cfd74d65d832137e20e193c960802afba73b5d38sm             * Create an EGL surface we can render into.
979cfd74d65d832137e20e193c960802afba73b5d38sm             */
980cfd74d65d832137e20e193c960802afba73b5d38sm            mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
981cfd74d65d832137e20e193c960802afba73b5d38sm                    mEglDisplay, mEglConfig, holder);
982cfd74d65d832137e20e193c960802afba73b5d38sm
983cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
984cfd74d65d832137e20e193c960802afba73b5d38sm                throwEglException("createWindowSurface");
985cfd74d65d832137e20e193c960802afba73b5d38sm            }
986cfd74d65d832137e20e193c960802afba73b5d38sm
987cfd74d65d832137e20e193c960802afba73b5d38sm            /*
988cfd74d65d832137e20e193c960802afba73b5d38sm             * Before we can issue GL commands, we need to make sure
989cfd74d65d832137e20e193c960802afba73b5d38sm             * the context is current and bound to a surface.
990cfd74d65d832137e20e193c960802afba73b5d38sm             */
991cfd74d65d832137e20e193c960802afba73b5d38sm            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
992cfd74d65d832137e20e193c960802afba73b5d38sm                throwEglException("eglMakeCurrent");
993cfd74d65d832137e20e193c960802afba73b5d38sm            }
994cfd74d65d832137e20e193c960802afba73b5d38sm
995cfd74d65d832137e20e193c960802afba73b5d38sm            GL gl = mEglContext.getGL();
996cfd74d65d832137e20e193c960802afba73b5d38sm            if (mGLWrapper != null) {
997cfd74d65d832137e20e193c960802afba73b5d38sm                gl = mGLWrapper.wrap(gl);
998cfd74d65d832137e20e193c960802afba73b5d38sm            }
999cfd74d65d832137e20e193c960802afba73b5d38sm
1000cfd74d65d832137e20e193c960802afba73b5d38sm            if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) {
1001cfd74d65d832137e20e193c960802afba73b5d38sm                int configFlags = 0;
1002cfd74d65d832137e20e193c960802afba73b5d38sm                Writer log = null;
1003cfd74d65d832137e20e193c960802afba73b5d38sm                if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
1004cfd74d65d832137e20e193c960802afba73b5d38sm                    configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
1005cfd74d65d832137e20e193c960802afba73b5d38sm                }
1006cfd74d65d832137e20e193c960802afba73b5d38sm                if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
1007cfd74d65d832137e20e193c960802afba73b5d38sm                    log = new LogWriter();
1008cfd74d65d832137e20e193c960802afba73b5d38sm                }
1009cfd74d65d832137e20e193c960802afba73b5d38sm                gl = GLDebugHelper.wrap(gl, configFlags, log);
1010cfd74d65d832137e20e193c960802afba73b5d38sm            }
1011cfd74d65d832137e20e193c960802afba73b5d38sm            return gl;
1012cfd74d65d832137e20e193c960802afba73b5d38sm        }
1013cfd74d65d832137e20e193c960802afba73b5d38sm
1014cfd74d65d832137e20e193c960802afba73b5d38sm        /**
1015cfd74d65d832137e20e193c960802afba73b5d38sm         * Display the current render surface.
1016cfd74d65d832137e20e193c960802afba73b5d38sm         * @return false if the context has been lost.
1017cfd74d65d832137e20e193c960802afba73b5d38sm         */
1018cfd74d65d832137e20e193c960802afba73b5d38sm        public boolean swap() {
1019cfd74d65d832137e20e193c960802afba73b5d38sm            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
1020cfd74d65d832137e20e193c960802afba73b5d38sm
1021cfd74d65d832137e20e193c960802afba73b5d38sm            /*
1022cfd74d65d832137e20e193c960802afba73b5d38sm             * Always check for EGL_CONTEXT_LOST, which means the context
1023cfd74d65d832137e20e193c960802afba73b5d38sm             * and all associated data were lost (For instance because
1024cfd74d65d832137e20e193c960802afba73b5d38sm             * the device went to sleep). We need to sleep until we
1025cfd74d65d832137e20e193c960802afba73b5d38sm             * get a new surface.
1026cfd74d65d832137e20e193c960802afba73b5d38sm             */
1027cfd74d65d832137e20e193c960802afba73b5d38sm            return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
1028cfd74d65d832137e20e193c960802afba73b5d38sm        }
1029cfd74d65d832137e20e193c960802afba73b5d38sm
1030cfd74d65d832137e20e193c960802afba73b5d38sm        public void destroySurface() {
1031cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
1032cfd74d65d832137e20e193c960802afba73b5d38sm                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
1033cfd74d65d832137e20e193c960802afba73b5d38sm                        EGL10.EGL_NO_SURFACE,
1034cfd74d65d832137e20e193c960802afba73b5d38sm                        EGL10.EGL_NO_CONTEXT);
1035cfd74d65d832137e20e193c960802afba73b5d38sm                mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
1036cfd74d65d832137e20e193c960802afba73b5d38sm                mEglSurface = null;
1037cfd74d65d832137e20e193c960802afba73b5d38sm            }
1038cfd74d65d832137e20e193c960802afba73b5d38sm        }
1039cfd74d65d832137e20e193c960802afba73b5d38sm
1040cfd74d65d832137e20e193c960802afba73b5d38sm        public void finish() {
1041cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglContext != null) {
1042cfd74d65d832137e20e193c960802afba73b5d38sm                mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);
1043cfd74d65d832137e20e193c960802afba73b5d38sm                mEglContext = null;
1044cfd74d65d832137e20e193c960802afba73b5d38sm            }
1045cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglDisplay != null) {
1046cfd74d65d832137e20e193c960802afba73b5d38sm                mEgl.eglTerminate(mEglDisplay);
1047cfd74d65d832137e20e193c960802afba73b5d38sm                mEglDisplay = null;
1048cfd74d65d832137e20e193c960802afba73b5d38sm            }
1049cfd74d65d832137e20e193c960802afba73b5d38sm        }
1050cfd74d65d832137e20e193c960802afba73b5d38sm
1051cfd74d65d832137e20e193c960802afba73b5d38sm        private void throwEglException(String function) {
1052cfd74d65d832137e20e193c960802afba73b5d38sm            throw new RuntimeException(function + " failed: " + mEgl.eglGetError());
1053cfd74d65d832137e20e193c960802afba73b5d38sm        }
1054cfd74d65d832137e20e193c960802afba73b5d38sm
1055cfd74d65d832137e20e193c960802afba73b5d38sm        /** Checks to see if the current context is valid.  **/
1056cfd74d65d832137e20e193c960802afba73b5d38sm        public boolean verifyContext() {
1057cfd74d65d832137e20e193c960802afba73b5d38sm        	EGLContext currentContext = mEgl.eglGetCurrentContext();
1058cfd74d65d832137e20e193c960802afba73b5d38sm			return currentContext != EGL10.EGL_NO_CONTEXT && mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
1059cfd74d65d832137e20e193c960802afba73b5d38sm		}
1060cfd74d65d832137e20e193c960802afba73b5d38sm
1061cfd74d65d832137e20e193c960802afba73b5d38sm        EGL10 mEgl;
1062cfd74d65d832137e20e193c960802afba73b5d38sm        EGLDisplay mEglDisplay;
1063cfd74d65d832137e20e193c960802afba73b5d38sm        EGLSurface mEglSurface;
1064cfd74d65d832137e20e193c960802afba73b5d38sm        EGLConfig mEglConfig;
1065cfd74d65d832137e20e193c960802afba73b5d38sm        EGLContext mEglContext;
1066cfd74d65d832137e20e193c960802afba73b5d38sm
1067cfd74d65d832137e20e193c960802afba73b5d38sm    }
1068cfd74d65d832137e20e193c960802afba73b5d38sm
1069cfd74d65d832137e20e193c960802afba73b5d38sm    /**
1070cfd74d65d832137e20e193c960802afba73b5d38sm     * A generic GL Thread. Takes care of initializing EGL and GL. Delegates
1071cfd74d65d832137e20e193c960802afba73b5d38sm     * to a Renderer instance to do the actual drawing. Can be configured to
1072cfd74d65d832137e20e193c960802afba73b5d38sm     * render continuously or on request.
1073cfd74d65d832137e20e193c960802afba73b5d38sm     *
1074cfd74d65d832137e20e193c960802afba73b5d38sm     * All potentially blocking synchronization is done through the
1075cfd74d65d832137e20e193c960802afba73b5d38sm     * sGLThreadManager object. This avoids multiple-lock ordering issues.
1076cfd74d65d832137e20e193c960802afba73b5d38sm     *
1077cfd74d65d832137e20e193c960802afba73b5d38sm     */
1078cfd74d65d832137e20e193c960802afba73b5d38sm    private class GLThread extends Thread {
1079cfd74d65d832137e20e193c960802afba73b5d38sm		public GLThread(Renderer renderer) {
1080cfd74d65d832137e20e193c960802afba73b5d38sm            super();
1081cfd74d65d832137e20e193c960802afba73b5d38sm            mWidth = 0;
1082cfd74d65d832137e20e193c960802afba73b5d38sm            mHeight = 0;
1083cfd74d65d832137e20e193c960802afba73b5d38sm            mRequestRender = true;
1084cfd74d65d832137e20e193c960802afba73b5d38sm            mRenderMode = RENDERMODE_CONTINUOUSLY;
1085cfd74d65d832137e20e193c960802afba73b5d38sm            mRenderer = renderer;
1086cfd74d65d832137e20e193c960802afba73b5d38sm        }
1087cfd74d65d832137e20e193c960802afba73b5d38sm
1088cfd74d65d832137e20e193c960802afba73b5d38sm
1089cfd74d65d832137e20e193c960802afba73b5d38sm		@Override
1090cfd74d65d832137e20e193c960802afba73b5d38sm        public void run() {
1091cfd74d65d832137e20e193c960802afba73b5d38sm            setName("GLThread " + getId());
1092cfd74d65d832137e20e193c960802afba73b5d38sm            if (LOG_THREADS) {
1093cfd74d65d832137e20e193c960802afba73b5d38sm                DebugLog.i("GLThread", "starting tid=" + getId());
1094cfd74d65d832137e20e193c960802afba73b5d38sm            }
1095cfd74d65d832137e20e193c960802afba73b5d38sm
1096cfd74d65d832137e20e193c960802afba73b5d38sm            try {
1097cfd74d65d832137e20e193c960802afba73b5d38sm                guardedRun();
1098cfd74d65d832137e20e193c960802afba73b5d38sm            } catch (InterruptedException e) {
1099cfd74d65d832137e20e193c960802afba73b5d38sm                // fall thru and exit normally
1100cfd74d65d832137e20e193c960802afba73b5d38sm            } finally {
1101cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.threadExiting(this);
1102cfd74d65d832137e20e193c960802afba73b5d38sm            }
1103cfd74d65d832137e20e193c960802afba73b5d38sm        }
1104cfd74d65d832137e20e193c960802afba73b5d38sm
1105cfd74d65d832137e20e193c960802afba73b5d38sm        /*
1106cfd74d65d832137e20e193c960802afba73b5d38sm         * This private method should only be called inside a
1107cfd74d65d832137e20e193c960802afba73b5d38sm         * synchronized(sGLThreadManager) block.
1108cfd74d65d832137e20e193c960802afba73b5d38sm         */
1109cfd74d65d832137e20e193c960802afba73b5d38sm        private void stopEglLocked() {
1110cfd74d65d832137e20e193c960802afba73b5d38sm            if (mHaveEglSurface) {
1111cfd74d65d832137e20e193c960802afba73b5d38sm            	mHaveEglSurface = false;
1112cfd74d65d832137e20e193c960802afba73b5d38sm                mEglHelper.destroySurface();
1113cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.releaseEglSurfaceLocked(this);
1114cfd74d65d832137e20e193c960802afba73b5d38sm            }
1115cfd74d65d832137e20e193c960802afba73b5d38sm        }
1116cfd74d65d832137e20e193c960802afba73b5d38sm
1117cfd74d65d832137e20e193c960802afba73b5d38sm        private void guardedRun() throws InterruptedException {
1118cfd74d65d832137e20e193c960802afba73b5d38sm            mEglHelper = new EglHelper();
1119cfd74d65d832137e20e193c960802afba73b5d38sm            mHaveEglContext = false;
1120cfd74d65d832137e20e193c960802afba73b5d38sm            mHaveEglSurface = false;
1121cfd74d65d832137e20e193c960802afba73b5d38sm            try {
1122cfd74d65d832137e20e193c960802afba73b5d38sm                GL10 gl = null;
1123cfd74d65d832137e20e193c960802afba73b5d38sm                boolean createEglSurface = false;
1124cfd74d65d832137e20e193c960802afba73b5d38sm                boolean sizeChanged = false;
1125cfd74d65d832137e20e193c960802afba73b5d38sm                boolean wantRenderNotification = false;
1126cfd74d65d832137e20e193c960802afba73b5d38sm                boolean doRenderNotification = false;
1127cfd74d65d832137e20e193c960802afba73b5d38sm                int w = 0;
1128cfd74d65d832137e20e193c960802afba73b5d38sm                int h = 0;
1129cfd74d65d832137e20e193c960802afba73b5d38sm                Runnable event = null;
11309d4cc2572d37983607df38b0f4216ed76ac51814sm                int framesSinceResetHack = 0;
1131cfd74d65d832137e20e193c960802afba73b5d38sm                while (true) {
1132cfd74d65d832137e20e193c960802afba73b5d38sm                    synchronized (sGLThreadManager) {
1133cfd74d65d832137e20e193c960802afba73b5d38sm                        while (true) {
1134cfd74d65d832137e20e193c960802afba73b5d38sm                            if (mShouldExit) {
1135cfd74d65d832137e20e193c960802afba73b5d38sm                                return;
1136cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1137cfd74d65d832137e20e193c960802afba73b5d38sm
1138cfd74d65d832137e20e193c960802afba73b5d38sm                            if (! mEventQueue.isEmpty()) {
1139cfd74d65d832137e20e193c960802afba73b5d38sm                                event = mEventQueue.remove(0);
1140cfd74d65d832137e20e193c960802afba73b5d38sm                                break;
1141cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1142cfd74d65d832137e20e193c960802afba73b5d38sm
1143cfd74d65d832137e20e193c960802afba73b5d38sm                            // Do we need to release the EGL surface?
1144cfd74d65d832137e20e193c960802afba73b5d38sm                            if (mHaveEglSurface && mPaused) {
1145cfd74d65d832137e20e193c960802afba73b5d38sm                                if (LOG_SURFACE) {
1146cfd74d65d832137e20e193c960802afba73b5d38sm                                    DebugLog.i("GLThread", "releasing EGL surface because paused tid=" + getId());
1147cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1148cfd74d65d832137e20e193c960802afba73b5d38sm                                stopEglLocked();
1149cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1150cfd74d65d832137e20e193c960802afba73b5d38sm
1151cfd74d65d832137e20e193c960802afba73b5d38sm                            // Have we lost the surface view surface?
1152cfd74d65d832137e20e193c960802afba73b5d38sm                            if ((! mHasSurface) && (! mWaitingForSurface)) {
1153cfd74d65d832137e20e193c960802afba73b5d38sm                                if (LOG_SURFACE) {
1154cfd74d65d832137e20e193c960802afba73b5d38sm                                    DebugLog.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
1155cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1156cfd74d65d832137e20e193c960802afba73b5d38sm                                if (mHaveEglSurface) {
1157cfd74d65d832137e20e193c960802afba73b5d38sm                                    stopEglLocked();
1158cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1159cfd74d65d832137e20e193c960802afba73b5d38sm                                mWaitingForSurface = true;
1160cfd74d65d832137e20e193c960802afba73b5d38sm                                sGLThreadManager.notifyAll();
1161cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1162cfd74d65d832137e20e193c960802afba73b5d38sm
1163cfd74d65d832137e20e193c960802afba73b5d38sm                            // Have we acquired the surface view surface?
1164cfd74d65d832137e20e193c960802afba73b5d38sm                            if (mHasSurface && mWaitingForSurface) {
1165cfd74d65d832137e20e193c960802afba73b5d38sm                                if (LOG_SURFACE) {
1166cfd74d65d832137e20e193c960802afba73b5d38sm                                    DebugLog.i("GLThread", "noticed surfaceView surface acquired tid=" + getId());
1167cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1168cfd74d65d832137e20e193c960802afba73b5d38sm                                mWaitingForSurface = false;
1169cfd74d65d832137e20e193c960802afba73b5d38sm                                sGLThreadManager.notifyAll();
1170cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1171cfd74d65d832137e20e193c960802afba73b5d38sm
1172cfd74d65d832137e20e193c960802afba73b5d38sm                            if (doRenderNotification) {
1173cfd74d65d832137e20e193c960802afba73b5d38sm                                wantRenderNotification = false;
1174cfd74d65d832137e20e193c960802afba73b5d38sm                                doRenderNotification = false;
1175cfd74d65d832137e20e193c960802afba73b5d38sm                                mRenderComplete = true;
1176cfd74d65d832137e20e193c960802afba73b5d38sm                                sGLThreadManager.notifyAll();
1177cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1178cfd74d65d832137e20e193c960802afba73b5d38sm
1179cfd74d65d832137e20e193c960802afba73b5d38sm                            // Ready to draw?
1180cfd74d65d832137e20e193c960802afba73b5d38sm                            if ((!mPaused) && mHasSurface
1181cfd74d65d832137e20e193c960802afba73b5d38sm                                && (mWidth > 0) && (mHeight > 0)
1182cfd74d65d832137e20e193c960802afba73b5d38sm                                && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {
1183cfd74d65d832137e20e193c960802afba73b5d38sm
1184cfd74d65d832137e20e193c960802afba73b5d38sm                            	if (mHaveEglContext && !mHaveEglSurface) {
1185cfd74d65d832137e20e193c960802afba73b5d38sm                            		// Let's make sure the context hasn't been lost.
1186cfd74d65d832137e20e193c960802afba73b5d38sm                            		if (!mEglHelper.verifyContext()) {
1187cfd74d65d832137e20e193c960802afba73b5d38sm                            			mEglHelper.finish();
1188cfd74d65d832137e20e193c960802afba73b5d38sm                            			mRenderer.onSurfaceLost();
1189cfd74d65d832137e20e193c960802afba73b5d38sm                            			mHaveEglContext = false;
1190cfd74d65d832137e20e193c960802afba73b5d38sm                            		}
1191cfd74d65d832137e20e193c960802afba73b5d38sm                            	}
1192cfd74d65d832137e20e193c960802afba73b5d38sm                                // If we don't have an egl surface, try to acquire one.
1193cfd74d65d832137e20e193c960802afba73b5d38sm                                if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglSurfaceLocked(this)) {
1194cfd74d65d832137e20e193c960802afba73b5d38sm                                	mHaveEglContext = true;
1195cfd74d65d832137e20e193c960802afba73b5d38sm                                    mEglHelper.start();
1196cfd74d65d832137e20e193c960802afba73b5d38sm
1197cfd74d65d832137e20e193c960802afba73b5d38sm                                    sGLThreadManager.notifyAll();
1198cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1199cfd74d65d832137e20e193c960802afba73b5d38sm
1200cfd74d65d832137e20e193c960802afba73b5d38sm                                if (mHaveEglContext && !mHaveEglSurface) {
1201cfd74d65d832137e20e193c960802afba73b5d38sm                                	mHaveEglSurface = true;
1202cfd74d65d832137e20e193c960802afba73b5d38sm                                	createEglSurface = true;
1203cfd74d65d832137e20e193c960802afba73b5d38sm                                    sizeChanged = true;
1204cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1205cfd74d65d832137e20e193c960802afba73b5d38sm
1206cfd74d65d832137e20e193c960802afba73b5d38sm                                if (mHaveEglSurface) {
1207cfd74d65d832137e20e193c960802afba73b5d38sm                                    if (mSizeChanged) {
1208cfd74d65d832137e20e193c960802afba73b5d38sm                                        sizeChanged = true;
1209cfd74d65d832137e20e193c960802afba73b5d38sm                                        w = mWidth;
1210cfd74d65d832137e20e193c960802afba73b5d38sm                                        h = mHeight;
1211cfd74d65d832137e20e193c960802afba73b5d38sm                                        wantRenderNotification = true;
1212cfd74d65d832137e20e193c960802afba73b5d38sm
1213cfd74d65d832137e20e193c960802afba73b5d38sm                                        if (DRAW_TWICE_AFTER_SIZE_CHANGED) {
1214cfd74d65d832137e20e193c960802afba73b5d38sm                                            // We keep mRequestRender true so that we draw twice after the size changes.
1215cfd74d65d832137e20e193c960802afba73b5d38sm                                            // (Once because of mSizeChanged, the second time because of mRequestRender.)
1216cfd74d65d832137e20e193c960802afba73b5d38sm                                            // This forces the updated graphics onto the screen.
1217cfd74d65d832137e20e193c960802afba73b5d38sm                                        } else {
1218cfd74d65d832137e20e193c960802afba73b5d38sm                                            mRequestRender = false;
1219cfd74d65d832137e20e193c960802afba73b5d38sm                                        }
1220cfd74d65d832137e20e193c960802afba73b5d38sm                                        mSizeChanged = false;
1221cfd74d65d832137e20e193c960802afba73b5d38sm                                    } else {
1222cfd74d65d832137e20e193c960802afba73b5d38sm                                        mRequestRender = false;
1223cfd74d65d832137e20e193c960802afba73b5d38sm                                    }
1224cfd74d65d832137e20e193c960802afba73b5d38sm                                    sGLThreadManager.notifyAll();
1225cfd74d65d832137e20e193c960802afba73b5d38sm                                    break;
1226cfd74d65d832137e20e193c960802afba73b5d38sm                                }
1227cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1228cfd74d65d832137e20e193c960802afba73b5d38sm
1229cfd74d65d832137e20e193c960802afba73b5d38sm                            // By design, this is the only place in a GLThread thread where we wait().
1230cfd74d65d832137e20e193c960802afba73b5d38sm                            if (LOG_THREADS) {
1231cfd74d65d832137e20e193c960802afba73b5d38sm                                DebugLog.i("GLThread", "waiting tid=" + getId());
1232cfd74d65d832137e20e193c960802afba73b5d38sm                            }
1233cfd74d65d832137e20e193c960802afba73b5d38sm                            sGLThreadManager.wait();
1234cfd74d65d832137e20e193c960802afba73b5d38sm                        }
1235cfd74d65d832137e20e193c960802afba73b5d38sm                    } // end of synchronized(sGLThreadManager)
1236cfd74d65d832137e20e193c960802afba73b5d38sm
1237cfd74d65d832137e20e193c960802afba73b5d38sm                    if (event != null) {
1238cfd74d65d832137e20e193c960802afba73b5d38sm                        event.run();
1239cfd74d65d832137e20e193c960802afba73b5d38sm                        event = null;
1240cfd74d65d832137e20e193c960802afba73b5d38sm                        continue;
1241cfd74d65d832137e20e193c960802afba73b5d38sm                    }
1242cfd74d65d832137e20e193c960802afba73b5d38sm
1243cfd74d65d832137e20e193c960802afba73b5d38sm                    if (mHasFocus) {
1244cfd74d65d832137e20e193c960802afba73b5d38sm	                    if (createEglSurface) {
1245cfd74d65d832137e20e193c960802afba73b5d38sm	                        gl = (GL10) mEglHelper.createSurface(getHolder());
1246cfd74d65d832137e20e193c960802afba73b5d38sm	                        sGLThreadManager.checkGLDriver(gl);
1247cfd74d65d832137e20e193c960802afba73b5d38sm	                        if (LOG_RENDERER) {
1248cfd74d65d832137e20e193c960802afba73b5d38sm	                            DebugLog.w("GLThread", "onSurfaceCreated");
1249cfd74d65d832137e20e193c960802afba73b5d38sm	                        }
1250cfd74d65d832137e20e193c960802afba73b5d38sm	                        mGL = gl;
1251cfd74d65d832137e20e193c960802afba73b5d38sm	                        mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
1252cfd74d65d832137e20e193c960802afba73b5d38sm	                        createEglSurface = false;
12539d4cc2572d37983607df38b0f4216ed76ac51814sm	                        framesSinceResetHack = 0;
1254cfd74d65d832137e20e193c960802afba73b5d38sm	                    }
1255cfd74d65d832137e20e193c960802afba73b5d38sm
1256cfd74d65d832137e20e193c960802afba73b5d38sm
1257cfd74d65d832137e20e193c960802afba73b5d38sm	                    if (sizeChanged) {
1258cfd74d65d832137e20e193c960802afba73b5d38sm	                        if (LOG_RENDERER) {
1259cfd74d65d832137e20e193c960802afba73b5d38sm	                            DebugLog.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")");
1260cfd74d65d832137e20e193c960802afba73b5d38sm	                        }
1261cfd74d65d832137e20e193c960802afba73b5d38sm	                        mRenderer.onSurfaceChanged(gl, w, h);
1262cfd74d65d832137e20e193c960802afba73b5d38sm	                        sizeChanged = false;
1263cfd74d65d832137e20e193c960802afba73b5d38sm	                    }
1264cfd74d65d832137e20e193c960802afba73b5d38sm
1265cfd74d65d832137e20e193c960802afba73b5d38sm
1266cfd74d65d832137e20e193c960802afba73b5d38sm
1267cfd74d65d832137e20e193c960802afba73b5d38sm	                    if (LOG_RENDERER) {
1268cfd74d65d832137e20e193c960802afba73b5d38sm	                        DebugLog.w("GLThread", "onDrawFrame");
1269cfd74d65d832137e20e193c960802afba73b5d38sm	                    }
12709d4cc2572d37983607df38b0f4216ed76ac51814sm
12719d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // Some phones (Motorola Cliq, Backflip; also the
12729d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // Huawei Pulse, and maybe the Samsung Behold II), use a
12739d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // broken graphics driver from Qualcomm.  It fails in a
12749d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // very specific case: when the EGL context is lost due to
12759d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // resource constraints, and then recreated, if GL commands
12769d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // are sent within two frames of the surface being created
12779d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // then eglSwapBuffers() will hang.  Normally, applications using
12789d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // the stock GLSurfaceView never run into this problem because it
12799d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // discards the EGL context explicitly on every pause.  But
12809d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // I've modified this class to not do that--I only want to reload
12819d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // textures when the context is actually lost--so this bug
12829d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // revealed itself as black screens on devices like the Cliq.
12839d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // Thus, in "safe mode," I force two swaps to occur before
12849d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // issuing any GL commands.  Don't ask me how long it took
12859d4cc2572d37983607df38b0f4216ed76ac51814sm	                    // to figure this out.
12866cb78e547641bcab6f18ec34badca0840e000992Keun young Park                        // CTS: do not use safe mode.
12876cb78e547641bcab6f18ec34badca0840e000992Keun young Park                        mWatchDog.reset();
12886cb78e547641bcab6f18ec34badca0840e000992Keun young Park                        mRenderer.onDrawFrame(gl);
12899d4cc2572d37983607df38b0f4216ed76ac51814sm
12909d4cc2572d37983607df38b0f4216ed76ac51814sm	                    framesSinceResetHack++;
12919d4cc2572d37983607df38b0f4216ed76ac51814sm
1292cfd74d65d832137e20e193c960802afba73b5d38sm	                    if(!mEglHelper.swap()) {
1293cfd74d65d832137e20e193c960802afba73b5d38sm	                        if (LOG_SURFACE) {
1294cfd74d65d832137e20e193c960802afba73b5d38sm	                            DebugLog.i("GLThread", "egl surface lost tid=" + getId());
1295cfd74d65d832137e20e193c960802afba73b5d38sm	                        }
12969d4cc2572d37983607df38b0f4216ed76ac51814sm
12979d4cc2572d37983607df38b0f4216ed76ac51814sm	                        stopEglLocked();
1298cfd74d65d832137e20e193c960802afba73b5d38sm	                    }
1299cfd74d65d832137e20e193c960802afba73b5d38sm
1300cfd74d65d832137e20e193c960802afba73b5d38sm                    }
1301cfd74d65d832137e20e193c960802afba73b5d38sm	                if (wantRenderNotification) {
1302cfd74d65d832137e20e193c960802afba73b5d38sm	                    doRenderNotification = true;
1303cfd74d65d832137e20e193c960802afba73b5d38sm	                }
1304cfd74d65d832137e20e193c960802afba73b5d38sm                }
1305cfd74d65d832137e20e193c960802afba73b5d38sm
1306cfd74d65d832137e20e193c960802afba73b5d38sm            } finally {
1307cfd74d65d832137e20e193c960802afba73b5d38sm            	mGL = null;
1308cfd74d65d832137e20e193c960802afba73b5d38sm                /*
1309cfd74d65d832137e20e193c960802afba73b5d38sm                 * clean-up everything...
1310cfd74d65d832137e20e193c960802afba73b5d38sm                 */
1311cfd74d65d832137e20e193c960802afba73b5d38sm                synchronized (sGLThreadManager) {
1312cfd74d65d832137e20e193c960802afba73b5d38sm                    stopEglLocked();
1313cfd74d65d832137e20e193c960802afba73b5d38sm                    mEglHelper.finish();
1314cfd74d65d832137e20e193c960802afba73b5d38sm                }
1315cfd74d65d832137e20e193c960802afba73b5d38sm            }
1316cfd74d65d832137e20e193c960802afba73b5d38sm        }
1317cfd74d65d832137e20e193c960802afba73b5d38sm
1318cfd74d65d832137e20e193c960802afba73b5d38sm        public void setRenderMode(int renderMode) {
1319cfd74d65d832137e20e193c960802afba73b5d38sm            if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
1320cfd74d65d832137e20e193c960802afba73b5d38sm                throw new IllegalArgumentException("renderMode");
1321cfd74d65d832137e20e193c960802afba73b5d38sm            }
1322cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1323cfd74d65d832137e20e193c960802afba73b5d38sm                mRenderMode = renderMode;
1324cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1325cfd74d65d832137e20e193c960802afba73b5d38sm            }
1326cfd74d65d832137e20e193c960802afba73b5d38sm        }
1327cfd74d65d832137e20e193c960802afba73b5d38sm
1328cfd74d65d832137e20e193c960802afba73b5d38sm        public int getRenderMode() {
1329cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1330cfd74d65d832137e20e193c960802afba73b5d38sm                return mRenderMode;
1331cfd74d65d832137e20e193c960802afba73b5d38sm            }
1332cfd74d65d832137e20e193c960802afba73b5d38sm        }
1333cfd74d65d832137e20e193c960802afba73b5d38sm
1334cfd74d65d832137e20e193c960802afba73b5d38sm        public void requestRender() {
1335cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1336cfd74d65d832137e20e193c960802afba73b5d38sm                mRequestRender = true;
1337cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1338cfd74d65d832137e20e193c960802afba73b5d38sm            }
1339cfd74d65d832137e20e193c960802afba73b5d38sm        }
1340cfd74d65d832137e20e193c960802afba73b5d38sm
1341cfd74d65d832137e20e193c960802afba73b5d38sm        public void surfaceCreated() {
1342cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1343cfd74d65d832137e20e193c960802afba73b5d38sm                if (LOG_THREADS) {
1344cfd74d65d832137e20e193c960802afba73b5d38sm                    DebugLog.i("GLThread", "surfaceCreated tid=" + getId());
1345cfd74d65d832137e20e193c960802afba73b5d38sm                }
1346cfd74d65d832137e20e193c960802afba73b5d38sm                mHasSurface = true;
1347cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1348cfd74d65d832137e20e193c960802afba73b5d38sm            }
1349cfd74d65d832137e20e193c960802afba73b5d38sm        }
1350cfd74d65d832137e20e193c960802afba73b5d38sm
1351cfd74d65d832137e20e193c960802afba73b5d38sm        public void surfaceDestroyed() {
1352cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1353cfd74d65d832137e20e193c960802afba73b5d38sm                if (LOG_THREADS) {
1354cfd74d65d832137e20e193c960802afba73b5d38sm                    DebugLog.i("GLThread", "surfaceDestroyed tid=" + getId());
1355cfd74d65d832137e20e193c960802afba73b5d38sm                }
1356cfd74d65d832137e20e193c960802afba73b5d38sm                mHasSurface = false;
1357cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1358cfd74d65d832137e20e193c960802afba73b5d38sm                while((!mWaitingForSurface) && (!mExited)) {
1359cfd74d65d832137e20e193c960802afba73b5d38sm                    try {
1360cfd74d65d832137e20e193c960802afba73b5d38sm                        sGLThreadManager.wait();
1361cfd74d65d832137e20e193c960802afba73b5d38sm                    } catch (InterruptedException e) {
1362cfd74d65d832137e20e193c960802afba73b5d38sm                        Thread.currentThread().interrupt();
1363cfd74d65d832137e20e193c960802afba73b5d38sm                    }
1364cfd74d65d832137e20e193c960802afba73b5d38sm                }
1365cfd74d65d832137e20e193c960802afba73b5d38sm            }
1366cfd74d65d832137e20e193c960802afba73b5d38sm        }
1367cfd74d65d832137e20e193c960802afba73b5d38sm
1368cfd74d65d832137e20e193c960802afba73b5d38sm        public void onPause() {
1369cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (sGLThreadManager) {
1370cfd74d65d832137e20e193c960802afba73b5d38sm                mPaused = true;
1371cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1372cfd74d65d832137e20e193c960802afba73b5d38sm            }
1373cfd74d65d832137e20e193c960802afba73b5d38sm        }
1374cfd74d65d832137e20e193c960802afba73b5d38sm
1375cfd74d65d832137e20e193c960802afba73b5d38sm        public void onResume() {
1376cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (sGLThreadManager) {
1377cfd74d65d832137e20e193c960802afba73b5d38sm                mPaused = false;
1378cfd74d65d832137e20e193c960802afba73b5d38sm                mRequestRender = true;
1379cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1380cfd74d65d832137e20e193c960802afba73b5d38sm            }
1381cfd74d65d832137e20e193c960802afba73b5d38sm        }
1382cfd74d65d832137e20e193c960802afba73b5d38sm
1383cfd74d65d832137e20e193c960802afba73b5d38sm        public void onWindowResize(int w, int h) {
1384cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (sGLThreadManager) {
1385cfd74d65d832137e20e193c960802afba73b5d38sm                mWidth = w;
1386cfd74d65d832137e20e193c960802afba73b5d38sm                mHeight = h;
1387cfd74d65d832137e20e193c960802afba73b5d38sm                mSizeChanged = true;
1388cfd74d65d832137e20e193c960802afba73b5d38sm                mRequestRender = true;
1389cfd74d65d832137e20e193c960802afba73b5d38sm                mRenderComplete = false;
1390cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1391cfd74d65d832137e20e193c960802afba73b5d38sm
1392cfd74d65d832137e20e193c960802afba73b5d38sm                // Wait for thread to react to resize and render a frame
1393cfd74d65d832137e20e193c960802afba73b5d38sm                while (! mExited && !mPaused && !mRenderComplete ) {
1394cfd74d65d832137e20e193c960802afba73b5d38sm                    if (LOG_SURFACE) {
1395cfd74d65d832137e20e193c960802afba73b5d38sm                        DebugLog.i("Main thread", "onWindowResize waiting for render complete.");
1396cfd74d65d832137e20e193c960802afba73b5d38sm                    }
1397cfd74d65d832137e20e193c960802afba73b5d38sm                    try {
1398cfd74d65d832137e20e193c960802afba73b5d38sm                        sGLThreadManager.wait();
1399cfd74d65d832137e20e193c960802afba73b5d38sm                    } catch (InterruptedException ex) {
1400cfd74d65d832137e20e193c960802afba73b5d38sm                        Thread.currentThread().interrupt();
1401cfd74d65d832137e20e193c960802afba73b5d38sm                    }
1402cfd74d65d832137e20e193c960802afba73b5d38sm                }
1403cfd74d65d832137e20e193c960802afba73b5d38sm            }
1404cfd74d65d832137e20e193c960802afba73b5d38sm        }
1405cfd74d65d832137e20e193c960802afba73b5d38sm
1406cfd74d65d832137e20e193c960802afba73b5d38sm		public void loadTextures(TextureLibrary library) {
1407cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (this) {
1408cfd74d65d832137e20e193c960802afba73b5d38sm                assert mGL != null;
1409cfd74d65d832137e20e193c960802afba73b5d38sm                if (mGL != null && mHasSurface) {
1410cfd74d65d832137e20e193c960802afba73b5d38sm                    mRenderer.loadTextures(mGL, library);
1411cfd74d65d832137e20e193c960802afba73b5d38sm                }
1412cfd74d65d832137e20e193c960802afba73b5d38sm            }
1413cfd74d65d832137e20e193c960802afba73b5d38sm        }
1414cfd74d65d832137e20e193c960802afba73b5d38sm
1415cfd74d65d832137e20e193c960802afba73b5d38sm        public void flushTextures(TextureLibrary library) {
1416cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (this) {
1417cfd74d65d832137e20e193c960802afba73b5d38sm                assert mGL != null;
1418cfd74d65d832137e20e193c960802afba73b5d38sm                if (mGL != null) {
1419cfd74d65d832137e20e193c960802afba73b5d38sm                    mRenderer.flushTextures(mGL, library);
1420cfd74d65d832137e20e193c960802afba73b5d38sm                }
1421cfd74d65d832137e20e193c960802afba73b5d38sm            }
1422cfd74d65d832137e20e193c960802afba73b5d38sm        }
1423cfd74d65d832137e20e193c960802afba73b5d38sm
1424cfd74d65d832137e20e193c960802afba73b5d38sm        public void loadBuffers(BufferLibrary library) {
1425cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (this) {
1426cfd74d65d832137e20e193c960802afba73b5d38sm                assert mGL != null;
1427cfd74d65d832137e20e193c960802afba73b5d38sm                if (mGL != null) {
1428cfd74d65d832137e20e193c960802afba73b5d38sm                    mRenderer.loadBuffers(mGL, library);
1429cfd74d65d832137e20e193c960802afba73b5d38sm                }
1430cfd74d65d832137e20e193c960802afba73b5d38sm            }
1431cfd74d65d832137e20e193c960802afba73b5d38sm        }
1432cfd74d65d832137e20e193c960802afba73b5d38sm
1433cfd74d65d832137e20e193c960802afba73b5d38sm        public void flushBuffers(BufferLibrary library) {
1434cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized (this) {
1435cfd74d65d832137e20e193c960802afba73b5d38sm                assert mGL != null;
1436cfd74d65d832137e20e193c960802afba73b5d38sm                if (mGL != null) {
1437cfd74d65d832137e20e193c960802afba73b5d38sm                    mRenderer.flushBuffers(mGL, library);
1438cfd74d65d832137e20e193c960802afba73b5d38sm                }
1439cfd74d65d832137e20e193c960802afba73b5d38sm            }
1440cfd74d65d832137e20e193c960802afba73b5d38sm        }
1441cfd74d65d832137e20e193c960802afba73b5d38sm
1442cfd74d65d832137e20e193c960802afba73b5d38sm        // On some Qualcomm devices (such as the HTC Magic running Android 1.6),
1443cfd74d65d832137e20e193c960802afba73b5d38sm        // there's a bug in the graphics driver that will cause glViewport() to
1444cfd74d65d832137e20e193c960802afba73b5d38sm        // do the wrong thing in a very specific situation.  When the screen is
1445cfd74d65d832137e20e193c960802afba73b5d38sm        // rotated, if a surface is created in one layout (say, portrait view)
1446cfd74d65d832137e20e193c960802afba73b5d38sm        // and then rotated to another, subsequent calls to glViewport are clipped.
1447cfd74d65d832137e20e193c960802afba73b5d38sm        // So, if the window is, say, 320x480 when the surface is created, and
1448cfd74d65d832137e20e193c960802afba73b5d38sm        // then the rotation occurs and glViewport() is called with the new
1449cfd74d65d832137e20e193c960802afba73b5d38sm        // size of 480x320, devices with the buggy driver will clip the viewport
1450cfd74d65d832137e20e193c960802afba73b5d38sm        // to the old width (which means 320x320...ugh!).  This is fixed in
1451cfd74d65d832137e20e193c960802afba73b5d38sm        // Android 2.1 Qualcomm devices (like Nexus One) and doesn't affect
1452cfd74d65d832137e20e193c960802afba73b5d38sm        // non-Qualcomm devices (like the Motorola DROID).
1453cfd74d65d832137e20e193c960802afba73b5d38sm        //
1454cfd74d65d832137e20e193c960802afba73b5d38sm        // Unfortunately, under Android 1.6 this exact case occurs when the
1455cfd74d65d832137e20e193c960802afba73b5d38sm        // screen is put to sleep and then wakes up again.  The lock screen
1456cfd74d65d832137e20e193c960802afba73b5d38sm        // comes up in portrait mode, but at the same time the window surface
1457cfd74d65d832137e20e193c960802afba73b5d38sm        // is also created in the backgrounded game.  When the lock screen is closed
1458cfd74d65d832137e20e193c960802afba73b5d38sm        // and the game comes forward, the window is fixed to the correct size
1459cfd74d65d832137e20e193c960802afba73b5d38sm        // which causes the bug to occur.
1460cfd74d65d832137e20e193c960802afba73b5d38sm
1461cfd74d65d832137e20e193c960802afba73b5d38sm        // The solution used here is to simply never render when the window surface
1462cfd74d65d832137e20e193c960802afba73b5d38sm        // does not have the focus.  When the lock screen (or menu) is up, rendering
1463cfd74d65d832137e20e193c960802afba73b5d38sm        // will stop.  This resolves the driver bug (as the egl surface won't be created
1464cfd74d65d832137e20e193c960802afba73b5d38sm        // until after the screen size has been fixed), and is generally good practice
1465cfd74d65d832137e20e193c960802afba73b5d38sm        // since you don't want to be doing a lot of CPU intensive work when the lock
1466cfd74d65d832137e20e193c960802afba73b5d38sm        // screen is up (to preserve battery life).
1467cfd74d65d832137e20e193c960802afba73b5d38sm
1468cfd74d65d832137e20e193c960802afba73b5d38sm        public void onWindowFocusChanged(boolean hasFocus) {
1469cfd74d65d832137e20e193c960802afba73b5d38sm        	synchronized(sGLThreadManager) {
1470cfd74d65d832137e20e193c960802afba73b5d38sm        		mHasFocus = hasFocus;
1471cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1472cfd74d65d832137e20e193c960802afba73b5d38sm        	}
1473cfd74d65d832137e20e193c960802afba73b5d38sm        	if (LOG_SURFACE) {
1474cfd74d65d832137e20e193c960802afba73b5d38sm                DebugLog.i("Main thread", "Focus " + (mHasFocus ? "gained" : "lost"));
1475cfd74d65d832137e20e193c960802afba73b5d38sm            }
1476cfd74d65d832137e20e193c960802afba73b5d38sm
1477cfd74d65d832137e20e193c960802afba73b5d38sm		}
1478cfd74d65d832137e20e193c960802afba73b5d38sm
1479cfd74d65d832137e20e193c960802afba73b5d38sm        public void requestExitAndWait() {
1480cfd74d65d832137e20e193c960802afba73b5d38sm            // don't call this from GLThread thread or it is a guaranteed
1481cfd74d65d832137e20e193c960802afba73b5d38sm            // deadlock!
1482cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1483cfd74d65d832137e20e193c960802afba73b5d38sm                mShouldExit = true;
1484cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1485cfd74d65d832137e20e193c960802afba73b5d38sm                while (! mExited) {
1486cfd74d65d832137e20e193c960802afba73b5d38sm                    try {
1487cfd74d65d832137e20e193c960802afba73b5d38sm                        sGLThreadManager.wait();
1488cfd74d65d832137e20e193c960802afba73b5d38sm                    } catch (InterruptedException ex) {
1489cfd74d65d832137e20e193c960802afba73b5d38sm                        Thread.currentThread().interrupt();
1490cfd74d65d832137e20e193c960802afba73b5d38sm                    }
1491cfd74d65d832137e20e193c960802afba73b5d38sm                }
1492cfd74d65d832137e20e193c960802afba73b5d38sm            }
1493cfd74d65d832137e20e193c960802afba73b5d38sm        }
1494cfd74d65d832137e20e193c960802afba73b5d38sm
1495cfd74d65d832137e20e193c960802afba73b5d38sm        /**
1496cfd74d65d832137e20e193c960802afba73b5d38sm         * Queue an "event" to be run on the GL rendering thread.
1497cfd74d65d832137e20e193c960802afba73b5d38sm         * @param r the runnable to be run on the GL rendering thread.
1498cfd74d65d832137e20e193c960802afba73b5d38sm         */
1499cfd74d65d832137e20e193c960802afba73b5d38sm        public void queueEvent(Runnable r) {
1500cfd74d65d832137e20e193c960802afba73b5d38sm            if (r == null) {
1501cfd74d65d832137e20e193c960802afba73b5d38sm                throw new IllegalArgumentException("r must not be null");
1502cfd74d65d832137e20e193c960802afba73b5d38sm            }
1503cfd74d65d832137e20e193c960802afba73b5d38sm            synchronized(sGLThreadManager) {
1504cfd74d65d832137e20e193c960802afba73b5d38sm                mEventQueue.add(r);
1505cfd74d65d832137e20e193c960802afba73b5d38sm                sGLThreadManager.notifyAll();
1506cfd74d65d832137e20e193c960802afba73b5d38sm            }
1507cfd74d65d832137e20e193c960802afba73b5d38sm        }
15089d4cc2572d37983607df38b0f4216ed76ac51814sm
15099d4cc2572d37983607df38b0f4216ed76ac51814sm        public void setSafeMode(boolean on) {
15109d4cc2572d37983607df38b0f4216ed76ac51814sm        	mSafeMode = on;
15119d4cc2572d37983607df38b0f4216ed76ac51814sm        }
1512cfd74d65d832137e20e193c960802afba73b5d38sm
1513cfd74d65d832137e20e193c960802afba73b5d38sm        // Once the thread is started, all accesses to the following member
1514cfd74d65d832137e20e193c960802afba73b5d38sm        // variables are protected by the sGLThreadManager monitor
1515cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mShouldExit;
1516cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mExited;
1517cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mPaused;
1518cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mHasSurface;
1519cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mWaitingForSurface;
1520cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mHaveEglContext;
1521cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mHaveEglSurface;
1522cfd74d65d832137e20e193c960802afba73b5d38sm        private int mWidth;
1523cfd74d65d832137e20e193c960802afba73b5d38sm        private int mHeight;
1524cfd74d65d832137e20e193c960802afba73b5d38sm        private int mRenderMode;
1525cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mRequestRender;
1526cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mRenderComplete;
1527cfd74d65d832137e20e193c960802afba73b5d38sm        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
1528cfd74d65d832137e20e193c960802afba73b5d38sm        private GL10 mGL;
1529cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mHasFocus;
15309d4cc2572d37983607df38b0f4216ed76ac51814sm        private boolean mSafeMode = false;
1531cfd74d65d832137e20e193c960802afba73b5d38sm
1532cfd74d65d832137e20e193c960802afba73b5d38sm        // End of member variables protected by the sGLThreadManager monitor.
1533cfd74d65d832137e20e193c960802afba73b5d38sm
1534cfd74d65d832137e20e193c960802afba73b5d38sm        private Renderer mRenderer;
1535cfd74d65d832137e20e193c960802afba73b5d38sm        private EglHelper mEglHelper;
1536cfd74d65d832137e20e193c960802afba73b5d38sm    }
1537cfd74d65d832137e20e193c960802afba73b5d38sm
1538cfd74d65d832137e20e193c960802afba73b5d38sm    static class LogWriter extends Writer {
1539cfd74d65d832137e20e193c960802afba73b5d38sm
1540cfd74d65d832137e20e193c960802afba73b5d38sm        @Override public void close() {
1541cfd74d65d832137e20e193c960802afba73b5d38sm            flushBuilder();
1542cfd74d65d832137e20e193c960802afba73b5d38sm        }
1543cfd74d65d832137e20e193c960802afba73b5d38sm
1544cfd74d65d832137e20e193c960802afba73b5d38sm        @Override public void flush() {
1545cfd74d65d832137e20e193c960802afba73b5d38sm            flushBuilder();
1546cfd74d65d832137e20e193c960802afba73b5d38sm        }
1547cfd74d65d832137e20e193c960802afba73b5d38sm
1548cfd74d65d832137e20e193c960802afba73b5d38sm        @Override public void write(char[] buf, int offset, int count) {
1549cfd74d65d832137e20e193c960802afba73b5d38sm            for(int i = 0; i < count; i++) {
1550cfd74d65d832137e20e193c960802afba73b5d38sm                char c = buf[offset + i];
1551cfd74d65d832137e20e193c960802afba73b5d38sm                if ( c == '\n') {
1552cfd74d65d832137e20e193c960802afba73b5d38sm                    flushBuilder();
1553cfd74d65d832137e20e193c960802afba73b5d38sm                }
1554cfd74d65d832137e20e193c960802afba73b5d38sm                else {
1555cfd74d65d832137e20e193c960802afba73b5d38sm                    mBuilder.append(c);
1556cfd74d65d832137e20e193c960802afba73b5d38sm                }
1557cfd74d65d832137e20e193c960802afba73b5d38sm            }
1558cfd74d65d832137e20e193c960802afba73b5d38sm        }
1559cfd74d65d832137e20e193c960802afba73b5d38sm
1560cfd74d65d832137e20e193c960802afba73b5d38sm        private void flushBuilder() {
1561cfd74d65d832137e20e193c960802afba73b5d38sm            if (mBuilder.length() > 0) {
1562cfd74d65d832137e20e193c960802afba73b5d38sm                DebugLog.v("GLSurfaceView", mBuilder.toString());
1563cfd74d65d832137e20e193c960802afba73b5d38sm                mBuilder.delete(0, mBuilder.length());
1564cfd74d65d832137e20e193c960802afba73b5d38sm            }
1565cfd74d65d832137e20e193c960802afba73b5d38sm        }
1566cfd74d65d832137e20e193c960802afba73b5d38sm
1567cfd74d65d832137e20e193c960802afba73b5d38sm        private StringBuilder mBuilder = new StringBuilder();
1568cfd74d65d832137e20e193c960802afba73b5d38sm    }
1569cfd74d65d832137e20e193c960802afba73b5d38sm
1570cfd74d65d832137e20e193c960802afba73b5d38sm
1571cfd74d65d832137e20e193c960802afba73b5d38sm    private void checkRenderThreadState() {
1572cfd74d65d832137e20e193c960802afba73b5d38sm        if (mGLThread != null) {
1573cfd74d65d832137e20e193c960802afba73b5d38sm            throw new IllegalStateException(
1574cfd74d65d832137e20e193c960802afba73b5d38sm                    "setRenderer has already been called for this instance.");
1575cfd74d65d832137e20e193c960802afba73b5d38sm        }
1576cfd74d65d832137e20e193c960802afba73b5d38sm    }
1577cfd74d65d832137e20e193c960802afba73b5d38sm
1578cfd74d65d832137e20e193c960802afba73b5d38sm    private static class GLThreadManager {
1579cfd74d65d832137e20e193c960802afba73b5d38sm
1580cfd74d65d832137e20e193c960802afba73b5d38sm        public synchronized void threadExiting(GLThread thread) {
1581cfd74d65d832137e20e193c960802afba73b5d38sm            if (LOG_THREADS) {
1582cfd74d65d832137e20e193c960802afba73b5d38sm                DebugLog.i("GLThread", "exiting tid=" +  thread.getId());
1583cfd74d65d832137e20e193c960802afba73b5d38sm            }
1584cfd74d65d832137e20e193c960802afba73b5d38sm            thread.mExited = true;
1585cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglOwner == thread) {
1586cfd74d65d832137e20e193c960802afba73b5d38sm                mEglOwner = null;
1587cfd74d65d832137e20e193c960802afba73b5d38sm            }
1588cfd74d65d832137e20e193c960802afba73b5d38sm            notifyAll();
1589cfd74d65d832137e20e193c960802afba73b5d38sm        }
1590cfd74d65d832137e20e193c960802afba73b5d38sm
1591cfd74d65d832137e20e193c960802afba73b5d38sm        /*
1592cfd74d65d832137e20e193c960802afba73b5d38sm         * Tries once to acquire the right to use an EGL
1593cfd74d65d832137e20e193c960802afba73b5d38sm         * surface. Does not block. Requires that we are already
1594cfd74d65d832137e20e193c960802afba73b5d38sm         * in the sGLThreadManager monitor when this is called.
1595cfd74d65d832137e20e193c960802afba73b5d38sm         *
1596cfd74d65d832137e20e193c960802afba73b5d38sm         * @return true if the right to use an EGL surface was acquired.
1597cfd74d65d832137e20e193c960802afba73b5d38sm         */
1598cfd74d65d832137e20e193c960802afba73b5d38sm        public boolean tryAcquireEglSurfaceLocked(GLThread thread) {
1599cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglOwner == thread || mEglOwner == null) {
1600cfd74d65d832137e20e193c960802afba73b5d38sm                mEglOwner = thread;
1601cfd74d65d832137e20e193c960802afba73b5d38sm                notifyAll();
1602cfd74d65d832137e20e193c960802afba73b5d38sm                return true;
1603cfd74d65d832137e20e193c960802afba73b5d38sm            }
1604cfd74d65d832137e20e193c960802afba73b5d38sm            checkGLESVersion();
1605cfd74d65d832137e20e193c960802afba73b5d38sm            if (mMultipleGLESContextsAllowed) {
1606cfd74d65d832137e20e193c960802afba73b5d38sm                return true;
1607cfd74d65d832137e20e193c960802afba73b5d38sm            }
1608cfd74d65d832137e20e193c960802afba73b5d38sm            return false;
1609cfd74d65d832137e20e193c960802afba73b5d38sm        }
1610cfd74d65d832137e20e193c960802afba73b5d38sm        /*
1611cfd74d65d832137e20e193c960802afba73b5d38sm         * Releases the EGL surface. Requires that we are already in the
1612cfd74d65d832137e20e193c960802afba73b5d38sm         * sGLThreadManager monitor when this is called.
1613cfd74d65d832137e20e193c960802afba73b5d38sm         */
1614cfd74d65d832137e20e193c960802afba73b5d38sm        public void releaseEglSurfaceLocked(GLThread thread) {
1615cfd74d65d832137e20e193c960802afba73b5d38sm            if (mEglOwner == thread) {
1616cfd74d65d832137e20e193c960802afba73b5d38sm                mEglOwner = null;
1617cfd74d65d832137e20e193c960802afba73b5d38sm            }
1618cfd74d65d832137e20e193c960802afba73b5d38sm            notifyAll();
1619cfd74d65d832137e20e193c960802afba73b5d38sm        }
1620cfd74d65d832137e20e193c960802afba73b5d38sm
1621cfd74d65d832137e20e193c960802afba73b5d38sm        public synchronized void checkGLDriver(GL10 gl) {
1622cfd74d65d832137e20e193c960802afba73b5d38sm            if (! mGLESDriverCheckComplete) {
1623cfd74d65d832137e20e193c960802afba73b5d38sm                checkGLESVersion();
1624cfd74d65d832137e20e193c960802afba73b5d38sm                if (mGLESVersion < kGLES_20) {
1625cfd74d65d832137e20e193c960802afba73b5d38sm                    String renderer = gl.glGetString(GL10.GL_RENDERER);
1626cfd74d65d832137e20e193c960802afba73b5d38sm                    mMultipleGLESContextsAllowed = false;
1627cfd74d65d832137e20e193c960802afba73b5d38sm                    notifyAll();
1628cfd74d65d832137e20e193c960802afba73b5d38sm                }
1629cfd74d65d832137e20e193c960802afba73b5d38sm                mGLESDriverCheckComplete = true;
1630cfd74d65d832137e20e193c960802afba73b5d38sm            }
1631cfd74d65d832137e20e193c960802afba73b5d38sm        }
1632cfd74d65d832137e20e193c960802afba73b5d38sm
1633cfd74d65d832137e20e193c960802afba73b5d38sm        private void checkGLESVersion() {
1634cfd74d65d832137e20e193c960802afba73b5d38sm            if (! mGLESVersionCheckComplete) {
1635cfd74d65d832137e20e193c960802afba73b5d38sm                mGLESVersion = ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
1636cfd74d65d832137e20e193c960802afba73b5d38sm                if (mGLESVersion >= kGLES_20) {
1637cfd74d65d832137e20e193c960802afba73b5d38sm                    mMultipleGLESContextsAllowed = true;
1638cfd74d65d832137e20e193c960802afba73b5d38sm                }
1639cfd74d65d832137e20e193c960802afba73b5d38sm                mGLESVersionCheckComplete = true;
1640cfd74d65d832137e20e193c960802afba73b5d38sm            }
1641cfd74d65d832137e20e193c960802afba73b5d38sm
1642cfd74d65d832137e20e193c960802afba73b5d38sm        }
1643cfd74d65d832137e20e193c960802afba73b5d38sm
1644cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mGLESVersionCheckComplete;
1645cfd74d65d832137e20e193c960802afba73b5d38sm        private int mGLESVersion;
1646cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mGLESDriverCheckComplete;
1647cfd74d65d832137e20e193c960802afba73b5d38sm        private boolean mMultipleGLESContextsAllowed;
1648cfd74d65d832137e20e193c960802afba73b5d38sm        private int mGLContextCount;
1649cfd74d65d832137e20e193c960802afba73b5d38sm        private static final int kGLES_20 = 0x20000;
1650cfd74d65d832137e20e193c960802afba73b5d38sm        private GLThread mEglOwner;
1651cfd74d65d832137e20e193c960802afba73b5d38sm
1652cfd74d65d832137e20e193c960802afba73b5d38sm    }
1653cfd74d65d832137e20e193c960802afba73b5d38sm
1654cfd74d65d832137e20e193c960802afba73b5d38sm    private static final GLThreadManager sGLThreadManager = new GLThreadManager();
1655cfd74d65d832137e20e193c960802afba73b5d38sm    private boolean mSizeChanged = true;
1656cfd74d65d832137e20e193c960802afba73b5d38sm
1657cfd74d65d832137e20e193c960802afba73b5d38sm    private GLThread mGLThread;
1658cfd74d65d832137e20e193c960802afba73b5d38sm    private EGLConfigChooser mEGLConfigChooser;
1659cfd74d65d832137e20e193c960802afba73b5d38sm    private EGLContextFactory mEGLContextFactory;
1660cfd74d65d832137e20e193c960802afba73b5d38sm    private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
1661cfd74d65d832137e20e193c960802afba73b5d38sm    private GLWrapper mGLWrapper;
1662cfd74d65d832137e20e193c960802afba73b5d38sm    private int mDebugFlags;
1663cfd74d65d832137e20e193c960802afba73b5d38sm    private int mEGLContextClientVersion;
16646cb78e547641bcab6f18ec34badca0840e000992Keun young Park    private final RenderingWatchDog mWatchDog = new RenderingWatchDog();
1665cfd74d65d832137e20e193c960802afba73b5d38sm
1666cfd74d65d832137e20e193c960802afba73b5d38sm}
1667