Add visual profiling feature

When profiling is enabled with debug.hwui.profile set to true,
setting debug.hwui.profile_visualizer to true will display the
profiling data directly on screen.

Change-Id: I3d5fe3f0347090815087b1cbfce66b8e76d9347b
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 7a38b40..747856c 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -64,6 +64,7 @@
     "DrawTextOnPath",
     "DrawPosText",
     "DrawText",
+    "DrawRects",
     "ResetShader",
     "SetupShader",
     "ResetColorFilter",
@@ -633,6 +634,13 @@
                         text.text(), text.length(), count, paint);
             }
             break;
+            case DrawRects: {
+                int32_t count = 0;
+                float* rects = getFloats(count);
+                SkPaint* paint = getPaint(renderer);
+                ALOGD("%s%s %d, %p", (char*) indent, OP_NAMES[op], count / 4, paint);
+            }
+            break;
             case ResetShader: {
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
@@ -1277,6 +1285,14 @@
                         x, y, positions, paint, length);
             }
             break;
+            case DrawRects: {
+                int32_t count = 0;
+                float* rects = getFloats(count);
+                SkPaint* paint = getPaint(renderer);
+                DISPLAY_LIST_LOGD("%s%s %d, %p", (char*) indent, OP_NAMES[op], count, paint);
+                drawGlStatus |= renderer.drawRects(rects, count / 4, paint);
+            }
+            break;
             case ResetShader: {
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 renderer.resetShader();
@@ -1814,6 +1830,15 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
+    if (count <= 0) return DrawGlInfo::kStatusDone;
+
+    addOp(DisplayList::DrawRects);
+    addFloats(rects, count * 4);
+    addPaint(paint);
+    return DrawGlInfo::kStatusDone;
+}
+
 void DisplayListRenderer::resetShader() {
     addOp(DisplayList::ResetShader);
 }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index e42def5..fb01753 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -106,6 +106,7 @@
         DrawTextOnPath,
         DrawPosText,
         DrawText,
+        DrawRects,
         ResetShader,
         SetupShader,
         ResetColorFilter,
@@ -608,6 +609,7 @@
             const float* positions, SkPaint* paint);
     virtual status_t drawText(const char* text, int bytesCount, int count,
             float x, float y, const float* positions, SkPaint* paint, float length);
+    virtual status_t drawRects(const float* rects, int count, SkPaint* paint);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index ca9a38e..4b1d8ec 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1254,7 +1254,8 @@
     return !clip.intersects(transformed);
 }
 
-bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint) {
+bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom,
+        SkPaint* paint) {
     if (paint->getStyle() != SkPaint::kFill_Style) {
         float outset = paint->getStrokeWidth() * 0.5f;
         return quickReject(left - outset, top - outset, right + outset, bottom + outset);
@@ -3030,6 +3031,76 @@
     }
 }
 
+status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
+    if (mSnapshot->isIgnored()) {
+        return DrawGlInfo::kStatusDone;
+    }
+
+    float left = FLT_MAX;
+    float top = FLT_MAX;
+    float right = FLT_MIN;
+    float bottom = FLT_MIN;
+
+    int vertexCount = 0;
+    Vertex mesh[count * 6];
+    Vertex* vertex = mesh;
+
+    for (int i = 0; i < count; i++) {
+        int index = i * 4;
+        float l = rects[index + 0];
+        float t = rects[index + 1];
+        float r = rects[index + 2];
+        float b = rects[index + 3];
+
+        if (!quickRejectNoScissor(left, top, right, bottom)) {
+            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);
+            bottom = fmaxf(bottom, b);
+        }
+    }
+
+    if (count == 0) return DrawGlInfo::kStatusDone;
+
+    int color = paint->getColor();
+    // If a shader is set, preserve only the alpha
+    if (mShader) {
+        color |= 0x00ffffff;
+    }
+    SkXfermode::Mode mode = getXfermode(paint->getXfermode());
+
+    setupDraw();
+    setupDrawNoTexture();
+    setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+    setupDrawShader();
+    setupDrawColorFilter();
+    setupDrawBlending(mode);
+    setupDrawProgram();
+    setupDrawDirtyRegionsDisabled();
+    setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f);
+    setupDrawColorUniforms();
+    setupDrawShaderUniforms();
+    setupDrawColorFilterUniforms();
+    setupDrawVertices((GLvoid*) &mesh[0].position[0]);
+
+    if (hasLayer()) {
+        dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+    }
+
+    glDrawArrays(GL_TRIANGLES, 0, vertexCount);
+
+    return DrawGlInfo::kStatusDrew;
+}
+
 void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
         int color, SkXfermode::Mode mode, bool ignoreTransform) {
     // If a shader is set, preserve only the alpha
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f165581..b1d3cc3 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -201,6 +201,7 @@
             const float* positions, SkPaint* paint);
     virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
             const float* positions, SkPaint* paint, float length = -1.0f);
+    virtual status_t drawRects(const float* rects, int count, SkPaint* paint);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
@@ -216,6 +217,10 @@
 
     SkPaint* filterPaint(SkPaint* paint);
 
+    ANDROID_API bool isCurrentTransformSimple() {
+        return mSnapshot->transform->isSimple();
+    }
+
     /**
      * Sets the alpha on the current snapshot. This alpha value will be modulated
      * with other alpha values when drawing primitives.