Merge change I971f6fd3 into eclair
* changes: Improve GLSurfaceView to avoid deadlocks and race conditions.
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user