Merge "Destroy layers and flush layers cache when a window is destroyed."
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>() {
|
||||
|
||||
@@ -139,6 +139,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9230,10 +9230,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
|
||||
|
||||
destroyDrawingCache();
|
||||
|
||||
if (mHardwareLayer != null) {
|
||||
mHardwareLayer.destroy();
|
||||
mHardwareLayer = null;
|
||||
}
|
||||
destroyLayer();
|
||||
|
||||
if (mDisplayList != null) {
|
||||
mDisplayList.invalidate();
|
||||
@@ -9605,21 +9602,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;
|
||||
@@ -9745,6 +9731,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
|
||||
|
||||
@@ -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;
|
||||
@@ -872,7 +879,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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,8 @@ class Caches: public Singleton<Caches> {
|
||||
|
||||
public:
|
||||
enum FlushMode {
|
||||
kFlushMode_Moderate = 0,
|
||||
kFlushMode_Layers = 0,
|
||||
kFlushMode_Moderate,
|
||||
kFlushMode_Full
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace uirenderer {
|
||||
// Defines
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MIN_WRITER_SIZE 16384
|
||||
#define MIN_WRITER_SIZE 4096
|
||||
|
||||
// Debug
|
||||
#if DEBUG_DISPLAY_LIST
|
||||
|
||||
Reference in New Issue
Block a user