DisplayList overhaul

Change-Id: I53418d580c98f706e971545cff81b9921c12cc5f
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 23c33ca..112f8d3f 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -48,179 +48,10 @@
     fflush(file);
 }
 
-DisplayList::DisplayList(const DisplayListRenderer& recorder) :
-    mDestroyed(false), mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
-    mStaticMatrix(NULL), mAnimationMatrix(NULL) {
+DisplayList::DisplayList() :
+        mDisplayListData(0), mDestroyed(false), mTransformMatrix(NULL), mTransformCamera(NULL),
+        mTransformMatrix3D(NULL), mStaticMatrix(NULL), mAnimationMatrix(NULL) {
 
-    initFromDisplayListRenderer(recorder);
-}
-
-DisplayList::~DisplayList() {
-    mDestroyed = true;
-    clearResources();
-}
-
-void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
-    if (displayList) {
-        DISPLAY_LIST_LOGD("Deferring display list destruction");
-        Caches::getInstance().deleteDisplayListDeferred(displayList);
-    }
-}
-
-void DisplayList::clearResources() {
-    mDisplayListData = NULL;
-
-    delete mTransformMatrix;
-    delete mTransformCamera;
-    delete mTransformMatrix3D;
-    delete mStaticMatrix;
-    delete mAnimationMatrix;
-
-    mTransformMatrix = NULL;
-    mTransformCamera = NULL;
-    mTransformMatrix3D = NULL;
-    mStaticMatrix = NULL;
-    mAnimationMatrix = NULL;
-
-    Caches& caches = Caches::getInstance();
-    caches.unregisterFunctors(mFunctorCount);
-    caches.resourceCache.lock();
-
-    for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        const SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcountLocked(bitmap);
-        caches.resourceCache.destructorLocked(bitmap);
-    }
-
-    for (size_t i = 0; i < mPatchResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mShaders.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
-        caches.resourceCache.destructorLocked(mShaders.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mSourcePaths.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mLayers.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
-    }
-
-    caches.resourceCache.unlock();
-
-    for (size_t i = 0; i < mPaints.size(); i++) {
-        delete mPaints.itemAt(i);
-    }
-
-    for (size_t i = 0; i < mRegions.size(); i++) {
-        delete mRegions.itemAt(i);
-    }
-
-    for (size_t i = 0; i < mPaths.size(); i++) {
-        delete mPaths.itemAt(i);
-    }
-
-    for (size_t i = 0; i < mMatrices.size(); i++) {
-        delete mMatrices.itemAt(i);
-    }
-
-    mBitmapResources.clear();
-    mOwnedBitmapResources.clear();
-    mPatchResources.clear();
-    mShaders.clear();
-    mSourcePaths.clear();
-    mPaints.clear();
-    mRegions.clear();
-    mPaths.clear();
-    mMatrices.clear();
-    mLayers.clear();
-}
-
-void DisplayList::reset() {
-    clearResources();
-    init();
-}
-
-void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
-    if (reusing) {
-        // re-using display list - clear out previous allocations
-        clearResources();
-    }
-
-    init();
-
-    mDisplayListData = recorder.getDisplayListData();
-    mSize = mDisplayListData->allocator.usedSize();
-
-    if (mSize == 0) {
-        return;
-    }
-
-    mFunctorCount = recorder.getFunctorCount();
-
-    Caches& caches = Caches::getInstance();
-    caches.registerFunctors(mFunctorCount);
-    caches.resourceCache.lock();
-
-    const Vector<const SkBitmap*>& bitmapResources = recorder.getBitmapResources();
-    for (size_t i = 0; i < bitmapResources.size(); i++) {
-        const SkBitmap* resource = bitmapResources.itemAt(i);
-        mBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<const SkBitmap*>& ownedBitmapResources = recorder.getOwnedBitmapResources();
-    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
-        const SkBitmap* resource = ownedBitmapResources.itemAt(i);
-        mOwnedBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<const Res_png_9patch*>& patchResources = recorder.getPatchResources();
-    for (size_t i = 0; i < patchResources.size(); i++) {
-        const Res_png_9patch* resource = patchResources.itemAt(i);
-        mPatchResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<SkiaShader*>& shaders = recorder.getShaders();
-    for (size_t i = 0; i < shaders.size(); i++) {
-        SkiaShader* resource = shaders.itemAt(i);
-        mShaders.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const SortedVector<const SkPath*>& sourcePaths = recorder.getSourcePaths();
-    for (size_t i = 0; i < sourcePaths.size(); i++) {
-        mSourcePaths.add(sourcePaths.itemAt(i));
-        caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
-    }
-
-    const Vector<Layer*>& layers = recorder.getLayers();
-    for (size_t i = 0; i < layers.size(); i++) {
-        mLayers.add(layers.itemAt(i));
-        caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
-    }
-
-    caches.resourceCache.unlock();
-
-    mPaints.appendVector(recorder.getPaints());
-    mRegions.appendVector(recorder.getRegions());
-    mPaths.appendVector(recorder.getPaths());
-    mMatrices.appendVector(recorder.getMatrices());
-}
-
-void DisplayList::init() {
-    mSize = 0;
-    mIsRenderable = true;
-    mFunctorCount = 0;
     mLeft = 0;
     mTop = 0;
     mRight = 0;
@@ -256,8 +87,28 @@
     mCaching = false;
 }
 
-size_t DisplayList::getSize() {
-    return mSize;
+DisplayList::~DisplayList() {
+    LOG_ALWAYS_FATAL_IF(mDestroyed, "Double destroyed DisplayList %p", this);
+
+    mDestroyed = true;
+    delete mDisplayListData;
+    delete mTransformMatrix;
+    delete mTransformCamera;
+    delete mTransformMatrix3D;
+    delete mStaticMatrix;
+    delete mAnimationMatrix;
+}
+
+void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
+    if (displayList) {
+        DISPLAY_LIST_LOGD("Deferring display list destruction");
+        Caches::getInstance().deleteDisplayListDeferred(displayList);
+    }
+}
+
+void DisplayList::setData(DisplayListData* data) {
+    delete mDisplayListData;
+    mDisplayListData = data;
 }
 
 /**
@@ -518,7 +369,7 @@
         const mat4* transformFromProjectionSurface) {
     m3dNodes.clear();
     mProjectedNodes.clear();
-    if (mDisplayListData == NULL || mSize == 0) return;
+    if (mDisplayListData == NULL || mDisplayListData->isEmpty()) return;
 
     // TODO: should avoid this calculation in most cases
     // TODO: just calculate single matrix, down to all leaf composited elements
@@ -716,10 +567,10 @@
 template <class T>
 void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
     if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging
-        ALOGW("Error: %s is drawing after destruction, size %d", getName(), mSize);
+        ALOGW("Error: %s is drawing after destruction, size %d", getName());
         CRASH();
     }
-    if (mSize == 0 || mAlpha <= 0) {
+    if (mDisplayListData->isEmpty() || mAlpha <= 0) {
         DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
         return;
     }
@@ -777,5 +628,67 @@
     renderer.setOverrideLayerAlpha(1.0f);
 }
 
+void DisplayListData::cleanupResources() {
+    Caches& caches = Caches::getInstance();
+    caches.unregisterFunctors(functorCount);
+    caches.resourceCache.lock();
+
+    for (size_t i = 0; i < bitmapResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
+    }
+
+    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
+        const SkBitmap* bitmap = ownedBitmapResources.itemAt(i);
+        caches.resourceCache.decrementRefcountLocked(bitmap);
+        caches.resourceCache.destructorLocked(bitmap);
+    }
+
+    for (size_t i = 0; i < patchResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
+    }
+
+    for (size_t i = 0; i < shaders.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(shaders.itemAt(i));
+        caches.resourceCache.destructorLocked(shaders.itemAt(i));
+    }
+
+    for (size_t i = 0; i < sourcePaths.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
+    }
+
+    for (size_t i = 0; i < layers.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(layers.itemAt(i));
+    }
+
+    caches.resourceCache.unlock();
+
+    for (size_t i = 0; i < paints.size(); i++) {
+        delete paints.itemAt(i);
+    }
+
+    for (size_t i = 0; i < regions.size(); i++) {
+        delete regions.itemAt(i);
+    }
+
+    for (size_t i = 0; i < paths.size(); i++) {
+        delete paths.itemAt(i);
+    }
+
+    for (size_t i = 0; i < matrices.size(); i++) {
+        delete matrices.itemAt(i);
+    }
+
+    bitmapResources.clear();
+    ownedBitmapResources.clear();
+    patchResources.clear();
+    shaders.clear();
+    sourcePaths.clear();
+    paints.clear();
+    regions.clear();
+    paths.clear();
+    matrices.clear();
+    layers.clear();
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 9487fae..aba40b6 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -107,11 +107,13 @@
 };
 
 /**
- * Refcounted structure that holds the list of commands used in display list stream.
+ * Data structure that holds the list of commands used in display list stream
  */
-class DisplayListData : public LightRefBase<DisplayListData> {
+class DisplayListData {
 public:
-    DisplayListData() : projectionReceiveIndex(-1) {}
+    DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {}
+    virtual ~DisplayListData() { cleanupResources(); }
+
     // allocator into which all ops were allocated
     LinearAllocator allocator;
 
@@ -123,6 +125,27 @@
 
     // index of DisplayListOp restore, after which projected descendents should be drawn
     int projectionReceiveIndex;
+
+    Vector<const SkBitmap*> bitmapResources;
+    Vector<const SkBitmap*> ownedBitmapResources;
+    Vector<const Res_png_9patch*> patchResources;
+
+    Vector<const SkPaint*> paints;
+    Vector<const SkPath*> paths;
+    SortedVector<const SkPath*> sourcePaths;
+    Vector<const SkRegion*> regions;
+    Vector<const SkMatrix*> matrices;
+    Vector<SkiaShader*> shaders;
+    Vector<Layer*> layers;
+    uint32_t functorCount;
+    bool hasDrawOps;
+
+    bool isEmpty() {
+        return !displayListOps.size();
+    }
+
+private:
+    void cleanupResources();
 };
 
 /**
@@ -139,7 +162,7 @@
  */
 class DisplayList {
 public:
-    DisplayList(const DisplayListRenderer& recorder);
+    ANDROID_API DisplayList();
     ANDROID_API ~DisplayList();
 
     // See flags defined in DisplayList.java
@@ -147,11 +170,10 @@
         kReplayFlag_ClipChildren = 0x1
     };
 
-    ANDROID_API size_t getSize();
     ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
     ANDROID_API static void outputLogBuffer(int fd);
 
-    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
+    ANDROID_API void setData(DisplayListData* newData);
 
     void computeOrdering();
     void defer(DeferStateStruct& deferStruct, const int level);
@@ -159,14 +181,8 @@
 
     ANDROID_API void output(uint32_t level = 1);
 
-    ANDROID_API void reset();
-
-    void setRenderable(bool renderable) {
-        mIsRenderable = renderable;
-    }
-
     bool isRenderable() const {
-        return mIsRenderable;
+        return mDisplayListData && mDisplayListData->hasDrawOps;
     }
 
     void setName(const char* name) {
@@ -571,10 +587,6 @@
     template <class T>
     inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
 
-    void init();
-
-    void clearResources();
-
     void updateMatrix();
 
     class TextContainer {
@@ -591,24 +603,7 @@
         const char* mText;
     };
 
-    Vector<const SkBitmap*> mBitmapResources;
-    Vector<const SkBitmap*> mOwnedBitmapResources;
-    Vector<const Res_png_9patch*> mPatchResources;
-
-    Vector<const SkPaint*> mPaints;
-    Vector<const SkPath*> mPaths;
-    SortedVector<const SkPath*> mSourcePaths;
-    Vector<const SkRegion*> mRegions;
-    Vector<const SkMatrix*> mMatrices;
-    Vector<SkiaShader*> mShaders;
-    Vector<Layer*> mLayers;
-
-    sp<DisplayListData> mDisplayListData;
-
-    size_t mSize;
-
-    bool mIsRenderable;
-    uint32_t mFunctorCount;
+    DisplayListData* mDisplayListData;
 
     String8 mName;
     bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0cbf088..5abfe79 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -32,83 +32,28 @@
 namespace uirenderer {
 
 DisplayListRenderer::DisplayListRenderer():
-        mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
+        mCaches(Caches::getInstance()),
         mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
-        mHasDrawOps(false), mFunctorCount(0) {
+        mRestoreSaveCount(-1), mDisplayListData(0) {
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
-    reset();
-}
-
-void DisplayListRenderer::reset() {
-    mDisplayListData = new DisplayListData();
-    mCaches.resourceCache.lock();
-
-    for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mPatchResources.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mShaders.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mSourcePaths.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mLayers.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
-    }
-
-    mCaches.resourceCache.unlock();
-
-    mBitmapResources.clear();
-    mOwnedBitmapResources.clear();
-    mPatchResources.clear();
-    mSourcePaths.clear();
-
-    mShaders.clear();
-    mShaderMap.clear();
-
-    mPaints.clear();
-    mPaintMap.clear();
-
-    mRegions.clear();
-    mRegionMap.clear();
-
-    mPaths.clear();
-    mPathMap.clear();
-
-    mMatrices.clear();
-
-    mLayers.clear();
-
-    mHasDrawOps = false;
-    mFunctorCount = 0;
+    LOG_ALWAYS_FATAL_IF(mDisplayListData,
+            "Destroyed a DisplayListRenderer during a record!");
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
-    if (!displayList) {
-        displayList = new DisplayList(*this);
-    } else {
-        displayList->initFromDisplayListRenderer(*this, true);
-    }
-    // TODO: should just avoid setting the DisplayList's DisplayListData
-    displayList->setRenderable(mHasDrawOps);
-    return displayList;
+DisplayListData* DisplayListRenderer::finishRecording() {
+    mShaderMap.clear();
+    mPaintMap.clear();
+    mRegionMap.clear();
+    mPathMap.clear();
+    DisplayListData* data = mDisplayListData;
+    mDisplayListData = 0;
+    return data;
 }
 
 void DisplayListRenderer::setViewport(int width, int height) {
@@ -120,6 +65,11 @@
 
 status_t DisplayListRenderer::prepareDirty(float left, float top,
         float right, float bottom, bool opaque) {
+
+    LOG_ALWAYS_FATAL_IF(mDisplayListData,
+            "prepareDirty called a second time during a recording!");
+    mDisplayListData = new DisplayListData();
+
     initializeSaveStack(0, 0, getWidth(), getHeight());
 
     mDirtyClip = opaque;
@@ -142,7 +92,7 @@
 status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
     // Ignore dirty during recording, it matters only when we replay
     addDrawOp(new (alloc()) DrawFunctorOp(functor));
-    mFunctorCount++;
+    mDisplayListData->functorCount++;
     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
 }
 
@@ -501,7 +451,7 @@
         op->setQuickRejected(rejected);
     }
 
-    mHasDrawOps = true;
+    mDisplayListData->hasDrawOps = true;
     addOpInternal(op);
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 7e62c5d..6c11e59 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -61,7 +61,7 @@
     ANDROID_API DisplayListRenderer();
     virtual ~DisplayListRenderer();
 
-    ANDROID_API DisplayList* getDisplayList(DisplayList* displayList);
+    ANDROID_API DisplayListData* finishRecording();
 
     virtual bool isRecording() const { return true; }
 
@@ -162,59 +162,6 @@
     // TODO: rename for consistency
     virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
 
-// ----------------------------------------------------------------------------
-// DisplayList / resource management
-// ----------------------------------------------------------------------------
-    ANDROID_API void reset();
-
-    sp<DisplayListData> getDisplayListData() const {
-        return mDisplayListData;
-    }
-
-    const Vector<const SkBitmap*>& getBitmapResources() const {
-        return mBitmapResources;
-    }
-
-    const Vector<const SkBitmap*>& getOwnedBitmapResources() const {
-        return mOwnedBitmapResources;
-    }
-
-    const Vector<const Res_png_9patch*>& getPatchResources() const {
-        return mPatchResources;
-    }
-
-    const Vector<SkiaShader*>& getShaders() const {
-        return mShaders;
-    }
-
-    const Vector<const SkPaint*>& getPaints() const {
-        return mPaints;
-    }
-
-    const Vector<const SkPath*>& getPaths() const {
-        return mPaths;
-    }
-
-    const SortedVector<const SkPath*>& getSourcePaths() const {
-        return mSourcePaths;
-    }
-
-    const Vector<const SkRegion*>& getRegions() const {
-        return mRegions;
-    }
-
-    const Vector<Layer*>& getLayers() const {
-        return mLayers;
-    }
-
-    const Vector<const SkMatrix*>& getMatrices() const {
-        return mMatrices;
-    }
-
-    uint32_t getFunctorCount() const {
-        return mFunctorCount;
-    }
-
 private:
     void insertRestoreToCount();
     void insertTranslate();
@@ -252,11 +199,11 @@
             pathCopy = newPathCopy;
             // replaceValueFor() performs an add if the entry doesn't exist
             mPathMap.replaceValueFor(path, pathCopy);
-            mPaths.add(pathCopy);
+            mDisplayListData->paths.add(pathCopy);
         }
-        if (mSourcePaths.indexOf(path) < 0) {
+        if (mDisplayListData->sourcePaths.indexOf(path) < 0) {
             mCaches.resourceCache.incrementRefcount(path);
-            mSourcePaths.add(path);
+            mDisplayListData->sourcePaths.add(path);
         }
         return pathCopy;
     }
@@ -271,7 +218,7 @@
             paintCopy = new SkPaint(*paint);
             // replaceValueFor() performs an add if the entry doesn't exist
             mPaintMap.replaceValueFor(paint, paintCopy);
-            mPaints.add(paintCopy);
+            mDisplayListData->paints.add(paintCopy);
         }
 
         return paintCopy;
@@ -288,7 +235,7 @@
             regionCopy = new SkRegion(*region);
             // replaceValueFor() performs an add if the entry doesn't exist
             mRegionMap.replaceValueFor(region, regionCopy);
-            mRegions.add(regionCopy);
+            mDisplayListData->regions.add(regionCopy);
         }
 
         return regionCopy;
@@ -299,14 +246,14 @@
             // Copying the matrix is cheap and prevents against the user changing
             // the original matrix before the operation that uses it
             const SkMatrix* copy = new SkMatrix(*matrix);
-            mMatrices.add(copy);
+            mDisplayListData->matrices.add(copy);
             return copy;
         }
         return matrix;
     }
 
     inline Layer* refLayer(Layer* layer) {
-        mLayers.add(layer);
+        mDisplayListData->layers.add(layer);
         mCaches.resourceCache.incrementRefcount(layer);
         return layer;
     }
@@ -316,13 +263,13 @@
         // correctly, such as creating the bitmap from scratch, drawing with it, changing its
         // contents, and drawing again. The only fix would be to always copy it the first time,
         // which doesn't seem worth the extra cycles for this unlikely case.
-        mBitmapResources.add(bitmap);
+        mDisplayListData->bitmapResources.add(bitmap);
         mCaches.resourceCache.incrementRefcount(bitmap);
         return bitmap;
     }
 
     inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) {
-        mOwnedBitmapResources.add(bitmap);
+        mDisplayListData->ownedBitmapResources.add(bitmap);
         mCaches.resourceCache.incrementRefcount(bitmap);
         return bitmap;
     }
