Reduce the number of GL commands generated by the UI

This optimization along with the previous one lets us render an
application like Gmail using only 30% of the number of GL commands
previously required

Change-Id: Ifee63edaf495e04490b5abd5433bb9a07bc327a8
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index fcac053..59d3fcc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -144,6 +144,7 @@
     glDisable(GL_DITHER);
     glEnable(GL_SCISSOR_TEST);
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
     glEnableVertexAttribArray(Program::kBindingPosition);
 }
 
@@ -199,7 +200,9 @@
         }
     }
     mCaches.unbindMeshBuffer();
+    mCaches.unbindIndicesBuffer();
     mCaches.resetVertexPointers();
+    mCaches.disbaleTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::resume() {
@@ -212,7 +215,6 @@
     dirtyClip();
 
     glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     mCaches.blend = true;
     glEnable(GL_BLEND);
@@ -771,7 +773,7 @@
             layer->setFilter(GL_LINEAR);
             setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
         }
-        setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
+        setupDrawMeshIndices(&mesh[0].position[0], &mesh[0].texture[0]);
 
         for (size_t i = 0; i < count; i++) {
             const android::Rect* r = &rects[i];
@@ -800,7 +802,6 @@
             glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL);
         }
 
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
         finishDrawTexture();
 
 #if DEBUG_LAYERS_AS_REGIONS
@@ -1015,7 +1016,6 @@
     mColorA = mColorR = mColorG = mColorB = 0.0f;
     mTextureUnit = 0;
     mTrackDirtyRegions = true;
-    mTexCoordsSlot = -1;
 }
 
 void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
@@ -1027,6 +1027,10 @@
     mDescription.hasExternalTexture = true;
 }
 
+void OpenGLRenderer::setupDrawNoTexture() {
+    mCaches.disbaleTexCoordsVertexArray();
+}
+
 void OpenGLRenderer::setupDrawAALine() {
     mDescription.isAA = true;
 }
@@ -1203,22 +1207,19 @@
 void OpenGLRenderer::setupDrawSimpleMesh() {
     bool force = mCaches.bindMeshBuffer();
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
+    mCaches.unbindIndicesBuffer();
 }
 
 void OpenGLRenderer::setupDrawTexture(GLuint texture) {
     bindTexture(texture);
     glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
-
-    mTexCoordsSlot = mCaches.currentProgram->texCoords;
-    glEnableVertexAttribArray(mTexCoordsSlot);
+    mCaches.enableTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
     bindExternalTexture(texture);
     glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
-
-    mTexCoordsSlot = mCaches.currentProgram->texCoords;
-    glEnableVertexAttribArray(mTexCoordsSlot);
+    mCaches.enableTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::setupDrawTextureTransform() {
@@ -1239,8 +1240,18 @@
     }
 
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
-    if (mTexCoordsSlot >= 0) {
-        mCaches.bindTexCoordsVertexPointer(force, mTexCoordsSlot, texCoords);
+    if (mCaches.currentProgram->texCoords >= 0) {
+        mCaches.bindTexCoordsVertexPointer(force, mCaches.currentProgram->texCoords, texCoords);
+    }
+
+    mCaches.unbindIndicesBuffer();
+}
+
+void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords) {
+    bool force = mCaches.unbindMeshBuffer();
+    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
+    if (mCaches.currentProgram->texCoords >= 0) {
+        mCaches.bindTexCoordsVertexPointer(force, mCaches.currentProgram->texCoords, texCoords);
     }
 }
 
@@ -1248,6 +1259,7 @@
     bool force = mCaches.unbindMeshBuffer();
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
             vertices, gVertexStride);
+    mCaches.unbindIndicesBuffer();
 }
 
 /**
@@ -1267,6 +1279,7 @@
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
             vertices, gAAVertexStride);
     mCaches.resetTexCoordsVertexPointer();
+    mCaches.unbindIndicesBuffer();
 
     int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
     glEnableVertexAttribArray(widthSlot);
@@ -1285,7 +1298,6 @@
 }
 
 void OpenGLRenderer::finishDrawTexture() {
-    glDisableVertexAttribArray(mTexCoordsSlot);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1624,6 +1636,7 @@
     }
 
     setupDraw();
+    setupDrawNoTexture();
     setupDrawAALine();
     setupDrawColor(color);
     setupDrawColorFilter();
@@ -1734,6 +1747,7 @@
 
     getAlphaAndMode(paint, &alpha, &mode);
     setupDraw();
+    setupDrawNoTexture();
     if (isAA) {
         setupDrawAALine();
     }
@@ -1943,6 +1957,7 @@
     TextureVertex* vertex = &pointsData[0];
 
     setupDraw();
+    setupDrawNoTexture();
     setupDrawPoint(strokeWidth);
     setupDrawColor(paint->getColor(), alpha);
     setupDrawColorFilter();
@@ -2186,13 +2201,6 @@
     bool hasActiveLayer = false;
 #endif
 
-    float* buffer = fontRenderer.getMeshBuffer();
-    int offset = fontRenderer.getMeshTexCoordsOffset();
-
-    bool force = mCaches.unbindMeshBuffer();
-    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, buffer);
-    mCaches.bindTexCoordsVertexPointer(force, mTexCoordsSlot, buffer + offset);
-
     if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
             hasActiveLayer ? &bounds : NULL)) {
 #if RENDER_LAYERS_AS_REGIONS
@@ -2205,9 +2213,6 @@
 #endif
     }
 
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glDisableVertexAttribArray(mCaches.currentProgram->texCoords);
-
     drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
 }
 
@@ -2437,6 +2442,7 @@
     }
 
     setupDraw();
+    setupDrawNoTexture();
     setupDrawColor(color);
     setupDrawShader();
     setupDrawColorFilter();