From 448455fe783b0a711340322dca272b8cc0ebe473 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 22 Jul 2013 13:57:50 -0700 Subject: Use global indices array to draw layers An array of indices local to a layer would only be necessary if we changed the way we resolve T-junctions. Since we only ever draw quads, let's just use the indices we use everywhere else. This change also uses the global indices array to render list of colored rectangles to save on the number of vertices generated CPU-side. Change-Id: Ia6d1970b0e9247805af5a114ca2a84b5d0b7c282 --- libs/hwui/Layer.cpp | 2 -- libs/hwui/Layer.h | 1 - libs/hwui/LayerRenderer.cpp | 21 -------------- libs/hwui/OpenGLRenderer.cpp | 68 ++++++++++++++++++++++++++++++-------------- libs/hwui/OpenGLRenderer.h | 9 +++++- 5 files changed, 54 insertions(+), 47 deletions(-) (limited to 'libs/hwui') diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 73082c1..bd371a3 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -31,7 +31,6 @@ namespace uirenderer { Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight): caches(Caches::getInstance()), texture(caches) { mesh = NULL; - meshIndices = NULL; meshElementCount = 0; cacheable = true; dirty = false; @@ -57,7 +56,6 @@ Layer::~Layer() { deleteTexture(); delete[] mesh; - delete[] meshIndices; delete deferredList; } diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index ebd5543..b70042f 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -277,7 +277,6 @@ struct Layer { * If the layer can be rendered as a mesh, this is non-null. */ TextureVertex* mesh; - uint16_t* meshIndices; GLsizei meshElementCount; /** diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index cfb1e97..f8076cc 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -130,10 +130,7 @@ void LayerRenderer::generateMesh() { if (mLayer->region.isRect() || mLayer->region.isEmpty()) { if (mLayer->mesh) { delete[] mLayer->mesh; - delete[] mLayer->meshIndices; - mLayer->mesh = NULL; - mLayer->meshIndices = NULL; mLayer->meshElementCount = 0; } @@ -154,17 +151,11 @@ void LayerRenderer::generateMesh() { if (mLayer->mesh && mLayer->meshElementCount < elementCount) { delete[] mLayer->mesh; - delete[] mLayer->meshIndices; - mLayer->mesh = NULL; - mLayer->meshIndices = NULL; } - bool rebuildIndices = false; if (!mLayer->mesh) { mLayer->mesh = new TextureVertex[count * 4]; - mLayer->meshIndices = new uint16_t[elementCount]; - rebuildIndices = true; } mLayer->meshElementCount = elementCount; @@ -173,7 +164,6 @@ void LayerRenderer::generateMesh() { const float height = mLayer->layer.getHeight(); TextureVertex* mesh = mLayer->mesh; - uint16_t* indices = mLayer->meshIndices; for (size_t i = 0; i < count; i++) { const android::Rect* r = &rects[i]; @@ -187,17 +177,6 @@ void LayerRenderer::generateMesh() { TextureVertex::set(mesh++, r->right, r->top, u2, v1); TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); - - if (rebuildIndices) { - uint16_t quad = i * 4; - int index = i * 6; - indices[index ] = quad; // top-left - indices[index + 1] = quad + 1; // top-right - indices[index + 2] = quad + 2; // bottom-left - indices[index + 3] = quad + 2; // bottom-left - indices[index + 4] = quad + 1; // top-right - indices[index + 5] = quad + 3; // bottom-right - } } } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 3e84273..06315ba 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -107,6 +107,15 @@ static const Blender gBlendsSwap[] = { }; /////////////////////////////////////////////////////////////////////////////// +// Functions +/////////////////////////////////////////////////////////////////////////////// + +template +static inline T min(T a, T b) { + return a < b ? a : b; +} + +/////////////////////////////////////////////////////////////////////////////// // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// @@ -1284,7 +1293,6 @@ void OpenGLRenderer::drawRegionRects(const Region& region) { void OpenGLRenderer::drawRegionRects(const SkRegion& region, int color, SkXfermode::Mode mode, bool dirty) { - int count = 0; Vector rects; SkRegion::Iterator it(region); @@ -1294,11 +1302,10 @@ void OpenGLRenderer::drawRegionRects(const SkRegion& region, int color, rects.push(r.fTop); rects.push(r.fRight); rects.push(r.fBottom); - count += 4; it.next(); } - drawColorRects(rects.array(), count, color, mode, true, dirty, false); + drawColorRects(rects.array(), rects.size(), color, mode, true, dirty, false); } void OpenGLRenderer::dirtyLayer(const float left, const float top, @@ -1328,6 +1335,21 @@ void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { } } +void OpenGLRenderer::drawIndexedQuads(Vertex* mesh, GLsizei quadsCount) { + GLsizei elementsCount = quadsCount * 6; + while (elementsCount > 0) { + GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6); + + setupDrawIndexedVertices(&mesh[0].position[0]); + glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, NULL); + + elementsCount -= drawCount; + // Though there are 4 vertices in a quad, we use 6 indices per + // quad to draw with GL_TRIANGLES + mesh += (drawCount / 6) * 4; + } +} + void OpenGLRenderer::clearLayerRegions() { const size_t count = mLayers.size(); if (count == 0) return; @@ -1342,17 +1364,15 @@ void OpenGLRenderer::clearLayerRegions() { // is likely different so we need to disable clipping here bool scissorChanged = mCaches.disableScissor(); - Vertex mesh[count * 6]; + Vertex mesh[count * 4]; Vertex* vertex = mesh; for (uint32_t i = 0; i < count; i++) { Rect* bounds = mLayers.itemAt(i); - Vertex::set(vertex++, bounds->left, bounds->bottom); Vertex::set(vertex++, bounds->left, bounds->top); Vertex::set(vertex++, bounds->right, bounds->top); Vertex::set(vertex++, bounds->left, bounds->bottom); - Vertex::set(vertex++, bounds->right, bounds->top); Vertex::set(vertex++, bounds->right, bounds->bottom); delete bounds; @@ -1368,9 +1388,8 @@ void OpenGLRenderer::clearLayerRegions() { setupDrawProgram(); setupDrawPureColorUniforms(); setupDrawModelViewTranslate(0.0f, 0.0f, 0.0f, 0.0f, true); - setupDrawVertices(&mesh[0].position[0]); - glDrawArrays(GL_TRIANGLES, 0, count * 6); + drawIndexedQuads(&mesh[0], count); if (scissorChanged) mCaches.enableScissor(); } else { @@ -1976,10 +1995,10 @@ void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, G } } -void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) { +void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) { bool force = mCaches.unbindMeshBuffer(); + mCaches.bindIndicesBuffer(); mCaches.bindPositionVertexPointer(force, vertices, gVertexStride); - mCaches.unbindIndicesBuffer(); } void OpenGLRenderer::finishDrawTexture() { @@ -3139,11 +3158,22 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { setupDrawModelViewTranslate(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight()); } - setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]); - DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, - glDrawElements(GL_TRIANGLES, layer->meshElementCount, - GL_UNSIGNED_SHORT, layer->meshIndices)); + TextureVertex* mesh = &layer->mesh[0]; + GLsizei elementsCount = layer->meshElementCount; + + while (elementsCount > 0) { + GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6); + + setupDrawMeshIndices(&mesh[0].position[0], &mesh[0].texture[0]); + DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, + glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, NULL)); + + elementsCount -= drawCount; + // Though there are 4 vertices in a quad, we use 6 indices per + // quad to draw with GL_TRIANGLES + mesh += (drawCount / 6) * 4; + } finishDrawTexture(); @@ -3361,8 +3391,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color float right = FLT_MIN; float bottom = FLT_MIN; - int vertexCount = 0; - Vertex mesh[count * 6]; + Vertex mesh[count]; Vertex* vertex = mesh; for (int index = 0; index < count; index += 4) { @@ -3371,15 +3400,11 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color float r = rects[index + 2]; float b = rects[index + 3]; - Vertex::set(vertex++, l, b); Vertex::set(vertex++, l, t); Vertex::set(vertex++, r, t); Vertex::set(vertex++, l, b); - Vertex::set(vertex++, r, t); Vertex::set(vertex++, r, b); - vertexCount += 6; - left = fminf(left, l); top = fminf(top, t); right = fmaxf(right, r); @@ -3402,13 +3427,12 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color setupDrawColorUniforms(); setupDrawShaderUniforms(); setupDrawColorFilterUniforms(); - setupDrawVertices((GLvoid*) &mesh[0].position[0]); if (dirty && hasLayer()) { dirtyLayer(left, top, right, bottom, currentTransform()); } - glDrawArrays(GL_TRIANGLES, 0, vertexCount); + drawIndexedQuads(&mesh[0], count / 4); return DrawGlInfo::kStatusDrew; } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 5e731b4..eb42540 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -850,6 +850,13 @@ private: bool ignoreTransform, bool ignoreScale = false, bool dirty = true); /** + * Draws the specified list of vertices as quads using indexed GL_TRIANGLES. + * If the number of vertices to draw exceeds the number of indices we have + * pre-allocated, this method will generate several glDrawElements() calls. + */ + void drawIndexedQuads(Vertex* mesh, GLsizei quadsCount); + + /** * Draws text underline and strike-through if needed. * * @param text The text to decor @@ -988,7 +995,7 @@ private: void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0); void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors); void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0); - void setupDrawVertices(GLvoid* vertices); + void setupDrawIndexedVertices(GLvoid* vertices); void finishDrawTexture(); void accountForClear(SkXfermode::Mode mode); -- cgit v1.1