diff options
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 53 | ||||
| -rw-r--r-- | core/java/android/view/TextureView.java | 13 |
2 files changed, 51 insertions, 15 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index aa0ac74cf513..8bc36b7e03aa 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -237,6 +237,17 @@ public abstract class HardwareRenderer { abstract boolean validate(); /** + * This method ensures the hardware renderer is in a valid state + * before executing the specified action. + * + * This method will attempt to set a valid state even if the window + * the renderer is attached to was destroyed. + * + * @return true if the action was run + */ + abstract boolean safelyRun(Runnable action); + + /** * Setup the hardware renderer for drawing. This is called whenever the * size of the target surface changes or when the surface is first created. * @@ -1380,26 +1391,40 @@ public abstract class HardwareRenderer { } @Override - void destroyHardwareResources(View view) { - if (view != null) { - boolean needsContext = true; - if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false; - - if (needsContext) { - Gl20RendererEglContext managedContext = - (Gl20RendererEglContext) sEglContextStorage.get(); - if (managedContext == null) return; - usePbufferSurface(managedContext.getContext()); - } - - destroyResources(view); - GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); + boolean safelyRun(Runnable action) { + boolean needsContext = true; + if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false; + + if (needsContext) { + Gl20RendererEglContext managedContext = + (Gl20RendererEglContext) sEglContextStorage.get(); + if (managedContext == null) return false; + usePbufferSurface(managedContext.getContext()); + } + try { + action.run(); + } finally { if (needsContext) { sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } } + + return true; + } + + @Override + void destroyHardwareResources(final View view) { + if (view != null) { + safelyRun(new Runnable() { + @Override + public void run() { + destroyResources(view); + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); + } + }); + } } private static void destroyResources(View view) { diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 3cd8b715b669..ba62e65e36f0 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -204,7 +204,18 @@ public class TextureView extends View { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - destroySurface(); + if (mLayer != null && mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) { + boolean success = mAttachInfo.mHardwareRenderer.safelyRun(new Runnable() { + @Override + public void run() { + destroySurface(); + } + }); + + if (!success) { + Log.w(LOG_TAG, "TextureView was not able to destroy its surface: " + this); + } + } } private void destroySurface() { |