Use VBOs to render most geometries.

Change-Id: I4360dc4fe5693ab425450c107282b2c22db4dca7
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 437a9ef..5bf0ccc 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -6,10 +6,10 @@
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SRC_FILES:= \
 		utils/SortedListImpl.cpp \
-		DisplayListRenderer.cpp \
-		FboCache.cpp \
 		FontRenderer.cpp \
 		GammaFontRenderer.cpp \
+		DisplayListRenderer.cpp \
+		FboCache.cpp \
 		GradientCache.cpp \
 		LayerCache.cpp \
 		Matrix.cpp \
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 2952a66..e6e494d 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -23,11 +23,12 @@
 
 #include <utils/Singleton.h>
 
+#include "FontRenderer.h"
+#include "GammaFontRenderer.h"
 #include "TextureCache.h"
 #include "LayerCache.h"
 #include "GradientCache.h"
 #include "PatchCache.h"
-#include "GammaFontRenderer.h"
 #include "ProgramCache.h"
 #include "PathCache.h"
 #include "TextDropShadowCache.h"
@@ -37,15 +38,55 @@
 namespace android {
 namespace uirenderer {
 
+///////////////////////////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////////////////////////
+
+#define REQUIRED_TEXTURE_UNITS_COUNT 3
+
+// Generates simple and textured vertices
+#define FV(x, y, u, v) { { x, y }, { u, v } }
+
+// This array is never used directly but used as a memcpy source in the
+// OpenGLRenderer constructor
+static const TextureVertex gMeshVertices[] = {
+        FV(0.0f, 0.0f, 0.0f, 0.0f),
+        FV(1.0f, 0.0f, 1.0f, 0.0f),
+        FV(0.0f, 1.0f, 0.0f, 1.0f),
+        FV(1.0f, 1.0f, 1.0f, 1.0f)
+};
+static const GLsizei gMeshStride = sizeof(TextureVertex);
+static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
+static const GLsizei gMeshCount = 4;
+
+///////////////////////////////////////////////////////////////////////////////
+// Debug
+///////////////////////////////////////////////////////////////////////////////
+
 struct CacheLogger {
     CacheLogger() {
         LOGD("Creating caches");
     }
 }; // struct CacheLogger
 
+///////////////////////////////////////////////////////////////////////////////
+// Caches
+///////////////////////////////////////////////////////////////////////////////
+
 class Caches: public Singleton<Caches> {
     Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO),
             lastDstMode(GL_ZERO), currentProgram(NULL) {
+        GLint maxTextureUnits;
+        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+        if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
+            LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
+        }
+
+        glGenBuffers(1, &meshBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
+
+        currentBuffer = meshBuffer;
     }
 
     friend class Singleton<Caches>;
@@ -53,11 +94,41 @@
     CacheLogger logger;
 
 public:
+    /**
+     * Binds the VBO used to render simple textured quads.
+     */
+    inline void bindMeshBuffer() {
+        bindMeshBuffer(meshBuffer);
+    }
+
+    /**
+     * Binds the specified VBO.
+     */
+    inline void bindMeshBuffer(const GLuint buffer) {
+        if (currentBuffer != buffer) {
+            glBindBuffer(GL_ARRAY_BUFFER, buffer);
+            currentBuffer = buffer;
+        }
+    }
+
+    /**
+     * Unbinds the VBO used to render simple textured quads.
+     */
+    inline void unbindMeshBuffer() {
+        if (currentBuffer) {
+            glBindBuffer(GL_ARRAY_BUFFER, 0);
+            currentBuffer = 0;
+        }
+    }
+
     bool blend;
     GLenum lastSrcMode;
     GLenum lastDstMode;
     Program* currentProgram;
 
+    GLuint meshBuffer;
+    GLuint currentBuffer;
+
     TextureCache textureCache;
     LayerCache layerCache;
     GradientCache gradientCache;
diff --git a/libs/hwui/Line.h b/libs/hwui/Line.h
index 64bdd6a..c529354 100644
--- a/libs/hwui/Line.h
+++ b/libs/hwui/Line.h
@@ -96,12 +96,8 @@
         ty = lineWidth <= 1.0f ? -gLineAABias : -half - gLineAABias;
     }
 
-    inline GLvoid* getVertices() const {
-        return &mPatch->vertices[0].position[0];
-    }
-
-    inline GLvoid* getTexCoords() const {
-        return &mPatch->vertices[0].texture[0];
+    inline GLuint getMeshBuffer() const {
+        return mPatch->meshBuffer;
     }
 
     inline GLsizei getElementsCount() const {
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 1a0fcf4..83ea615 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -55,9 +55,11 @@
 }
 
 bool Matrix4::changesBounds() {
-    return !(almost(data[0], 1.0f) && almost(data[1], 0.0f) && almost(data[2], 0.0f) &&
-             almost(data[4], 0.0f) && almost(data[5], 1.0f) && almost(data[6], 0.0f) &&
-             almost(data[8], 0.0f) && almost(data[9], 0.0f) && almost(data[10], 1.0f));
+    return !(ALMOST_EQUAL(data[0], 1.0f) && ALMOST_EQUAL(data[1], 0.0f) &&
+             ALMOST_EQUAL(data[2], 0.0f) && ALMOST_EQUAL(data[4], 0.0f) &&
+             ALMOST_EQUAL(data[5], 1.0f) && ALMOST_EQUAL(data[6], 0.0f) &&
+             ALMOST_EQUAL(data[8], 0.0f) && ALMOST_EQUAL(data[9], 0.0f) &&
+             ALMOST_EQUAL(data[10], 1.0f));
 }
 
 void Matrix4::load(const float* v) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 481e2df..5ab5f06 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -35,11 +35,6 @@
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
 
-#define REQUIRED_TEXTURE_UNITS_COUNT 3
-
-// Generates simple and textured vertices
-#define FV(x, y, u, v) { { x, y }, { u, v } }
-
 #define RAD_TO_DEG (180.0f / 3.14159265f)
 #define MIN_ANGLE 0.001f
 
@@ -50,17 +45,6 @@
 // Globals
 ///////////////////////////////////////////////////////////////////////////////
 
-// This array is never used directly but used as a memcpy source in the
-// OpenGLRenderer constructor
-static const TextureVertex gMeshVertices[] = {
-        FV(0.0f, 0.0f, 0.0f, 0.0f),
-        FV(1.0f, 0.0f, 1.0f, 0.0f),
-        FV(0.0f, 1.0f, 0.0f, 1.0f),
-        FV(1.0f, 1.0f, 1.0f, 1.0f)
-};
-static const GLsizei gMeshStride = sizeof(TextureVertex);
-static const GLsizei gMeshCount = 4;
-
 /**
  * Structure mapping Skia xfermodes to OpenGL blending factors.
  */
@@ -124,12 +108,6 @@
 
     mFirstSnapshot = new Snapshot;
 
-    GLint maxTextureUnits;
-    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
-    if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
-        LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
-    }
-
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 }
 
