Move DisplayList to its own cpp file

Change-Id: Ic9c1bbf4673ad5c756f3908b2ab7e699edd6a119
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 6bc7aef..db64c99 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -11,6 +11,7 @@
 		FontRenderer.cpp \
 		GammaFontRenderer.cpp \
 		Caches.cpp \
+		DisplayList.cpp \
 		DisplayListLogBuffer.cpp \
 		DisplayListRenderer.cpp \
 		Dither.cpp \
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
new file mode 100644
index 0000000..a52ea98
--- /dev/null
+++ b/libs/hwui/DisplayList.cpp
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DisplayList.h"
+#include "DisplayListOp.h"
+#include "DisplayListLogBuffer.h"
+
+namespace android {
+namespace uirenderer {
+
+void DisplayList::outputLogBuffer(int fd) {
+    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+    if (logBuffer.isEmpty()) {
+        return;
+    }
+
+    FILE *file = fdopen(fd, "a");
+
+    fprintf(file, "\nRecent DisplayList operations\n");
+    logBuffer.outputCommands(file);
+
+    String8 cachesLog;
+    Caches::getInstance().dumpMemoryUsage(cachesLog);
+    fprintf(file, "\nCaches:\n%s", cachesLog.string());
+    fprintf(file, "\n");
+
+    fflush(file);
+}
+
+DisplayList::DisplayList(const DisplayListRenderer& recorder) :
+    mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
+    mStaticMatrix(NULL), mAnimationMatrix(NULL) {
+
+    initFromDisplayListRenderer(recorder);
+}
+
+DisplayList::~DisplayList() {
+    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++) {
+        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
+        caches.resourceCache.decrementRefcountLocked(bitmap);
+        caches.resourceCache.destructorLocked(bitmap);
+    }
+
+    for (size_t i = 0; i < mFilterResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mFilterResources.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++) {
+        SkPath* path = mPaths.itemAt(i);
+        caches.pathCache.remove(path);
+        delete path;
+    }
+
+    for (size_t i = 0; i < mMatrices.size(); i++) {
+        delete mMatrices.itemAt(i);
+    }
+
+    mBitmapResources.clear();
+    mOwnedBitmapResources.clear();
+    mFilterResources.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<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
+    for (size_t i = 0; i < bitmapResources.size(); i++) {
+        SkBitmap* resource = bitmapResources.itemAt(i);
+        mBitmapResources.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
+    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
+    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
+        SkBitmap* resource = ownedBitmapResources.itemAt(i);
+        mOwnedBitmapResources.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
+    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
+    for (size_t i = 0; i < filterResources.size(); i++) {
+        SkiaColorFilter* resource = filterResources.itemAt(i);
+        mFilterResources.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<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;
+    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() {
+    return mSize;
+}
+
+/**
+ * This function is a simplified version of replay(), where we simply retrieve and log the
+ * display list. This function should remain in sync with the replay() function.
+ */
+void DisplayList::output(uint32_t level) {
+    ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this,
+            mName.string(), isRenderable());
+
+    ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+    outputViewProperties(level);
+    int flags = DisplayListOp::kOpLogFlag_Recurse;
+    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
+        mDisplayListData->displayListOps[i]->output(level, flags);
+    }
+    ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string());
+}
+
+void DisplayList::updateMatrix() {
+    if (mMatrixDirty) {
+        if (!mTransformMatrix) {
+            mTransformMatrix = new SkMatrix();
+        }
+        if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
+            mTransformMatrix->reset();
+        } else {
+            if (!mPivotExplicitlySet) {
+                if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
+                    mPrevWidth = mWidth;
+                    mPrevHeight = mHeight;
+                    mPivotX = mPrevWidth / 2;
+                    mPivotY = mPrevHeight / 2;
+                }
+            }
+            if ((mMatrixFlags & ROTATION_3D) == 0) {
+                mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
+                mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
+                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+            } else {
+                if (!mTransformCamera) {
+                    mTransformCamera = new Sk3DView();
+                    mTransformMatrix3D = new SkMatrix();
+                }
+                mTransformMatrix->reset();
+                mTransformCamera->save();
+                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+                mTransformCamera->rotateX(mRotationX);
+                mTransformCamera->rotateY(mRotationY);
+                mTransformCamera->rotateZ(-mRotation);
+                mTransformCamera->getMatrix(mTransformMatrix3D);
+                mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
+                mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
+                        mPivotY + mTranslationY);
+                mTransformMatrix->postConcat(*mTransformMatrix3D);
+                mTransformCamera->restore();
+            }
+        }
+        mMatrixDirty = false;
+    }
+}
+
+void DisplayList::outputViewProperties(uint32_t level) {
+    updateMatrix();
+    if (mLeft != 0 || mTop != 0) {
+        ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
+    }
+    if (mStaticMatrix) {
+        ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING,
+                level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix));
+    }
+    if (mAnimationMatrix) {
+        ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING,
+                level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix));
+    }
+    if (mMatrixFlags != 0) {
+        if (mMatrixFlags == TRANSLATION) {
+            ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY);
+        } else {
+            ALOGD("%*sConcatMatrix %p: " MATRIX_STRING,
+                    level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix));
+        }
+    }
+    if (mAlpha < 1 && !mCaching) {
+        if (!mHasOverlappingRendering) {
+            ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha);
+        } else {
+            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+            if (mClipChildren) {
+                flags |= SkCanvas::kClipToLayer_SaveFlag;
+            }
+            ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
+                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+                    mMultipliedAlpha, flags);
+        }
+    }
+    if (mClipChildren && !mCaching) {
+        ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
+                (float) mRight - mLeft, (float) mBottom - mTop);
+    }
+}
+
+void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
+#if DEBUG_DISPLAYLIST
+    outputViewProperties(level);
+#endif
+    updateMatrix();
+    if (mLeft != 0 || mTop != 0) {
+        renderer.translate(mLeft, mTop);
+    }
+    if (mStaticMatrix) {
+        renderer.concatMatrix(mStaticMatrix);
+    } else if (mAnimationMatrix) {
+        renderer.concatMatrix(mAnimationMatrix);
+    }
+    if (mMatrixFlags != 0) {
+        if (mMatrixFlags == TRANSLATION) {
+            renderer.translate(mTranslationX, mTranslationY);
+        } else {
+            renderer.concatMatrix(mTransformMatrix);
+        }
+    }
+    if (mAlpha < 1 && !mCaching) {
+        if (!mHasOverlappingRendering) {
+            renderer.setAlpha(mAlpha);
+        } else {
+            // TODO: should be able to store the size of a DL at record time and not
+            // have to pass it into this call. In fact, this information might be in the
+            // location/size info that we store with the new native transform data.
+            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+            if (mClipChildren) {
+                flags |= SkCanvas::kClipToLayer_SaveFlag;
+            }
+            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
+                    mMultipliedAlpha, flags);
+        }
+    }
+    if (mClipChildren && !mCaching) {
+        renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
+                SkRegion::kIntersect_Op);
+    }
+}
+
+status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
+    status_t drawGlStatus = DrawGlInfo::kStatusDone;
+
+#if DEBUG_DISPLAY_LIST
+    Rect* clipRect = renderer.getClipRect();
+    DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
+            (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
+            clipRect->right, clipRect->bottom);
+#endif
+
+    renderer.startMark(mName.string());
+
+    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+    DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
+            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
+    setViewProperties(renderer, level);
+
+    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
+        DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
+        renderer.restoreToCount(restoreTo);
+        renderer.endMark();
+        return drawGlStatus;
+    }
+
+    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+    int saveCount = renderer.getSaveCount() - 1;
+    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
+        DisplayListOp *op = mDisplayListData->displayListOps[i];
+#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
+        Caches::getInstance().eventMark(strlen(op->name()), op->name());
+#endif
+
+        drawGlStatus |= op->replay(renderer, dirty, flags,
+                saveCount, level, mCaching, mMultipliedAlpha);
+        logBuffer.writeCommand(level, op->name());
+    }
+
+    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
+    renderer.restoreToCount(restoreTo);
+    renderer.endMark();
+
+    DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
+            drawGlStatus);
+    return drawGlStatus;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
new file mode 100644
index 0000000..70a9755
--- /dev/null
+++ b/libs/hwui/DisplayList.h
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_DISPLAY_LIST_H
+#define ANDROID_HWUI_DISPLAY_LIST_H
+
+#include <SkCamera.h>
+#include <SkMatrix.h>
+
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <cutils/compiler.h>
+
+#include "utils/LinearAllocator.h"
+
+#include "Debug.h"
+
+#define TRANSLATION 0x0001
+#define ROTATION    0x0002
+#define ROTATION_3D 0x0004
+#define SCALE       0x0008
+#define PIVOT       0x0010
+
+class SkBitmap;
+class SkPaint;
+class SkPath;
+class SkRegion;
+
+namespace android {
+namespace uirenderer {
+
+class DisplayListOp;
+class DisplayListRenderer;
+class OpenGLRenderer;
+class Rect;
+class Layer;
+class SkiaColorFilter;
+class SkiaShader;
+
+/**
+ * Refcounted structure that holds data used in display list stream
+ */
+class DisplayListData: public LightRefBase<DisplayListData> {
+public:
+    LinearAllocator allocator;
+    Vector<DisplayListOp*> displayListOps;
+};
+
+/**
+ * Replays recorded drawing commands.
+ */
+class DisplayList {
+public:
+    DisplayList(const DisplayListRenderer& recorder);
+    ANDROID_API ~DisplayList();
+
+    // See flags defined in DisplayList.java
+    enum ReplayFlag {
+        kReplayFlag_ClipChildren = 0x1
+    };
+
+    void setViewProperties(OpenGLRenderer& renderer, uint32_t level);
+    void outputViewProperties(uint32_t level);
+
+    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);
+
+    status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0);
+
+    void output(uint32_t level = 0);
+
+    ANDROID_API void reset();
+
+    void setRenderable(bool renderable) {
+        mIsRenderable = renderable;
+    }
+
+    bool isRenderable() const {
+        return mIsRenderable;
+    }
+
+    void setName(const char* name) {
+        if (name) {
+            mName.setTo(name);
+        }
+    }
+
+    void setClipChildren(bool clipChildren) {
+        mClipChildren = clipChildren;
+    }
+
+    void setStaticMatrix(SkMatrix* matrix) {
+        delete mStaticMatrix;
+        mStaticMatrix = new SkMatrix(*matrix);
+    }
+
+    void setAnimationMatrix(SkMatrix* matrix) {
+        delete mAnimationMatrix;
+        if (matrix) {
+            mAnimationMatrix = new SkMatrix(*matrix);
+        } else {
+            mAnimationMatrix = NULL;
+        }
+    }
+
+    void setAlpha(float alpha) {
+        alpha = fminf(1.0f, fmaxf(0.0f, alpha));
+        if (alpha != mAlpha) {
+            mAlpha = alpha;
+            mMultipliedAlpha = (int) (255 * alpha);
+        }
+    }
+
+    void setHasOverlappingRendering(bool hasOverlappingRendering) {
+        mHasOverlappingRendering = hasOverlappingRendering;
+    }
+
+    void setTranslationX(float translationX) {
+        if (translationX != mTranslationX) {
+            mTranslationX = translationX;
+            mMatrixDirty = true;
+            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
+                mMatrixFlags &= ~TRANSLATION;
+            } else {
+                mMatrixFlags |= TRANSLATION;
+            }
+        }
+    }
+
+    void setTranslationY(float translationY) {
+        if (translationY != mTranslationY) {
+            mTranslationY = translationY;
+            mMatrixDirty = true;
+            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
+                mMatrixFlags &= ~TRANSLATION;
+            } else {
+                mMatrixFlags |= TRANSLATION;
+            }
+        }
+    }
+
+    void setRotation(float rotation) {
+        if (rotation != mRotation) {
+            mRotation = rotation;
+            mMatrixDirty = true;
+            if (mRotation == 0.0f) {
+                mMatrixFlags &= ~ROTATION;
+            } else {
+                mMatrixFlags |= ROTATION;
+            }
+        }
+    }
+
+    void setRotationX(float rotationX) {
+        if (rotationX != mRotationX) {
+            mRotationX = rotationX;
+            mMatrixDirty = true;
+            if (mRotationX == 0.0f && mRotationY == 0.0f) {
+                mMatrixFlags &= ~ROTATION_3D;
+            } else {
+                mMatrixFlags |= ROTATION_3D;
+            }
+        }
+    }
+
+    void setRotationY(float rotationY) {
+        if (rotationY != mRotationY) {
+            mRotationY = rotationY;
+            mMatrixDirty = true;
+            if (mRotationX == 0.0f && mRotationY == 0.0f) {
+                mMatrixFlags &= ~ROTATION_3D;
+            } else {
+                mMatrixFlags |= ROTATION_3D;
+            }
+        }
+    }
+
+    void setScaleX(float scaleX) {
+        if (scaleX != mScaleX) {
+            mScaleX = scaleX;
+            mMatrixDirty = true;
+            if (mScaleX == 1.0f && mScaleY == 1.0f) {
+                mMatrixFlags &= ~SCALE;
+            } else {
+                mMatrixFlags |= SCALE;
+            }
+        }
+    }
+
+    void setScaleY(float scaleY) {
+        if (scaleY != mScaleY) {
+            mScaleY = scaleY;
+            mMatrixDirty = true;
+            if (mScaleX == 1.0f && mScaleY == 1.0f) {
+                mMatrixFlags &= ~SCALE;
+            } else {
+                mMatrixFlags |= SCALE;
+            }
+        }
+    }
+
+    void setPivotX(float pivotX) {
+        mPivotX = pivotX;
+        mMatrixDirty = true;
+        if (mPivotX == 0.0f && mPivotY == 0.0f) {
+            mMatrixFlags &= ~PIVOT;
+        } else {
+            mMatrixFlags |= PIVOT;
+        }
+        mPivotExplicitlySet = true;
+    }
+
+    void setPivotY(float pivotY) {
+        mPivotY = pivotY;
+        mMatrixDirty = true;
+        if (mPivotX == 0.0f && mPivotY == 0.0f) {
+            mMatrixFlags &= ~PIVOT;
+        } else {
+            mMatrixFlags |= PIVOT;
+        }
+        mPivotExplicitlySet = true;
+    }
+
+    void setCameraDistance(float distance) {
+        if (distance != mCameraDistance) {
+            mCameraDistance = distance;
+            mMatrixDirty = true;
+            if (!mTransformCamera) {
+                mTransformCamera = new Sk3DView();
+                mTransformMatrix3D = new SkMatrix();
+            }
+            mTransformCamera->setCameraLocation(0, 0, distance);
+        }
+    }
+
+    void setLeft(int left) {
+        if (left != mLeft) {
+            mLeft = left;
+            mWidth = mRight - mLeft;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void setTop(int top) {
+        if (top != mTop) {
+            mTop = top;
+            mHeight = mBottom - mTop;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void setRight(int right) {
+        if (right != mRight) {
+            mRight = right;
+            mWidth = mRight - mLeft;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void setBottom(int bottom) {
+        if (bottom != mBottom) {
+            mBottom = bottom;
+            mHeight = mBottom - mTop;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void setLeftTop(int left, int top) {
+        if (left != mLeft || top != mTop) {
+            mLeft = left;
+            mTop = top;
+            mWidth = mRight - mLeft;
+            mHeight = mBottom - mTop;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
+            mLeft = left;
+            mTop = top;
+            mRight = right;
+            mBottom = bottom;
+            mWidth = mRight - mLeft;
+            mHeight = mBottom - mTop;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void offsetLeftRight(int offset) {
+        if (offset != 0) {
+            mLeft += offset;
+            mRight += offset;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void offsetTopBottom(int offset) {
+        if (offset != 0) {
+            mTop += offset;
+            mBottom += offset;
+            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+                mMatrixDirty = true;
+            }
+        }
+    }
+
+    void setCaching(bool caching) {
+        mCaching = caching;
+    }
+
+    int getWidth() {
+        return mWidth;
+    }
+
+    int getHeight() {
+        return mHeight;
+    }
+
+private:
+    void init();
+
+    void clearResources();
+
+    void updateMatrix();
+
+    class TextContainer {
+    public:
+        size_t length() const {
+            return mByteLength;
+        }
+
+        const char* text() const {
+            return (const char*) mText;
+        }
+
+        size_t mByteLength;
+        const char* mText;
+    };
+
+    Vector<SkBitmap*> mBitmapResources;
+    Vector<SkBitmap*> mOwnedBitmapResources;
+    Vector<SkiaColorFilter*> mFilterResources;
+
+    Vector<SkPaint*> mPaints;
+    Vector<SkPath*> mPaths;
+    SortedVector<SkPath*> mSourcePaths;
+    Vector<SkRegion*> mRegions;
+    Vector<SkMatrix*> mMatrices;
+    Vector<SkiaShader*> mShaders;
+    Vector<Layer*> mLayers;
+
+    sp<DisplayListData> mDisplayListData;
+
+    size_t mSize;
+
+    bool mIsRenderable;
+    uint32_t mFunctorCount;
+
+    String8 mName;
+
+    // View properties
+    bool mClipChildren;
+    float mAlpha;
+    int mMultipliedAlpha;
+    bool mHasOverlappingRendering;
+    float mTranslationX, mTranslationY;
+    float mRotation, mRotationX, mRotationY;
+    float mScaleX, mScaleY;
+    float mPivotX, mPivotY;
+    float mCameraDistance;
+    int mLeft, mTop, mRight, mBottom;
+    int mWidth, mHeight;
+    int mPrevWidth, mPrevHeight;
+    bool mPivotExplicitlySet;
+    bool mMatrixDirty;
+    bool mMatrixIsIdentity;
+    uint32_t mMatrixFlags;
+    SkMatrix* mTransformMatrix;
+    Sk3DView* mTransformCamera;
+    SkMatrix* mTransformMatrix3D;
+    SkMatrix* mStaticMatrix;
+    SkMatrix* mAnimationMatrix;
+    bool mCaching;
+}; // class DisplayList
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_OPENGL_RENDERER_H
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6425b43..78b432c 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -19,6 +19,8 @@
 
 #include <SkXfermode.h>
 
+#include <private/hwui/DrawGlInfo.h>
+
 #include "OpenGLRenderer.h"
 #include "DisplayListRenderer.h"
 #include "utils/LinearAllocator.h"
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 17ed8ac..31291b1 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -20,6 +20,7 @@
 
 #include <private/hwui/DrawGlInfo.h>
 
+#include "DisplayList.h"
 #include "DisplayListLogBuffer.h"
 #include "DisplayListOp.h"
 #include "DisplayListRenderer.h"
@@ -28,425 +29,6 @@
 namespace android {
 namespace uirenderer {
 
-///////////////////////////////////////////////////////////////////////////////
-// Display list
-///////////////////////////////////////////////////////////////////////////////
-
-void DisplayList::outputLogBuffer(int fd) {
-    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
-    if (logBuffer.isEmpty()) {
-        return;
-    }
-
-    FILE *file = fdopen(fd, "a");
-
-    fprintf(file, "\nRecent DisplayList operations\n");
-    logBuffer.outputCommands(file);
-
-    String8 cachesLog;
-    Caches::getInstance().dumpMemoryUsage(cachesLog);
-    fprintf(file, "\nCaches:\n%s", cachesLog.string());
-    fprintf(file, "\n");
-
-    fflush(file);
-}
-
-DisplayList::DisplayList(const DisplayListRenderer& recorder) :
-    mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
-    mStaticMatrix(NULL), mAnimationMatrix(NULL) {
-
-    initFromDisplayListRenderer(recorder);
-}
-
-DisplayList::~DisplayList() {
-    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++) {
-        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcountLocked(bitmap);
-        caches.resourceCache.destructorLocked(bitmap);
-    }
-
-    for (size_t i = 0; i < mFilterResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mFilterResources.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++) {
-        SkPath* path = mPaths.itemAt(i);
-        caches.pathCache.remove(path);
-        delete path;
-    }
-
-    for (size_t i = 0; i < mMatrices.size(); i++) {
-        delete mMatrices.itemAt(i);
-    }
-
-    mBitmapResources.clear();
-    mOwnedBitmapResources.clear();
-    mFilterResources.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<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
-    for (size_t i = 0; i < bitmapResources.size(); i++) {
-        SkBitmap* resource = bitmapResources.itemAt(i);
-        mBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
-    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
-        SkBitmap* resource = ownedBitmapResources.itemAt(i);
-        mOwnedBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
-    for (size_t i = 0; i < filterResources.size(); i++) {
-        SkiaColorFilter* resource = filterResources.itemAt(i);
-        mFilterResources.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<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;
-    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() {
-    return mSize;
-}
-
-/**
- * This function is a simplified version of replay(), where we simply retrieve and log the
- * display list. This function should remain in sync with the replay() function.
- */
-void DisplayList::output(uint32_t level) {
-    ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this,
-            mName.string(), isRenderable());
-
-    ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
-    outputViewProperties(level);
-    int flags = DisplayListOp::kOpLogFlag_Recurse;
-    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
-        mDisplayListData->displayListOps[i]->output(level, flags);
-    }
-    ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string());
-}
-
-void DisplayList::updateMatrix() {
-    if (mMatrixDirty) {
-        if (!mTransformMatrix) {
-            mTransformMatrix = new SkMatrix();
-        }
-        if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
-            mTransformMatrix->reset();
-        } else {
-            if (!mPivotExplicitlySet) {
-                if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
-                    mPrevWidth = mWidth;
-                    mPrevHeight = mHeight;
-                    mPivotX = mPrevWidth / 2;
-                    mPivotY = mPrevHeight / 2;
-                }
-            }
-            if ((mMatrixFlags & ROTATION_3D) == 0) {
-                mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
-                mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
-                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
-            } else {
-                if (!mTransformCamera) {
-                    mTransformCamera = new Sk3DView();
-                    mTransformMatrix3D = new SkMatrix();
-                }
-                mTransformMatrix->reset();
-                mTransformCamera->save();
-                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
-                mTransformCamera->rotateX(mRotationX);
-                mTransformCamera->rotateY(mRotationY);
-                mTransformCamera->rotateZ(-mRotation);
-                mTransformCamera->getMatrix(mTransformMatrix3D);
-                mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
-                mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
-                        mPivotY + mTranslationY);
-                mTransformMatrix->postConcat(*mTransformMatrix3D);
-                mTransformCamera->restore();
-            }
-        }
-        mMatrixDirty = false;
-    }
-}
-
-void DisplayList::outputViewProperties(uint32_t level) {
-    updateMatrix();
-    if (mLeft != 0 || mTop != 0) {
-        ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
-    }
-    if (mStaticMatrix) {
-        ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING,
-                level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix));
-    }
-    if (mAnimationMatrix) {
-        ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING,
-                level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix));
-    }
-    if (mMatrixFlags != 0) {
-        if (mMatrixFlags == TRANSLATION) {
-            ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY);
-        } else {
-            ALOGD("%*sConcatMatrix %p: " MATRIX_STRING,
-                    level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix));
-        }
-    }
-    if (mAlpha < 1 && !mCaching) {
-        if (!mHasOverlappingRendering) {
-            ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha);
-        } else {
-            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
-            if (mClipChildren) {
-                flags |= SkCanvas::kClipToLayer_SaveFlag;
-            }
-            ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
-                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
-                    mMultipliedAlpha, flags);
-        }
-    }
-    if (mClipChildren && !mCaching) {
-        ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
-                (float) mRight - mLeft, (float) mBottom - mTop);
-    }
-}
-
-void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
-#if DEBUG_DISPLAYLIST
-    outputViewProperties(level);
-#endif
-    updateMatrix();
-    if (mLeft != 0 || mTop != 0) {
-        renderer.translate(mLeft, mTop);
-    }
-    if (mStaticMatrix) {
-        renderer.concatMatrix(mStaticMatrix);
-    } else if (mAnimationMatrix) {
-        renderer.concatMatrix(mAnimationMatrix);
-    }
-    if (mMatrixFlags != 0) {
-        if (mMatrixFlags == TRANSLATION) {
-            renderer.translate(mTranslationX, mTranslationY);
-        } else {
-            renderer.concatMatrix(mTransformMatrix);
-        }
-    }
-    if (mAlpha < 1 && !mCaching) {
-        if (!mHasOverlappingRendering) {
-            renderer.setAlpha(mAlpha);
-        } else {
-            // TODO: should be able to store the size of a DL at record time and not
-            // have to pass it into this call. In fact, this information might be in the
-            // location/size info that we store with the new native transform data.
-            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
-            if (mClipChildren) {
-                flags |= SkCanvas::kClipToLayer_SaveFlag;
-            }
-            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
-                    mMultipliedAlpha, flags);
-        }
-    }
-    if (mClipChildren && !mCaching) {
-        renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
-                SkRegion::kIntersect_Op);
-    }
-}
-
-status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
-    status_t drawGlStatus = DrawGlInfo::kStatusDone;
-
-#if DEBUG_DISPLAY_LIST
-    Rect* clipRect = renderer.getClipRect();
-    DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
-            (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
-            clipRect->right, clipRect->bottom);
-#endif
-
-    renderer.startMark(mName.string());
-
-    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
-    DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
-            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
-    setViewProperties(renderer, level);
-
-    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
-        DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
-        renderer.restoreToCount(restoreTo);
-        renderer.endMark();
-        return drawGlStatus;
-    }
-
-    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
-    int saveCount = renderer.getSaveCount() - 1;
-    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
-        DisplayListOp *op = mDisplayListData->displayListOps[i];
-#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
-        Caches::getInstance().eventMark(strlen(op->name()), op->name());
-#endif
-
-        drawGlStatus |= op->replay(renderer, dirty, flags,
-                saveCount, level, mCaching, mMultipliedAlpha);
-        logBuffer.writeCommand(level, op->name());
-    }
-
-    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
-    renderer.restoreToCount(restoreTo);
-    renderer.endMark();
-
-    DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
-            drawGlStatus);
-    return drawGlStatus;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Base structure
-///////////////////////////////////////////////////////////////////////////////
-
 DisplayListRenderer::DisplayListRenderer():
         mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
         mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b25288b..97a2508 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -17,21 +17,14 @@
 #ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
 #define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
 
