Share Caches' index buffer with FontRenderer

This reduces state changes when we draw 9patches and text together,
which happens *a lot*. Also disable the NV profiling extension by
default since it doesn't play nice with display lists deferrals.
To enable it set debug.hwui.nv_profiling to true.

Change-Id: I518b44b7d294e5def10c78911ceb9f01ae401609
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 31b0f6a..1089b7c 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -386,8 +386,8 @@
 
 bool Caches::bindIndicesBuffer() {
     if (!mMeshIndices) {
-        uint16_t* regionIndices = new uint16_t[REGION_MESH_QUAD_COUNT * 6];
-        for (int i = 0; i < REGION_MESH_QUAD_COUNT; i++) {
+        uint16_t* regionIndices = new uint16_t[gMaxNumberOfQuads * 6];
+        for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
             uint16_t quad = i * 4;
             int index = i * 6;
             regionIndices[index    ] = quad;       // top-left
@@ -400,7 +400,7 @@
 
         glGenBuffers(1, &mMeshIndices);
         bool force = bindIndicesBuffer(mMeshIndices);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, REGION_MESH_QUAD_COUNT * 6 * sizeof(uint16_t),
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t),
                 regionIndices, GL_STATIC_DRAW);
 
         delete[] regionIndices;
@@ -638,7 +638,7 @@
 TextureVertex* Caches::getRegionMesh() {
     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
     if (!mRegionMesh) {
-        mRegionMesh = new TextureVertex[REGION_MESH_QUAD_COUNT * 4];
+        mRegionMesh = new TextureVertex[gMaxNumberOfQuads * 4];
     }
 
     return mRegionMesh;
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index bdde8fb..b7a97ad 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -58,7 +58,8 @@
 // GL ES 2.0 defines that at least 16 texture units must be supported
 #define REQUIRED_TEXTURE_UNITS_COUNT 3
 
-#define REGION_MESH_QUAD_COUNT 512
+// Maximum number of quads that pre-allocated meshes can draw
+static const uint32_t gMaxNumberOfQuads = 2048;
 
 // Generates simple and textured vertices
 #define FV(x, y, u, v) { { x, y }, { u, v } }
@@ -181,7 +182,7 @@
 
     /**
      * Binds a global indices buffer that can draw up to
-     * REGION_MESH_QUAD_COUNT quads.
+     * gMaxNumberOfQuads quads.
      */
     bool bindIndicesBuffer();
     bool bindIndicesBuffer(const GLuint buffer);
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index eefdb84..218c18e 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -26,6 +26,7 @@
 
 #include "Debug.h"
 #include "Extensions.h"
+#include "Properties.h"
 
 namespace android {
 
@@ -63,7 +64,13 @@
 
     // Query EGL extensions
     findExtensions(eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS), mEglExtensionList);
-    mHasNvSystemTime = hasEglExtension("EGL_NV_system_time");
+
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_DEBUG_NV_PROFILING, property, NULL) > 0) {
+        mHasNvSystemTime = !strcmp(property, "true") && hasEglExtension("EGL_NV_system_time");
+    } else {
+        mHasNvSystemTime = false;
+    }
 
     const char* version = (const char*) glGetString(GL_VERSION);
 
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 3e3d882..79a7a93 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -64,8 +64,6 @@
 
     mLinearFiltering = false;
 
-    mIndexBufferID = 0;
-
     mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH;
     mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT;
     mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH;
@@ -111,12 +109,6 @@
     }
     mCacheTextures.clear();
 
-    if (mInitialized) {
-        // Unbinding the buffer shouldn't be necessary but it crashes with some drivers
-        Caches::getInstance().unbindIndicesBuffer();
-        glDeleteBuffers(1, &mIndexBufferID);
-    }
-
     LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
     while (it.next()) {
         delete it.value();
@@ -319,33 +311,6 @@
     mCurrentCacheTexture = mCacheTextures[0];
 }
 