@@ -201,6 +179,8 @@
     glDisable(GL_DITHER);
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    mCaches.bindMeshBuffer();
 
     if (mCaches.blend) {
         glEnable(GL_BLEND);
@@ -514,11 +494,13 @@
     }
 
     const Rect& texCoords = layer->texCoords;
+    mCaches.unbindMeshBuffer();
     resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
 
     if (fboLayer) {
-        drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
-                layer->texture, layer->alpha / 255.0f, layer->mode, layer->blend);
+        drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
+                layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
+                &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount);
     } else {
         drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
                 1.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
@@ -698,9 +680,16 @@
     const float u2 = srcRight / width;
     const float v2 = srcBottom / height;
 
+    mCaches.unbindMeshBuffer();
     resetDrawTextureTexCoords(u1, v1, u2, v2);
 
-    drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndMode(paint, &alpha, &mode);
+
+    drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
+            mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+            GL_TRIANGLE_STRIP, gMeshCount);
 
     resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
 }
@@ -728,8 +717,8 @@
         // Specify right and bottom as +1.0f from left/top to prevent scaling since the
         // patch mesh already defines the final size
         drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f,
-                mode, texture->blend, &mesh->vertices[0].position[0],
-                &mesh->vertices[0].texture[0], GL_TRIANGLES, mesh->verticesCount);
+                mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
+                GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer);
     }
 }
 
@@ -750,7 +739,8 @@
     if (isAA) {
         GLuint textureUnit = 0;
         setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
-                mode, false, true, mCaches.line.getVertices(), mCaches.line.getTexCoords());
+                mode, false, true, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
+                mCaches.line.getMeshBuffer());
     } else {
         setupColorRect(0.0f, 0.0f, 1.0f, 1.0f, r, g, b, a, mode, false);
     }
@@ -891,11 +881,12 @@
     // Assume that the modelView matrix does not force scales, rotates, etc.
     const bool linearFilter = mSnapshot->transform->changesBounds();
     setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit,
-            x, y, r, g, b, a, mode, false, true);
+            x, y, r, g, b, a, mode, false, true, NULL, NULL);
 
     const Rect& clip = mSnapshot->getLocalClip();
     clearLayerRegions();
 
