From 32d416518473f3bf5323d660e5910ca5633ffed6 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Sun, 8 Nov 2009 10:55:56 +0800 Subject: [PATCH] Allow a GLThread to release and reacquire the EGL Surface as needed. We currently only allow one GLThread to have an active EGL Surface at a time.(This may be lifted in the future, when EGL and GL are reentrant.) Prior to this change we would enforce this rule by having older GLThreads quit when a new GLThread started. That had the drawback of leaving the older GLSurfaceViews in a zombie state -- their GLThreads would be gone. We now enforce this rule by just releasing and reacquiring the EGL surface context as needed. Specific changes to the code: created private helper methods - startEgl and stopEgl to help manage starting and stopping EGL. Move the calls to sGLThreadManager start and end from the outermost run method into the startEgl / stopEgl methods. Reworked the wait loop to handle starting and stopping EGL as needed. needToWait() gets simpler -- just looks at current status. sGLThreadManager.shouldQuit was replaced by shouldHaveEgl. This is another step in fixing bug 2228262. --- opengl/java/android/opengl/GLSurfaceView.java | 78 ++++++++++++++++----------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index ac27a2dbe064..03301639cd29 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -971,33 +971,41 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * accesses EGL. */ try { - try { - sGLThreadManager.start(this); - } catch (InterruptedException e) { - return; - } guardedRun(); } catch (InterruptedException e) { // fall thru and exit normally } finally { - try { - sGLThreadManager.end(this); - } finally { - synchronized(this) { - if (LOG_THREADS) { - Log.i("GLThread", "exiting tid=" + getId()); - } - mDone = true; - notifyAll(); + synchronized(this) { + if (LOG_THREADS) { + Log.i("GLThread", "exiting tid=" + getId()); } + mDone = true; + notifyAll(); } } } + private void startEgl() throws InterruptedException { + if (! mHaveEgl) { + mHaveEgl = true; + sGLThreadManager.start(this); + mEglHelper.start(); + } + } + + private void stopEgl() { + if (mHaveEgl) { + mHaveEgl = false; + mEglHelper.destroySurface(); + mEglHelper.finish(); + sGLThreadManager.end(this); + } + } + private void guardedRun() throws InterruptedException { mEglHelper = new EglHelper(); try { - mEglHelper.start(); + startEgl(); GL10 gl = null; boolean tellRendererSurfaceCreated = true; @@ -1021,20 +1029,30 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback r.run(); } if (mPaused) { - mEglHelper.destroySurface(); - mEglHelper.finish(); + stopEgl(); needStart = true; } - while (needToWait()) { - if (LOG_THREADS) { - Log.i("GLThread", "needToWait tid=" + getId()); - } + while(true) { if (!mHasSurface) { if (!mWaitingForSurface) { - mEglHelper.destroySurface(); + stopEgl(); mWaitingForSurface = true; notifyAll(); } + } else { + boolean shouldHaveEgl = sGLThreadManager.shouldHaveEgl(this); + if (mHaveEgl && (!shouldHaveEgl)) { + stopEgl(); + } else if ((!mHaveEgl) && shouldHaveEgl) { + startEgl(); + needStart = true; + } + } + if (!needToWait()) { + break; + } + if (LOG_THREADS) { + Log.i("GLThread", "needToWait tid=" + getId()); } wait(); } @@ -1053,7 +1071,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } if (needStart) { - mEglHelper.start(); + startEgl(); tellRendererSurfaceCreated = true; changed = true; } @@ -1084,21 +1102,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback /* * clean-up everything... */ - mEglHelper.destroySurface(); - mEglHelper.finish(); + stopEgl(); } } private boolean needToWait() { - if (sGLThreadManager.shouldQuit(this)) { - mDone = true; - notifyAll(); - } if (mDone) { return false; } - if (mPaused || (! mHasSurface)) { + if (mPaused || (! mHasSurface) || (! mHaveEgl)) { return true; } @@ -1223,6 +1236,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private boolean mPaused; private boolean mHasSurface; private boolean mWaitingForSurface; + private boolean mHaveEgl; private int mWidth; private int mHeight; private int mRenderMode; @@ -1273,9 +1287,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } static class GLThreadManager { - public boolean shouldQuit(GLThread thread) { + public boolean shouldHaveEgl(GLThread thread) { synchronized(this) { - return thread != mMostRecentGLThread; + return thread == mMostRecentGLThread || mMostRecentGLThread == null; } } public void start(GLThread thread) throws InterruptedException { -- 2.11.0