Skip to content

Commit 6a2d17f

Browse files
committed
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
1 parent 933a754 commit 6a2d17f

File tree

9 files changed

+69
-34
lines changed

9 files changed

+69
-34
lines changed

core/java/android/view/DisplayList.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,4 +332,11 @@ public abstract void setTransformationInfo(float alpha, float translationX, floa
332332
* @see View#offsetTopAndBottom(int)
333333
*/
334334
public abstract void offsetTopBottom(int offset);
335+
336+
/**
337+
* Reset native resources. This is called when cleaning up the state of DisplayLists
338+
* during destruction of hardware resources, to ensure that we do not hold onto
339+
* obsolete resources after related resources are gone.
340+
*/
341+
public abstract void reset();
335342
}

core/java/android/view/GLES20DisplayList.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ public void clear() {
8686
}
8787
}
8888

89+
@Override
90+
public void reset() {
91+
if (hasNativeDisplayList()) {
92+
nReset(mFinalizer.mNativeDisplayList);
93+
}
94+
}
95+
8996
@Override
9097
public boolean isValid() {
9198
return mValid;
@@ -294,6 +301,7 @@ public void offsetTopBottom(int offset) {
294301
}
295302
}
296303

304+
private static native void nReset(int displayList);
297305
private static native void nOffsetTopBottom(int displayList, int offset);
298306
private static native void nOffsetLeftRight(int displayList, int offset);
299307
private static native void nSetLeftTopRightBottom(int displayList, int left, int top,

core/java/android/view/HardwareRenderer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,9 @@ void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
15081508
@Override
15091509
void destroyLayers(View view) {
15101510
if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {
1511+
if (mCanvas != null) {
1512+
mCanvas.clearLayerUpdates();
1513+
}
15111514
destroyHardwareLayer(view);
15121515
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
15131516
}
@@ -1556,6 +1559,9 @@ void destroyHardwareResources(final View view) {
15561559
safelyRun(new Runnable() {
15571560
@Override
15581561
public void run() {
1562+
if (mCanvas != null) {
1563+
mCanvas.clearLayerUpdates();
1564+
}
15591565
destroyResources(view);
15601566
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
15611567
}

core/java/android/view/View.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12394,6 +12394,9 @@ boolean destroyLayer(boolean valid) {
1239412394
mHardwareLayer.destroy();
1239512395
mHardwareLayer = null;
1239612396

12397+
if (mDisplayList != null) {
12398+
mDisplayList.reset();
12399+
}
1239712400
invalidate(true);
1239812401
invalidateParentCaches();
1239912402
}

core/jni/android/graphics/Canvas.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,9 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
931931
SkIRect ir;
932932
bool result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
933933

934+
if (!result) {
935+
r.setEmpty();
936+
}
934937
r.round(&ir);
935938
(void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
936939
return result;

core/jni/android_view_GLES20DisplayList.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ using namespace uirenderer;
3636
*/
3737
#ifdef USE_OPENGL_RENDERER
3838

39+
static void android_view_GLES20DisplayList_reset(JNIEnv* env,
40+
jobject clazz, DisplayList* displayList) {
41+
displayList->reset();
42+
}
43+
3944
// ----------------------------------------------------------------------------
4045
// DisplayList view properties
4146
// ----------------------------------------------------------------------------
@@ -185,6 +190,7 @@ const char* const kClassPathName = "android/view/GLES20DisplayList";
185190

186191
static JNINativeMethod gMethods[] = {
187192
#ifdef USE_OPENGL_RENDERER
193+
{ "nReset", "(I)V", (void*) android_view_GLES20DisplayList_reset },
188194
{ "nSetCaching", "(IZ)V", (void*) android_view_GLES20DisplayList_setCaching },
189195
{ "nSetStaticMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setStaticMatrix },
190196
{ "nSetAnimationMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setAnimationMatrix },

libs/hwui/Caches.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,6 @@ void Caches::deleteDisplayListDeferred(DisplayList* displayList) {
268268
void Caches::flush(FlushMode mode) {
269269
FLUSH_LOGD("Flushing caches (mode %d)", mode);
270270

271-
clearGarbage();
272-
273271
switch (mode) {
274272
case kFlushMode_Full:
275273
textureCache.clear();
@@ -293,6 +291,8 @@ void Caches::flush(FlushMode mode) {
293291
layerCache.clear();
294292
break;
295293
}
294+
295+
clearGarbage();
296296
}
297297

298298
///////////////////////////////////////////////////////////////////////////////

libs/hwui/DisplayListRenderer.cpp

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -105,35 +105,6 @@ DisplayList::~DisplayList() {
105105
clearResources();
106106
}
107107

108-
void DisplayList::initProperties() {
109-
mLeft = 0;
110-
mTop = 0;
111-
mRight = 0;
112-
mBottom = 0;
113-
mClipChildren = true;
114-
mAlpha = 1;
115-
mMultipliedAlpha = 255;
116-
mHasOverlappingRendering = true;
117-
mTranslationX = 0;
118-
mTranslationY = 0;
119-
mRotation = 0;
120-
mRotationX = 0;
121-
mRotationY= 0;
122-
mScaleX = 1;
123-
mScaleY = 1;
124-
mPivotX = 0;
125-
mPivotY = 0;
126-
mCameraDistance = 0;
127-
mMatrixDirty = false;
128-
mMatrixFlags = 0;
129-
mPrevWidth = -1;
130-
mPrevHeight = -1;
131-
mWidth = 0;
132-
mHeight = 0;
133-
mPivotExplicitlySet = false;
134-
mCaching = false;
135-
}
136-
137108
void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
138109
if (displayList) {
139110
DISPLAY_LIST_LOGD("Deferring display list destruction");
@@ -215,17 +186,21 @@ void DisplayList::clearResources() {
215186
mLayers.clear();
216187
}
217188

189+
void DisplayList::reset() {
190+
clearResources();
191+
init();
192+
}
193+
218194
void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
219-
const SkWriter32& writer = recorder.writeStream();
220195

221196
if (reusing) {
222197
// re-using display list - clear out previous allocations
223198
clearResources();
224199
}
225200

226201
init();
227-
initProperties();
228202

203+
const SkWriter32& writer = recorder.writeStream();
229204
if (writer.size() == 0) {
230205
return;
231206
}
@@ -303,6 +278,32 @@ void DisplayList::init() {
303278
mSize = 0;
304279
mIsRenderable = true;
305280
mFunctorCount = 0;
281+
mLeft = 0;
282+
mTop = 0;
283+
mRight = 0;
284+
mBottom = 0;
285+
mClipChildren = true;
286+
mAlpha = 1;
287+
mMultipliedAlpha = 255;
288+
mHasOverlappingRendering = true;
289+
mTranslationX = 0;
290+
mTranslationY = 0;
291+
mRotation = 0;
292+
mRotationX = 0;
293+
mRotationY= 0;
294+
mScaleX = 1;
295+
mScaleY = 1;
296+
mPivotX = 0;
297+
mPivotY = 0;
298+
mCameraDistance = 0;
299+
mMatrixDirty = false;
300+
mMatrixFlags = 0;
301+
mPrevWidth = -1;
302+
mPrevHeight = -1;
303+
mWidth = 0;
304+
mHeight = 0;
305+
mPivotExplicitlySet = false;
306+
mCaching = false;
306307
}
307308

308309
size_t DisplayList::getSize() {

libs/hwui/DisplayListRenderer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ class DisplayList {
137137

138138
void output(OpenGLRenderer& renderer, uint32_t level = 0);
139139

140+
ANDROID_API void reset();
141+
140142
void setRenderable(bool renderable) {
141143
mIsRenderable = renderable;
142144
}
@@ -399,7 +401,6 @@ class DisplayList {
399401

400402
private:
401403
void init();
402-
void initProperties();
403404

404405
void clearResources();
405406

0 commit comments

Comments
 (0)