diff options
| author | 2013-06-25 02:23:08 +0000 | |
|---|---|---|
| committer | 2013-06-25 02:23:08 +0000 | |
| commit | e981c516e7ffec1f77a41705a61961b57eb10cab (patch) | |
| tree | 64fb6c7cfb9d2598c6f9499628d8fabf5e611b32 | |
| parent | d982851d29e2164122f829da2914978b6ae569b5 (diff) | |
| parent | cc6b7caff0b428c1a5fc5bf6d7a94f50ac8cb649 (diff) | |
Merge "Make sure we have a valid EGL context before drawing Bug #9404946"
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index bcefdbaf5d90..281bd7e9a2b7 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -1360,7 +1360,7 @@ public abstract class HardwareRenderer { @Override boolean validate() { - return checkCurrent() != SURFACE_STATE_ERROR; + return checkRenderContext() != SURFACE_STATE_ERROR; } @Override @@ -1413,8 +1413,7 @@ public abstract class HardwareRenderer { return; } - final int surfaceState = checkCurrent(); - if (surfaceState != SURFACE_STATE_ERROR) { + if (checkRenderContext() != SURFACE_STATE_ERROR) { int status = mCanvas.invokeFunctors(mRedrawClip); handleFunctorStatus(attachInfo, status); } @@ -1433,7 +1432,8 @@ public abstract class HardwareRenderer { view.mPrivateFlags |= View.PFLAG_DRAWN; - final int surfaceState = checkCurrent(); + // We are already on the correct thread + final int surfaceState = checkRenderContextUnsafe(); if (surfaceState != SURFACE_STATE_ERROR) { HardwareCanvas canvas = mCanvas; attachInfo.mHardwareCanvas = canvas; @@ -1446,6 +1446,13 @@ public abstract class HardwareRenderer { DisplayList displayList = buildDisplayList(view, canvas); + // buildDisplayList() calls into user code which can cause + // an eglMakeCurrent to happen with a different surface/context. + // We must therefore check again here. + if (checkRenderContextUnsafe() == SURFACE_STATE_ERROR) { + return; + } + int saveCount = 0; int status = DisplayList.STATUS_DONE; @@ -1500,9 +1507,6 @@ public abstract class HardwareRenderer { HardwareCanvas canvas, DisplayList displayList) { if (mDebugOverdraw == OVERDRAW_TYPE_COUNT) { - // TODO: Use an alpha layer allocated from a GraphicBuffer - // The alpha format will help with rendering performance and - // the GraphicBuffer will let us skip the read pixels step if (mDebugOverdrawLayer == null) { mDebugOverdrawLayer = createHardwareLayer(mWidth, mHeight, true); } else if (mDebugOverdrawLayer.getWidth() != mWidth || @@ -1725,21 +1729,39 @@ public abstract class HardwareRenderer { } /** - * Ensures the current EGL context is the one we expect. + * Ensures the current EGL context and surface are the ones we expect. + * This method throws an IllegalStateException if invoked from a thread + * that did not initialize EGL. * * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current, * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one + * + * @see #checkRenderContextUnsafe() */ - int checkCurrent() { + int checkRenderContext() { if (mEglThread != Thread.currentThread()) { throw new IllegalStateException("Hardware acceleration can only be used with a " + "single UI thread.\nOriginal thread: " + mEglThread + "\n" + "Current thread: " + Thread.currentThread()); } - if (!mEglContext.equals(sEgl.eglGetCurrentContext()) || - !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) { + return checkRenderContextUnsafe(); + } + + /** + * Ensures the current EGL context and surface are the ones we expect. + * This method does not check the current thread. + * + * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current, + * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or + * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one + * + * @see #checkRenderContext() + */ + private int checkRenderContextUnsafe() { + if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) || + !mEglContext.equals(sEgl.eglGetCurrentContext())) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { Log.e(LOG_TAG, "eglMakeCurrent failed " + GLUtils.getEGLErrorString(sEgl.eglGetError())); @@ -2193,8 +2215,7 @@ public abstract class HardwareRenderer { @Override boolean safelyRun(Runnable action) { - boolean needsContext = true; - if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false; + boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR; if (needsContext) { Gl20RendererEglContext managedContext = |