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;
}