diff options
author | Android (Google) Code Review <android-gerrit@google.com> | 2009-11-06 01:23:52 -0500 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-11-06 01:23:52 -0500 |
commit | 84872738f291faf25ae07235cde382d38c796567 (patch) | |
tree | c77d98955b43f69f4e47d63561d2482933e510d8 /opengl | |
parent | 13bf8260134d516cbcc982d360d9f21067f47fa6 (diff) | |
parent | 8b2c9c9ecb08d25244fa97fb42c2c315ae3cf03d (diff) | |
download | frameworks_base-84872738f291faf25ae07235cde382d38c796567.zip frameworks_base-84872738f291faf25ae07235cde382d38c796567.tar.gz frameworks_base-84872738f291faf25ae07235cde382d38c796567.tar.bz2 |
Merge change I971f6fd3 into eclair
* changes:
Improve GLSurfaceView to avoid deadlocks and race conditions.
Diffstat (limited to 'opengl')
-rw-r--r-- | opengl/java/android/opengl/GLSurfaceView.java | 86 |
1 files changed, 74 insertions, 12 deletions
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 695d061..952eff2 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -145,6 +145,7 @@ import android.view.SurfaceView; * */ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback { + private final static boolean LOG_THREADS = false; /** * The renderer only renders * when the surface is created, or when {@link #requestRender} is called. @@ -952,11 +953,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mRequestRender = true; mRenderMode = RENDERMODE_CONTINUOUSLY; mRenderer = renderer; - setName("GLThread"); } @Override public void run() { + setName("GLThread " + getId()); + if (LOG_THREADS) { + Log.i("GLThread", "starting tid=" + getId()); + } + /* * When the android framework launches a second instance of * an activity, the new instance's onCreate() method may be @@ -967,7 +972,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback */ try { try { - sEglSemaphore.acquire(); + sGLThreadManager.start(this); } catch (InterruptedException e) { return; } @@ -975,7 +980,17 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } catch (InterruptedException e) { // fall thru and exit normally } finally { - sEglSemaphore.release(); + try { + sGLThreadManager.end(this); + } finally { + synchronized(this) { + if (LOG_THREADS) { + Log.i("GLThread", "exiting tid=" + getId()); + } + mDone = true; + notifyAll(); + } + } } } @@ -1011,11 +1026,14 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback needStart = true; } while (needToWait()) { + if (LOG_THREADS) { + Log.i("GLThread", "needToWait tid=" + getId()); + } if (!mHasSurface) { if (!mWaitingForSurface) { mEglHelper.destroySurface(); mWaitingForSurface = true; - notify(); + notifyAll(); } } wait(); @@ -1031,6 +1049,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (mHasSurface && mWaitingForSurface) { changed = true; mWaitingForSurface = false; + notifyAll(); } } if (needStart) { @@ -1071,6 +1090,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } private boolean needToWait() { + if (sGLThreadManager.shouldQuit(this)) { + mDone = true; + notifyAll(); + } if (mDone) { return false; } @@ -1093,7 +1116,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback synchronized(this) { mRenderMode = renderMode; if (renderMode == RENDERMODE_CONTINUOUSLY) { - notify(); + notifyAll(); } } } @@ -1107,22 +1130,28 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback public void requestRender() { synchronized(this) { mRequestRender = true; - notify(); + notifyAll(); } } public void surfaceCreated() { synchronized(this) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceCreated tid=" + getId()); + } mHasSurface = true; - notify(); + notifyAll(); } } public void surfaceDestroyed() { synchronized(this) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceDestroyed tid=" + getId()); + } mHasSurface = false; - notify(); - while(!mWaitingForSurface && isAlive()) { + notifyAll(); + while(!mWaitingForSurface && isAlive() && ! mDone) { try { wait(); } catch (InterruptedException e) { @@ -1135,13 +1164,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback public void onPause() { synchronized (this) { mPaused = true; + notifyAll(); } } public void onResume() { synchronized (this) { mPaused = false; - notify(); + mRequestRender = true; + notifyAll(); } } @@ -1150,7 +1181,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mWidth = w; mHeight = h; mSizeChanged = true; - notify(); + notifyAll(); } } @@ -1159,7 +1190,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback // deadlock! synchronized(this) { mDone = true; - notify(); + notifyAll(); } try { join(); @@ -1241,7 +1272,38 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } + static class GLThreadManager { + public boolean shouldQuit(GLThread thread) { + synchronized(this) { + return thread != mMostRecentGLThread; + } + } + public void start(GLThread thread) throws InterruptedException { + GLThread oldThread = null; + synchronized(this) { + mMostRecentGLThread = thread; + oldThread = mMostRecentGLThread; + } + if (oldThread != null) { + synchronized(oldThread) { + oldThread.notifyAll(); + } + } + sEglSemaphore.acquire(); + } + public void end(GLThread thread) { + sEglSemaphore.release(); + synchronized(this) { + if (mMostRecentGLThread == thread) { + mMostRecentGLThread = null; + } + } + } + private GLThread mMostRecentGLThread; + } + private static final Semaphore sEglSemaphore = new Semaphore(1); + private static final GLThreadManager sGLThreadManager = new GLThreadManager(); private boolean mSizeChanged = true; private GLThread mGLThread; |