@@ -336,52 +283,31 @@
             shaderCopy = shader->copy();
             // replaceValueFor() performs an add if the entry doesn't exist
             mShaderMap.replaceValueFor(shader, shaderCopy);
-            mShaders.add(shaderCopy);
+            mDisplayListData->shaders.add(shaderCopy);
             mCaches.resourceCache.incrementRefcount(shaderCopy);
         }
         return shaderCopy;
     }
 
     inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
-        mPatchResources.add(patch);
+        mDisplayListData->patchResources.add(patch);
         mCaches.resourceCache.incrementRefcount(patch);
         return patch;
     }
 
-    // TODO: move these to DisplayListData
-    Vector<const SkBitmap*> mBitmapResources;
-    Vector<const SkBitmap*> mOwnedBitmapResources;
-    Vector<const Res_png_9patch*> mPatchResources;
-
-    Vector<const SkPaint*> mPaints;
     DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
-
-    Vector<const SkPath*> mPaths;
     DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
-
-    SortedVector<const SkPath*> mSourcePaths;
-
-    Vector<const SkRegion*> mRegions;
     DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
-
-    Vector<SkiaShader*> mShaders;
     DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
 
-    Vector<const SkMatrix*> mMatrices;
-
-    Vector<Layer*> mLayers;
-
     int mRestoreSaveCount;
 
     Caches& mCaches;