-#include <SkChunkAlloc.h>
-#include <SkFlattenable.h>
 #include <SkMatrix.h>
-#include <SkCamera.h>
 #include <SkPaint.h>
 #include <SkPath.h>
-#include <SkRefCnt.h>
-#include <SkTDArray.h>
-#include <SkTSearch.h>
-
 #include <cutils/compiler.h>
 
+#include "DisplayList.h"
 #include "DisplayListLogBuffer.h"
 #include "OpenGLRenderer.h"
-#include "utils/LinearAllocator.h"
 
 namespace android {
 namespace uirenderer {
@@ -50,12 +43,6 @@
     #define DISPLAY_LIST_LOGD(...)
 #endif
 
-#define TRANSLATION 0x0001
-#define ROTATION    0x0002
-#define ROTATION_3D 0x0004
-#define SCALE       0x0008
-#define PIVOT       0x0010
-
 ///////////////////////////////////////////////////////////////////////////////
 // Display list
 ///////////////////////////////////////////////////////////////////////////////
@@ -65,370 +52,6 @@
 class DrawOp;
 class StateOp;
 
-/**
- * Refcounted structure that holds data used in display list stream
- */
-class DisplayListData: public LightRefBase<DisplayListData> {
-public:
-    LinearAllocator allocator;
-    Vector<DisplayListOp*> displayListOps;
-};
-
-/**
- * Replays recorded drawing commands.
- */
-class DisplayList {
-public:
-    DisplayList(const DisplayListRenderer& recorder);
-    ANDROID_API ~DisplayList();
-
-    // See flags defined in DisplayList.java
-    enum ReplayFlag {
-        kReplayFlag_ClipChildren = 0x1
-    };
-
-    void setViewProperties(OpenGLRenderer& renderer, uint32_t level);
-    void outputViewProperties(uint32_t level);
-
-    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);
-
-    status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0);
-
-    void output(uint32_t level = 0);
-
-    ANDROID_API void reset();
-
-    void setRenderable(bool renderable) {
-        mIsRenderable = renderable;
-    }
-
-    bool isRenderable() const {
-        return mIsRenderable;
-    }
-
-    void setName(const char* name) {
-        if (name) {
-            mName.setTo(name);
-        }
-    }
-
-    void setClipChildren(bool clipChildren) {
-        mClipChildren = clipChildren;
-    }
-
-    void setStaticMatrix(SkMatrix* matrix) {
-        delete mStaticMatrix;
-        mStaticMatrix = new SkMatrix(*matrix);
-    }
-
-    void setAnimationMatrix(SkMatrix* matrix) {
-        delete mAnimationMatrix;
-        if (matrix) {
-            mAnimationMatrix = new SkMatrix(*matrix);
-        } else {
-            mAnimationMatrix = NULL;
-        }
-    }
-
-    void setAlpha(float alpha) {
-        alpha = fminf(1.0f, fmaxf(0.0f, alpha));
-        if (alpha != mAlpha) {
-            mAlpha = alpha;
-            mMultipliedAlpha = (int) (255 * alpha);
-        }
-    }
-
-    void setHasOverlappingRendering(bool hasOverlappingRendering) {
-        mHasOverlappingRendering = hasOverlappingRendering;
-    }
-
-    void setTranslationX(float translationX) {
-        if (translationX != mTranslationX) {
-            mTranslationX = translationX;
-            mMatrixDirty = true;
-            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
-                mMatrixFlags &= ~TRANSLATION;
-            } else {
-                mMatrixFlags |= TRANSLATION;
-            }
-        }
-    }
-
-    void setTranslationY(float translationY) {
-        if (translationY != mTranslationY) {
-            mTranslationY = translationY;
-            mMatrixDirty = true;
-            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
-                mMatrixFlags &= ~TRANSLATION;
-            } else {
-                mMatrixFlags |= TRANSLATION;
-            }
-        }
-    }
-
-    void setRotation(float rotation) {
-        if (rotation != mRotation) {
-            mRotation = rotation;
-            mMatrixDirty = true;
-            if (mRotation == 0.0f) {
-                mMatrixFlags &= ~ROTATION;
-            } else {
-                mMatrixFlags |= ROTATION;
-            }
-        }
-    }
-
-    void setRotationX(float rotationX) {
-        if (rotationX != mRotationX) {
-            mRotationX = rotationX;
-            mMatrixDirty = true;
-            if (mRotationX == 0.0f && mRotationY == 0.0f) {
-                mMatrixFlags &= ~ROTATION_3D;
-            } else {
-                mMatrixFlags |= ROTATION_3D;
-            }
-        }
-    }
-
-    void setRotationY(float rotationY) {
-        if (rotationY != mRotationY) {
-            mRotationY = rotationY;
-            mMatrixDirty = true;
-            if (mRotationX == 0.0f && mRotationY == 0.0f) {
-                mMatrixFlags &= ~ROTATION_3D;
-            } else {
-                mMatrixFlags |= ROTATION_3D;
-            }
-        }
-    }
-
-    void setScaleX(float scaleX) {
-        if (scaleX != mScaleX) {
-            mScaleX = scaleX;
-            mMatrixDirty = true;
-            if (mScaleX == 1.0f && mScaleY == 1.0f) {
-                mMatrixFlags &= ~SCALE;
-            } else {
-                mMatrixFlags |= SCALE;
-            }
-        }
-    }
-
-    void setScaleY(float scaleY) {
-        if (scaleY != mScaleY) {
-            mScaleY = scaleY;
-            mMatrixDirty = true;
-            if (mScaleX == 1.0f && mScaleY == 1.0f) {
-                mMatrixFlags &= ~SCALE;
-            } else {
-                mMatrixFlags |= SCALE;
-            }
-        }
-    }
-
-    void setPivotX(float pivotX) {
-        mPivotX = pivotX;
-        mMatrixDirty = true;
-        if (mPivotX == 0.0f && mPivotY == 0.0f) {
-            mMatrixFlags &= ~PIVOT;
-        } else {
-            mMatrixFlags |= PIVOT;
-        }
-        mPivotExplicitlySet = true;
-    }
-
-    void setPivotY(float pivotY) {
-        mPivotY = pivotY;
-        mMatrixDirty = true;
-        if (mPivotX == 0.0f && mPivotY == 0.0f) {
-            mMatrixFlags &= ~PIVOT;
-        } else {
-            mMatrixFlags |= PIVOT;
-        }
-        mPivotExplicitlySet = true;
-    }
-
-    void setCameraDistance(float distance) {
-        if (distance != mCameraDistance) {
-            mCameraDistance = distance;
-            mMatrixDirty = true;
-            if (!mTransformCamera) {
-                mTransformCamera = new Sk3DView();
-                mTransformMatrix3D = new SkMatrix();
-            }
-            mTransformCamera->setCameraLocation(0, 0, distance);
-        }
-    }
-
-    void setLeft(int left) {
-        if (left != mLeft) {
-            mLeft = left;
-            mWidth = mRight - mLeft;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void setTop(int top) {
-        if (top != mTop) {
-            mTop = top;
-            mHeight = mBottom - mTop;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void setRight(int right) {
-        if (right != mRight) {
-            mRight = right;
-            mWidth = mRight - mLeft;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void setBottom(int bottom) {
-        if (bottom != mBottom) {
-            mBottom = bottom;
-            mHeight = mBottom - mTop;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void setLeftTop(int left, int top) {
-        if (left != mLeft || top != mTop) {
-            mLeft = left;
-            mTop = top;
-            mWidth = mRight - mLeft;
-            mHeight = mBottom - mTop;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
-        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
-            mLeft = left;
-            mTop = top;
-            mRight = right;
-            mBottom = bottom;
-            mWidth = mRight - mLeft;
-            mHeight = mBottom - mTop;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void offsetLeftRight(int offset) {
-        if (offset != 0) {
-            mLeft += offset;
-            mRight += offset;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void offsetTopBottom(int offset) {
-        if (offset != 0) {
-            mTop += offset;
-            mBottom += offset;
-            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
-                mMatrixDirty = true;
-            }
-        }
-    }
-
-    void setCaching(bool caching) {
-        mCaching = caching;
-    }
-
-    int getWidth() {
-        return mWidth;
-    }
-
-    int getHeight() {
-        return mHeight;
-    }
-
-private:
-    void init();
-
-    void clearResources();
-
-    void updateMatrix();
-
-    class TextContainer {
-    public:
-        size_t length() const {
-            return mByteLength;
-        }
-
-        const char* text() const {
-            return (const char*) mText;
-        }
-
-        size_t mByteLength;
-        const char* mText;
-    };
-
-    Vector<SkBitmap*> mBitmapResources;
-    Vector<SkBitmap*> mOwnedBitmapResources;
-    Vector<SkiaColorFilter*> mFilterResources;
-
-    Vector<SkPaint*> mPaints;
-    Vector<SkPath*> mPaths;
-    SortedVector<SkPath*> mSourcePaths;
-    Vector<SkRegion*> mRegions;
-    Vector<SkMatrix*> mMatrices;
-    Vector<SkiaShader*> mShaders;
-    Vector<Layer*> mLayers;
-
-    sp<DisplayListData> mDisplayListData;
-
-    size_t mSize;
-
-    bool mIsRenderable;
-    uint32_t mFunctorCount;
-
-    String8 mName;
-
-    // View properties
-    bool mClipChildren;
-    float mAlpha;
-    int mMultipliedAlpha;
-    bool mHasOverlappingRendering;
-    float mTranslationX, mTranslationY;
-    float mRotation, mRotationX, mRotationY;
-    float mScaleX, mScaleY;
-    float mPivotX, mPivotY;
-    float mCameraDistance;
-    int mLeft, mTop, mRight, mBottom;
-    int mWidth, mHeight;
-    int mPrevWidth, mPrevHeight;
-    bool mPivotExplicitlySet;
-    bool mMatrixDirty;
-    bool mMatrixIsIdentity;
-    uint32_t mMatrixFlags;
-    SkMatrix* mTransformMatrix;
-    Sk3DView* mTransformCamera;
-    SkMatrix* mTransformMatrix3D;
-    SkMatrix* mStaticMatrix;
-    SkMatrix* mAnimationMatrix;
-    bool mCaching;
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 // Renderer
 ///////////////////////////////////////////////////////////////////////////////