Adding display lists to the GL renderer (checkpoint.)

Change-Id: Iaa49757600a53b39369dbb23f8c3feab282518e6
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index e8ffd99..43af702 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -5,6 +5,7 @@
 # defined in the current device/board configuration
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SRC_FILES:= \
+		DisplayListRenderer.cpp \
 		FboCache.cpp \
 		FontRenderer.cpp \
 		GammaFontRenderer.cpp \
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
new file mode 100644
index 0000000..16b6b56
--- /dev/null
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "DisplayListRenderer.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Base structure
+///////////////////////////////////////////////////////////////////////////////
+
+DisplayListRenderer::DisplayListRenderer():
+        mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) {
+    mBitmapIndex = mMatrixIndex = mPaintIndex = 1;
+    mPathHeap = NULL;
+}
+
+DisplayListRenderer::~DisplayListRenderer() {
+    reset();
+}
+
+void DisplayListRenderer::reset() {
+    if (mPathHeap) {
+        mPathHeap->unref();
+        mPathHeap = NULL;
+    }
+
+    mBitmaps.reset();
+    mMatrices.reset();
+    mPaints.reset();
+
+    mWriter.reset();
+    mHeap.reset();
+
+    mRCRecorder.reset();
+    mTFRecorder.reset();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Operations
+///////////////////////////////////////////////////////////////////////////////
+
+void DisplayListRenderer::acquireContext() {
+    addOp(AcquireContext);
+    OpenGLRenderer::acquireContext();
+}
+
+void DisplayListRenderer::releaseContext() {
+    addOp(ReleaseContext);
+    OpenGLRenderer::releaseContext();
+}
+
+int DisplayListRenderer::save(int flags) {
+    addOp(Save);
+    addInt(flags);
+    return OpenGLRenderer::save(flags);
+}
+
+void DisplayListRenderer::restore() {
+    addOp(Restore);
+    OpenGLRenderer::restore();
+}
+
+void DisplayListRenderer::restoreToCount(int saveCount) {
+    addOp(RestoreToCount);
+    addInt(saveCount);
+    OpenGLRenderer::restoreToCount(saveCount);
+}
+
+int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
+        const SkPaint* p, int flags) {
+    addOp(SaveLayer);
+    addBounds(left, top, right, bottom);
+    addPaint(p);
+    addInt(flags);
+    return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
+}
+
+void DisplayListRenderer::translate(float dx, float dy) {
+    addOp(Translate);
+    addPoint(dx, dy);
+    OpenGLRenderer::translate(dx, dy);
+}
+
+void DisplayListRenderer::rotate(float degrees) {
+    addOp(Rotate);
+    addFloat(degrees);
+    OpenGLRenderer::rotate(degrees);
+}
+
+void DisplayListRenderer::scale(float sx, float sy) {
+    addOp(Scale);
+    addPoint(sx, sy);
+    OpenGLRenderer::scale(sx, sy);
+}
+
+void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
+    addOp(SetMatrix);
+    addMatrix(matrix);
+    OpenGLRenderer::setMatrix(matrix);
+}
+
+void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
+    addOp(ConcatMatrix);
+    addMatrix(matrix);
+    OpenGLRenderer::concatMatrix(matrix);
+}
+
+bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
+        SkRegion::Op op) {
+    addOp(ClipRect);
+    addBounds(left, top, right, bottom);
+    addInt(op);
+    return OpenGLRenderer::clipRect(left, top, right, bottom, op);
+}
+
+void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
+        const SkPaint* paint) {
+    addOp(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);
+    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);
+    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);
+    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);
+    addInt(color);
+    addInt(mode);
+    OpenGLRenderer::drawColor(color, mode);
+}
+
+void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
+        const SkPaint* paint) {
+    addOp(DrawRect);
+    addBounds(left, top, right, bottom);
+    addPaint(paint);
+    OpenGLRenderer::drawRect(left, top, right, bottom, paint);
+}
+
+void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
+    addOp(DrawPath);
+    addPath(path);
+    addPaint(paint);
+    OpenGLRenderer::drawPath(path, paint);
+}
+
+void DisplayListRenderer::drawLines(float* points, int count, const SkPaint* paint) {
+    addOp(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);
+    addText(text, bytesCount);
+    addInt(count);
+    addPoint(x, y);
+    addPaint(paint);
+    OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
+}
+
+void DisplayListRenderer::resetShader() {
+    addOp(ResetShader);
+    OpenGLRenderer::resetShader();
+}
+
+void DisplayListRenderer::setupShader(SkiaShader* shader) {
+    // TODO: Implement
+    OpenGLRenderer::setupShader(shader);
+}
+
+void DisplayListRenderer::resetColorFilter() {
+    addOp(ResetColorFilter);
+    OpenGLRenderer::resetColorFilter();
+}
+
+void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
+    // TODO: Implement
+    OpenGLRenderer::setupColorFilter(filter);
+}
+
+void DisplayListRenderer::resetShadow() {
+    addOp(ResetShadow);
+    OpenGLRenderer::resetShadow();
+}
+
+void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
+    addOp(SetupShadow);
+    addFloat(radius);
+    addPoint(dx, dy);
+    addInt(color);
+    OpenGLRenderer::setupShadow(radius, dx, dy, color);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Recording management
+///////////////////////////////////////////////////////////////////////////////
+
+int DisplayListRenderer::find(SkTDArray<const SkFlatPaint*>& paints, const SkPaint* paint) {
+    if (paint == NULL) {
+        return 0;
+    }
+
+    SkFlatPaint* flat = SkFlatPaint::Flatten(&mHeap, *paint, mPaintIndex,
+            &mRCRecorder, &mTFRecorder);
+    int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
+            paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
+    if (index >= 0) {
+        (void) mHeap.unalloc(flat);
+        return paints[index]->index();
+    }
+
+    index = ~index;
+    *paints.insert(index) = flat;
+    return mPaintIndex++;
+}
+
+int DisplayListRenderer::find(SkTDArray<const SkFlatMatrix*>& matrices, const SkMatrix* matrix) {
+    if (matrix == NULL) {
+        return 0;
+    }
+
+    SkFlatMatrix* flat = SkFlatMatrix::Flatten(&mHeap, *matrix, mMatrixIndex);
+    int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
+            matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
+    if (index >= 0) {
+        (void) mHeap.unalloc(flat);
+        return matrices[index]->index();
+    }
+    index = ~index;
+    *matrices.insert(index) = flat;
+    return mMatrixIndex++;
+}
+
+int DisplayListRenderer::find(SkTDArray<const SkFlatBitmap*>& bitmaps, const SkBitmap& bitmap) {
+    SkFlatBitmap* flat = SkFlatBitmap::Flatten(&mHeap, bitmap, mBitmapIndex, &mRCRecorder);
+    int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
+            bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
+    if (index >= 0) {
+        (void) mHeap.unalloc(flat);
+        return bitmaps[index]->index();
+    }
+    index = ~index;
+    *bitmaps.insert(index) = flat;
+    return mBitmapIndex++;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
new file mode 100644
index 0000000..7a20b59
--- /dev/null
+++ b/libs/hwui/DisplayListRenderer.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2010 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_UI_DISPLAY_LIST_RENDERER_H
+#define ANDROID_UI_DISPLAY_LIST_RENDERER_H
+
+#include <SkChunkAlloc.h>
+#include <SkFlattenable.h>
+#include <SkMatrix.h>
+#include <SkPaint.h>
+#include <SkPath.h>
+#include <SkPictureFlat.h>
+#include <SkRefCnt.h>
+#include <SkTDArray.h>
+#include <SkTSearch.h>
+
+#include "OpenGLRenderer.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#define MIN_WRITER_SIZE 16384
+#define HEAP_BLOCK_SIZE 4096
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+///////////////////////////////////////////////////////////////////////////////
+
+class PathHeap: public SkRefCnt {
+public:
+    PathHeap(): mHeap(64 * sizeof(SkPath)) {
+    };
+
+    PathHeap(SkFlattenableReadBuffer& buffer): mHeap(64 * sizeof(SkPath)) {
+        int count = buffer.readS32();
+
+        mPaths.setCount(count);
+        SkPath** ptr = mPaths.begin();
+        SkPath* p = (SkPath*) mHeap.allocThrow(count * sizeof(SkPath));
+
+        for (int i = 0; i < count; i++) {
+            new (p) SkPath;
+            p->unflatten(buffer);
+            *ptr++ = p;
+            p++;
+        }
+    }
+
+    ~PathHeap() {
+        SkPath** iter = mPaths.begin();
+        SkPath** stop = mPaths.end();
+        while (iter < stop) {
+            (*iter)->~SkPath();
+            iter++;
+        }
+    }
+
+    int append(const SkPath& path) {
+        SkPath* p = (SkPath*) mHeap.allocThrow(sizeof(SkPath));
+        new (p) SkPath(path);
+        *mPaths.append() = p;
+        return mPaths.count();
+    }
+
+    int count() const { return mPaths.count(); }
+
+    const SkPath& operator[](int index) const {
+        return *mPaths[index];
+    }
+
+    void flatten(SkFlattenableWriteBuffer& buffer) const {
+        int count = mPaths.count();
+
+        buffer.write32(count);
+        SkPath** iter = mPaths.begin();
+        SkPath** stop = mPaths.end();
+        while (iter < stop) {
+            (*iter)->flatten(buffer);
+            iter++;
+        }
+    }
+
+private:
+    SkChunkAlloc mHeap;
+    SkTDArray<SkPath*> mPaths;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Records drawing commands in a display list for latter playback.
+ */
+class DisplayListRenderer: public OpenGLRenderer {
+public:
+    DisplayListRenderer();
+    ~DisplayListRenderer();
+
+    enum Op {
+        AcquireContext,
+        ReleaseContext,
+        Save,
+        Restore,
+        RestoreToCount,
+        SaveLayer,
+        SaveLayerAlpha,
+        Translate,
+        Rotate,
+        Scale,
+        SetMatrix,
+        ConcatMatrix,
+        ClipRect,
+        DrawBitmap,
+        DrawBitmapMatrix,
+        DrawBitmapRect,
+        DrawPatch,
+        DrawColor,
+        DrawRect,
+        DrawPath,
+        DrawLines,
+        DrawText,
+        ResetShader,
+        SetupShader,
+        ResetColorFilter,
+        SetupColorFilter,
+        ResetShadow,
+        SetupShadow
+    };
+
+    void acquireContext();
+    void releaseContext();
+
+    int save(int flags);
+    void restore();
+    void restoreToCount(int saveCount);
+
+    int saveLayer(float left, float top, float right, float bottom,
+            const SkPaint* p, int flags);
+
+    void translate(float dx, float dy);
+    void rotate(float degrees);
+    void scale(float sx, float sy);
+
+    void setMatrix(SkMatrix* matrix);
+    void concatMatrix(SkMatrix* matrix);
+
+    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
+
+    void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
+    void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
+    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
+            float srcRight, float srcBottom, float dstLeft, float dstTop,
+            float dstRight, float dstBottom, const SkPaint* paint);
+    void 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);
+    void drawColor(int color, SkXfermode::Mode mode);
+    void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
+    void drawPath(SkPath* path, SkPaint* paint);
+    void drawLines(float* points, int count, const SkPaint* paint);
+    void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
+
+    void resetShader();
+    void setupShader(SkiaShader* shader);
+
+    void resetColorFilter();
+    void setupColorFilter(SkiaColorFilter* filter);
+
+    void resetShadow();
+    void setupShadow(float radius, float dx, float dy, int color);
+
+    void reset();
+
+private:
+    inline void addOp(Op drawOp) {
+        mWriter.writeInt(drawOp);
+    }
+
+    inline void addInt(int value) {
+        mWriter.writeInt(value);
+    }
+
+    void addInts(const int32_t* values, uint32_t count) {
+        for (uint32_t i = 0; i < count; i++) {
+            mWriter.writeInt(values[i]);
+        }
+    }
+
+    inline void addFloat(float value) {
+        mWriter.writeScalar(value);
+    }
+
+    void addFloats(const float* values, int count) {
+        for (int i = 0; i < count; i++) {
+            mWriter.writeScalar(values[i]);
+        }
+    }
+
+    inline void addPoint(float x, float y) {
+        mWriter.writeScalar(x);
+        mWriter.writeScalar(y);
+    }
+
+    inline void addBounds(float left, float top, float right, float bottom) {
+        mWriter.writeScalar(left);
+        mWriter.writeScalar(top);
+        mWriter.writeScalar(right);
+        mWriter.writeScalar(bottom);
+    }
+
+    inline void addText(const void* text, size_t byteLength) {
+        mWriter.writeInt(byteLength);
+        mWriter.writePad(text, byteLength);
+    }
+
+    inline void addPath(const SkPath* path) {
+        if (mPathHeap == NULL) {
+            mPathHeap = new PathHeap();
+        }
+        addInt(mPathHeap->append(*path));
+    }
+
+    int find(SkTDArray<const SkFlatPaint*>& paints, const SkPaint* paint);
+
+    inline void addPaint(const SkPaint* paint) {
+        addInt(find(mPaints, paint));
+    }
+
+    int find(SkTDArray<const SkFlatMatrix*>& matrices, const SkMatrix* matrix);
+
+    inline void addMatrix(const SkMatrix* matrix) {
+        addInt(find(mMatrices, matrix));
+    }
+
+    int find(SkTDArray<const SkFlatBitmap*>& bitmaps, const SkBitmap& bitmap);
+
+    inline void addBitmap(const SkBitmap* bitmap) {
+        addInt(find(mBitmaps, *bitmap));
+    }
+
+    SkChunkAlloc mHeap;
+
+    int mBitmapIndex;
+    SkTDArray<const SkFlatBitmap*> mBitmaps;
+
+    int mMatrixIndex;
+    SkTDArray<const SkFlatMatrix*> mMatrices;
+
+    int mPaintIndex;
+    SkTDArray<const SkFlatPaint*> mPaints;
+
+    PathHeap* mPathHeap;
+    SkWriter32 mWriter;
+
+    SkRefCntRecorder mRCRecorder;
+    SkRefCntRecorder mTFRecorder;
+
+}; // class DisplayListRenderer
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_DISPLAY_LIST_RENDERER_H
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
index f5a4286..4e5123e 100644
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ b/libs/hwui/OpenGLDebugRenderer.cpp
@@ -71,11 +71,13 @@
             dstLeft, dstTop, dstRight, dstBottom, paint);
 }
 