-    sp<DisplayListData> mDisplayListData;
+    DisplayListData* mDisplayListData;
 
     float mTranslateX;
     float mTranslateY;
     bool mHasTranslate;
-    bool mHasDrawOps;
-
-    uint32_t mFunctorCount;
 
     friend class DisplayList;
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index fe781bd..0568851 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -373,6 +373,10 @@
     mCanvas->setViewport(width, height);
 }
 
+void CanvasContext::swapDisplayListData(DisplayList* displayList, DisplayListData* newData) {
+    displayList->setData(newData);
+}
+
 void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
     mGlobalContext->makeCurrent(mEglSurface);
     for (size_t i = 0; i < layerUpdaters->size(); i++) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 5fac582..2c9348c 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -32,6 +32,7 @@
 
 class DeferredLayerUpdater;
 class DisplayList;
+class DisplayListData;
 class OpenGLRenderer;
 class Rect;
 
@@ -62,6 +63,7 @@
     bool initialize(EGLNativeWindowType window);
     void updateSurface(EGLNativeWindowType window);
     void setup(int width, int height);
+    void swapDisplayListData(DisplayList* displayList, DisplayListData* newData);
     void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
     void drawDisplayList(DisplayList* displayList, Rect* dirty);
     void destroyCanvas();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 0c667fd..c3bf404 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -117,6 +117,20 @@
     post(task);
 }
 
