diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 38ed9321653d5..0f5dd3aa56678 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -16,6 +16,13 @@ package android.opengl; +import android.content.Context; +import android.os.Trace; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + import java.io.Writer; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -29,15 +36,6 @@ import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; -import android.content.Context; -import android.content.pm.ConfigurationInfo; -import android.os.SystemProperties; -import android.os.Trace; -import android.util.AttributeSet; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - /** * An implementation of SurfaceView that uses the dedicated surface for * displaying OpenGL rendering. @@ -119,9 +117,9 @@ * {@link #setRenderMode}. The default is continuous rendering. *

*

Activity Life-cycle

- * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients - * are required to call {@link #onPause()} when the activity pauses and - * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to + * A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients + * are required to call {@link #onPause()} when the activity stops and + * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate * the OpenGL display. *

@@ -294,10 +292,12 @@ public int getDebugFlags() { * resumed. *

* If set to true, then the EGL context may be preserved when the GLSurfaceView is paused. - * Whether the EGL context is actually preserved or not depends upon whether the - * Android device that the program is running on can support an arbitrary number of EGL - * contexts or not. Devices that can only support a limited number of EGL contexts must - * release the EGL context in order to allow multiple applications to share the GPU. + *

+ * Prior to API level 11, whether the EGL context is actually preserved or not + * depends upon whether the Android device can support an arbitrary number of + * EGL contexts or not. Devices that can only support a limited number of EGL + * contexts must release the EGL context in order to allow multiple applications + * to share the GPU. *

* If set to false, the EGL context will be released when the GLSurfaceView is paused, * and recreated when the GLSurfaceView is resumed. @@ -554,9 +554,13 @@ public void surfaceRedrawNeeded(SurfaceHolder holder) { /** - * Inform the view that the activity is paused. The owner of this view must - * call this method when the activity is paused. Calling this method will - * pause the rendering thread. + * Pause the rendering thread, optionally tearing down the EGL context + * depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}. + * + * This method should be called when it is no longer desirable for the + * GLSurfaceView to continue rendering, such as in response to + * {@link android.app.Activity#onStop Activity.onStop}. + * * Must not be called before a renderer has been set. */ public void onPause() { @@ -564,10 +568,12 @@ public void onPause() { } /** - * Inform the view that the activity is resumed. The owner of this view must - * call this method when the activity is resumed. Calling this method will - * recreate the OpenGL display and resume the rendering - * thread. + * Resumes the rendering thread, re-creating the OpenGL context if necessary. It + * is the counterpart to {@link #onPause()}. + * + * This method should typically be called in + * {@link android.app.Activity#onStart Activity.onStart}. + * * Must not be called before a renderer has been set. */ public void onResume() { @@ -1354,7 +1360,7 @@ private void guardedRun() throws InterruptedException { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); boolean preserveEglContextOnPause = view == null ? false : view.mPreserveEGLContextOnPause; - if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { + if (!preserveEglContextOnPause) { stopEglContextLocked(); if (LOG_SURFACE) { Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); @@ -1362,16 +1368,6 @@ private void guardedRun() throws InterruptedException { } } - // When pausing, optionally terminate EGL: - if (pausing) { - if (sGLThreadManager.shouldTerminateEGLWhenPausing()) { - mEglHelper.finish(); - if (LOG_SURFACE) { - Log.i("GLThread", "terminating EGL because paused tid=" + getId()); - } - } - } - // Have we lost the SurfaceView surface? if ((! mHasSurface) && (! mWaitingForSurface)) { if (LOG_SURFACE) { @@ -1411,7 +1407,7 @@ private void guardedRun() throws InterruptedException { if (! mHaveEglContext) { if (askedToReleaseEglContext) { askedToReleaseEglContext = false; - } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) { + } else { try { mEglHelper.start(); } catch (RuntimeException t) { @@ -1506,7 +1502,6 @@ private void guardedRun() throws InterruptedException { if (createGlInterface) { gl = (GL10) mEglHelper.createGL(); - sGLThreadManager.checkGLDriver(gl); createGlInterface = false; } @@ -1888,111 +1883,16 @@ public synchronized void threadExiting(GLThread thread) { Log.i("GLThread", "exiting tid=" + thread.getId()); } thread.mExited = true; - if (mEglOwner == thread) { - mEglOwner = null; - } notifyAll(); } - /* - * Tries once to acquire the right to use an EGL - * context. Does not block. Requires that we are already - * in the sGLThreadManager monitor when this is called. - * - * @return true if the right to use an EGL context was acquired. - */ - public boolean tryAcquireEglContextLocked(GLThread thread) { - if (mEglOwner == thread || mEglOwner == null) { - mEglOwner = thread; - notifyAll(); - return true; - } - checkGLESVersion(); - if (mMultipleGLESContextsAllowed) { - return true; - } - // Notify the owning thread that it should release the context. - // TODO: implement a fairness policy. Currently - // if the owning thread is drawing continuously it will just - // reacquire the EGL context. - if (mEglOwner != null) { - mEglOwner.requestReleaseEglContextLocked(); - } - return false; - } - /* * Releases the EGL context. Requires that we are already in the * sGLThreadManager monitor when this is called. */ public void releaseEglContextLocked(GLThread thread) { - if (mEglOwner == thread) { - mEglOwner = null; - } notifyAll(); } - - public synchronized boolean shouldReleaseEGLContextWhenPausing() { - // Release the EGL context when pausing even if - // the hardware supports multiple EGL contexts. - // Otherwise the device could run out of EGL contexts. - return mLimitedGLESContexts; - } - - public synchronized boolean shouldTerminateEGLWhenPausing() { - checkGLESVersion(); - return !mMultipleGLESContextsAllowed; - } - - public synchronized void checkGLDriver(GL10 gl) { - if (! mGLESDriverCheckComplete) { - checkGLESVersion(); - String renderer = gl.glGetString(GL10.GL_RENDERER); - if (mGLESVersion < kGLES_20) { - mMultipleGLESContextsAllowed = - ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); - notifyAll(); - } - mLimitedGLESContexts = !mMultipleGLESContextsAllowed; - if (LOG_SURFACE) { - Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " - + mMultipleGLESContextsAllowed - + " mLimitedGLESContexts = " + mLimitedGLESContexts); - } - mGLESDriverCheckComplete = true; - } - } - - private void checkGLESVersion() { - if (! mGLESVersionCheckComplete) { - mGLESVersion = SystemProperties.getInt( - "ro.opengles.version", - ConfigurationInfo.GL_ES_VERSION_UNDEFINED); - if (mGLESVersion >= kGLES_20) { - mMultipleGLESContextsAllowed = true; - } - if (LOG_SURFACE) { - Log.w(TAG, "checkGLESVersion mGLESVersion =" + - " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); - } - mGLESVersionCheckComplete = true; - } - } - - /** - * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides - * support for hardware-accelerated views, therefore multiple EGL contexts are - * supported on all Android 3.0+ EGL drivers. - */ - private boolean mGLESVersionCheckComplete; - private int mGLESVersion; - private boolean mGLESDriverCheckComplete; - private boolean mMultipleGLESContextsAllowed; - private boolean mLimitedGLESContexts; - private static final int kGLES_20 = 0x20000; - private static final String kMSM7K_RENDERER_PREFIX = - "Q3Dimension MSM7500 "; - private GLThread mEglOwner; } private static final GLThreadManager sGLThreadManager = new GLThreadManager();