Loading opengl/java/android/opengl/GLSurfaceView.java +158 −139 Original line number Original line Diff line number Diff line Loading @@ -955,6 +955,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * to a Renderer instance to do the actual drawing. Can be configured to * to a Renderer instance to do the actual drawing. Can be configured to * render continuously or on request. * render continuously or on request. * * * All potentially blocking synchronization is done through the * sGLThreadManager object. This avoids multiple-lock ordering issues. * */ */ class GLThread extends Thread { class GLThread extends Thread { GLThread(Renderer renderer) { GLThread(Renderer renderer) { Loading @@ -974,51 +977,31 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback Log.i("GLThread", "starting tid=" + getId()); 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 * called before the first instance returns from onDestroy(). * * This semaphore ensures that only one instance at a time * accesses EGL. */ try { try { guardedRun(); guardedRun(); } catch (InterruptedException e) { } catch (InterruptedException e) { // fall thru and exit normally // fall thru and exit normally } finally { } finally { synchronized(this) { sGLThreadManager.threadExiting(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() { /* * This private method should only be called inside a * synchronized(sGLThreadManager) block. */ private void stopEglLocked() { if (mHaveEgl) { if (mHaveEgl) { mHaveEgl = false; mHaveEgl = false; mEglHelper.destroySurface(); mEglHelper.destroySurface(); mEglHelper.finish(); mEglHelper.finish(); sGLThreadManager.end(this); sGLThreadManager.releaseEglSurface(this); } } } } private void guardedRun() throws InterruptedException { private void guardedRun() throws InterruptedException { mEglHelper = new EglHelper(); mEglHelper = new EglHelper(); try { try { startEgl(); GL10 gl = null; GL10 gl = null; boolean tellRendererSurfaceCreated = true; boolean tellRendererSurfaceCreated = true; boolean tellRendererSurfaceChanged = true; boolean tellRendererSurfaceChanged = true; Loading @@ -1027,50 +1010,59 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * This is our main activity thread's loop, we go until * This is our main activity thread's loop, we go until * asked to quit. * asked to quit. */ */ while (!mDone) { while (!isDone()) { /* /* * Update the asynchronous state (window size) * Update the asynchronous state (window size) */ */ int w, h; int w = 0; boolean changed; int h = 0; boolean changed = false; boolean needStart = false; boolean needStart = false; synchronized (this) { boolean eventsWaiting = false; Runnable r; while ((r = getEvent()) != null) { synchronized (sGLThreadManager) { r.run(); while (true) { } // Manage acquiring and releasing the SurfaceView // surface and the EGL surface. if (mPaused) { if (mPaused) { stopEgl(); stopEglLocked(); needStart = true; } } while(true) { if (!mHasSurface) { if (!mHasSurface) { if (!mWaitingForSurface) { if (!mWaitingForSurface) { stopEgl(); stopEglLocked(); mWaitingForSurface = true; mWaitingForSurface = true; notifyAll(); sGLThreadManager.notifyAll(); } } } else { } else { boolean shouldHaveEgl = sGLThreadManager.shouldHaveEgl(this); if (!mHaveEgl) { if (mHaveEgl && (!shouldHaveEgl)) { if (sGLThreadManager.tryAcquireEglSurface(this)) { stopEgl(); mHaveEgl = true; } else if ((!mHaveEgl) && shouldHaveEgl) { mEglHelper.start(); startEgl(); mRequestRender = true; needStart = true; needStart = true; } } } } if (!needToWait()) { break; } if (LOG_THREADS) { Log.i("GLThread", "needToWait tid=" + getId()); } wait(); } } // Check if we need to wait. If not, update any state // that needs to be updated, copy any state that // needs to be copied, and use "break" to exit the // wait loop. if (mDone) { if (mDone) { return; } if (mEventsWaiting) { eventsWaiting = true; mEventsWaiting = false; break; break; } } if ( (! mPaused) && mHasSurface && mHaveEgl && (mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)) ) { changed = mSizeChanged; changed = mSizeChanged; w = mWidth; w = mWidth; h = mHeight; h = mHeight; Loading @@ -1079,11 +1071,36 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (mHasSurface && mWaitingForSurface) { if (mHasSurface && mWaitingForSurface) { changed = true; changed = true; mWaitingForSurface = false; mWaitingForSurface = false; notifyAll(); sGLThreadManager.notifyAll(); } break; } // By design, this is the only place where we wait(). if (LOG_THREADS) { Log.i("GLThread", "waiting tid=" + getId()); } } sGLThreadManager.wait(); } } } // end of synchronized(sGLThreadManager) /* * Handle queued events */ if (eventsWaiting) { Runnable r; while ((r = getEvent()) != null) { r.run(); if (isDone()) { return; } } // Go back and see if we need to wait to render. continue; } if (needStart) { if (needStart) { startEgl(); tellRendererSurfaceCreated = true; tellRendererSurfaceCreated = true; changed = true; changed = true; } } Loading Loading @@ -1115,71 +1132,63 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback /* /* * clean-up everything... * clean-up everything... */ */ stopEgl(); synchronized (sGLThreadManager) { stopEglLocked(); } } } } private boolean needToWait() { if (mDone) { return false; } if (mPaused || (! mHasSurface) || (! mHaveEgl)) { return true; } } if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { private boolean isDone() { return false; synchronized (sGLThreadManager) { return mDone; } } return true; } } public void setRenderMode(int renderMode) { public void setRenderMode(int renderMode) { if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { throw new IllegalArgumentException("renderMode"); throw new IllegalArgumentException("renderMode"); } } synchronized(this) { synchronized(sGLThreadManager) { mRenderMode = renderMode; mRenderMode = renderMode; if (renderMode == RENDERMODE_CONTINUOUSLY) { if (renderMode == RENDERMODE_CONTINUOUSLY) { notifyAll(); sGLThreadManager.notifyAll(); } } } } } } public int getRenderMode() { public int getRenderMode() { synchronized(this) { synchronized(sGLThreadManager) { return mRenderMode; return mRenderMode; } } } } public void requestRender() { public void requestRender() { synchronized(this) { synchronized(sGLThreadManager) { mRequestRender = true; mRequestRender = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void surfaceCreated() { public void surfaceCreated() { synchronized(this) { synchronized(sGLThreadManager) { if (LOG_THREADS) { if (LOG_THREADS) { Log.i("GLThread", "surfaceCreated tid=" + getId()); Log.i("GLThread", "surfaceCreated tid=" + getId()); } } mHasSurface = true; mHasSurface = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void surfaceDestroyed() { public void surfaceDestroyed() { synchronized(this) { synchronized(sGLThreadManager) { if (LOG_THREADS) { if (LOG_THREADS) { Log.i("GLThread", "surfaceDestroyed tid=" + getId()); Log.i("GLThread", "surfaceDestroyed tid=" + getId()); } } mHasSurface = false; mHasSurface = false; notifyAll(); sGLThreadManager.notifyAll(); while(!mWaitingForSurface && isAlive() && ! mDone) { while(!mWaitingForSurface && isAlive() && ! mDone) { try { try { wait(); sGLThreadManager.wait(); } catch (InterruptedException e) { } catch (InterruptedException e) { Thread.currentThread().interrupt(); Thread.currentThread().interrupt(); } } Loading @@ -1188,35 +1197,35 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } public void onPause() { public void onPause() { synchronized (this) { synchronized (sGLThreadManager) { mPaused = true; mPaused = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void onResume() { public void onResume() { synchronized (this) { synchronized (sGLThreadManager) { mPaused = false; mPaused = false; mRequestRender = true; mRequestRender = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void onWindowResize(int w, int h) { public void onWindowResize(int w, int h) { synchronized (this) { synchronized (sGLThreadManager) { mWidth = w; mWidth = w; mHeight = h; mHeight = h; mSizeChanged = true; mSizeChanged = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void requestExitAndWait() { public void requestExitAndWait() { // don't call this from GLThread thread or it is a guaranteed // don't call this from GLThread thread or it is a guaranteed // deadlock! // deadlock! synchronized(this) { synchronized(sGLThreadManager) { mDone = true; mDone = true; notifyAll(); sGLThreadManager.notifyAll(); } } try { try { join(); join(); Loading @@ -1232,6 +1241,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback public void queueEvent(Runnable r) { public void queueEvent(Runnable r) { synchronized(this) { synchronized(this) { mEventQueue.add(r); mEventQueue.add(r); synchronized(sGLThreadManager) { mEventsWaiting = true; sGLThreadManager.notifyAll(); } } } } } Loading @@ -1245,6 +1258,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback return null; return null; } } // Once the thread is started, all accesses to the following member // variables are protected by the sGLThreadManager monitor private boolean mDone; private boolean mDone; private boolean mPaused; private boolean mPaused; private boolean mHasSurface; private boolean mHasSurface; Loading @@ -1254,6 +1269,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private int mHeight; private int mHeight; private int mRenderMode; private int mRenderMode; private boolean mRequestRender; private boolean mRequestRender; private boolean mEventsWaiting; // End of member variables protected by the sGLThreadManager monitor. private Renderer mRenderer; private Renderer mRenderer; private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); private EglHelper mEglHelper; private EglHelper mEglHelper; Loading Loading @@ -1300,58 +1318,46 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } private static class GLThreadManager { private static class GLThreadManager { public boolean shouldHaveEgl(GLThread thread) { if (mMultipleGLESContextsAllowed) { return true; } else { synchronized(this) { return thread == mMostRecentGLThread || mMostRecentGLThread == null; } } } public void start(GLThread thread) throws InterruptedException { if (! mGLESVersionCheckComplete) { mGLESVersion = SystemProperties.getInt( "ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); if (mGLESVersion >= kGLES_20) { mMultipleGLESContextsAllowed = true; } mGLESVersionCheckComplete = true; } GLThread oldThread = null; public synchronized void threadExiting(GLThread thread) { synchronized(this) { if (LOG_THREADS) { oldThread = mMostRecentGLThread; Log.i("GLThread", "exiting tid=" + thread.getId()); mMostRecentGLThread = thread; } } if (oldThread != null && ! mMultipleGLESContextsAllowed) { thread.mDone = true; synchronized(oldThread) { if (mEglOwner == thread) { oldThread.notifyAll(); mEglOwner = null; } } notifyAll(); } } synchronized(this) { /* while ((! mMultipleGLESContextsAllowed) * Tries to acquire the right to use an EGL && mGLContextCount > 0) { * surface. Does not block. wait(); * @return true if the right to use an EGL surface was acquired. */ public synchronized boolean tryAcquireEglSurface(GLThread thread) { if (mEglOwner == thread || mEglOwner == null) { mEglOwner = thread; notifyAll(); return true; } } checkGLESVersion(); mGLContextCount++; if (mMultipleGLESContextsAllowed) { return true; } } return false; } } public synchronized void end(GLThread thread) { public synchronized void releaseEglSurface(GLThread thread) { mGLContextCount--; if (mEglOwner == thread) { notifyAll(); mEglOwner = null; if (mMostRecentGLThread == thread) { mMostRecentGLThread = null; } } notifyAll(); } } public synchronized void checkGLDriver(GL10 gl) { public synchronized void checkGLDriver(GL10 gl) { if (! mGLESDriverCheckComplete) { if (! mGLESDriverCheckComplete) { checkGLESVersion(); if (mGLESVersion < kGLES_20) { if (mGLESVersion < kGLES_20) { String renderer = gl.glGetString(GL10.GL_RENDERER); String renderer = gl.glGetString(GL10.GL_RENDERER); mMultipleGLESContextsAllowed = mMultipleGLESContextsAllowed = Loading @@ -1362,16 +1368,29 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } } } private void checkGLESVersion() { if (! mGLESVersionCheckComplete) { mGLESVersion = SystemProperties.getInt( "ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); if (mGLESVersion >= kGLES_20) { mMultipleGLESContextsAllowed = true; } mGLESVersionCheckComplete = true; } } private boolean mGLESVersionCheckComplete; private boolean mGLESVersionCheckComplete; private int mGLESVersion; private int mGLESVersion; private GLThread mMostRecentGLThread; private boolean mGLESDriverCheckComplete; private boolean mGLESDriverCheckComplete; private boolean mMultipleGLESContextsAllowed; private boolean mMultipleGLESContextsAllowed; private int mGLContextCount; private int mGLContextCount; private static final int kGLES_20 = 0x20000; private static final int kGLES_20 = 0x20000; private static final String kMSM7K_RENDERER_PREFIX = private static final String kMSM7K_RENDERER_PREFIX = "Q3Dimension MSM7500 "; "Q3Dimension MSM7500 "; }; private GLThread mEglOwner; } private static final GLThreadManager sGLThreadManager = new GLThreadManager(); private static final GLThreadManager sGLThreadManager = new GLThreadManager(); private boolean mSizeChanged = true; private boolean mSizeChanged = true; Loading Loading
opengl/java/android/opengl/GLSurfaceView.java +158 −139 Original line number Original line Diff line number Diff line Loading @@ -955,6 +955,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * to a Renderer instance to do the actual drawing. Can be configured to * to a Renderer instance to do the actual drawing. Can be configured to * render continuously or on request. * render continuously or on request. * * * All potentially blocking synchronization is done through the * sGLThreadManager object. This avoids multiple-lock ordering issues. * */ */ class GLThread extends Thread { class GLThread extends Thread { GLThread(Renderer renderer) { GLThread(Renderer renderer) { Loading @@ -974,51 +977,31 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback Log.i("GLThread", "starting tid=" + getId()); 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 * called before the first instance returns from onDestroy(). * * This semaphore ensures that only one instance at a time * accesses EGL. */ try { try { guardedRun(); guardedRun(); } catch (InterruptedException e) { } catch (InterruptedException e) { // fall thru and exit normally // fall thru and exit normally } finally { } finally { synchronized(this) { sGLThreadManager.threadExiting(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() { /* * This private method should only be called inside a * synchronized(sGLThreadManager) block. */ private void stopEglLocked() { if (mHaveEgl) { if (mHaveEgl) { mHaveEgl = false; mHaveEgl = false; mEglHelper.destroySurface(); mEglHelper.destroySurface(); mEglHelper.finish(); mEglHelper.finish(); sGLThreadManager.end(this); sGLThreadManager.releaseEglSurface(this); } } } } private void guardedRun() throws InterruptedException { private void guardedRun() throws InterruptedException { mEglHelper = new EglHelper(); mEglHelper = new EglHelper(); try { try { startEgl(); GL10 gl = null; GL10 gl = null; boolean tellRendererSurfaceCreated = true; boolean tellRendererSurfaceCreated = true; boolean tellRendererSurfaceChanged = true; boolean tellRendererSurfaceChanged = true; Loading @@ -1027,50 +1010,59 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * This is our main activity thread's loop, we go until * This is our main activity thread's loop, we go until * asked to quit. * asked to quit. */ */ while (!mDone) { while (!isDone()) { /* /* * Update the asynchronous state (window size) * Update the asynchronous state (window size) */ */ int w, h; int w = 0; boolean changed; int h = 0; boolean changed = false; boolean needStart = false; boolean needStart = false; synchronized (this) { boolean eventsWaiting = false; Runnable r; while ((r = getEvent()) != null) { synchronized (sGLThreadManager) { r.run(); while (true) { } // Manage acquiring and releasing the SurfaceView // surface and the EGL surface. if (mPaused) { if (mPaused) { stopEgl(); stopEglLocked(); needStart = true; } } while(true) { if (!mHasSurface) { if (!mHasSurface) { if (!mWaitingForSurface) { if (!mWaitingForSurface) { stopEgl(); stopEglLocked(); mWaitingForSurface = true; mWaitingForSurface = true; notifyAll(); sGLThreadManager.notifyAll(); } } } else { } else { boolean shouldHaveEgl = sGLThreadManager.shouldHaveEgl(this); if (!mHaveEgl) { if (mHaveEgl && (!shouldHaveEgl)) { if (sGLThreadManager.tryAcquireEglSurface(this)) { stopEgl(); mHaveEgl = true; } else if ((!mHaveEgl) && shouldHaveEgl) { mEglHelper.start(); startEgl(); mRequestRender = true; needStart = true; needStart = true; } } } } if (!needToWait()) { break; } if (LOG_THREADS) { Log.i("GLThread", "needToWait tid=" + getId()); } wait(); } } // Check if we need to wait. If not, update any state // that needs to be updated, copy any state that // needs to be copied, and use "break" to exit the // wait loop. if (mDone) { if (mDone) { return; } if (mEventsWaiting) { eventsWaiting = true; mEventsWaiting = false; break; break; } } if ( (! mPaused) && mHasSurface && mHaveEgl && (mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)) ) { changed = mSizeChanged; changed = mSizeChanged; w = mWidth; w = mWidth; h = mHeight; h = mHeight; Loading @@ -1079,11 +1071,36 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (mHasSurface && mWaitingForSurface) { if (mHasSurface && mWaitingForSurface) { changed = true; changed = true; mWaitingForSurface = false; mWaitingForSurface = false; notifyAll(); sGLThreadManager.notifyAll(); } break; } // By design, this is the only place where we wait(). if (LOG_THREADS) { Log.i("GLThread", "waiting tid=" + getId()); } } sGLThreadManager.wait(); } } } // end of synchronized(sGLThreadManager) /* * Handle queued events */ if (eventsWaiting) { Runnable r; while ((r = getEvent()) != null) { r.run(); if (isDone()) { return; } } // Go back and see if we need to wait to render. continue; } if (needStart) { if (needStart) { startEgl(); tellRendererSurfaceCreated = true; tellRendererSurfaceCreated = true; changed = true; changed = true; } } Loading Loading @@ -1115,71 +1132,63 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback /* /* * clean-up everything... * clean-up everything... */ */ stopEgl(); synchronized (sGLThreadManager) { stopEglLocked(); } } } } private boolean needToWait() { if (mDone) { return false; } if (mPaused || (! mHasSurface) || (! mHaveEgl)) { return true; } } if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { private boolean isDone() { return false; synchronized (sGLThreadManager) { return mDone; } } return true; } } public void setRenderMode(int renderMode) { public void setRenderMode(int renderMode) { if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { throw new IllegalArgumentException("renderMode"); throw new IllegalArgumentException("renderMode"); } } synchronized(this) { synchronized(sGLThreadManager) { mRenderMode = renderMode; mRenderMode = renderMode; if (renderMode == RENDERMODE_CONTINUOUSLY) { if (renderMode == RENDERMODE_CONTINUOUSLY) { notifyAll(); sGLThreadManager.notifyAll(); } } } } } } public int getRenderMode() { public int getRenderMode() { synchronized(this) { synchronized(sGLThreadManager) { return mRenderMode; return mRenderMode; } } } } public void requestRender() { public void requestRender() { synchronized(this) { synchronized(sGLThreadManager) { mRequestRender = true; mRequestRender = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void surfaceCreated() { public void surfaceCreated() { synchronized(this) { synchronized(sGLThreadManager) { if (LOG_THREADS) { if (LOG_THREADS) { Log.i("GLThread", "surfaceCreated tid=" + getId()); Log.i("GLThread", "surfaceCreated tid=" + getId()); } } mHasSurface = true; mHasSurface = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void surfaceDestroyed() { public void surfaceDestroyed() { synchronized(this) { synchronized(sGLThreadManager) { if (LOG_THREADS) { if (LOG_THREADS) { Log.i("GLThread", "surfaceDestroyed tid=" + getId()); Log.i("GLThread", "surfaceDestroyed tid=" + getId()); } } mHasSurface = false; mHasSurface = false; notifyAll(); sGLThreadManager.notifyAll(); while(!mWaitingForSurface && isAlive() && ! mDone) { while(!mWaitingForSurface && isAlive() && ! mDone) { try { try { wait(); sGLThreadManager.wait(); } catch (InterruptedException e) { } catch (InterruptedException e) { Thread.currentThread().interrupt(); Thread.currentThread().interrupt(); } } Loading @@ -1188,35 +1197,35 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } public void onPause() { public void onPause() { synchronized (this) { synchronized (sGLThreadManager) { mPaused = true; mPaused = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void onResume() { public void onResume() { synchronized (this) { synchronized (sGLThreadManager) { mPaused = false; mPaused = false; mRequestRender = true; mRequestRender = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void onWindowResize(int w, int h) { public void onWindowResize(int w, int h) { synchronized (this) { synchronized (sGLThreadManager) { mWidth = w; mWidth = w; mHeight = h; mHeight = h; mSizeChanged = true; mSizeChanged = true; notifyAll(); sGLThreadManager.notifyAll(); } } } } public void requestExitAndWait() { public void requestExitAndWait() { // don't call this from GLThread thread or it is a guaranteed // don't call this from GLThread thread or it is a guaranteed // deadlock! // deadlock! synchronized(this) { synchronized(sGLThreadManager) { mDone = true; mDone = true; notifyAll(); sGLThreadManager.notifyAll(); } } try { try { join(); join(); Loading @@ -1232,6 +1241,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback public void queueEvent(Runnable r) { public void queueEvent(Runnable r) { synchronized(this) { synchronized(this) { mEventQueue.add(r); mEventQueue.add(r); synchronized(sGLThreadManager) { mEventsWaiting = true; sGLThreadManager.notifyAll(); } } } } } Loading @@ -1245,6 +1258,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback return null; return null; } } // Once the thread is started, all accesses to the following member // variables are protected by the sGLThreadManager monitor private boolean mDone; private boolean mDone; private boolean mPaused; private boolean mPaused; private boolean mHasSurface; private boolean mHasSurface; Loading @@ -1254,6 +1269,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private int mHeight; private int mHeight; private int mRenderMode; private int mRenderMode; private boolean mRequestRender; private boolean mRequestRender; private boolean mEventsWaiting; // End of member variables protected by the sGLThreadManager monitor. private Renderer mRenderer; private Renderer mRenderer; private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); private EglHelper mEglHelper; private EglHelper mEglHelper; Loading Loading @@ -1300,58 +1318,46 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } private static class GLThreadManager { private static class GLThreadManager { public boolean shouldHaveEgl(GLThread thread) { if (mMultipleGLESContextsAllowed) { return true; } else { synchronized(this) { return thread == mMostRecentGLThread || mMostRecentGLThread == null; } } } public void start(GLThread thread) throws InterruptedException { if (! mGLESVersionCheckComplete) { mGLESVersion = SystemProperties.getInt( "ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); if (mGLESVersion >= kGLES_20) { mMultipleGLESContextsAllowed = true; } mGLESVersionCheckComplete = true; } GLThread oldThread = null; public synchronized void threadExiting(GLThread thread) { synchronized(this) { if (LOG_THREADS) { oldThread = mMostRecentGLThread; Log.i("GLThread", "exiting tid=" + thread.getId()); mMostRecentGLThread = thread; } } if (oldThread != null && ! mMultipleGLESContextsAllowed) { thread.mDone = true; synchronized(oldThread) { if (mEglOwner == thread) { oldThread.notifyAll(); mEglOwner = null; } } notifyAll(); } } synchronized(this) { /* while ((! mMultipleGLESContextsAllowed) * Tries to acquire the right to use an EGL && mGLContextCount > 0) { * surface. Does not block. wait(); * @return true if the right to use an EGL surface was acquired. */ public synchronized boolean tryAcquireEglSurface(GLThread thread) { if (mEglOwner == thread || mEglOwner == null) { mEglOwner = thread; notifyAll(); return true; } } checkGLESVersion(); mGLContextCount++; if (mMultipleGLESContextsAllowed) { return true; } } return false; } } public synchronized void end(GLThread thread) { public synchronized void releaseEglSurface(GLThread thread) { mGLContextCount--; if (mEglOwner == thread) { notifyAll(); mEglOwner = null; if (mMostRecentGLThread == thread) { mMostRecentGLThread = null; } } notifyAll(); } } public synchronized void checkGLDriver(GL10 gl) { public synchronized void checkGLDriver(GL10 gl) { if (! mGLESDriverCheckComplete) { if (! mGLESDriverCheckComplete) { checkGLESVersion(); if (mGLESVersion < kGLES_20) { if (mGLESVersion < kGLES_20) { String renderer = gl.glGetString(GL10.GL_RENDERER); String renderer = gl.glGetString(GL10.GL_RENDERER); mMultipleGLESContextsAllowed = mMultipleGLESContextsAllowed = Loading @@ -1362,16 +1368,29 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } } } private void checkGLESVersion() { if (! mGLESVersionCheckComplete) { mGLESVersion = SystemProperties.getInt( "ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); if (mGLESVersion >= kGLES_20) { mMultipleGLESContextsAllowed = true; } mGLESVersionCheckComplete = true; } } private boolean mGLESVersionCheckComplete; private boolean mGLESVersionCheckComplete; private int mGLESVersion; private int mGLESVersion; private GLThread mMostRecentGLThread; private boolean mGLESDriverCheckComplete; private boolean mGLESDriverCheckComplete; private boolean mMultipleGLESContextsAllowed; private boolean mMultipleGLESContextsAllowed; private int mGLContextCount; private int mGLContextCount; private static final int kGLES_20 = 0x20000; private static final int kGLES_20 = 0x20000; private static final String kMSM7K_RENDERER_PREFIX = private static final String kMSM7K_RENDERER_PREFIX = "Q3Dimension MSM7500 "; "Q3Dimension MSM7500 "; }; private GLThread mEglOwner; } private static final GLThreadManager sGLThreadManager = new GLThreadManager(); private static final GLThreadManager sGLThreadManager = new GLThreadManager(); private boolean mSizeChanged = true; private boolean mSizeChanged = true; Loading