+CREATE_BRIDGE3(swapDisplayListData, CanvasContext* context, DisplayList* displayList,
+        DisplayListData* newData) {
+    args->context->swapDisplayListData(args->displayList, args->newData);
+    return NULL;
+}
+
+void RenderProxy::swapDisplayListData(DisplayList* displayList, DisplayListData* newData) {
+    SETUP_TASK(swapDisplayListData);
+    args->context = mContext;
+    args->displayList = displayList;
+    args->newData = newData;
+    post(task);
+}
+
 CREATE_BRIDGE4(drawDisplayList, CanvasContext* context, DisplayList* displayList,
         Rect dirty, const Vector<DeferredLayerUpdater*>* layerUpdates) {
     Rect* dirty = &args->dirty;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 8ff3d63..0934b98 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -33,6 +33,7 @@
 
 class DeferredLayerUpdater;
 class DisplayList;
+class DisplayListData;
 class Layer;
 class Rect;
 
@@ -59,6 +60,7 @@
     ANDROID_API bool initialize(EGLNativeWindowType window);
     ANDROID_API void updateSurface(EGLNativeWindowType window);
     ANDROID_API void setup(int width, int height);
+    ANDROID_API void swapDisplayListData(DisplayList* displayList, DisplayListData* newData);
     ANDROID_API void drawDisplayList(DisplayList* displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     ANDROID_API void destroyCanvas();