Merge "Fix texture corruption" into jb-mr1-dev
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 @@
      * @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 @@
     }
 
     @Override
+    public void reset() {
+        if (hasNativeDisplayList()) {
+            nReset(mFinalizer.mNativeDisplayList);
+        }
+    }
+
+    @Override
     public boolean isValid() {
         return mValid;
     }
@@ -294,6 +301,7 @@
         }
     }
 
+    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 @@
         @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 @@
                 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 @@
                 mHardwareLayer.destroy();
                 mHardwareLayer = null;
 
+                if (mDisplayList != null) {
+                    mDisplayList.reset();
+                }
                 invalidate(true);
                 invalidateParentCaches();
             }
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 5c27602..2a02f7c 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -931,6 +931,9 @@
         SkIRect ir;
         bool     result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
 
+        if (!result) {
+            r.setEmpty();
+        }
         r.round(&ir);
         (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
         return result;
diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp
index b307a2f..c5f52df 100644
--- a/core/jni/android_view_GLES20DisplayList.cpp
+++ b/core/jni/android_view_GLES20DisplayList.cpp
@@ -36,6 +36,11 @@
  */
 #ifdef USE_OPENGL_RENDERER
 
+static void android_view_GLES20DisplayList_reset(JNIEnv* env,
+        jobject clazz, DisplayList* displayList) {
+    displayList->reset();
+}
+
 // ----------------------------------------------------------------------------
 // DisplayList view properties
 // ----------------------------------------------------------------------------
@@ -185,6 +190,7 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
+    { "nReset",                "(I)V",   (void*) android_view_GLES20DisplayList_reset },
     { "nSetCaching",           "(IZ)V",  (void*) android_view_GLES20DisplayList_setCaching },
     { "nSetStaticMatrix",      "(II)V",  (void*) android_view_GLES20DisplayList_setStaticMatrix },
     { "nSetAnimationMatrix",   "(II)V",  (void*) android_view_GLES20DisplayList_setAnimationMatrix },
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index e443294..7853ae4 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -268,8 +268,6 @@
 void Caches::flush(FlushMode mode) {
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
-    clearGarbage();
-
     switch (mode) {
         case kFlushMode_Full:
             textureCache.clear();
@@ -293,6 +291,8 @@
             layerCache.clear();
             break;
     }
+
+    clearGarbage();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index f84c847..589d5c2 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -105,35 +105,6 @@
     clearResources();
 }
 
-void DisplayList::initProperties() {
-    mLeft = 0;
-    mTop = 0;
-    mRight = 0;
-    mBottom = 0;
-    mClipChildren = true;
-    mAlpha = 1;
-    mMultipliedAlpha = 255;
-    mHasOverlappingRendering = true;
-    mTranslationX = 0;
-    mTranslationY = 0;
-    mRotation = 0;
-    mRotationX = 0;
-    mRotationY= 0;
-    mScaleX = 1;
-    mScaleY = 1;
-    mPivotX = 0;
-    mPivotY = 0;
-    mCameraDistance = 0;
-    mMatrixDirty = false;
-    mMatrixFlags = 0;
-    mPrevWidth = -1;
-    mPrevHeight = -1;
-    mWidth = 0;
-    mHeight = 0;
-    mPivotExplicitlySet = false;
-    mCaching = false;
-}
-
 void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
     if (displayList) {
         DISPLAY_LIST_LOGD("Deferring display list destruction");
@@ -215,8 +186,12 @@
     mLayers.clear();
 }
 
+void DisplayList::reset() {
+    clearResources();
+    init();
+}
+
 void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
-    const SkWriter32& writer = recorder.writeStream();
 
     if (reusing) {
         // re-using display list - clear out previous allocations
@@ -224,8 +199,8 @@
     }
 
     init();
-    initProperties();
 
+    const SkWriter32& writer = recorder.writeStream();
     if (writer.size() == 0) {
         return;
     }
@@ -303,6 +278,32 @@
     mSize = 0;
     mIsRenderable = true;
     mFunctorCount = 0;
+    mLeft = 0;
+    mTop = 0;
+    mRight = 0;
+    mBottom = 0;
+    mClipChildren = true;
+    mAlpha = 1;
+    mMultipliedAlpha = 255;
+    mHasOverlappingRendering = true;
+    mTranslationX = 0;
+    mTranslationY = 0;
+    mRotation = 0;
+    mRotationX = 0;
+    mRotationY= 0;
+    mScaleX = 1;
+    mScaleY = 1;
+    mPivotX = 0;
+    mPivotY = 0;
+    mCameraDistance = 0;
+    mMatrixDirty = false;
+    mMatrixFlags = 0;
+    mPrevWidth = -1;
+    mPrevHeight = -1;
+    mWidth = 0;
+    mHeight = 0;
+    mPivotExplicitlySet = false;
+    mCaching = false;
 }
 
 size_t DisplayList::getSize() {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 39061f4..2610055 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -137,6 +137,8 @@
 
     void output(OpenGLRenderer& renderer, uint32_t level = 0);
 
+    ANDROID_API void reset();
+
     void setRenderable(bool renderable) {
         mIsRenderable = renderable;
     }
@@ -399,7 +401,6 @@
 
 private:
     void init();
-    void initProperties();
 
     void clearResources();