Merge "Destroy layers and flush layers cache when a window is destroyed."

This commit is contained in:
Romain Guy
2011-07-27 16:31:19 -07:00
committed by Android (Google) Code Review
8 changed files with 84 additions and 46 deletions

View 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

View 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>() {

View File

@@ -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;
}
}
}

View File

@@ -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

View 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;
@@ -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) {

View 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;
}
}

View File

@@ -101,7 +101,8 @@ class Caches: public Singleton<Caches> {
public:
enum FlushMode {
kFlushMode_Moderate = 0,
kFlushMode_Layers = 0,
kFlushMode_Moderate,
kFlushMode_Full
};

View File

@@ -37,7 +37,7 @@ namespace uirenderer {
// Defines
///////////////////////////////////////////////////////////////////////////////
#define MIN_WRITER_SIZE 16384
#define MIN_WRITER_SIZE 4096
// Debug
#if DEBUG_DISPLAY_LIST