+    mCaches.unbindMeshBuffer();
     fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -1009,21 +1000,20 @@
         bool transforms, bool applyFilters) {
     setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit,
             x, y, r, g, b, a, mode, transforms, applyFilters,
-            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
+            (GLvoid*) 0, (GLvoid*) gMeshTextureOffset);
 }
 
 void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
         GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
         SkXfermode::Mode mode, bool transforms, bool applyFilters) {
-    setupTextureAlpha8(texture, width, height, textureUnit,
-            x, y, r, g, b, a, mode, transforms, applyFilters,
-            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
+    setupTextureAlpha8(texture, width, height, textureUnit, x, y, r, g, b, a, mode,
+            transforms, applyFilters, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset);
 }
 
 void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
         GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
         SkXfermode::Mode mode, bool transforms, bool applyFilters,
-        GLvoid* vertices, GLvoid* texCoords) {
+        GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
      // Describe the required shaders
      ProgramDescription description;
      description.hasTexture = true;
@@ -1051,11 +1041,17 @@
      int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
      glEnableVertexAttribArray(texCoordsSlot);
 
-     // Setup attributes
-     glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-             gMeshStride, vertices);
-     glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
-             gMeshStride, texCoords);
+     if (texCoords) {
+         // Setup attributes
+         if (!vertices) {
+             mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+         } else {
+             mCaches.unbindMeshBuffer();
+         }
+         glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+                 gMeshStride, vertices);
+         glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
+     }
 
      // Setup uniforms
      if (transforms) {
@@ -1188,8 +1184,9 @@
     useProgram(mCaches.programCache.get(description));
 
     // Setup attributes
+    mCaches.bindMeshBuffer();
     glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-            gMeshStride, &mMeshVertices[0].position[0]);
+            gMeshStride, 0);
 
     // Setup uniforms
     mModelView.loadTranslate(left, top, 0.0f);
@@ -1218,21 +1215,20 @@
     getAlphaAndMode(paint, &alpha, &mode);
 
     drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
-            texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+            texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
             GL_TRIANGLE_STRIP, gMeshCount);
 }
 
 void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
         GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
     drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
-            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
-            GL_TRIANGLE_STRIP, gMeshCount);
+            (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount);
 }
 
 void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
         GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
         GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool swapSrcDst, bool ignoreTransform) {
+        bool swapSrcDst, bool ignoreTransform, GLuint vbo) {
     clearLayerRegions();
 
     ProgramDescription description;
@@ -1267,6 +1263,12 @@
     // Mesh
     int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
     glEnableVertexAttribArray(texCoordsSlot);
+
+    if (!vertices) {
+        mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+    } else {
+        mCaches.unbindMeshBuffer();
+    }
     glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
             gMeshStride, vertices);
     glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 423614b..1d8a3d9 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -234,8 +234,9 @@
             const Texture* texture, const SkPaint* paint);
 
     /**
-     * Draws a textured mesh with the specified texture. If the indices are omitted, the
-     * mesh is drawn as a simple quad.
+     * Draws a textured mesh with the specified texture. If the indices are omitted,
+     * the mesh is drawn as a simple quad. The mesh pointers become offsets when a
+     * VBO is bound.
      *
      * @param left The left coordinate of the rectangle
      * @param top The top coordinate of the rectangle
@@ -247,15 +248,15 @@
      * @param blend True if the texture contains an alpha channel
      * @param vertices The vertices that define the mesh
      * @param texCoords The texture coordinates of each vertex
-     * @param indices The indices of the vertices, can be NULL
      * @param elementsCount The number of elements in the mesh, required by indices
      * @param swapSrcDst Whether or not the src and dst blending operations should be swapped
      * @param ignoreTransform True if the current transform should be ignored
+     * @param vbo The VBO used to draw the mesh
      */
     void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
             float alpha, SkXfermode::Mode mode, bool blend,
             GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool swapSrcDst = false, bool ignoreTransform = false);
+            bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0);
 
     /**
      * Prepares the renderer to draw the specified shadow.
@@ -315,12 +316,12 @@
 
     /**
      * Same as above setupTextureAlpha8() but specifies the mesh's vertices
-     * and texCoords pointers.
+     * and texCoords pointers. The pointers become offsets when a VBO is bound.
      */
     void setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
             GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
             SkXfermode::Mode mode, bool transforms, bool applyFilters,
