public void onWindowResize(int w, int h) { synchronized (GL_THREAD_MANAGER) { mWidth = w; mHeight = h; mSizeChanged = true; mRequestRender = true; mSurfaceTextureReady = true; mRenderComplete = false; GL_THREAD_MANAGER.notifyAll(); // Wait for thread to react to resize and render a frame while (!mExited && !mPaused && !mRenderComplete && (mGLThread != null && mGLThread.ableToDraw())) { if (LOG_SURFACE) { Log.i( "Main thread", "onWindowResize waiting for render complete from tid=" + mGLThread.getId()); } try { GL_THREAD_MANAGER.wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } }
public void requestExitAndWait() { // don't call this from GLThread thread or it is a guaranteed // deadlock! synchronized (GL_THREAD_MANAGER) { mShouldExit = true; GL_THREAD_MANAGER.notifyAll(); while (!mExited) { try { GL_THREAD_MANAGER.wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } mSurface = null; }
public void surfaceDestroyed() { synchronized (GL_THREAD_MANAGER) { if (LOG_THREADS) { Log.i("GLThread", "surfaceDestroyed tid=" + getId()); } mHasSurface = false; mSurfaceTextureReady = false; GL_THREAD_MANAGER.notifyAll(); while ((!mWaitingForSurface) && (!mExited)) { Log.i("Main thread", "surfaceDestroyed waiting for !mWaitingForSurface."); try { GL_THREAD_MANAGER.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }
public void onPause() { synchronized (GL_THREAD_MANAGER) { if (LOG_PAUSE_RESUME) { Log.i("GLThread", "onPause tid=" + getId()); } mSurfaceTextureReady = true; mRequestPaused = true; GL_THREAD_MANAGER.notifyAll(); while ((!mExited) && (!mPaused)) { if (LOG_PAUSE_RESUME) { Log.i("Main thread", "onPause waiting for mPaused."); } try { GL_THREAD_MANAGER.wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } }
public void surfaceCreated(SurfaceTexture surfaceTexture, int width, int height) { synchronized (GL_THREAD_MANAGER) { if (LOG_THREADS) { Log.i("GLThread", "surfaceCreated tid=" + getId()); } mWidth = width; mHeight = height; mSurface = surfaceTexture; mSurfaceTextureReady = true; mHasSurface = true; GL_THREAD_MANAGER.notifyAll(); while ((mWaitingForSurface) && (!mExited)) { try { GL_THREAD_MANAGER.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }
public void onResume() { synchronized (GL_THREAD_MANAGER) { if (LOG_PAUSE_RESUME) { Log.i("GLThread", "onResume tid=" + getId()); } mRequestPaused = false; mRequestRender = true; mRenderComplete = false; GL_THREAD_MANAGER.notifyAll(); // No need to wait really resume if there is no surface, while ((!mExited) && mPaused && (!mRenderComplete) && (mHasSurface)) { if (LOG_PAUSE_RESUME) { Log.i("Main thread", "onResume waiting for !mPaused."); } try { GL_THREAD_MANAGER.wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } }
private void guardedRun() throws InterruptedException { mEglHelper = new EglHelper(); mHaveEglContext = false; mHaveEglSurface = false; try { GL10 gl = null; boolean createEglContext = false; boolean lostEglContext = false; boolean sizeChanged = false; boolean wantRenderNotification = false; boolean doRenderNotification = false; boolean askedToReleaseEglContext = false; Runnable event = null; while (true) { synchronized (GL_THREAD_MANAGER) { while (true) { if (mShouldExit) { return; } if (!mEventQueue.isEmpty()) { event = mEventQueue.remove(0); break; } // Update the pause state. if (mPaused != mRequestPaused) { mPaused = mRequestPaused; GL_THREAD_MANAGER.notifyAll(); if (LOG_PAUSE_RESUME) { Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId()); } } // 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(); stopEglContextLocked(); lostEglContext = false; } // Do we need to release the EGL surface? if (mHaveEglSurface && mPaused) { if (LOG_SURFACE) { Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); } stopEglSurfaceLocked(); if (GL_THREAD_MANAGER.shouldReleaseEGLContextWhenPausing()) { stopEglContextLocked(); if (LOG_SURFACE) { Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); } } if (GL_THREAD_MANAGER.shouldTerminateEGLWhenPausing()) { mEglHelper.finish(); if (LOG_SURFACE) { Log.i("GLThread", "terminating EGL because paused tid=" + getId()); } } // Notify render that GLThread is going to pause mRenderer.onPaused(); } // Have we lost the surface view surface? if ((!mHasSurface) && (!mWaitingForSurface)) { if (LOG_SURFACE) { Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); } if (mHaveEglSurface) { stopEglSurfaceLocked(); } mWaitingForSurface = true; // Notify the wait in surfaceDestroyed() to avoid ANR // with low memory case, Activity Manager destroys hardware resource of // SurfaceTexture directly. GL_THREAD_MANAGER.notifyAll(); } // Have we acquired the surface view surface? if (mHasSurface && mWaitingForSurface) { if (LOG_SURFACE) { Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); } mWaitingForSurface = false; GL_THREAD_MANAGER.notifyAll(); } if (doRenderNotification) { if (LOG_SURFACE) { Log.i("GLThread", "sending render notification tid=" + getId()); } wantRenderNotification = false; doRenderNotification = false; mRenderComplete = true; GL_THREAD_MANAGER.notifyAll(); } // Ready to draw? if (readyToDraw()) { // If we don't have an EGL context, try to acquire one. if (!mHaveEglContext) { if (askedToReleaseEglContext) { askedToReleaseEglContext = false; } else if (GL_THREAD_MANAGER.tryAcquireEglContextLocked(this)) { try { mEglHelper.start(mSurface); } catch (RuntimeException t) { GL_THREAD_MANAGER.releaseEglContextLocked(this); throw t; } mHaveEglContext = true; createEglContext = true; GL_THREAD_MANAGER.notifyAll(); } } if (mHaveEglContext && !mHaveEglSurface) { mHaveEglSurface = true; sizeChanged = true; } if (mHaveEglSurface) { if (mSizeChanged) { sizeChanged = true; 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. // (Once because of mSizeChanged, the second time because of mRequestRender.) // This forces the updated graphics onto the screen. } else { mRequestRender = false; mSurfaceTextureReady = false; } mSizeChanged = false; } else { mRequestRender = false; mSurfaceTextureReady = false; } GL_THREAD_MANAGER.notifyAll(); break; } } // By design, this is the only place in a GLThread thread where we wait(). if (LOG_THREADS) { Log.i( "GLThread", "waiting tid=" + getId() + " mHaveEglContext: " + mHaveEglContext + " mHaveEglSurface: " + mHaveEglSurface + " mPaused: " + mPaused + " mHasSurface: " + mHasSurface + " mSurfaceTextureReady: " + mSurfaceTextureReady + " mWaitingForSurface: " + mWaitingForSurface + " mWidth: " + mWidth + " mHeight: " + mHeight + " mRequestRender: " + mRequestRender + " mRenderMode: " + mRenderMode); } GL_THREAD_MANAGER.wait(); } } // end of synchronized(GL_THREAD_MANAGER) if (event != null) { event.run(); event = null; continue; } if (!mHasSurface) { continue; } if (createEglContext) { if (LOG_RENDERER) { Log.w("GLThread", "onSurfaceCreated"); } gl = (GL10) mEglHelper.mEglContext.getGL(); mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); createEglContext = false; } if (sizeChanged) { if (LOG_RENDERER) { Log.w("GLThread", "onSurfaceChanged(" + mWidth + ", " + mHeight + ")"); } mEglHelper.purgeBuffers(); mRenderer.onSurfaceChanged(gl, mWidth, mHeight); sizeChanged = false; } if (LOG_RENDERER_DRAW_FRAME) { Log.w("GLThread", "onDrawFrame tid=" + getId()); } mRenderer.onDrawFrame(gl); if (!mEglHelper.swap()) { if (LOG_SURFACE) { Log.i("GLThread", "egl context lost tid=" + getId()); } lostEglContext = true; } if (wantRenderNotification) { doRenderNotification = true; } } } finally { /* * clean-up everything... */ synchronized (GL_THREAD_MANAGER) { stopEglSurfaceLocked(); stopEglContextLocked(); } } }