diff options
author | Jack Palevich <jackpal@google.com> | 2012-03-29 12:23:57 -0700 |
---|---|---|
committer | Jack Palevich <jackpal@google.com> | 2012-03-29 12:23:57 -0700 |
commit | db6c78b5bdf264abe8f6de97f67ca5e90fb6a05a (patch) | |
tree | cf23eb1f3affd7590cc1ac34d8f53bd66d4814e7 /opengl | |
parent | db2026000a1d832b60d73e0a046bc8137fbb1960 (diff) | |
download | frameworks_base-db6c78b5bdf264abe8f6de97f67ca5e90fb6a05a.zip frameworks_base-db6c78b5bdf264abe8f6de97f67ca5e90fb6a05a.tar.gz frameworks_base-db6c78b5bdf264abe8f6de97f67ca5e90fb6a05a.tar.bz2 |
Make GLSurfaceView handle eglSwapBuffers errors more robustly.
A careful reading of the EGL spec, as well as experience with many
different EGL drivers, has shown that it is error prone to attempt to
discriminate between different error conditions.
We now treat any error besides EGL_CONTEXT_LOST as an indication that the
EGL context is in a bad state, most likely due to the window manager
having removed the underlying surface flinger surface.
In addition, we changed the way we deal with this kind of error:
Previously we would ignore the error and keep rendering. But if the
EGL context and surface has become invalid, it would be better to
stop drawing. We now stop drawing until the surface view surface is
recreated.
See b/6032663 for an example of this problem affecting the GMM app,
but note that GMM is using their own version of GLSurfaceView, so this
change won't help them directly. They'll have to make a similar change
to their version of GLSurfaceView.
Change-Id: Iffe3e1e3a3c7a91d03140fd34391eadeaecf777e
Signed-off-by: Jack Palevich <jackpal@google.com>
Diffstat (limited to 'opengl')
-rw-r--r-- | opengl/java/android/opengl/GLSurfaceView.java | 65 |
1 files changed, 31 insertions, 34 deletions
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index f69fc53..b868049 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -1130,36 +1130,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback /** * Display the current render surface. - * @return false if the context has been lost. + * @return the EGL error code from eglSwapBuffers. */ - public boolean swap() { + public int swap() { if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { - - /* - * Check for EGL_CONTEXT_LOST, which means the context - * and all associated data were lost (For instance because - * the device went to sleep). We need to sleep until we - * get a new surface. - */ - int error = mEgl.eglGetError(); - switch(error) { - case EGL11.EGL_CONTEXT_LOST: - return false; - case EGL10.EGL_BAD_CURRENT_SURFACE: - // The current surface is bad, probably because the window manager has closed - // the associated window. Ignore this error, on the assumption that the - // application will be closed soon. - break; - case EGL10.EGL_BAD_NATIVE_WINDOW: - // The native window is bad, probably because the window manager has closed it. - // Ignore this error, on the assumption that the application will be closed - // soon. - break; - default: - throwEglException("eglSwapBuffers", error); - } + return mEgl.eglGetError(); } - return true; + return EGL10.EGL_SUCCESS; } public void destroySurface() { @@ -1366,6 +1343,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback stopEglSurfaceLocked(); } mWaitingForSurface = true; + mSurfaceIsBad = false; sGLThreadManager.notifyAll(); } @@ -1423,7 +1401,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback h = mHeight; wantRenderNotification = true; if (LOG_SURFACE) { - Log.i("GLThread", "noticing that we want render notification tid=" + getId()); + Log.i("GLThread", + "noticing that we want render notification tid=" + + getId()); } // Destroy and recreate the EGL surface. @@ -1444,6 +1424,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback + " mHaveEglSurface: " + mHaveEglSurface + " mPaused: " + mPaused + " mHasSurface: " + mHasSurface + + " mSurfaceIsBad: " + mSurfaceIsBad + " mWaitingForSurface: " + mWaitingForSurface + " mWidth: " + mWidth + " mHeight: " + mHeight @@ -1509,11 +1490,26 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback view.mRenderer.onDrawFrame(gl); } } - if (!mEglHelper.swap()) { - if (LOG_SURFACE) { - Log.i("GLThread", "egl context lost tid=" + getId()); - } - lostEglContext = true; + int swapError = mEglHelper.swap(); + switch (swapError) { + case EGL10.EGL_SUCCESS: + break; + case EGL11.EGL_CONTEXT_LOST: + if (LOG_SURFACE) { + Log.i("GLThread", "egl context lost tid=" + getId()); + } + lostEglContext = true; + break; + default: + // Other errors typically mean that the current surface is bad, + // probably because the surfaceview surface has been destroyed, + // but we haven't been notified yet. + // Log the error to help developers understand why rendering stopped. + Log.w("GLThread", "eglSwapBuffers error: " + swapError + + ". Assume surfaceview surface is being destroyed. tid=" + + getId()); + mSurfaceIsBad = true; + break; } if (wantRenderNotification) { @@ -1537,7 +1533,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } private boolean readyToDraw() { - return (!mPaused) && mHasSurface + return (!mPaused) && mHasSurface && (!mSurfaceIsBad) && (mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); } @@ -1707,6 +1703,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private boolean mRequestPaused; private boolean mPaused; private boolean mHasSurface; + private boolean mSurfaceIsBad; private boolean mWaitingForSurface; private boolean mHaveEglContext; private boolean mHaveEglSurface; |