diff options
author | Jack Palevich <jackpal@google.com> | 2010-07-13 21:11:48 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-07-13 21:11:48 -0700 |
commit | 1f76f88c3821a1597b2f2884d937c54c2ba08a8e (patch) | |
tree | 3dd4250191b1903bd0895ed4b95e3c67da1e6ce4 /opengl | |
parent | 2388ad9eef109fa7f63c196c819c83f0376f0645 (diff) | |
parent | 43429036f5885063e522603e51c5f59f8b9e697a (diff) | |
download | frameworks_base-1f76f88c3821a1597b2f2884d937c54c2ba08a8e.zip frameworks_base-1f76f88c3821a1597b2f2884d937c54c2ba08a8e.tar.gz frameworks_base-1f76f88c3821a1597b2f2884d937c54c2ba08a8e.tar.bz2 |
am 43429036: am 91216a7e: Merge "Fix deadlock when switching between two GLSurfaceViews" into gingerbread
Merge commit '43429036f5885063e522603e51c5f59f8b9e697a'
* commit '43429036f5885063e522603e51c5f59f8b9e697a':
Fix deadlock when switching between two GLSurfaceViews
Diffstat (limited to 'opengl')
-rw-r--r-- | opengl/java/android/opengl/GLSurfaceView.java | 92 |
1 files changed, 74 insertions, 18 deletions
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 2ff231d..41207f7 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -222,6 +222,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback // underlying surface is created and destroyed SurfaceHolder holder = getHolder(); holder.addCallback(this); + // setFormat is done by SurfaceView in SDK 2.3 and newer. Uncomment + // this statement if back-porting to 2.2 or older: + // holder.setFormat(PixelFormat.RGB_565); + // // setType is not needed for SDK 2.0 or newer. Uncomment this // statement if back-porting this code to older SDKs. // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); @@ -1103,7 +1107,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mRenderer = renderer; } - @Override public void run() { setName("GLThread " + getId()); @@ -1154,6 +1157,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback boolean sizeChanged = false; boolean wantRenderNotification = false; boolean doRenderNotification = false; + boolean askedToReleaseEglContext = false; int w = 0; int h = 0; Runnable event = null; @@ -1179,6 +1183,17 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } + // Do we need to give up the EGL context? + if (mShouldReleaseEglContext) { + if (LOG_SURFACE) { + Log.i("GLThread", "releasing EGL context because asked to tid=" + getId()); + } + stopEglSurfaceLocked(); + stopEglContextLocked(); + mShouldReleaseEglContext = false; + askedToReleaseEglContext = true; + } + // Have we lost the EGL context? if (lostEglContext) { stopEglSurfaceLocked(); @@ -1228,6 +1243,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } if (doRenderNotification) { + if (LOG_SURFACE) { + Log.i("GLThread", "sending render notification tid=" + getId()); + } wantRenderNotification = false; doRenderNotification = false; mRenderComplete = true; @@ -1235,22 +1253,24 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } // Ready to draw? - if ((!mPaused) && mHasSurface - && (mWidth > 0) && (mHeight > 0) - && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { + if (readyToDraw()) { // If we don't have an EGL context, try to acquire one. - if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglContextLocked(this)) { - try { - mEglHelper.start(); - } catch (RuntimeException t) { - sGLThreadManager.releaseEglContextLocked(this); - throw t; - } - mHaveEglContext = true; - createEglContext = true; + if (! mHaveEglContext) { + if (askedToReleaseEglContext) { + askedToReleaseEglContext = false; + } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) { + try { + mEglHelper.start(); + } catch (RuntimeException t) { + sGLThreadManager.releaseEglContextLocked(this); + throw t; + } + mHaveEglContext = true; + createEglContext = true; - sGLThreadManager.notifyAll(); + sGLThreadManager.notifyAll(); + } } if (mHaveEglContext && !mHaveEglSurface) { @@ -1265,6 +1285,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback w = mWidth; h = mHeight; wantRenderNotification = true; + if (LOG_SURFACE) { + Log.i("GLThread", "noticing that we want render notification tid=" + getId()); + } if (DRAW_TWICE_AFTER_SIZE_CHANGED) { // We keep mRequestRender true so that we draw twice after the size changes. @@ -1284,7 +1307,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback // By design, this is the only place in a GLThread thread where we wait(). if (LOG_THREADS) { - Log.i("GLThread", "waiting tid=" + getId()); + Log.i("GLThread", "waiting tid=" + getId() + + " mHaveEglContext: " + mHaveEglContext + + " mHaveEglSurface: " + mHaveEglSurface + + " mPaused: " + mPaused + + " mHasSurface: " + mHasSurface + + " mWaitingForSurface: " + mWaitingForSurface + + " mWidth: " + mWidth + + " mHeight: " + mHeight + + " mRequestRender: " + mRequestRender + + " mRenderMode: " + mRenderMode); } sGLThreadManager.wait(); } @@ -1326,7 +1358,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } if (LOG_RENDERER_DRAW_FRAME) { - Log.w("GLThread", "onDrawFrame"); + Log.w("GLThread", "onDrawFrame tid=" + getId()); } mRenderer.onDrawFrame(gl); if (!mEglHelper.swap()) { @@ -1352,6 +1384,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } + public boolean ableToDraw() { + return mHaveEglContext && mHaveEglSurface && readyToDraw(); + } + + private boolean readyToDraw() { + return (!mPaused) && mHasSurface + && (mWidth > 0) && (mHeight > 0) + && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); + } + public void setRenderMode(int renderMode) { if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { throw new IllegalArgumentException("renderMode"); @@ -1461,9 +1503,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback sGLThreadManager.notifyAll(); // Wait for thread to react to resize and render a frame - while (! mExited && !mPaused && !mRenderComplete ) { + while (! mExited && !mPaused && !mRenderComplete + && (mGLThread != null && mGLThread.ableToDraw())) { if (LOG_SURFACE) { - Log.i("Main thread", "onWindowResize waiting for render complete."); + Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + mGLThread.getId()); } try { sGLThreadManager.wait(); @@ -1490,6 +1533,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } + public void requestReleaseEglContextLocked() { + mShouldReleaseEglContext = true; + sGLThreadManager.notifyAll(); + } + /** * Queue an "event" to be run on the GL rendering thread. * @param r the runnable to be run on the GL rendering thread. @@ -1514,6 +1562,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private boolean mWaitingForSurface; private boolean mHaveEglContext; private boolean mHaveEglSurface; + private boolean mShouldReleaseEglContext; private int mWidth; private int mHeight; private int mRenderMode; @@ -1598,6 +1647,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback 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; } |