GLSurfaceView.java revision a605a51e63de2e7dc99ed085639a6f12b7f85af7
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.opengl;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.Writer;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.Semaphore;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL10;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGL11;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLConfig;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLContext;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLDisplay;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.egl.EGLSurface;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.microedition.khronos.opengles.GL10;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceView;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An implementation of SurfaceView that uses the dedicated surface for
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * displaying an OpenGL animation.  This allows the animation to run in a
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * separate thread, without requiring that it be driven by the update mechanism
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the view hierarchy.
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The application-specific rendering code is delegated to a GLView.Renderer
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance.
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int RENDERMODE_WHEN_DIRTY = 0;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int RENDERMODE_CONTUOUSLY = 1;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Check glError() after every GL call.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int DEBUG_CHECK_GL_ERROR = 1;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView".
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int DEBUG_LOG_GL_CALLS = 2;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GLSurfaceView(Context context) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        init();
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GLSurfaceView(Context context, AttributeSet attrs) {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        init();
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void init() {
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Install a SurfaceHolder.Callback so we get notified when the
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // underlying surface is created and destroyed
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SurfaceHolder holder = getHolder();
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        holder.addCallback(this);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the glWrapper to a new value. The current glWrapper is used
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * whenever a surface is created. The default value is null.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param glWrapper the new GLWrapper
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGLWrapper(GLWrapper glWrapper) {
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLWrapper = glWrapper;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the debug flags to a new value. The debug flags take effect
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * whenever a surface is created. The default value is zero.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param debugFlags the new debug flags
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #DEBUG_CHECK_GL_ERROR
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #DEBUG_LOG_GL_CALLS
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDebugFlags(int debugFlags) {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDebugFlags = debugFlags;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDebugFlags() {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDebugFlags;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the renderer associated with this view. Can only be called once.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param renderer
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setRenderer(Renderer renderer) {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mGLThread != null) {
110a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            throw new IllegalStateException(
111a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    "setRenderer has already been called for this instance.");
112a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
113a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        if (mEGLConfigChooser == null) {
114a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mEGLConfigChooser = new SimpleEGLConfigChooser(true);
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread = new GLThread(renderer);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.start();
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
121a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * Set the EGLConfigChooser associated with this view. If this method is
122a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * called at all, it must be called before {@link #setRenderer(Renderer)}
123a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * is called.
124a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
125a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * The supplied configChooser will be used to choose a configuration.
126a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * @param configChooser
127a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
128a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public void setEGLConfigChooser(EGLConfigChooser configChooser) {
129a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        if (mGLThread != null) {
130a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            throw new IllegalStateException(
131a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    "setRenderer has already been called for this instance.");
132a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
133a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        mEGLConfigChooser = configChooser;
134a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
135a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
136a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
137a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * Set the EGLConfigChooser associated with this view. If this method is
138a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * called, it must be called before {@link #setRenderer(Renderer)}
139a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * is called.
140a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
141a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * This method installs a config chooser which will choose a config
142a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * as close to 16-bit RGB as possible, with or without an optional depth
143a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * buffer as close to 16-bits as possible.
144a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
145a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * If no setEGLConfigChooser method is called, then by default the
146a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * view will choose a config as close to 16-bit RGB as possible, with
147a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * a depth buffer as close to 16-bits as possible.
148a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
149a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * @param needDepth
150a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
151a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public void setEGLConfigChooser(boolean needDepth) {
152a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
153a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
154a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
155a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
156a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * Set the EGLConfigChooser associated with this view. If this method is
157a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * called, it must be called before {@link #setRenderer(Renderer)}
158a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * is called.
159a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * <p>
160a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * This method installs a config chooser which will choose a config
161a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * with at least the specified component sizes, and as close
162a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * to the specified component sizes as possible.
163a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
164a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
165a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
166a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int alphaSize, int depthSize, int stencilSize) {
167a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
168a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                blueSize, alphaSize, depthSize, stencilSize));
169a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
170a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the rendering mode. When the renderMode is
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * RENDERMODE_CONTINUOUSLY, the renderer is called
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * repeatedly to re-render the scene. When the rendermode
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is created, or when requestRender is called. Defaults to RENDERMODE_CONTINUOUSLY.
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param renderMode one of the RENDERMODE_X constants
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setRenderMode(int renderMode) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.setRenderMode(renderMode);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the current rendering mode. May be called
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from any thread. Must not be called before a renderer has been set.
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the renderer will render continuously.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getRenderMode() {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGLThread.getRenderMode();
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request that the renderer render a frame. May be called
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from any thread. Must not be called before a renderer has been set.
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This method is typically used when the render mode has been set to
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * false, so that frames are only rendered on demand.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestRender() {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.requestRender();
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void surfaceCreated(SurfaceHolder holder) {
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.surfaceCreated();
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void surfaceDestroyed(SurfaceHolder holder) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Surface will be destroyed when we return
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.surfaceDestroyed();
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.onWindowResize(w, h);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inform the view that the activity is paused. The owner of this view must
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * call this method when the activity is paused.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onPause() {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.onPause();
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inform the view that the activity is resumed. The owner of this view must
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * call this method when the activity is resumed.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onResume() {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.onResume();
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Queue an "event" to be run on the GL rendering thread.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param r the runnable to be run on the GL rendering thread.
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void queueEvent(Runnable r) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.queueEvent(r);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onDetachedFromWindow() {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onDetachedFromWindow();
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGLThread.requestExitAndWait();
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface GLWrapper {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      GL wrap(GL gl);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A generic renderer interface.
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Renderer {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Surface created.
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when the surface is created. Called when the application
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * starts, and whenever the GPU is reinitialized. This will
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * typically happen when the device awakes after going to sleep.
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Set your textures here.
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param gl the GL interface. Use <code>instanceof</code> to
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * test if the interface supports GL11 or higher interfaces.
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param config the EGLConfig of the created surface. Can be used
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to create matching pbuffers.
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSurfaceCreated(GL10 gl, EGLConfig config);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Surface changed size.
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called after the surface is created and whenever
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the OpenGL ES surface size changes. Set your viewport here.
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param gl the GL interface. Use <code>instanceof</code> to
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * test if the interface supports GL11 or higher interfaces.
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param width
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param height
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onSurfaceChanged(GL10 gl, int width, int height);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Draw the current frame.
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param gl the GL interface. Use <code>instanceof</code> to
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * test if the interface supports GL11 or higher interfaces.
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onDrawFrame(GL10 gl);
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
287a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * An interface for choosing a configuration from a list of
288a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * potential configurations.
289a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
290a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
291a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    public interface EGLConfigChooser {
292a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        /**
293a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * Choose a configuration from the list. Implementors typically
294a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * implement this method by calling
295a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * {@link EGL10#eglChooseConfig} and iterating through the results.
296a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * @param egl the EGL10 for the current display.
297a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * @param display the current display.
298a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         * @return the chosen configuration.
299a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich         */
300a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
301a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
302a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
303a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private static abstract class BaseConfigChooser
304a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            implements EGLConfigChooser {
305a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public BaseConfigChooser(int[] configSpec) {
306a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mConfigSpec = configSpec;
307a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
308a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
309a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int[] num_config = new int[1];
310a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config);
311a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
312a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int numConfigs = num_config[0];
313a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
314a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            if (numConfigs <= 0) {
315a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                throw new IllegalArgumentException(
316a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        "No configs match configSpec");
317a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
318a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
319a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            EGLConfig[] configs = new EGLConfig[numConfigs];
320a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
321a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    num_config);
322a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            EGLConfig config = chooseConfig(egl, display, configs);
323a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            if (config == null) {
324a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                throw new IllegalArgumentException("No config chosen");
325a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
326a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            return config;
327a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
328a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
329a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
330a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                EGLConfig[] configs);
331a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
332a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int[] mConfigSpec;
333a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
334a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
335a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private static class ComponentSizeChooser extends BaseConfigChooser {
336a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
337a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int alphaSize, int depthSize, int stencilSize) {
338a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            super(new int[] {
339a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_RED_SIZE, redSize,
340a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_GREEN_SIZE, greenSize,
341a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_BLUE_SIZE, blueSize,
342a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_ALPHA_SIZE, alphaSize,
343a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_DEPTH_SIZE, depthSize,
344a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_STENCIL_SIZE, stencilSize,
345a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    EGL10.EGL_NONE});
346a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mValue = new int[1];
347a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mRedSize = redSize;
348a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mGreenSize = greenSize;
349a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mBlueSize = blueSize;
350a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mAlphaSize = alphaSize;
351a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mDepthSize = depthSize;
352a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mStencilSize = stencilSize;
353a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich       }
354a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
355a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        @Override
356a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
357a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                EGLConfig[] configs) {
358a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            EGLConfig closestConfig = null;
359a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            int closestDistance = 1000;
360a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            for(EGLConfig config : configs) {
361a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int r = findConfigAttrib(egl, display, config,
362a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        EGL10.EGL_RED_SIZE, 0);
363a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int g = findConfigAttrib(egl, display, config,
364a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                         EGL10.EGL_GREEN_SIZE, 0);
365a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int b = findConfigAttrib(egl, display, config,
366a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                          EGL10.EGL_BLUE_SIZE, 0);
367a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int a = findConfigAttrib(egl, display, config,
368a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        EGL10.EGL_ALPHA_SIZE, 0);
369a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int d = findConfigAttrib(egl, display, config,
370a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        EGL10.EGL_DEPTH_SIZE, 0);
371a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int s = findConfigAttrib(egl, display, config,
372a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                        EGL10.EGL_STENCIL_SIZE, 0);
373a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                int distance = Math.abs(r - mRedSize)
374a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    + Math.abs(g - mGreenSize)
375a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    + Math.abs(b - mBlueSize) + Math.abs(a - mAlphaSize)
376a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    + Math.abs(d - mDepthSize) + Math.abs(s - mStencilSize);
377a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                if (distance < closestDistance) {
378a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    closestDistance = distance;
379a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    closestConfig = config;
380a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                }
381a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
382a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            return closestConfig;
383a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
384a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
385a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        private int findConfigAttrib(EGL10 egl, EGLDisplay display,
386a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                EGLConfig config, int attribute, int defaultValue) {
387a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
388a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
389a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                return mValue[0];
390a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            }
391a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            return defaultValue;
392a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
393a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
394a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        private int[] mValue;
395a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        // Subclasses can adjust these values:
396a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mRedSize;
397a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mGreenSize;
398a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mBlueSize;
399a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mAlphaSize;
400a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mDepthSize;
401a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        protected int mStencilSize;
402a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
403a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
404a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
405a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * This class will choose a supported surface as close to
406a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     * RGB565 as possible, with or without a depth buffer.
407a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     *
408a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich     */
409a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private static class SimpleEGLConfigChooser extends ComponentSizeChooser {
410a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public SimpleEGLConfigChooser(boolean withDepthBuffer) {
411a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
412a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            // Adjust target values. This way we'll accept a 4444 or
413a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            // 555 buffer if there's no 565 buffer available.
414a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mRedSize = 5;
415a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mGreenSize = 6;
416a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mBlueSize = 5;
417a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        }
418a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    }
419a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich
420a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    /**
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An EGL helper class.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class EglHelper {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public EglHelper() {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Initialize EGL for a given configuration spec.
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param configSpec
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
433a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich        public void start(){
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Get an EGL instance
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl = (EGL10) EGLContext.getEGL();
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Get to the default display.
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * We can now initialize EGL for that display
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int[] version = new int[2];
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl.eglInitialize(mEglDisplay, version);
449a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            * Create an OpenGL ES context. This must be done only once, an
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            * OpenGL context is a somewhat heavy object.
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    EGL10.EGL_NO_CONTEXT, null);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglSurface = null;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * React to the creation of a new surface by creating and returning an
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * OpenGL interface that renders to that surface.
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GL createSurface(SurfaceHolder holder) {
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *  The window size has changed, so we need to create a new
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *  surface.
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglSurface != null) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /*
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * Unbind and destroy the old EGL surface, if
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 * there is one.
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 */
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Create an EGL surface we can render into.
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEglConfig, holder, null);
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Before we can issue GL commands, we need to make sure
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * the context is current and bound to a surface.
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEglContext);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GL gl = mEglContext.getGL();
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mGLWrapper != null) {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                gl = mGLWrapper.wrap(gl);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS))!= 0) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int configFlags = 0;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Writer log = null;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log = new LogWriter();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                gl = GLDebugHelper.wrap(gl, configFlags, log);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return gl;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Display the current render surface.
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return false if the context has been lost.
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean swap() {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Always check for EGL_CONTEXT_LOST, which means the context
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * and all associated data were lost (For instance because
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * the device went to sleep). We need to sleep until we
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * get a new surface.
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void finish() {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglSurface != null) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EGL10.EGL_NO_SURFACE,
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        EGL10.EGL_NO_CONTEXT);
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEglSurface = null;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglContext != null) {
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEglContext = null;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEglDisplay != null) {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEgl.eglTerminate(mEglDisplay);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEglDisplay = null;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGL10 mEgl;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLDisplay mEglDisplay;
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLSurface mEglSurface;
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLConfig mEglConfig;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EGLContext mEglContext;
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A generic GL Thread. Takes care of initializing EGL and GL. Delegates
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to a Renderer instance to do the actual drawing. Can be configured to
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * render continuously or on request.
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class GLThread extends Thread {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        GLThread(Renderer renderer) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDone = false;
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWidth = 0;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeight = 0;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRequestRender = true;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRenderMode = RENDERMODE_CONTUOUSLY;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRenderer = renderer;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setName("GLThread");
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * When the android framework launches a second instance of
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * an activity, the new instance's onCreate() method may be
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * called before the first instance returns from onDestroy().
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             *
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * This semaphore ensures that only one instance at a time
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * accesses EGL.
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sEglSemaphore.acquire();
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (InterruptedException e) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                guardedRun();
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException e) {
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // fall thru and exit normally
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sEglSemaphore.release();
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void guardedRun() throws InterruptedException {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglHelper = new EglHelper();
599a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich            mEglHelper.start();
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GL10 gl = null;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean tellRendererSurfaceCreated = true;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean tellRendererSurfaceChanged = true;
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * This is our main activity thread's loop, we go until
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * asked to quit.
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (!mDone) {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                /*
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 *  Update the asynchronous state (window size)
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                 */
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int w, h;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean needStart = false;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (this) {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Runnable r;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((r = getEvent()) != null) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        r.run();
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mPaused) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mEglHelper.finish();
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        needStart = true;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while (needToWait()) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        wait();
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mDone) {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    changed = mSizeChanged;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    w = mWidth;
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    h = mHeight;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSizeChanged = false;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRequestRender = false;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (needStart) {
639a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich                    mEglHelper.start();
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceCreated = true;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    changed = true;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (changed) {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    gl = (GL10) mEglHelper.createSurface(getHolder());
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceChanged = true;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (tellRendererSurfaceCreated) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceCreated = false;
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (tellRendererSurfaceChanged) {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRenderer.onSurfaceChanged(gl, w, h);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    tellRendererSurfaceChanged = false;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((w > 0) && (h > 0)) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /* draw a frame here */
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mRenderer.onDrawFrame(gl);
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    /*
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     * Once we're done with GL, we need to call swapBuffers()
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     * to instruct the system to display the rendered frame
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     */
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEglHelper.swap();
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * clean-up everything...
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEglHelper.finish();
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean needToWait() {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDone) {
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPaused || (! mHasSurface)) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTUOUSLY))) {
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setRenderMode(int renderMode) {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTUOUSLY)) ) {
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("renderMode");
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRenderMode = renderMode;
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (renderMode == RENDERMODE_CONTUOUSLY) {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    notify();
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getRenderMode() {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mRenderMode;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void requestRender() {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRequestRender = true;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void surfaceCreated() {
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHasSurface = true;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void surfaceDestroyed() {
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHasSurface = false;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onPause() {
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPaused = true;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onResume() {
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPaused = false;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onWindowResize(int w, int h) {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWidth = w;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeight = h;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSizeChanged = true;
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void requestExitAndWait() {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't call this from GLThread thread or it is a guaranteed
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // deadlock!
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDone = true;
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notify();
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                join();
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException ex) {
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Thread.currentThread().interrupt();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Queue an "event" to be run on the GL rendering thread.
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param r the runnable to be run on the GL rendering thread.
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void queueEvent(Runnable r) {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEventQueue.add(r);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Runnable getEvent() {
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(this) {
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mEventQueue.size() > 0) {
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return mEventQueue.remove(0);
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mDone;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mPaused;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mHasSurface;
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mWidth;
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mHeight;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mRenderMode;
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mRequestRender;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Renderer mRenderer;
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private EglHelper mEglHelper;
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static class LogWriter extends Writer {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void close() {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flushBuilder();
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void flush() {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flushBuilder();
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void write(char[] buf, int offset, int count) {
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for(int i = 0; i < count; i++) {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                char c = buf[offset + i];
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ( c == '\n') {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    flushBuilder();
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                else {
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mBuilder.append(c);
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void flushBuilder() {
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBuilder.length() > 0) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.v("GLSurfaceView", mBuilder.toString());
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBuilder.delete(0, mBuilder.length());
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private StringBuilder mBuilder = new StringBuilder();
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Semaphore sEglSemaphore = new Semaphore(1);
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mSizeChanged = true;
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GLThread mGLThread;
832a605a51e63de2e7dc99ed085639a6f12b7f85af7Jack Palevich    private EGLConfigChooser mEGLConfigChooser;
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GLWrapper mGLWrapper;
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mDebugFlags;
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
836