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