-            GLvoid* vertices, GLvoid* texCoords);
+            GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
 
     /**
      * Draws text underline and strike-through if needed.
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 560decf..c2ebee0 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -19,12 +19,16 @@
 #include <cmath>
 
 #include <utils/Log.h>
+#include <utils/String8.h>
 
 #include "Patch.h"
+#include "Caches.h"
 
 namespace android {
 namespace uirenderer {
 
+class Caches;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
@@ -32,11 +36,14 @@
 Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads) {
     // 2 triangles per patch, 3 vertices per triangle
     verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
-    vertices = new TextureVertex[verticesCount];
+    mVertices = new TextureVertex[verticesCount];
+
+    glGenBuffers(1, &meshBuffer);
 }
 
 Patch::~Patch() {
-    delete[] vertices;
+    delete[] mVertices;
+    glDeleteBuffers(1, &meshBuffer);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -77,7 +84,7 @@
         stretchY = yStretch / yStretchTex;
     }
 
-    TextureVertex* vertex = vertices;
+    TextureVertex* vertex = mVertices;
     uint32_t quadCount = 0;
 
     float previousStepY = 0.0f;
@@ -108,6 +115,10 @@
 
     generateRow(vertex, y1, bottom - top, v1, 1.0f, xDivs, width, stretchX,
             right - left, bitmapWidth, quadCount, colorKey);
+
+    Caches::getInstance().bindMeshBuffer(meshBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
+                mVertices, GL_STATIC_DRAW);
 }
 
 inline void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 54c9d6c..869b3bf 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -19,6 +19,8 @@
 
 #include <sys/types.h>
 
+#include <GLES2/gl2.h>
+
 #include "Vertex.h"
 #include "utils/Compare.h"
 
@@ -59,14 +61,14 @@
     uint32_t colorKey;
 
     bool operator<(const PatchDescription& rhs) const {
-        compare(bitmapWidth) {
-            compare(bitmapHeight) {
-                compare(pixelWidth) {
-                    compare(pixelHeight) {
-                        compareI(xCount) {
-                            compareI(yCount) {
-                                compareI(emptyCount) {
-                                    compareI(colorKey) return false;
+        FLOAT_COMPARE(bitmapWidth) {
+            FLOAT_COMPARE(bitmapHeight) {
+                FLOAT_COMPARE(pixelWidth) {
+                    FLOAT_COMPARE(pixelHeight) {
+                        INT_COMPARE(xCount) {
+                            INT_COMPARE(yCount) {
+                                INT_COMPARE(emptyCount) {
+                                    INT_COMPARE(colorKey) return false;
                                 }
                             }
                         }
@@ -92,10 +94,12 @@
             const uint32_t width, const uint32_t height,
             const uint32_t colorKey = 0);
 
-    TextureVertex* vertices;
+    GLuint meshBuffer;
     uint32_t verticesCount;
 
 private:
+    TextureVertex* mVertices;
+
     static inline void generateRow(TextureVertex*& vertex, float y1, float y2,
             float v1, float v2, const int32_t xDivs[], uint32_t xCount,
             float stretchX, float width, float bitmapWidth,
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 0fad628..71bab91 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -68,7 +68,7 @@
     }
 
     // If the 9patch is made of only transparent quads
-    if (transparentQuads == (width + 1) * (height + 1)) {
+    if (transparentQuads == int8_t((width + 1) * (height + 1))) {
         return NULL;
     }
 
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 0c74261..af6822d 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -64,12 +64,12 @@
     float strokeWidth;
 
     bool operator<(const PathCacheEntry& rhs) const {
-        compareI(path) {
-            compareI(join) {
-                compareI(cap) {
-                    compareI(style) {
-                        compare(miter) {
-                            compare(strokeWidth) return false;
+        INT_COMPARE(path) {
+            INT_COMPARE(join) {
+                INT_COMPARE(cap) {
+                    INT_COMPARE(style) {
+                        FLOAT_COMPARE(miter) {
+                            FLOAT_COMPARE(strokeWidth) return false;
                         }
                     }
                 }
diff --git a/libs/hwui/utils/Compare.h b/libs/hwui/utils/Compare.h
index 754b470..ddb9c0b 100644
--- a/libs/hwui/utils/Compare.h
+++ b/libs/hwui/utils/Compare.h
@@ -21,19 +21,19 @@
 
 #define EPSILON 0.00001f
 
-#define almost(u, v) (fabs((u) - (v)) < EPSILON)
+#define ALMOST_EQUAL(u, v) (fabs((u) - (v)) < EPSILON)
 
 /**
  * Compare floats.
  */
-#define compare(a) \
+#define FLOAT_COMPARE(a) \
     if (a < rhs.a) return true; \
-    if (almost(a, rhs.a))
+    if (ALMOST_EQUAL(a, rhs.a))
 
 /**
  * Compare integers.
  */
-#define compareI(a) \
+#define INT_COMPARE(a) \
     if (a < rhs.a) return true; \
     if (a == rhs.a)