Convert DisplayList to a value-type wrapper

Make DisplayList its own type instead of an alias,
pushing the Skia aspect behind it mostly. Removes a bunch
of manual memory management and opens the door to DisplayList
being a union type with multiple implementations

Test: builds (somehow), boots, hwuiunit passes, CtsUiRendering passes
Change-Id: I1d7806aa3afc5d9ece08b06959920078a5814c59
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index dc63e5d..3aa5b4b 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -18,6 +18,8 @@
 
 #include "pipeline/skia/SkiaDisplayList.h"
 
+#include <memory>
+
 namespace android {
 namespace uirenderer {
 
@@ -29,7 +31,119 @@
 /**
  * Data structure that holds the list of commands used in display list stream
  */
-using DisplayList = skiapipeline::SkiaDisplayList;
+//using DisplayList = skiapipeline::SkiaDisplayList;
+class DisplayList {
+public:
+    // Constructs an empty (invalid) DisplayList
+    explicit DisplayList() {}
+
+    // Constructs a DisplayList from a SkiaDisplayList
+    explicit DisplayList(std::unique_ptr<skiapipeline::SkiaDisplayList> impl)
+        : mImpl(std::move(impl)) {}
+
+    // Move support
+    DisplayList(DisplayList&& other) : mImpl(std::move(other.mImpl)) {}
+    DisplayList& operator=(DisplayList&& other) {
+        mImpl = std::move(other.mImpl);
+        return *this;
+    }
+
+    // No copy support
+    DisplayList(const DisplayList& other) = delete;
+    DisplayList& operator=(const DisplayList&) = delete;
+
+    void updateChildren(std::function<void(RenderNode*)> updateFn) {
+        mImpl->updateChildren(std::move(updateFn));
+    }
+
+    [[nodiscard]] explicit operator bool() const {
+        return mImpl.get() != nullptr;
+    }
+
+    // If true this DisplayList contains a backing content, even if that content is empty
+    // If false, there this DisplayList is in an "empty" state
+    [[nodiscard]] bool isValid() const {
+        return mImpl.get() != nullptr;
+    }
+
+    [[nodiscard]] bool isEmpty() const {
+        return !hasContent();
+    }
+
+    [[nodiscard]] bool hasContent() const {
+        return mImpl && !(mImpl->isEmpty());
+    }
+
+    [[nodiscard]] bool containsProjectionReceiver() const {
+        return mImpl && mImpl->containsProjectionReceiver();
+    }
+
+    [[nodiscard]] skiapipeline::SkiaDisplayList* asSkiaDl() {
+        return mImpl.get();
+    }
+
+    [[nodiscard]] const skiapipeline::SkiaDisplayList* asSkiaDl() const {
+        return mImpl.get();
+    }
+
+    [[nodiscard]] bool hasVectorDrawables() const {
+        return mImpl && mImpl->hasVectorDrawables();
+    }
+
+    void clear(RenderNode* owningNode = nullptr) {
+        if (mImpl && owningNode && mImpl->reuseDisplayList(owningNode)) {
+            // TODO: This is a bit sketchy to have a unique_ptr temporarily owned twice
+            // Do something to cleanup reuseDisplayList passing itself to the RenderNode
+            mImpl.release();
+        } else {
+            mImpl = nullptr;
+        }
+    }
+
+    [[nodiscard]] size_t getUsedSize() const {
+        return mImpl ? mImpl->getUsedSize() : 0;
+    }
+
+    [[nodiscard]] size_t getAllocatedSize() const {
+        return mImpl ? mImpl->getAllocatedSize() : 0;
+    }
+
+    void output(std::ostream& output, uint32_t level) const {
+        if (mImpl) {
+            mImpl->output(output, level);
+        }
+    }
+
+    [[nodiscard]] bool hasFunctor() const {
+        return mImpl && mImpl->hasFunctor();
+    }
+
+    bool prepareListAndChildren(
+            TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+            std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
+        return mImpl && mImpl->prepareListAndChildren(
+                observer, info, functorsNeedLayer, std::move(childFn));
+    }
+
+    void syncContents(const WebViewSyncData& data) {
+        if (mImpl) {
+            mImpl->syncContents(data);
+        }
+    }
+
+    [[nodiscard]] bool hasText() const {
+        return mImpl && mImpl->hasText();
+    }
+
+    void applyColorTransform(ColorTransform transform) {
+        if (mImpl) {
+            mImpl->mDisplayList.applyColorTransform(transform);
+        }
+    }
+
+private:
+    std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
+};
 
 }  // namespace uirenderer
 }  // namespace android