-// Avoid having to reallocate memory and render quad by quad
-void FontRenderer::initVertexArrayBuffers() {
-    uint32_t numIndices = gMaxNumberOfQuads * 6;
-    uint32_t indexBufferSizeBytes = numIndices * sizeof(uint16_t);
-    uint16_t* indexBufferData = (uint16_t*) malloc(indexBufferSizeBytes);
-
-    // Four verts, two triangles , six indices per quad
-    for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
-        int i6 = i * 6;
-        int i4 = i * 4;
-
-        indexBufferData[i6 + 0] = i4 + 0;
-        indexBufferData[i6 + 1] = i4 + 1;
-        indexBufferData[i6 + 2] = i4 + 2;
-
-        indexBufferData[i6 + 3] = i4 + 0;
-        indexBufferData[i6 + 4] = i4 + 2;
-        indexBufferData[i6 + 5] = i4 + 3;
-    }
-
-    glGenBuffers(1, &mIndexBufferID);
-    Caches::getInstance().bindIndicesBuffer(mIndexBufferID);
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSizeBytes, indexBufferData, GL_STATIC_DRAW);
-
-    free(indexBufferData);
-}
-
 // We don't want to allocate anything unless we actually draw text
 void FontRenderer::checkInit() {
     if (mInitialized) {
@@ -353,7 +318,6 @@
     }
 
     initTextTexture();
-    initVertexArrayBuffers();
 
     mInitialized = true;
 }
@@ -416,7 +380,7 @@
                 if (mFunctor) (*mFunctor)(0, NULL);
 
                 checkTextureUpdate();
-                caches.bindIndicesBuffer(mIndexBufferID);
+                caches.bindIndicesBuffer();
 
                 if (!mDrawn) {
                     // If returns true, a VBO was bound and we must
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index cbbd871..c1072ed 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -105,8 +105,6 @@
 private:
     friend class Font;
 
-    static const uint32_t gMaxNumberOfQuads = 2048;
-
     const uint8_t* mGammaTable;
 
     void allocateTextureMemory(CacheTexture* cacheTexture);
@@ -118,7 +116,6 @@
     CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
 
     void flushAllAndInvalidate();
-    void initVertexArrayBuffers();
 
     void checkInit();
     void initRender(const Rect* clip, Rect* bounds, Functor* functor);
@@ -160,8 +157,6 @@
 
     bool mUploadTexture;
 
-    uint32_t mIndexBufferID;
-
     Functor* mFunctor;
     const Rect* mClip;
     Rect* mBounds;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a704b3d..0daf9c7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1230,7 +1230,7 @@
 
             numQuads++;
 
-            if (numQuads >= REGION_MESH_QUAD_COUNT) {
+            if (numQuads >= gMaxNumberOfQuads) {
                 DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
                                 GL_UNSIGNED_SHORT, NULL));
                 numQuads = 0;
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index dbbb956..86b0aa2 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -76,6 +76,12 @@
 #define PROPERTY_DEBUG_OVERDRAW "debug.hwui.overdraw"
 
 /**
+ * Used to enable/disable PerfHUD ES profiling. The accepted values
+ * are "true" and "false". The default value is "false".
+ */
+#define PROPERTY_DEBUG_NV_PROFILING "debug.hwui.nv_profiling"
+
+/**
  * Used to enable/disable non-rectangular clipping debugging.
  *
  * The accepted values are:
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
index 8c3ea0b..208b1ff 100644
--- a/libs/hwui/font/CacheTexture.h
+++ b/libs/hwui/font/CacheTexture.h
@@ -151,9 +151,9 @@
             float x3, float y3, float u3, float v3,
             float x4, float y4, float u4, float v4) {
         TextureVertex* mesh = mMesh + mCurrentQuad * 4;
-        TextureVertex::set(mesh++, x1, y1, u1, v1);
         TextureVertex::set(mesh++, x2, y2, u2, v2);
         TextureVertex::set(mesh++, x3, y3, u3, v3);
+        TextureVertex::set(mesh++, x1, y1, u1, v1);
         TextureVertex::set(mesh++, x4, y4, u4, v4);
         mCurrentQuad++;
     }