-void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-        float left, float top, float right, float bottom, const SkPaint* paint) {
+void OpenGLDebugRenderer::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) {
     mPrimitivesCount++;
     StopWatch w("drawPatch");
-    OpenGLRenderer::drawPatch(bitmap, patch, left, top, right, bottom, paint);
+    OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, width, height,
+            left, top, right, bottom, paint);
 }
 
 void OpenGLDebugRenderer::drawColor(int color, SkXfermode::Mode mode) {
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index 37fac93..ce15512 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -45,8 +45,9 @@
     void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
             float dstRight, float dstBottom, const SkPaint* paint);
-    void drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top,
-            float right, float bottom, const SkPaint* paint);
+    void 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);
     void drawColor(int color, SkXfermode::Mode mode);
     void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
     void drawPath(SkPath* path, SkPaint* paint);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dbd499e..23de3a5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -585,8 +585,9 @@
     resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
 }
 
-void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-        float left, float top, float right, float bottom, const SkPaint* paint) {
+void OpenGLRenderer::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) {
     if (quickReject(left, top, right, bottom)) {
         return;
     }
@@ -600,9 +601,9 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    Patch* mesh = mCaches.patchCache.get(patch);
+    Patch* mesh = mCaches.patchCache.get(width, height);
     mesh->updateVertices(bitmap->width(), bitmap->height(),left, top, right, bottom,
-            &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs);
+            xDivs, yDivs, width, height);
 
     // Specify right and bottom as +1.0f from left/top to prevent scaling since the
     // patch mesh already defines the final size
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index af2a70b..d505d80 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -28,7 +28,6 @@
 #include <SkXfermode.h>
 
 #include <utils/RefBase.h>
