Add display lists caching.

Change-Id: Iac3a248a81ed8cb076a83ef9d186b8ebba685b4c
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 16b6b56..ee90702 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -22,6 +22,229 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
+// Display list
+///////////////////////////////////////////////////////////////////////////////
+
+DisplayList::DisplayList(const DisplayListRenderer& recorder) {
+    const SkWriter32& writer = recorder.writeStream();
+    init();
+
+    if (writer.size() == 0) {
+        return;
+    }
+
+    size_t size = writer.size();
+    void* buffer = sk_malloc_throw(size);
+    writer.flatten(buffer);
+    mReader.setMemory(buffer, size);
+
+    mRCPlayback.reset(&recorder.mRCRecorder);
+    mRCPlayback.setupBuffer(mReader);
+
+    mTFPlayback.reset(&recorder.mTFRecorder);
+    mTFPlayback.setupBuffer(mReader);
+
+    const SkTDArray<const SkFlatBitmap*>& bitmaps = recorder.getBitmaps();
+    mBitmapCount = bitmaps.count();
+    if (mBitmapCount > 0) {
+        mBitmaps = new SkBitmap[mBitmapCount];
+        for (const SkFlatBitmap** flatBitmapPtr = bitmaps.begin();
+                flatBitmapPtr != bitmaps.end(); flatBitmapPtr++) {
+            const SkFlatBitmap* flatBitmap = *flatBitmapPtr;
+            int index = flatBitmap->index() - 1;
+            flatBitmap->unflatten(&mBitmaps[index], &mRCPlayback);
+        }
+    }
+
+    const SkTDArray<const SkFlatMatrix*>& matrices = recorder.getMatrices();
+    mMatrixCount = matrices.count();
+    if (mMatrixCount > 0) {
+        mMatrices = new SkMatrix[mMatrixCount];
+        for (const SkFlatMatrix** matrixPtr = matrices.begin();
+                matrixPtr != matrices.end(); matrixPtr++) {
+            const SkFlatMatrix* flatMatrix = *matrixPtr;
+            flatMatrix->unflatten(&mMatrices[flatMatrix->index() - 1]);
+        }
+    }
+
+    const SkTDArray<const SkFlatPaint*>& paints = recorder.getPaints();
+    mPaintCount = paints.count();
+    if (mPaintCount > 0) {
+        mPaints = new SkPaint[mPaintCount];
+        for (const SkFlatPaint** flatPaintPtr = paints.begin();
+                flatPaintPtr != paints.end(); flatPaintPtr++) {
+            const SkFlatPaint* flatPaint = *flatPaintPtr;
+            int index = flatPaint->index() - 1;
+            flatPaint->unflatten(&mPaints[index], &mRCPlayback, &mTFPlayback);
+        }
+    }
+
+    mPathHeap = recorder.mPathHeap;
+    mPathHeap->safeRef();
+}
+
+DisplayList::~DisplayList() {
+    sk_free((void*) mReader.base());
+
+    Caches& caches = Caches::getInstance();
+    for (int i = 0; i < mBitmapCount; i++) {
+        caches.textureCache.remove(&mBitmaps[i]);
+    }
+
+    delete[] mBitmaps;
+    delete[] mMatrices;
+    delete[] mPaints;
+
+    mPathHeap->safeUnref();
+}
+
+void DisplayList::init() {
+    mBitmaps = NULL;
+    mMatrices = NULL;
+    mPaints = NULL;
+    mPathHeap = NULL;
+    mBitmapCount = mMatrixCount = mPaintCount = 0;
+}
+
+void DisplayList::replay(OpenGLRenderer& renderer) {
+    TextContainer text;
+    mReader.rewind();
+
+    int saveCount = renderer.getSaveCount() - 1;
+
+    while (!mReader.eof()) {
+        switch (mReader.readInt()) {
+            case AcquireContext: {
+                renderer.acquireContext();
+            }
+            break;
+            case ReleaseContext: {
+                renderer.releaseContext();
+            }
+            break;
+            case Save: {
+                renderer.save(getInt());
+            }
+            break;
+            case Restore: {
+                renderer.restore();
+            }
+            break;
+            case RestoreToCount: {
+                renderer.restoreToCount(saveCount + getInt());
+            }
+            break;
+            case SaveLayer: {
+                renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(),
+                        getPaint(), getInt());
+            }
+            break;
+            case Translate: {
+                renderer.translate(getFloat(), getFloat());
+            }
+            break;
+            case Rotate: {
+                renderer.rotate(getFloat());
+            }
+            break;
+            case Scale: {
+                renderer.scale(getFloat(), getFloat());
+            }
+            break;
+            case SetMatrix: {
+                renderer.setMatrix(getMatrix());
+            }
+            break;
+            case ConcatMatrix: {
+                renderer.concatMatrix(getMatrix());
+            }
+            break;
+            case ClipRect: {
+                renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(),
+                        (SkRegion::Op) getInt());
+            }
+            break;
+            case DrawBitmap: {
+                renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawBitmapMatrix: {
+                renderer.drawBitmap(getBitmap(), getMatrix(), getPaint());
+            }
+            break;
+            case DrawBitmapRect: {
+                renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(),
+                        getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawPatch: {
+                int32_t* xDivs = NULL;
+                int32_t* yDivs = NULL;
+                uint32_t xDivsCount = 0;
+                uint32_t yDivsCount = 0;
+
+                SkBitmap* bitmap = getBitmap();
+
+                xDivs = getInts(xDivsCount);
+                yDivs = getInts(yDivsCount);
+
+                renderer.drawPatch(bitmap, xDivs, yDivs, xDivsCount, yDivsCount,
+                        getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawColor: {
+                renderer.drawColor(getInt(), (SkXfermode::Mode) getInt());
+            }
+            break;
+            case DrawRect: {
+                renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawPath: {
+                renderer.drawPath(getPath(), getPaint());
+            }
+            break;
+            case DrawLines: {
+                int count = 0;
+                float* points = getFloats(count);
+                renderer.drawLines(points, count, getPaint());
+            }
+            break;
+            case DrawText: {
+                getText(&text);
+                renderer.drawText(text.text(), text.length(), getInt(),
+                        getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case ResetShader: {
+                renderer.resetShader();
+            }
+            break;
+            case SetupShader: {
+                // TODO: Implement
+            }
+            break;
+            case ResetColorFilter: {
+                renderer.resetColorFilter();
+            }
+            break;
+            case SetupColorFilter: {
+                // TODO: Implement
+            }
+            break;
+            case ResetShadow: {
+                renderer.resetShadow();
+            }
+            break;
+            case SetupShadow: {
+                renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt());
+            }
+            break;
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -56,75 +279,89 @@
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
+void DisplayListRenderer::setViewport(int width, int height) {
+    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
+
+    mWidth = width;
+    mHeight = height;
+}
+
+void DisplayListRenderer::prepare() {
+    mSnapshot = new Snapshot(mFirstSnapshot,
+            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+    mSaveCount = 1;
+    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
+}
+
 void DisplayListRenderer::acquireContext() {
-    addOp(AcquireContext);
+    addOp(DisplayList::AcquireContext);
     OpenGLRenderer::acquireContext();
 }
 
 void DisplayListRenderer::releaseContext() {
-    addOp(ReleaseContext);
+    addOp(DisplayList::ReleaseContext);
     OpenGLRenderer::releaseContext();
 }
 
 int DisplayListRenderer::save(int flags) {
-    addOp(Save);
+    addOp(DisplayList::Save);
     addInt(flags);
     return OpenGLRenderer::save(flags);
 }
 
 void DisplayListRenderer::restore() {
-    addOp(Restore);
+    addOp(DisplayList::Restore);
     OpenGLRenderer::restore();
 }
 
 void DisplayListRenderer::restoreToCount(int saveCount) {
-    addOp(RestoreToCount);
+    addOp(DisplayList::RestoreToCount);
     addInt(saveCount);
     OpenGLRenderer::restoreToCount(saveCount);
 }
 
 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
         const SkPaint* p, int flags) {
-    addOp(SaveLayer);
+    addOp(DisplayList::SaveLayer);
     addBounds(left, top, right, bottom);
     addPaint(p);
     addInt(flags);
-    return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
+    return OpenGLRenderer::save(flags);
 }
 
 void DisplayListRenderer::translate(float dx, float dy) {
-    addOp(Translate);
+    addOp(DisplayList::Translate);
     addPoint(dx, dy);
     OpenGLRenderer::translate(dx, dy);
 }
 
 void DisplayListRenderer::rotate(float degrees) {
-    addOp(Rotate);
+    addOp(DisplayList::Rotate);
     addFloat(degrees);
     OpenGLRenderer::rotate(degrees);
 }
 
 void DisplayListRenderer::scale(float sx, float sy) {
-    addOp(Scale);
+    addOp(DisplayList::Scale);
     addPoint(sx, sy);
     OpenGLRenderer::scale(sx, sy);
 }
 
 void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
-    addOp(SetMatrix);
+    addOp(DisplayList::SetMatrix);
     addMatrix(matrix);
     OpenGLRenderer::setMatrix(matrix);
 }
 
 void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
-    addOp(ConcatMatrix);
+    addOp(DisplayList::ConcatMatrix);
     addMatrix(matrix);
     OpenGLRenderer::concatMatrix(matrix);
 }
 
 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
         SkRegion::Op op) {
-    addOp(ClipRect);
+    addOp(DisplayList::ClipRect);
     addBounds(left, top, right, bottom);
     addInt(op);
     return OpenGLRenderer::clipRect(left, top, right, bottom, op);
@@ -132,88 +369,77 @@
 
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
         const SkPaint* paint) {
-    addOp(DrawBitmap);
+    addOp(DisplayList::DrawBitmap);
     addBitmap(bitmap);
     addPoint(left, top);
     addPaint(paint);
-    OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
 }
 
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix,
         const SkPaint* paint) {
-    addOp(DrawBitmapMatrix);
+    addOp(DisplayList::DrawBitmapMatrix);
     addBitmap(bitmap);
     addMatrix(matrix);
     addPaint(paint);
-    OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
 }
 
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop,
         float dstRight, float dstBottom, const SkPaint* paint) {
-    addOp(DrawBitmapRect);
+    addOp(DisplayList::DrawBitmapRect);
     addBitmap(bitmap);
     addBounds(srcLeft, srcTop, srcRight, srcBottom);
     addBounds(dstLeft, dstTop, dstRight, dstBottom);
     addPaint(paint);
-    OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
-            dstLeft, dstTop, dstRight, dstBottom, paint);
 }
 
 void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
         uint32_t width, uint32_t height, float left, float top, float right, float bottom,
         const SkPaint* paint) {
-    addOp(DrawPatch);
+    addOp(DisplayList::DrawPatch);
     addBitmap(bitmap);
     addInts(xDivs, width);
     addInts(yDivs, height);
     addBounds(left, top, right, bottom);
     addPaint(paint);
-    OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, width, height,
-            left, top, right, bottom, paint);
 }
 
 void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
