Don't render degenerate triangles in 9patches.
Bug #3251983
Change-Id: Ib0b38a7b8111542372f4c4c106b6321c26fe4ad4
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index ebffd34..17b1d86 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -22,6 +22,7 @@
#include "Patch.h"
#include "Caches.h"
+#include "Properties.h"
namespace android {
namespace uirenderer {
@@ -31,19 +32,22 @@
///////////////////////////////////////////////////////////////////////////////
Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads):
- mXCount(xCount), mYCount(yCount) {
+ mXCount(xCount), mYCount(yCount), mEmptyQuads(emptyQuads) {
+ // Initialized with the maximum number of vertices we will need
// 2 triangles per patch, 3 vertices per triangle
- verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
- mVertices = new TextureVertex[verticesCount];
- hasEmptyQuads = emptyQuads > 0;
+ const int maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
+ mVertices = new TextureVertex[maxVertices];
mUploaded = false;
+ verticesCount = 0;
+ hasEmptyQuads = emptyQuads > 0;
+
mColorKey = 0;
mXDivs = new int32_t[mXCount];
mYDivs = new int32_t[mYCount];
- PATCH_LOGD(" patch: xCount = %d, yCount = %d, emptyQuads = %d, vertices = %d",
- xCount, yCount, emptyQuads, verticesCount);
+ PATCH_LOGD(" patch: xCount = %d, yCount = %d, emptyQuads = %d, max vertices = %d",
+ xCount, yCount, emptyQuads, maxVertices);
glGenBuffers(1, &meshBuffer);
}
@@ -104,7 +108,13 @@
void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
float left, float top, float right, float bottom) {
+#if RENDER_LAYERS_AS_REGIONS
if (hasEmptyQuads) quads.clear();
+#endif
+
+ // Reset the vertices count here, we will count exactly how many
+ // vertices we actually need when generating the quads
+ verticesCount = 0;
const uint32_t xStretchCount = (mXCount + 1) >> 1;
const uint32_t yStretchCount = (mYCount + 1) >> 1;
@@ -167,15 +177,19 @@
generateRow(vertex, y1, bottom - top, v1, 1.0f, stretchX, right - left,
bitmapWidth, quadCount);
- Caches::getInstance().bindMeshBuffer(meshBuffer);
- 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);
+ if (verticesCount > 0) {
+ Caches::getInstance().bindMeshBuffer(meshBuffer);
+ 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);
+ }
}
+
+ PATCH_LOGD(" patch: new vertices count = %d", verticesCount);
}
void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
@@ -211,22 +225,24 @@
void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2, uint32_t& quadCount) {
- uint32_t oldQuadCount = quadCount;
-
- // Degenerate quads are an artifact of our implementation and should not
- // be taken into account when checking for transparent quads
- if (x2 - x1 > 0.999f && y2 - y1 > 0.999f) {
+ const uint32_t oldQuadCount = quadCount;
+ const bool valid = fabs(x2 - x1) > 0.9999f && fabs(y2 - y1) > 0.9999f;
+ if (valid) {
quadCount++;
}
- if (((mColorKey >> oldQuadCount) & 0x1) == 1) {
+ // Skip degenerate and transparent (empty) quads
+ if (!valid || ((mColorKey >> oldQuadCount) & 0x1) == 1) {
return;
}
+#if RENDER_LAYERS_AS_REGIONS
+ // Record all non empty quads
if (hasEmptyQuads) {
Rect bounds(x1, y1, x2, y2);
quads.add(bounds);
}
+#endif
// Left triangle
TextureVertex::set(vertex++, x1, y1, u1, v1);
@@ -237,6 +253,15 @@
TextureVertex::set(vertex++, x1, y2, u1, v2);
TextureVertex::set(vertex++, x2, y1, u2, v1);
TextureVertex::set(vertex++, x2, y2, u2, v2);
+
+ // A quad is made of 2 triangles, 6 vertices
+ verticesCount += 6;
+
+#if DEBUG_PATCHES_VERTICES
+ PATCH_LOGD(" quad %d", oldQuadCount);
+ PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1);
+ PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2);
+#endif
}
}; // namespace uirenderer