Skip to content

Commit

Permalink
Optimize drawBitmapMesh using TRIANGLE_STRIP
Browse files Browse the repository at this point in the history
Draw BitmapMesh using STRIP instead of TRIANGLES.
Depending on where the bottleneck is located in the pipeline,
there is a potential for saving two-thirds of the time spent rendering.
The speedup is due to avoiding redundant operations,
i.e., mapping each vertex four times to texture and color attribute,
sending each vertex twice to the GPU, vertex processing of GPU ...

In this patch:
1. Refactoring mesh using Strip.
2. Batch triangles by adding degenerate triangles.
3. Optimize computing positions of texture and color attribute.

Benchmark: Drawing Bitmap(1152x768 px) with 200x200 meshes
Performance is doubled (from 26.4 fps to 53 fps, Nexus10).
Memory footprint: only 17% of original method.
(from 240000 to 40401 vertices with xy, uv, rgba data.)

Change-Id: I08c5c20d981d88528ce7b02012feefae468d6ec4
Signed-off-by: kui.zheng <[email protected]>
  • Loading branch information
kui.zheng authored and fusionjack committed Sep 1, 2014
1 parent 2ff3b05 commit e7dff0b
Showing 1 changed file with 54 additions and 37 deletions.
91 changes: 54 additions & 37 deletions libs/hwui/OpenGLRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2231,14 +2231,16 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
float right = FLT_MIN;
float bottom = FLT_MIN;

const uint32_t count = meshWidth * meshHeight * 6;
uint32_t vertexCountWidth = meshWidth + 1;
uint32_t vertexCountHeight = meshHeight + 1;
uint32_t vertexCount = vertexCountWidth * vertexCountHeight;

ColorTextureVertex mesh[count];
ColorTextureVertex mesh[vertexCount];
ColorTextureVertex* vertex = mesh;

bool cleanupColors = false;
if (!colors) {
uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1);
uint32_t colorsCount = vertexCountWidth * vertexCountHeight;
colors = new int[colorsCount];
memset(colors, 0xff, colorsCount * sizeof(int));
cleanupColors = true;
Expand All @@ -2248,41 +2250,56 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
Texture* texture = mCaches.assetAtlas.getEntryTexture(bitmap);
const UvMapper& mapper(getMapper(texture));

for (int32_t y = 0; y < meshHeight; y++) {
for (int32_t x = 0; x < meshWidth; x++) {
uint32_t i = (y * (meshWidth + 1) + x) * 2;

float u1 = float(x) / meshWidth;
float u2 = float(x + 1) / meshWidth;
float v1 = float(y) / meshHeight;
float v2 = float(y + 1) / meshHeight;

mapper.map(u1, v1, u2, v2);

int ax = i + (meshWidth + 1) * 2;
int ay = ax + 1;
int bx = i;
int by = bx + 1;
int cx = i + 2;
int cy = cx + 1;
int dx = i + (meshWidth + 1) * 2 + 2;
int dy = dx + 1;

ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);

ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);

left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx])));
top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy])));
right = fmaxf(right, fmaxf(vertices[ax], fmaxf(vertices[bx], vertices[cx])));
bottom = fmaxf(bottom, fmaxf(vertices[ay], fmaxf(vertices[by], vertices[cy])));
// Set vertices from Mesh's up to bottom (left to right in every row).
// Update V coordinate only once for every row.
for (uint32_t i = 0; i < vertexCountHeight; i++) {
float v = float(i) / meshHeight;
mapper.mapV(v);
for (uint32_t j = 0; j < vertexCountWidth; j++) {
uint32_t x = i * vertexCountWidth * 2 + j * 2;
uint32_t y = x + 1;
float u = float(j) / meshWidth;
mapper.mapU(u);

left = fminf(left, vertices[x]);
top = fminf(top, vertices[y]);
right = fmaxf(right, vertices[x]);
bottom = fmaxf(bottom, vertices[y]);

ColorTextureVertex::set(vertex++, vertices[x], vertices[y], u, v, colors[x/2]);
}
}

// Set index order from mesh's bottom to up, So that
// construct the same triangle mesh with original implementation.
// Or, May result in diffrent interpolated color.
//
// For each row, add degenerate triangle for triangle strip
// Take below for example:
// v00 --- v01 --- v02 --- v03
// | ... | ... | ... |
// v10 --- v11 --- v12 --- v13
// | ... | ... | ... |
// v20 --- v21 --- v22 --- v23
// Indices are: v20, v20, v10, v21, v11, v22, v12, v23, v13, v13,
// v10, v10, v00, v11, v01, v12, v02, v13, v03, v03
uint32_t indexCount = meshHeight * (meshWidth * 2 + 4);
uint16_t indices[indexCount];
uint32_t currVertexRow = meshHeight;
uint32_t index = 0;
while (currVertexRow > 0) {
uint32_t upVertexRow = currVertexRow - 1;
indices[index++] = currVertexRow * vertexCountWidth;
indices[index++] = currVertexRow * vertexCountWidth;
indices[index++] = upVertexRow * vertexCountWidth;
for (uint32_t i = 1; i <= meshWidth; i++) {
indices[index++] = currVertexRow * vertexCountWidth + i;
indices[index++] = upVertexRow * vertexCountWidth + i;
}
indices[index++] = upVertexRow * vertexCountWidth + meshWidth;
currVertexRow--;
}

if (quickReject(left, top, right, bottom)) {
if (cleanupColors) delete[] colors;
return DrawGlInfo::kStatusDone;
Expand Down Expand Up @@ -2323,7 +2340,7 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
setupDrawColorFilterUniforms();
setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0], &mesh[0].color[0]);

glDrawArrays(GL_TRIANGLES, 0, count);
glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, indices);

int slot = mCaches.currentProgram->getAttrib("colors");
if (slot >= 0) {
Expand All @@ -2334,7 +2351,7 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes

return DrawGlInfo::kStatusDrew;
}

status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
Expand Down

0 comments on commit e7dff0b

Please sign in to comment.