-    addOp(DrawColor);
+    addOp(DisplayList::DrawColor);
     addInt(color);
     addInt(mode);
-    OpenGLRenderer::drawColor(color, mode);
 }
 
 void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
         const SkPaint* paint) {
-    addOp(DrawRect);
+    addOp(DisplayList::DrawRect);
     addBounds(left, top, right, bottom);
     addPaint(paint);
-    OpenGLRenderer::drawRect(left, top, right, bottom, paint);
 }
 
 void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
-    addOp(DrawPath);
+    addOp(DisplayList::DrawPath);
     addPath(path);
     addPaint(paint);
-    OpenGLRenderer::drawPath(path, paint);
 }
 
 void DisplayListRenderer::drawLines(float* points, int count, const SkPaint* paint) {
-    addOp(DrawLines);
+    addOp(DisplayList::DrawLines);
     addFloats(points, count);
     addPaint(paint);
-    OpenGLRenderer::drawLines(points, count, paint);
 }
 
 void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
         float x, float y, SkPaint* paint) {
-    addOp(DrawText);
+    addOp(DisplayList::DrawText);
     addText(text, bytesCount);
     addInt(count);
     addPoint(x, y);
     addPaint(paint);
-    OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
 }
 
 void DisplayListRenderer::resetShader() {
-    addOp(ResetShader);
+    addOp(DisplayList::ResetShader);
     OpenGLRenderer::resetShader();
 }
 
@@ -223,7 +449,7 @@
 }
 
 void DisplayListRenderer::resetColorFilter() {
-    addOp(ResetColorFilter);
+    addOp(DisplayList::ResetColorFilter);
     OpenGLRenderer::resetColorFilter();
 }
 
@@ -233,12 +459,12 @@
 }
 
 void DisplayListRenderer::resetShadow() {
-    addOp(ResetShadow);
+    addOp(DisplayList::ResetShadow);
     OpenGLRenderer::resetShadow();
 }
 
 void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
-    addOp(SetupShadow);
+    addOp(DisplayList::SetupShadow);
     addFloat(radius);
     addPoint(dx, dy);
     addInt(color);