Clear root level reorder lists to prevent accessing stale DisplayLists

bug:12581401

Adds temporary logging which should log/crash earlier on incorrectly
reordering hierarchies.

Change-Id: Iee00940718c3cc868161e754aff93cd3b2747094
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index a156341..3c8495e 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -261,6 +261,7 @@
     mHeight = 0;
     mPivotExplicitlySet = false;
     mCaching = false;
+    mOrderingId = 0;
 }
 
 size_t DisplayList::getSize() {
@@ -501,13 +502,20 @@
  */
 void DisplayList::computeOrdering() {
     ATRACE_CALL();
-    if (mDisplayListData == NULL) return;
+    m3dNodes.clear();
+    mProjectedNodes.clear();
+    mRootDisplayList = this;
+    mOrderingId++;
 
+    // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that
+    // transform properties are applied correctly to top level children
+    if (mDisplayListData == NULL) return;
     for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
         DrawDisplayListOp* childOp = mDisplayListData->children[i];
         childOp->mDisplayList->computeOrderingImpl(childOp,
                 &m3dNodes, &mat4::identity(),
-                &mProjectedNodes, &mat4::identity());
+                &mProjectedNodes, &mat4::identity(),
+                mRootDisplayList, mOrderingId);
     }
 }
 
@@ -516,7 +524,14 @@
         Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot,
         const mat4* transformFrom3dRoot,
         Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
-        const mat4* transformFromProjectionSurface) {
+        const mat4* transformFromProjectionSurface,
+        const void* rootDisplayList, const int orderingId) {
+    m3dNodes.clear();
+    mProjectedNodes.clear();
+
+    // Temporary, for logging
+    mRootDisplayList = rootDisplayList;
+    mOrderingId = orderingId;
 
     // TODO: should avoid this calculation in most cases
     // TODO: just calculate single matrix, down to all leaf composited elements
@@ -546,7 +561,6 @@
         opState->mSkipInOrderDraw = false;
     }
 
-    m3dNodes.clear();
     if (mIsContainedVolume) {
         // create a new 3d space for descendents by collecting them
         compositedChildrenOf3dRoot = &m3dNodes;
@@ -556,7 +570,6 @@
         transformFrom3dRoot = &localTransformFrom3dRoot;
     }
 
-    mProjectedNodes.clear();
     if (mDisplayListData != NULL && mDisplayListData->projectionIndex >= 0) {
         // create a new projection surface for descendents by collecting them
         compositedChildrenOfProjectionSurface = &mProjectedNodes;
@@ -571,7 +584,8 @@
             DrawDisplayListOp* childOp = mDisplayListData->children[i];
             childOp->mDisplayList->computeOrderingImpl(childOp,
                     compositedChildrenOf3dRoot, transformFrom3dRoot,
-                    compositedChildrenOfProjectionSurface, transformFromProjectionSurface);
+                    compositedChildrenOfProjectionSurface, transformFromProjectionSurface,
+                    rootDisplayList, orderingId);
         }
     }
 }
@@ -585,6 +599,7 @@
     }
     inline LinearAllocator& allocator() { return *(mDeferStruct.mAllocator); }
 
+    const DisplayList* getRoot() { return mDeferStruct.mRoot; }
 private:
     DeferStateStruct& mDeferStruct;
     const int mLevel;
@@ -607,6 +622,7 @@
     }
     inline LinearAllocator& allocator() { return *(mReplayStruct.mAllocator); }
 
+    const DisplayList* getRoot() { return mReplayStruct.mRoot; }
 private:
     ReplayStateStruct& mReplayStruct;
     const int mLevel;
@@ -643,6 +659,14 @@
         const float zValue = m3dNodes[i].key;
         DrawDisplayListOp* childOp = m3dNodes[i].value;
 
+        if (CC_UNLIKELY(handler.getRoot()->mRootDisplayList != childOp->mDisplayList->mRootDisplayList ||
+                handler.getRoot()->mOrderingId != childOp->mDisplayList->mOrderingId)) {
+            ALOGW("Error in 3d order computation: Root %p, order %d, expected %p %d",
+                    childOp->mDisplayList->mRootDisplayList, childOp->mDisplayList->mOrderingId,
+                    handler.getRoot()->mRootDisplayList, handler.getRoot()->mOrderingId);
+            CRASH();
+        }
+
         if (mode == kPositiveZChildren && zValue < 0.0f) continue;
         if (mode == kNegativeZChildren && zValue > 0.0f) break;
 