-#include <utils/ResourceTypes.h>
 #include <utils/Vector.h>
 
 #include "Extensions.h"
@@ -69,38 +68,39 @@
     virtual void prepare();
     virtual void finish();
 
-    void acquireContext();
-    void releaseContext();
+    virtual void acquireContext();
+    virtual void releaseContext();
 
     int getSaveCount() const;
-    int save(int flags);
-    void restore();
-    void restoreToCount(int saveCount);
+    virtual int save(int flags);
+    virtual void restore();
+    virtual void restoreToCount(int saveCount);
 
     virtual int saveLayer(float left, float top, float right, float bottom,
             const SkPaint* p, int flags);
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
             int alpha, int flags);
 
-    void translate(float dx, float dy);
-    void rotate(float degrees);
-    void scale(float sx, float sy);
+    virtual void translate(float dx, float dy);
+    virtual void rotate(float degrees);
+    virtual void scale(float sx, float sy);
 
-    void setMatrix(SkMatrix* matrix);
     void getMatrix(SkMatrix* matrix);
-    void concatMatrix(SkMatrix* matrix);
+    virtual void setMatrix(SkMatrix* matrix);
+    virtual void concatMatrix(SkMatrix* matrix);
 
     const Rect& getClipBounds();
     bool quickReject(float left, float top, float right, float bottom);
