OSDN Git Service

Destroy layers and flush layers cache when a window is destroyed.
authorRomain Guy <romainguy@google.com>
Wed, 27 Jul 2011 23:28:21 +0000 (16:28 -0700)
committerRomain Guy <romainguy@google.com>
Wed, 27 Jul 2011 23:29:39 +0000 (16:29 -0700)
Change-Id: I3fa1bc3ff50fb99e3d2e490925bd6b0a0f809fff

core/java/android/view/GLES20Canvas.java
core/java/android/view/GLES20RecordingCanvas.java
core/java/android/view/HardwareRenderer.java
core/java/android/view/View.java
core/java/android/view/ViewRootImpl.java
libs/hwui/Caches.cpp
libs/hwui/Caches.h
libs/hwui/DisplayListRenderer.h

index d561484..ac0abc3 100644 (file)
@@ -277,14 +277,25 @@ class GLES20Canvas extends HardwareCanvas {
     ///////////////////////////////////////////////////////////////////////////
 
     /**
+     * Must match Caches::FlushMode values
+     * 
      * @see #flushCaches(int) 
      */
-    public static final int FLUSH_CACHES_MODERATE = 0;
+    public static final int FLUSH_CACHES_LAYERS = 0;
+    
+    /**
+     * Must match Caches::FlushMode values
+     * 
+     * @see #flushCaches(int) 
+     */
+    public static final int FLUSH_CACHES_MODERATE = 1;
 
     /**
+     * Must match Caches::FlushMode values
+     * 
      * @see #flushCaches(int) 
      */
-    public static final int FLUSH_CACHES_FULL = 1;
+    public static final int FLUSH_CACHES_FULL = 2;
 
     /**
      * Flush caches to reclaim as much memory as possible. The amount of memory
index 078222b..c987f48 100644 (file)
@@ -38,7 +38,7 @@ import android.util.Pools;
 class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {
     // The recording canvas pool should be large enough to handle a deeply nested
     // view hierarchy because display lists are generated recursively.
-    private static final int POOL_LIMIT = 50;
+    private static final int POOL_LIMIT = 25;
 
     private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(
             Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {
index d2476af..5404e3a 100644 (file)
@@ -140,6 +140,13 @@ public abstract class HardwareRenderer {
     abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
 
     /**
+     * Destoys the layers used by the specified view hierarchy.
+     * 
+     * @param view The root of the view hierarchy
+     */
+    abstract void destroyLayers(View view);
+
+    /**
      * This method should be invoked whenever the current hardware renderer
      * context should be reset. 
      */
@@ -622,18 +629,8 @@ public abstract class HardwareRenderer {
                         + "from multiple threads");
             }
 
-            /*
-             *  The window size has changed, so we need to create a new
-             *  surface.
-             */
-            if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
-                /*
-                 * Unbind and destroy the old EGL surface, if
-                 * there is one.
-                 */
-                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-                sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
-            }
+            // In case we need to destroy an existing surface
+            destroySurface();
 
             // Create an EGL surface we can render into.
             mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null);
@@ -693,15 +690,21 @@ public abstract class HardwareRenderer {
 
             mDestroyed = true;
 
-            sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
+            destroySurface();
 
-            mEglSurface = null;
             mGl = null;
 
             setEnabled(false);
         }
 
+        void destroySurface() {
+            if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
+                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+                sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
+                mEglSurface = null;
+            }
+        }
+
         @Override
         void invalidate() {
             // Cancels any existing buffer to ensure we'll get a buffer
@@ -921,6 +924,34 @@ public abstract class HardwareRenderer {
             return ((GLES20TextureLayer) layer).getSurfaceTexture();
         }
 
+        @Override
+        void destroyLayers(View view) {
+            if (view != null && isEnabled()) {
+                checkCurrent();
+                destroyHardwareLayer(view);
+                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+            }
+        }
+
+        private void destroyHardwareLayer(View view) {
+            view.destroyLayer();
+            if (view instanceof ViewGroup) {
+                ViewGroup group = (ViewGroup) view;
+
+                int count = group.getChildCount();
+                for (int i = 0; i < count; i++) {
+                    destroyHardwareLayer(group.getChildAt(i));
+                }
+            }
+        }
+
+        static HardwareRenderer create(boolean translucent) {
+            if (GLES20Canvas.isAvailable()) {
+                return new Gl20Renderer(translucent);
+            }
+            return null;
+        }
+
         static void trimMemory(int level) {
             if (sEgl == null || sEglConfig == null) return;
 
@@ -950,12 +981,5 @@ public abstract class HardwareRenderer {
                     break;
             }
         }
-
-        static HardwareRenderer create(boolean translucent) {
-            if (GLES20Canvas.isAvailable()) {
-                return new Gl20Renderer(translucent);
-            }
-            return null;
-        }
     }
 }