@@ -704,6 +728,15 @@
         ALOGW("Error: %s is drawing after destruction, size %d", getName(), mSize);
         CRASH();
     }
+
+    if (CC_UNLIKELY(handler.getRoot()->mRootDisplayList != mRootDisplayList ||
+            handler.getRoot()->mOrderingId != mOrderingId)) {
+        ALOGW("Error in order computation: Root %p, order %d, expected %p %d",
+                mRootDisplayList, mOrderingId,
+                handler.getRoot()->mRootDisplayList, handler.getRoot()->mOrderingId);
+        CRASH();
+    }
+
     if (mSize == 0 || mAlpha <= 0) {
         DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
         return;
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 5399185..8026c4a 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -76,7 +76,7 @@
 class PlaybackStateStruct {
 protected:
     PlaybackStateStruct(OpenGLRenderer& renderer, int replayFlags, LinearAllocator* allocator)
-            : mRenderer(renderer), mReplayFlags(replayFlags), mAllocator(allocator){}
+            : mRenderer(renderer), mReplayFlags(replayFlags), mAllocator(allocator), mRoot(NULL) {}
 
 public:
     OpenGLRenderer& mRenderer;
@@ -85,6 +85,7 @@
     // Allocator with the lifetime of a single frame.
     // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator
     LinearAllocator * const mAllocator;
+    const DisplayList* mRoot; // TEMPORARY, for debug logging only
 };
 
 class DeferStateStruct : public PlaybackStateStruct {
@@ -195,6 +196,9 @@
     }
 
     void setProjectToContainedVolume(bool shouldProject) {
+        if (!mProjectToContainedVolume && shouldProject) {
+            ALOGD("DL %s(%p) marked for projection", getName(), this);
+        }
         mProjectToContainedVolume = shouldProject;
     }
 
@@ -260,6 +264,9 @@
 
     void setTranslationZ(float translationZ) {
         if (translationZ != mTranslationZ) {
+            if (mTranslationZ == 0.0f) {
+                ALOGD("DL %s(%p) marked for 3d compositing", getName(), this);
+            }
             mTranslationZ = translationZ;
             onTranslationUpdate();
         }
@@ -527,10 +534,11 @@
     void applyViewPropertyTransforms(mat4& matrix);
 
     void computeOrderingImpl(DrawDisplayListOp* opState,
-        Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot,
-        const mat4* transformFrom3dRoot,
-        Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
-        const mat4* transformFromProjectionSurface);
+            Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot,
+            const mat4* transformFrom3dRoot,
+            Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
+            const mat4* transformFromProjectionSurface,
+            const void* rootDisplayList, const int orderingId);
 
     template <class T>
     inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
@@ -623,6 +631,10 @@
 
     // for projection surfaces, contains a list of all children items
     Vector<DrawDisplayListOp*> mProjectedNodes;
+
+    // TEMPORARY, for debug logging only
+    const void* mRootDisplayList;
+    int mOrderingId;
 }; // class DisplayList
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 742ffd47..ed571fa 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -199,6 +199,7 @@
 
     DeferStateStruct deferredState(*deferredList, *renderer,
             DisplayList::kReplayFlag_ClipChildren);
+    deferredState.mRoot = displayList;
 
     renderer->initViewport(width, height);
     renderer->setupFrameState(dirtyRect.left, dirtyRect.top,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7ee803f..741e953 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1877,6 +1877,7 @@
         if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
             status = startFrame();
             ReplayStateStruct replayStruct(*this, dirty, replayFlags);
+            replayStruct.mRoot = displayList;
             displayList->replay(replayStruct, 0);
             return status | replayStruct.mDrawGlStatus;
         }
@@ -1884,6 +1885,7 @@
         bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
         DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
         DeferStateStruct deferStruct(deferredList, *this, replayFlags);
+        deferStruct.mRoot = displayList;
         displayList->defer(deferStruct, 0);
 
         flushLayers();