summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2012-09-30 12:14:13 -0700
committerChet Haase <chet@google.com>2012-09-30 15:35:08 -0700
commit6a2d17f71342f981c9df1dc5beff33e30eb3ae2b (patch)
treeaaf68defc949273eccdd48aa40927fe8895ad37d /core/java/android
parent933a7546c857dba7704a15b7f7f7847934f14912 (diff)
downloadframeworks_base-6a2d17f71342f981c9df1dc5beff33e30eb3ae2b.zip
frameworks_base-6a2d17f71342f981c9df1dc5beff33e30eb3ae2b.tar.gz
frameworks_base-6a2d17f71342f981c9df1dc5beff33e30eb3ae2b.tar.bz2
Fix texture corruption
When memory gets low on a device, activities flush everything they can. Hardware-accelerated activites, such as Launcher, flush GL resources and destroy the GL context. However, some resources were still hanging around, due to deferred destruction policies (we don't delete layers until the DisplayLists they are in are finalized, to ensure we don't deref deleted objects). This meant that we were referring to obsolete GL data in these objects. in particular, it meant that we might come around later, after a new GL context was created, and delete a texture object that was incorrect. We use the layer's "texture id" to refer to the texture underlying the layer. But if there's a new GL context, then this texture ID is no longer valid, and we may be deleting the texture that a different object (layer, icon, whatever) is referring to, because the driver may return that same ID under the new GL context. The fix is to more aggressively delete things that we know will not be used again when the GL context is destroyed. In particular, we delete all resources being used by all DisplayLists at GL context destruction time. Issue #7195815 Textures corruption on all devices, in many apps Change-Id: I52d2d208173690dbb794a83402d38f14ea4c6c22
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/view/DisplayList.java7
-rw-r--r--core/java/android/view/GLES20DisplayList.java8
-rw-r--r--core/java/android/view/HardwareRenderer.java6
-rw-r--r--core/java/android/view/View.java3
4 files changed, 24 insertions, 0 deletions
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index a42e156..5e34a36 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -332,4 +332,11 @@ public abstract class DisplayList {
* @see View#offsetTopAndBottom(int)
*/
public abstract void offsetTopBottom(int offset);
+
+ /**
+ * Reset native resources. This is called when cleaning up the state of DisplayLists
+ * during destruction of hardware resources, to ensure that we do not hold onto
+ * obsolete resources after related resources are gone.
+ */
+ public abstract void reset();
}
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 3bdd5c0..e9bd0c4 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -87,6 +87,13 @@ class GLES20DisplayList extends DisplayList {
}
@Override
+ public void reset() {
+ if (hasNativeDisplayList()) {
+ nReset(mFinalizer.mNativeDisplayList);
+ }
+ }
+
+ @Override
public boolean isValid() {
return mValid;
}
@@ -294,6 +301,7 @@ class GLES20DisplayList extends DisplayList {
}
}
+ private static native void nReset(int displayList);
private static native void nOffsetTopBottom(int displayList, int offset);
private static native void nOffsetLeftRight(int displayList, int offset);
private static native void nSetLeftTopRightBottom(int displayList, int left, int top,
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 28763b3..99987bf 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1508,6 +1508,9 @@ public abstract class HardwareRenderer {
@Override
void destroyLayers(View view) {
if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {
+ if (mCanvas != null) {
+ mCanvas.clearLayerUpdates();
+ }
destroyHardwareLayer(view);
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
}
@@ -1556,6 +1559,9 @@ public abstract class HardwareRenderer {
safelyRun(new Runnable() {
@Override
public void run() {
+ if (mCanvas != null) {
+ mCanvas.clearLayerUpdates();
+ }
destroyResources(view);
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6eca8fd..4b6f4ea 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12394,6 +12394,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mHardwareLayer.destroy();
mHardwareLayer = null;
+ if (mDisplayList != null) {
+ mDisplayList.reset();
+ }
invalidate(true);
invalidateParentCaches();
}