index 2213188..5b8a201 100644 (file)
@@ -9226,10 +9226,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
 
         destroyDrawingCache();
 
-        if (mHardwareLayer != null) {
-            mHardwareLayer.destroy();
-            mHardwareLayer = null;
-        }
+        destroyLayer();
 
         if (mDisplayList != null) {
             mDisplayList.invalidate();
@@ -9601,21 +9598,10 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
         // Destroy any previous software drawing cache if needed
         switch (mLayerType) {
             case LAYER_TYPE_HARDWARE:
-                if (mHardwareLayer != null) {
-                    mHardwareLayer.destroy();
-                    mHardwareLayer = null;
-                }
+                destroyLayer();
                 // fall through - unaccelerated views may use software layer mechanism instead
             case LAYER_TYPE_SOFTWARE:
-                if (mDrawingCache != null) {
-                    mDrawingCache.recycle();
-                    mDrawingCache = null;
-                }
-
-                if (mUnscaledDrawingCache != null) {
-                    mUnscaledDrawingCache.recycle();
-                    mUnscaledDrawingCache = null;
-                }
+                destroyDrawingCache();
                 break;
             default:
                 break;
@@ -9741,6 +9727,13 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
         return mHardwareLayer;
     }
 
+    void destroyLayer() {
+        if (mHardwareLayer != null) {
+            mHardwareLayer.destroy();
+            mHardwareLayer = null;
+        }
+    }
+
     /**
      * <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
index 35a40fc..57bf17f 100644 (file)
@@ -541,6 +541,13 @@ public final class ViewRootImpl extends Handler implements ViewParent,
         }
     }
 
+    private void destroyHardwareResources() {
+        if (mAttachInfo.mHardwareRenderer.isEnabled()) {
+            mAttachInfo.mHardwareRenderer.destroyLayers(mView);
+        }
+        mAttachInfo.mHardwareRenderer.destroy(false);
+    }
+
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
@@ -870,7 +877,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
             host.dispatchWindowVisibilityChanged(viewVisibility);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                 if (mAttachInfo.mHardwareRenderer != null) {
-                    mAttachInfo.mHardwareRenderer.destroy(false);
+                    destroyHardwareResources();
                 }                
             }
             if (viewVisibility == View.GONE) {
index 7114b6a..c5858e9 100644 (file)
@@ -173,13 +173,15 @@ void Caches::flush(FlushMode mode) {
             gradientCache.clear();
             // fall through
         case kFlushMode_Moderate:
-            layerCache.clear();
             pathCache.clear();
             roundRectShapeCache.clear();
             circleShapeCache.clear();
             ovalShapeCache.clear();
             rectShapeCache.clear();
             arcShapeCache.clear();
+            // fall through
+        case kFlushMode_Layers:
+            layerCache.clear();
             break;
     }
 }
index 76dff4b..cdcbf21 100644 (file)
@@ -101,7 +101,8 @@ class Caches: public Singleton<Caches> {
 
 public:
     enum FlushMode {
-        kFlushMode_Moderate = 0,
+        kFlushMode_Layers = 0,
+        kFlushMode_Moderate,
         kFlushMode_Full
     };
 
index 8157631..a3d346d 100644 (file)
@@ -37,7 +37,7 @@ namespace uirenderer {
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
 
-#define MIN_WRITER_SIZE 16384
+#define MIN_WRITER_SIZE 4096
 
 // Debug
 #if DEBUG_DISPLAY_LIST