diff options
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 73 | ||||
-rw-r--r-- | core/java/android/view/TextureView.java | 11 | ||||
-rw-r--r-- | core/java/android/view/View.java | 21 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 7 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 2 | ||||
-rw-r--r-- | opengl/java/android/opengl/ManagedEGLContext.java | 5 |
6 files changed, 92 insertions, 27 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 8e39d6e..f77cf7e 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -162,13 +162,21 @@ public abstract class HardwareRenderer { abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException; /** - * Destoys the layers used by the specified view hierarchy. + * Destroys the layers used by the specified view hierarchy. * * @param view The root of the view hierarchy */ abstract void destroyLayers(View view); /** + * Destroys all hardware rendering resources associated with the specified + * view hierarchy. + * + * @param view The root of the view hierarchy + */ + abstract void destroyHardwareResources(View view); + + /** * This method should be invoked whenever the current hardware renderer * context should be reset. * @@ -348,15 +356,6 @@ public abstract class HardwareRenderer { } /** - * Invoke this method when the system needs to clean up all resources - * associated with hardware rendering. - */ - static void terminate() { - Log.d(LOG_TAG, "Terminating hardware rendering"); - Gl20Renderer.terminate(); - } - - /** * Indicates whether hardware acceleration is currently enabled. * * @return True if hardware acceleration is in use, false otherwise. @@ -412,8 +411,8 @@ public abstract class HardwareRenderer { static final Object[] sEglLock = new Object[0]; int mWidth = -1, mHeight = -1; - static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage - = new ThreadLocal<Gl20Renderer.MyEGLContext>(); + static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage + = new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>(); EGLContext mEglContext; Thread mEglThread; @@ -565,13 +564,13 @@ public abstract class HardwareRenderer { } } - Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get(); + Gl20Renderer.Gl20RendererEglContext managedContext = sEglContextStorage.get(); mEglContext = managedContext != null ? managedContext.getContext() : null; mEglThread = Thread.currentThread(); if (mEglContext == null) { mEglContext = createContext(sEgl, sEglDisplay, sEglConfig); - sEglContextStorage.set(new Gl20Renderer.MyEGLContext(mEglContext)); + sEglContextStorage.set(new Gl20Renderer.Gl20RendererEglContext(mEglContext)); } } @@ -909,10 +908,10 @@ public abstract class HardwareRenderer { private static EGLSurface sPbuffer; private static final Object[] sPbufferLock = new Object[0]; - static class MyEGLContext extends ManagedEGLContext { + static class Gl20RendererEglContext extends ManagedEGLContext { final Handler mHandler = new Handler(); - public MyEGLContext(EGLContext context) { + public Gl20RendererEglContext(EGLContext context) { super(context); } @@ -939,7 +938,8 @@ public abstract class HardwareRenderer { sEglContextStorage.remove(); sEgl.eglDestroySurface(sEglDisplay, sPbuffer); - sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); sEgl.eglReleaseThread(); sEgl.eglTerminate(sEglDisplay); @@ -1046,10 +1046,9 @@ public abstract class HardwareRenderer { } } - private void destroyHardwareLayer(View view) { - if (view.destroyLayer()) { - view.invalidate(true); - } + private static void destroyHardwareLayer(View view) { + view.destroyLayer(); + if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; @@ -1059,6 +1058,36 @@ 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 = sEglContextStorage.get(); + if (managedContext == null) return; + usePbufferSurface(managedContext.getContext()); + } + + destroyResources(view); + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); + } + } + + private static void destroyResources(View view) { + view.destroyHardwareResources(); + + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + + int count = group.getChildCount(); + for (int i = 0; i < count; i++) { + destroyResources(group.getChildAt(i)); + } + } + } static HardwareRenderer create(boolean translucent) { if (GLES20Canvas.isAvailable()) { @@ -1070,7 +1099,7 @@ public abstract class HardwareRenderer { static void trimMemory(int level) { if (sEgl == null || sEglConfig == null) return; - Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get(); + Gl20RendererEglContext managedContext = sEglContextStorage.get(); // We do not have OpenGL objects if (managedContext == null) { return; diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 1697382..3fd2d83 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -203,7 +203,10 @@ public class TextureView extends View { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + destroySurface(); + } + private void destroySurface() { if (mLayer != null) { boolean shouldRelease = true; if (mListener != null) { @@ -301,6 +304,14 @@ public class TextureView extends View { } @Override + protected void destroyHardwareResources() { + super.destroyHardwareResources(); + destroySurface(); + invalidateParentCaches(); + invalidate(true); + } + + @Override HardwareLayer getHardwareLayer() { if (mLayer == null) { if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e2f3919..5002be7 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10073,7 +10073,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal switch (mLayerType) { case LAYER_TYPE_HARDWARE: destroyLayer(); - // fall through - unaccelerated views may use software layer mechanism instead + // fall through - non-accelerated views may use software layer mechanism instead case LAYER_TYPE_SOFTWARE: destroyDrawingCache(); break; @@ -10235,12 +10235,31 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mHardwareLayer != null) { mHardwareLayer.destroy(); mHardwareLayer = null; + + invalidate(true); + invalidateParentCaches(); + return true; } return false; } /** + * Destroys all hardware rendering resources. This method is invoked + * when the system needs to reclaim resources. Upon execution of this + * method, you should free any OpenGL resources created by the view. + * + * Note: you <strong>must</strong> call + * <code>super.destroyHardwareResources()</code> when overriding + * this method. + * + * @hide + */ + protected void destroyHardwareResources() { + destroyLayer(); + } + + /** * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b15b155..5f70a39 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -576,6 +576,13 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } + void terminateHardwareResources() { + if (mAttachInfo.mHardwareRenderer != null) { + mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView); + mAttachInfo.mHardwareRenderer.destroy(false); + } + } + void destroyHardwareLayers() { if (mThread != Thread.currentThread()) { if (mAttachInfo.mHardwareRenderer != null && diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 660e3f4..dfd1d55 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -425,7 +425,7 @@ public class WindowManagerImpl implements WindowManager { if (mViews == null) return; int count = mViews.length; for (int i = 0; i < count; i++) { - mRoots[i].destroyHardwareResources(); + mRoots[i].terminateHardwareResources(); } } // Terminate the hardware renderer to free all resources diff --git a/opengl/java/android/opengl/ManagedEGLContext.java b/opengl/java/android/opengl/ManagedEGLContext.java index d3a3662..1eafbca 100644 --- a/opengl/java/android/opengl/ManagedEGLContext.java +++ b/opengl/java/android/opengl/ManagedEGLContext.java @@ -47,8 +47,7 @@ import com.google.android.gles_jni.EGLImpl; public abstract class ManagedEGLContext { static final String TAG = "ManagedEGLContext"; - static final ArrayList<ManagedEGLContext> sActive - = new ArrayList<ManagedEGLContext>(); + static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>(); final EGLContext mContext; @@ -127,7 +126,7 @@ public abstract class ManagedEGLContext { sActive.clear(); } - for (int i=0; i<active.size(); i++) { + for (int i = 0; i < active.size(); i++) { active.get(i).execTerminate(); } |