Optimize state changes

Change-Id: Iae59bc8dfd6427d0967472462cc1994987092827
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6e2f1c3..fcac053 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -199,13 +199,13 @@
         }
     }
     mCaches.unbindMeshBuffer();
+    mCaches.resetVertexPointers();
 }
 
 void OpenGLRenderer::resume() {
     sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
 
     glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
-
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
     glEnable(GL_SCISSOR_TEST);
@@ -1201,16 +1201,15 @@
 }
 
 void OpenGLRenderer::setupDrawSimpleMesh() {
-    mCaches.bindMeshBuffer();
-    glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-            gMeshStride, 0);
+    bool force = mCaches.bindMeshBuffer();
+    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
 }
 
 void OpenGLRenderer::setupDrawTexture(GLuint texture) {
     bindTexture(texture);
     glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
 
-    mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+    mTexCoordsSlot = mCaches.currentProgram->texCoords;
     glEnableVertexAttribArray(mTexCoordsSlot);
 }
 
@@ -1218,7 +1217,7 @@
     bindExternalTexture(texture);
     glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
 
-    mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+    mTexCoordsSlot = mCaches.currentProgram->texCoords;
     glEnableVertexAttribArray(mTexCoordsSlot);
 }
 
@@ -1232,23 +1231,23 @@
 }
 
 void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
+    bool force = false;
     if (!vertices) {
-        mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+        force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
     } else {
-        mCaches.unbindMeshBuffer();
+        force = mCaches.unbindMeshBuffer();
     }
 
-    glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-            gMeshStride, vertices);
+    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
     if (mTexCoordsSlot >= 0) {
-        glVertexAttribPointer(mTexCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
+        mCaches.bindTexCoordsVertexPointer(force, mTexCoordsSlot, texCoords);
     }
 }
 
 void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
-    mCaches.unbindMeshBuffer();
-    glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-            gVertexStride, vertices);
+    bool force = mCaches.unbindMeshBuffer();
+    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
+            vertices, gVertexStride);
 }
 
 /**
@@ -1264,10 +1263,10 @@
  */
 void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
         GLvoid* lengthCoords, float boundaryWidthProportion) {
-    mCaches.unbindMeshBuffer();
-
-    glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-            gAAVertexStride, vertices);
+    bool force = mCaches.unbindMeshBuffer();
+    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
+            vertices, gAAVertexStride);
+    mCaches.resetTexCoordsVertexPointer();
 
     int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
     glEnableVertexAttribArray(widthSlot);
@@ -2186,12 +2185,14 @@
 #else
     bool hasActiveLayer = false;
 #endif
-    mCaches.unbindMeshBuffer();
 
-    // Tell font renderer the locations of position and texture coord
-    // attributes so it can bind its data properly
-    int positionSlot = mCaches.currentProgram->position;
-    fontRenderer.setAttributeBindingSlots(positionSlot, mTexCoordsSlot);
+    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,7 +2206,7 @@
     }
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
+    glDisableVertexAttribArray(mCaches.currentProgram->texCoords);
 
     drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
 }