From bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 23 Oct 2012 19:17:15 -0700 Subject: [PATCH] Ensure we have a GL context before deleting View layers Bug #7391098 The existing code was doing a make current to guarantee we have a current context. This can however fail when the surface is destroyed which could lead to GL calls without an EGL context, and therefore potential leaks. This change fixes the issue by using a technique found in HardwareRenderer.destroyHardwareResources(). If the surface is not available then we use a special 1x1 pbuffer as a way to get a valid context. Change-Id: I716d3799bf90120d793d76e90a83956837ecd491 --- core/java/android/view/HardwareRenderer.java | 53 +++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 59f941daf61e4..1c61324595018 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -1525,30 +1525,6 @@ public abstract class HardwareRenderer { ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture); } - @Override - void destroyLayers(View view) { - if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) { - if (mCanvas != null) { - mCanvas.clearLayerUpdates(); - } - destroyHardwareLayer(view); - GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); - } - } - - private static void destroyHardwareLayer(View view) { - view.destroyLayer(true); - - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - - int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - destroyHardwareLayer(group.getChildAt(i)); - } - } - } - @Override boolean safelyRun(Runnable action) { boolean needsContext = true; @@ -1573,6 +1549,35 @@ public abstract class HardwareRenderer { return true; } + @Override + void destroyLayers(final View view) { + if (view != null) { + safelyRun(new Runnable() { + @Override + public void run() { + if (mCanvas != null) { + mCanvas.clearLayerUpdates(); + } + destroyHardwareLayer(view); + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); + } + }); + } + } + + private static void destroyHardwareLayer(View view) { + view.destroyLayer(true); + + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + + int count = group.getChildCount(); + for (int i = 0; i < count; i++) { + destroyHardwareLayer(group.getChildAt(i)); + } + } + } + @Override void destroyHardwareResources(final View view) { if (view != null) {