Update 9patch structure when rendering with different divs/colors.
Bug #3221488

Change-Id: Ifc9e42a991d630feadc9e8032322f37504d09d6d
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9b2d476..7ca289d 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -30,32 +30,81 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads) {
+Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads):
+        mXCount(xCount), mYCount(yCount) {
     // 2 triangles per patch, 3 vertices per triangle
     verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
     mVertices = new TextureVertex[verticesCount];
     hasEmptyQuads = emptyQuads > 0;
+    mUploaded = false;
+
+    mColorKey = 0;
+    mXDivs = new int32_t[mXCount];
+    mYDivs = new int32_t[mYCount];
 
     glGenBuffers(1, &meshBuffer);
 }
 
 Patch::~Patch() {
     delete[] mVertices;
+    delete[] mXDivs;
+    delete[] mYDivs;
     glDeleteBuffers(1, &meshBuffer);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Patch management
+///////////////////////////////////////////////////////////////////////////////
+
+void Patch::copy(const int32_t* xDivs, const int32_t* yDivs) {
+    memcpy(mXDivs, xDivs, mXCount * sizeof(int32_t));
+    memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
+}
+
+void Patch::copy(const int32_t* yDivs) {
+    memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
+}
+
+void Patch::updateColorKey(const uint32_t colorKey) {
+    mColorKey = colorKey;
+}
+
+bool Patch::matches(const int32_t* xDivs, const int32_t* yDivs, const uint32_t colorKey) {
+    if (mColorKey != colorKey) {
+        updateColorKey(colorKey);
+        copy(xDivs, yDivs);
+        return false;
+    }
+
+    for (uint32_t i = 0; i < mXCount; i++) {
+        if (mXDivs[i] != xDivs[i]) {
+            // The Y divs may or may not match, copy everything
+            copy(xDivs, yDivs);
+            return false;
+        }
+    }
+
+    for (uint32_t i = 0; i < mYCount; i++) {
+        if (mYDivs[i] != yDivs[i]) {
+            // We know all the X divs match, copy only Y divs
+            copy(yDivs);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Vertices management
 ///////////////////////////////////////////////////////////////////////////////
 
 void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
-        float left, float top, float right, float bottom,
-        const int32_t* xDivs, const int32_t* yDivs,
-        const uint32_t width, const uint32_t height, const uint32_t colorKey) {
+        float left, float top, float right, float bottom) {
     if (hasEmptyQuads) quads.clear();
 
-    const uint32_t xStretchCount = (width + 1) >> 1;
-    const uint32_t yStretchCount = (height + 1) >> 1;
+    const uint32_t xStretchCount = (mXCount + 1) >> 1;
+    const uint32_t yStretchCount = (mYCount + 1) >> 1;
 
     float stretchX = 0.0f;
     float stretchY = 0.0;
@@ -64,8 +113,8 @@
 
     if (xStretchCount > 0) {
         uint32_t stretchSize = 0;
-        for (uint32_t i = 1; i < width; i += 2) {
-            stretchSize += xDivs[i] - xDivs[i - 1];
+        for (uint32_t i = 1; i < mXCount; i += 2) {
+            stretchSize += mXDivs[i] - mXDivs[i - 1];
         }
         const float xStretchTex = stretchSize;
         const float fixed = bitmapWidth - stretchSize;
@@ -75,8 +124,8 @@
 
     if (yStretchCount > 0) {
         uint32_t stretchSize = 0;
-        for (uint32_t i = 1; i < height; i += 2) {
-            stretchSize += yDivs[i] - yDivs[i - 1];
+        for (uint32_t i = 1; i < mYCount; i += 2) {
+            stretchSize += mYDivs[i] - mYDivs[i - 1];
         }
         const float yStretchTex = stretchSize;
         const float fixed = bitmapHeight - stretchSize;
@@ -92,8 +141,8 @@
     float y1 = 0.0f;
     float v1 = 0.0f;
 
-    for (uint32_t i = 0; i < height; i++) {
-        float stepY = yDivs[i];
+    for (uint32_t i = 0; i < mYCount; i++) {
+        float stepY = mYDivs[i];
 
         float y2 = 0.0f;
         if (i & 1) {
@@ -104,8 +153,7 @@
         }
         float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight;
 
-        generateRow(vertex, y1, y2, v1, v2, xDivs, width, stretchX,
-                right - left, bitmapWidth, quadCount, colorKey);
+        generateRow(vertex, y1, y2, v1, v2, stretchX, right - left, bitmapWidth, quadCount);
 
         y1 = y2;
         v1 = (stepY + 0.5f) / bitmapHeight;
@@ -113,25 +161,30 @@
         previousStepY = stepY;
     }
 
-    generateRow(vertex, y1, bottom - top, v1, 1.0f, xDivs, width, stretchX,
-            right - left, bitmapWidth, quadCount, colorKey);
+    generateRow(vertex, y1, bottom - top, v1, 1.0f, stretchX, right - left,
+            bitmapWidth, quadCount);
 
     Caches::getInstance().bindMeshBuffer(meshBuffer);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
-                mVertices, GL_STATIC_DRAW);
+    if (!mUploaded) {
+        glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
+                mVertices, GL_DYNAMIC_DRAW);
+        mUploaded = true;
+    } else {
+        glBufferSubData(GL_ARRAY_BUFFER, 0,
+                sizeof(TextureVertex) * verticesCount, mVertices);
+    }
 }
 
 void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
-        const int32_t xDivs[], uint32_t xCount, float stretchX, float width, float bitmapWidth,
-        uint32_t& quadCount, const uint32_t colorKey) {
+        float stretchX, float width, float bitmapWidth, uint32_t& quadCount) {
     float previousStepX = 0.0f;
 
     float x1 = 0.0f;
     float u1 = 0.0f;
 
     // Generate the row quad by quad
-    for (uint32_t i = 0; i < xCount; i++) {
-        float stepX = xDivs[i];
+    for (uint32_t i = 0; i < mXCount; i++) {
+        float stepX = mXDivs[i];
 
         float x2 = 0.0f;
         if (i & 1) {
@@ -142,7 +195,7 @@
         }
         float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;
 
-        generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount, colorKey);
+        generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
 
         x1 = x2;
         u1 = (stepX + 0.5f) / bitmapWidth;
@@ -150,12 +203,12 @@
         previousStepX = stepX;
     }
 
-    generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount, colorKey);
+    generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount);
 }
 
 void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
-            float u1, float v1, float u2, float v2, uint32_t& quadCount, const uint32_t colorKey) {
-    if (((colorKey >> quadCount++) & 0x1) == 1) {
+            float u1, float v1, float u2, float v2, uint32_t& quadCount) {
+    if (((mColorKey >> quadCount++) & 0x1) == 1) {
         return;
     }