Initial refactoring to enable the addition of the SkiaOpenGLPipeline.

Test: existing and new HWUI unit tests all pass.
Change-Id: I4f5c1dc839a2ed15d8b0f6245fe030684501b083
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 8c36ab5..a03ded6 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -51,7 +51,7 @@
 RenderNode::~RenderNode() {
     deleteDisplayList(nullptr);
     delete mStagingDisplayList;
-    LOG_ALWAYS_FATAL_IF(mLayer, "layer missed detachment!");
+    LOG_ALWAYS_FATAL_IF(hasLayer(), "layer missed detachment!");
 }
 
 void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
@@ -81,7 +81,7 @@
             << (properties().hasShadow() ? ", casting shadow" : "")
             << (isRenderable() ? "" : ", empty")
             << (properties().getProjectBackwards() ? ", projected" : "")
-            << (mLayer != nullptr ? ", on HW Layer" : "")
+            << (hasLayer() ? ", on HW Layer" : "")
             << ")" << std::endl;
 
     properties().debugOutputProperties(output, level + 1);
@@ -237,7 +237,7 @@
             || CC_UNLIKELY(!isRenderable())
             || CC_UNLIKELY(properties().getWidth() == 0)
             || CC_UNLIKELY(properties().getHeight() == 0)) {
-        if (CC_UNLIKELY(mLayer)) {
+        if (CC_UNLIKELY(hasLayer())) {
             renderthread::CanvasContext::destroyLayer(this);
         }
         return;
@@ -247,7 +247,7 @@
         damageSelf(info);
     }
 
-    if (!mLayer) {
+    if (!hasLayer()) {
         Caches::getInstance().dumpMemoryUsage();
         if (info.errorHandler) {
             std::ostringstream err;
@@ -295,9 +295,9 @@
 
     bool willHaveFunctor = false;
     if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayList) {
-        willHaveFunctor = !mStagingDisplayList->getFunctors().empty();
+        willHaveFunctor = mStagingDisplayList->hasFunctor();
     } else if (mDisplayList) {
-        willHaveFunctor = !mDisplayList->getFunctors().empty();
+        willHaveFunctor = mDisplayList->hasFunctor();
     }
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
@@ -310,15 +310,15 @@
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingDisplayListChanges(info);
     }
-    prepareSubTree(info, childFunctorsNeedLayer, mDisplayList);
 
     if (mDisplayList) {
-        for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) {
-            // If any vector drawable in the display list needs update, damage the node.
-            if (vectorDrawable->isDirty()) {
-                damageSelf(info);
-            }
-            vectorDrawable->setPropertyChangeWillBeConsumed(true);
+        info.out.hasFunctors |= mDisplayList->hasFunctor();
+        bool isDirty = mDisplayList->prepareListAndChildren(info, childFunctorsNeedLayer,
+                [](RenderNode* child, TreeInfo& info, bool functorsNeedLayer) {
+            child->prepareTreeImpl(info, functorsNeedLayer);
+        });
+        if (isDirty) {
+            damageSelf(info);
         }
     }
     pushLayerUpdate(info);
@@ -356,20 +356,15 @@
     // Make sure we inc first so that we don't fluctuate between 0 and 1,
     // which would thrash the layer cache
     if (mStagingDisplayList) {
-        for (auto&& child : mStagingDisplayList->getChildren()) {
-            child->renderNode->incParentRefCount();
-        }
+        mStagingDisplayList->updateChildren([](RenderNode* child) {
+            child->incParentRefCount();
+        });
     }
     deleteDisplayList(info ? info->observer : nullptr, info);
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
-        for (auto& iter : mDisplayList->getFunctors()) {
-            (*iter.functor)(DrawGlInfo::kModeSync, nullptr);
-        }
-        for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) {
-            vectorDrawable->syncProperties();
-        }
+        mDisplayList->syncContents();
     }
 }
 
@@ -386,40 +381,24 @@
 
 void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->decParentRefCount(observer, info);
+        mDisplayList->updateChildren([observer, info](RenderNode* child) {
+            child->decParentRefCount(observer, info);
+        });
+        if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) {
+            delete mDisplayList;
         }
     }
-    delete mDisplayList;
     mDisplayList = nullptr;
 }
 
-void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree) {
-    if (subtree) {
-        TextureCache& cache = Caches::getInstance().textureCache;
-        info.out.hasFunctors |= subtree->getFunctors().size();
-        for (auto&& bitmapResource : subtree->getBitmapResources()) {
-            void* ownerToken = &info.canvasContext;
-            info.prepareTextures = cache.prefetchAndMarkInUse(ownerToken, bitmapResource);
-        }
-        for (auto&& op : subtree->getChildren()) {
-            RenderNode* childNode = op->renderNode;
-            info.damageAccumulator->pushTransform(&op->localMatrix);
-            bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
-            childNode->prepareTreeImpl(info, childFunctorsNeedLayer);
-            info.damageAccumulator->popTransform();
-        }
-    }
-}
-
 void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) {
-    if (mLayer) {
+    if (hasLayer()) {
         renderthread::CanvasContext::destroyLayer(this);
     }
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->destroyHardwareResources(observer, info);
-        }
+        mDisplayList->updateChildren([observer, info](RenderNode* child) {
+            child->destroyHardwareResources(observer, info);
+        });
         if (mNeedsDisplayListSync) {
             // Next prepare tree we are going to push a new display list, so we can
             // drop our current one now