-    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
+    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
     virtual void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
             float dstRight, float dstBottom, const SkPaint* paint);
-    virtual void drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top,
-            float right, float bottom, const SkPaint* paint);
+    virtual void 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);
     virtual void drawColor(int color, SkXfermode::Mode mode);
     virtual void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
     virtual void drawPath(SkPath* path, SkPaint* paint);
@@ -108,14 +108,14 @@
     virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
             SkPaint* paint);
 
-    void resetShader();
-    void setupShader(SkiaShader* shader);
+    virtual void resetShader();
+    virtual void setupShader(SkiaShader* shader);
 
-    void resetColorFilter();
-    void setupColorFilter(SkiaColorFilter* filter);
+    virtual void resetColorFilter();
+    virtual void setupColorFilter(SkiaColorFilter* filter);
 
-    void resetShadow();
-    void setupShadow(float radius, float dx, float dy, int color);
+    virtual void resetShadow();
+    virtual void setupShadow(float radius, float dx, float dy, int color);
 
 protected:
     /**
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index a7c0cce..f2cf548 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -57,9 +57,7 @@
     mCache.setOnEntryRemovedListener(NULL);
 }
 
-Patch* PatchCache::get(const Res_png_9patch* patch) {
-    const uint32_t width = patch->numXDivs;
-    const uint32_t height = patch->numYDivs;
+Patch* PatchCache::get(uint32_t width, uint32_t height) {
     const PatchDescription description(width, height);
 
     Patch* mesh = mCache.get(description);
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 6dad831..b077469 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_UI_PATCH_CACHE_H
 #define ANDROID_UI_PATCH_CACHE_H
 
-#include <utils/ResourceTypes.h>
-
 #include "Patch.h"
 #include "GenerationCache.h"
 
@@ -55,7 +53,7 @@
      */
     void operator()(PatchDescription& description, Patch*& mesh);
 
-    Patch* get(const Res_png_9patch* patch);
+    Patch* get(uint32_t width, uint32_t height);
     void clear();
 
 private: