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
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 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// Functions
+///////////////////////////////////////////////////////////////////////////////
+
+template<typename T>
+static inline T min(T a, T b) {
+    return a < b ? a : b;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -1284,7 +1293,6 @@
 
 void OpenGLRenderer::drawRegionRects(const SkRegion& region, int color,
         SkXfermode::Mode mode, bool dirty) {
-    int count = 0;
     Vector<float> rects;
 
     SkRegion::Iterator it(region);
@@ -1294,11 +1302,10 @@
         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::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 @@
         // 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 @@
         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::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 @@
                 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 @@
     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 @@
         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 @@
     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;
 }