Merge "Merge \"update GlSurfaceView:onPause/Resume docs\" into nyc-mr1-dev am: ee557b2b99" into nyc-mr1-dev-plus-aosp
This commit is contained in:
committed by
Android (Google) Code Review
commit
acfdf0eab5
@@ -16,6 +16,13 @@
|
|||||||
|
|
||||||
package android.opengl;
|
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.io.Writer;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -29,15 +36,6 @@ import javax.microedition.khronos.egl.EGLSurface;
|
|||||||
import javax.microedition.khronos.opengles.GL;
|
import javax.microedition.khronos.opengles.GL;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
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
|
* An implementation of SurfaceView that uses the dedicated surface for
|
||||||
* displaying OpenGL rendering.
|
* displaying OpenGL rendering.
|
||||||
@@ -119,9 +117,9 @@ import android.view.SurfaceView;
|
|||||||
* {@link #setRenderMode}. The default is continuous rendering.
|
* {@link #setRenderMode}. The default is continuous rendering.
|
||||||
* <p>
|
* <p>
|
||||||
* <h3>Activity Life-cycle</h3>
|
* <h3>Activity Life-cycle</h3>
|
||||||
* A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients
|
* A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients
|
||||||
* are required to call {@link #onPause()} when the activity pauses and
|
* are required to call {@link #onPause()} when the activity stops and
|
||||||
* {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to
|
* {@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
|
* pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
|
||||||
* the OpenGL display.
|
* the OpenGL display.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -294,10 +292,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
* resumed.
|
* resumed.
|
||||||
* <p>
|
* <p>
|
||||||
* If set to true, then the EGL context may be preserved when the GLSurfaceView is paused.
|
* 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
|
* <p>
|
||||||
* Android device that the program is running on can support an arbitrary number of EGL
|
* Prior to API level 11, whether the EGL context is actually preserved or not
|
||||||
* contexts or not. Devices that can only support a limited number of EGL contexts must
|
* depends upon whether the Android device can support an arbitrary number of
|
||||||
* release the EGL context in order to allow multiple applications to share the GPU.
|
* 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.
|
||||||
* <p>
|
* <p>
|
||||||
* If set to false, the EGL context will be released when the GLSurfaceView is paused,
|
* If set to false, the EGL context will be released when the GLSurfaceView is paused,
|
||||||
* and recreated when the GLSurfaceView is resumed.
|
* and recreated when the GLSurfaceView is resumed.
|
||||||
@@ -554,9 +554,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the view that the activity is paused. The owner of this view must
|
* Pause the rendering thread, optionally tearing down the EGL context
|
||||||
* call this method when the activity is paused. Calling this method will
|
* depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}.
|
||||||
* pause the rendering thread.
|
*
|
||||||
|
* 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.
|
* Must not be called before a renderer has been set.
|
||||||
*/
|
*/
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
@@ -564,10 +568,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the view that the activity is resumed. The owner of this view must
|
* Resumes the rendering thread, re-creating the OpenGL context if necessary. It
|
||||||
* call this method when the activity is resumed. Calling this method will
|
* is the counterpart to {@link #onPause()}.
|
||||||
* recreate the OpenGL display and resume the rendering
|
*
|
||||||
* thread.
|
* This method should typically be called in
|
||||||
|
* {@link android.app.Activity#onStart Activity.onStart}.
|
||||||
|
*
|
||||||
* Must not be called before a renderer has been set.
|
* Must not be called before a renderer has been set.
|
||||||
*/
|
*/
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
@@ -1354,7 +1360,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
|
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
|
||||||
boolean preserveEglContextOnPause = view == null ?
|
boolean preserveEglContextOnPause = view == null ?
|
||||||
false : view.mPreserveEGLContextOnPause;
|
false : view.mPreserveEGLContextOnPause;
|
||||||
if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) {
|
if (!preserveEglContextOnPause) {
|
||||||
stopEglContextLocked();
|
stopEglContextLocked();
|
||||||
if (LOG_SURFACE) {
|
if (LOG_SURFACE) {
|
||||||
Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
|
Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
|
||||||
@@ -1362,16 +1368,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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?
|
// Have we lost the SurfaceView surface?
|
||||||
if ((! mHasSurface) && (! mWaitingForSurface)) {
|
if ((! mHasSurface) && (! mWaitingForSurface)) {
|
||||||
if (LOG_SURFACE) {
|
if (LOG_SURFACE) {
|
||||||
@@ -1411,7 +1407,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
if (! mHaveEglContext) {
|
if (! mHaveEglContext) {
|
||||||
if (askedToReleaseEglContext) {
|
if (askedToReleaseEglContext) {
|
||||||
askedToReleaseEglContext = false;
|
askedToReleaseEglContext = false;
|
||||||
} else if (sGLThreadManager.tryAcquireEglContextLocked(this)) {
|
} else {
|
||||||
try {
|
try {
|
||||||
mEglHelper.start();
|
mEglHelper.start();
|
||||||
} catch (RuntimeException t) {
|
} catch (RuntimeException t) {
|
||||||
@@ -1506,7 +1502,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
if (createGlInterface) {
|
if (createGlInterface) {
|
||||||
gl = (GL10) mEglHelper.createGL();
|
gl = (GL10) mEglHelper.createGL();
|
||||||
|
|
||||||
sGLThreadManager.checkGLDriver(gl);
|
|
||||||
createGlInterface = false;
|
createGlInterface = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1888,111 +1883,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
Log.i("GLThread", "exiting tid=" + thread.getId());
|
Log.i("GLThread", "exiting tid=" + thread.getId());
|
||||||
}
|
}
|
||||||
thread.mExited = true;
|
thread.mExited = true;
|
||||||
if (mEglOwner == thread) {
|
|
||||||
mEglOwner = null;
|
|
||||||
}
|
|
||||||
notifyAll();
|
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
|
* Releases the EGL context. Requires that we are already in the
|
||||||
* sGLThreadManager monitor when this is called.
|
* sGLThreadManager monitor when this is called.
|
||||||
*/
|
*/
|
||||||
public void releaseEglContextLocked(GLThread thread) {
|
public void releaseEglContextLocked(GLThread thread) {
|
||||||
if (mEglOwner == thread) {
|
|
||||||
mEglOwner = null;
|
|
||||||
}
|
|
||||||
notifyAll();
|
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();
|
private static final GLThreadManager sGLThreadManager = new GLThreadManager();
|
||||||
|
|||||||
Reference in New Issue
Block a user