diff options
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 15 | ||||
| -rw-r--r-- | core/java/android/view/GLES20RecordingCanvas.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 68 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 27 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 9 | ||||
| -rw-r--r-- | libs/hwui/Caches.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/Caches.h | 3 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.h | 2 |
8 files changed, 84 insertions, 46 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index d561484ee66d..ac0abc35125d 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -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 diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java index 078222be6fe9..c987f487d30b 100644 --- a/core/java/android/view/GLES20RecordingCanvas.java +++ b/core/java/android/view/GLES20RecordingCanvas.java @@ -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>() { diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index d2476af3b50b..5404e3a6acd3 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -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; - } } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 22131881239b..5b8a2019a0a9 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -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 diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 35a40fcfb234..57bf17f36b92 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -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) { diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 7114b6adc30e..c5858e93f23b 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -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; } } diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 76dff4b4078b..cdcbf2188532 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -101,7 +101,8 @@ class Caches: public Singleton<Caches> { public: enum FlushMode { - kFlushMode_Moderate = 0, + kFlushMode_Layers = 0, + kFlushMode_Moderate, kFlushMode_Full }; diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 81576313c15f..a3d346dd9bea 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -37,7 +37,7 @@ namespace uirenderer { // Defines /////////////////////////////////////////////////////////////////////////////// -#define MIN_WRITER_SIZE 16384 +#define MIN_WRITER_SIZE 4096 // Debug #if DEBUG_DISPLAY_LIST |