Clean up tessellation cache in prep for other tesselation types

bug:15536396

Also fixes compilation warning, avoids SkPaint deep copy

Change-Id: I74334f08b1d34c6789aabf968ff62db5bacbed1b
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 233f3f0..d578ef5 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1118,8 +1118,8 @@
             const DeferredDisplayState& state) {
         DrawStrokableOp::onDefer(renderer, deferInfo, state);
         if (!mPaint->getPathEffect()) {
-            renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix,
-                    mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy, mPaint);
+            renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
+                    mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
         }
     }
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0e47c6e2..fc4d40b 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -308,6 +308,10 @@
 
 status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
         float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
+    if (fabs(sweepAngle) > 360.0f) {
+        return drawOval(left, top, right, bottom, paint);
+    }
+
     paint = refPaint(paint);
     addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
                     startAngle, sweepAngle, useCenter, paint));
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8f3872a..6397478 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2556,8 +2556,8 @@
         return drawShape(left, top, texture, p);
     }
 
-    const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(*currentTransform(),
-            right - left, bottom - top, rx, ry, p);
+    const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(
+            *currentTransform(), *p, right - left, bottom - top, rx, ry);
     return drawVertexBuffer(left, top, *vertexBuffer, p);
 }
 
@@ -2611,10 +2611,6 @@
         return DrawGlInfo::kStatusDone;
     }
 
-    if (fabs(sweepAngle) >= 360.0f) {
-        return drawOval(left, top, right, bottom, p);
-    }
-
     // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
     if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || useCenter) {
         mCaches.activeTexture(0);
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index ef3d0d7..08b54ff 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -39,6 +39,8 @@
 
 TessellationCache::Description::Description()
         : type(kNone)
+        , scaleX(1.0f)
+        , scaleY(1.0f)
         , aa(false)
         , cap(SkPaint::kDefault_Cap)
         , style(SkPaint::kFill_Style)
@@ -46,21 +48,13 @@
     memset(&shape, 0, sizeof(Shape));
 }
 
-TessellationCache::Description::Description(Type type)
+TessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint)
         : type(type)
-        , aa(false)
-        , cap(SkPaint::kDefault_Cap)
-        , style(SkPaint::kFill_Style)
-        , strokeWidth(1.0f) {
-    memset(&shape, 0, sizeof(Shape));
-}
-
-TessellationCache::Description::Description(Type type, const SkPaint* paint)
-        : type(type)
-        , aa(paint->isAntiAlias())
-        , cap(paint->getStrokeCap())
-        , style(paint->getStyle())
-        , strokeWidth(paint->getStrokeWidth()) {
+        , aa(paint.isAntiAlias())
+        , cap(paint.getStrokeCap())
+        , style(paint.getStyle())
+        , strokeWidth(paint.getStrokeWidth()) {
+    PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
     memset(&shape, 0, sizeof(Shape));
 }
 
@@ -70,10 +64,20 @@
     hash = JenkinsHashMix(hash, cap);
     hash = JenkinsHashMix(hash, style);
     hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
+    hash = JenkinsHashMix(hash, android::hash_type(scaleX));
+    hash = JenkinsHashMix(hash, android::hash_type(scaleY));
     hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape));
     return JenkinsHashWhiten(hash);
 }
 
+void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const {
+    matrix->loadScale(scaleX, scaleY, 1.0f);
+    paint->setAntiAlias(aa);
+    paint->setStrokeCap(cap);
+    paint->setStyle(style);
+    paint->setStrokeWidth(strokeWidth);
+}
+
 TessellationCache::ShadowDescription::ShadowDescription()
         : nodeKey(NULL) {
     memset(&matrixData, 0, 16 * sizeof(float));
@@ -96,20 +100,15 @@
 
 class TessellationCache::TessellationTask : public Task<VertexBuffer*> {
 public:
-    TessellationTask(Tessellator tessellator, const Description& description,
-                const SkPaint* paint)
+    TessellationTask(Tessellator tessellator, const Description& description)
         : tessellator(tessellator)
-        , description(description)
-        , paint(*paint) {
+        , description(description) {
     }
 
     ~TessellationTask() {}
 
     Tessellator tessellator;
     Description description;
-
-    //copied, since input paint may not be immutable
-    const SkPaint paint;
 };
 
 class TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> {
@@ -121,7 +120,7 @@
     virtual void onProcess(const sp<Task<VertexBuffer*> >& task) {
         TessellationTask* t = static_cast<TessellationTask*>(task.get());
         ATRACE_NAME("shape tessellation");
-        VertexBuffer* buffer = t->tessellator(t->description, t->paint);
+        VertexBuffer* buffer = t->tessellator(t->description);
         t->setResult(buffer);
     }
 };
@@ -416,21 +415,12 @@
 // Tessellation precaching
 ///////////////////////////////////////////////////////////////////////////////
 
-static VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint,
-        float scaleX, float scaleY) {
-    VertexBuffer* buffer = new VertexBuffer();
-    Matrix4 matrix;
-    matrix.loadScale(scaleX, scaleY, 1);
-    PathTessellator::tessellatePath(path, paint, matrix, *buffer);
-    return buffer;
-}
-
 TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(
-        const Description& entry, Tessellator tessellator, const SkPaint* paint) {
+        const Description& entry, Tessellator tessellator) {
     Buffer* buffer = mCache.get(entry);
     if (!buffer) {
         // not cached, enqueue a task to fill the buffer
-        sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint);
+        sp<TessellationTask> task = new TessellationTask(tessellator, entry);
         buffer = new Buffer(task);
 
         if (mProcessor == NULL) {
@@ -442,43 +432,49 @@
     return buffer;
 }
 
+static VertexBuffer* tessellatePath(const TessellationCache::Description& description,
+        const SkPath& path) {
+    Matrix4 matrix;
+    SkPaint paint;
+    description.setupMatrixAndPaint(&matrix, &paint);
+    VertexBuffer* buffer = new VertexBuffer();
+    PathTessellator::tessellatePath(path, &paint, matrix, *buffer);
+    return buffer;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
-// Rounded rects
+// RoundRect
 ///////////////////////////////////////////////////////////////////////////////
 
-static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description,
-        const SkPaint& paint) {
-    SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth,
-            description.shape.roundRect.mHeight);
-    float rx = description.shape.roundRect.mRx;
-    float ry = description.shape.roundRect.mRy;
-    if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
-        float outset = paint.getStrokeWidth() / 2;
+static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) {
+    SkRect rect = SkRect::MakeWH(description.shape.roundRect.width,
+            description.shape.roundRect.height);
+    float rx = description.shape.roundRect.rx;
+    float ry = description.shape.roundRect.ry;
+    if (description.style == SkPaint::kStrokeAndFill_Style) {
+        float outset = description.strokeWidth / 2;
         rect.outset(outset, outset);
         rx += outset;
         ry += outset;
     }
     SkPath path;
     path.addRoundRect(rect, rx, ry);
-    return tessellatePath(path, &paint,
-            description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY);
+    return tessellatePath(description, path);
 }
 
-TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform,
-        float width, float height, float rx, float ry, const SkPaint* paint) {
-    Description entry(Description::kRoundRect, paint);
-    entry.shape.roundRect.mWidth = width;
-    entry.shape.roundRect.mHeight = height;
-    entry.shape.roundRect.mRx = rx;
-    entry.shape.roundRect.mRy = ry;
-    PathTessellator::extractTessellationScales(transform,
-            &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY);
-
-    return getOrCreateBuffer(entry, &tessellateRoundRect, paint);
+TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(
+        const Matrix4& transform, const SkPaint& paint,
+        float width, float height, float rx, float ry) {
+    Description entry(Description::kRoundRect, transform, paint);
+    entry.shape.roundRect.width = width;
+    entry.shape.roundRect.height = height;
+    entry.shape.roundRect.rx = rx;
+    entry.shape.roundRect.ry = ry;
+    return getOrCreateBuffer(entry, &tessellateRoundRect);
 }
-const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform,
-        float width, float height, float rx, float ry, const SkPaint* paint) {
-    return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer();
+const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint,
+        float width, float height, float rx, float ry) {
+    return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer();
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index d4ff943..688a699 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -50,30 +50,28 @@
         enum Type {
             kNone,
             kRoundRect,
-            kAmbientShadow,
-            kSpotShadow
         };
 
         Type type;
+        float scaleX;
+        float scaleY;
         bool aa;
         SkPaint::Cap cap;
         SkPaint::Style style;
         float strokeWidth;
         union Shape {
             struct RoundRect {
-                float mScaleX;
-                float mScaleY;
-                float mWidth;
-                float mHeight;
-                float mRx;
-                float mRy;
+                float width;
+                float height;
+                float rx;
+                float ry;
             } roundRect;
         } shape;
 
         Description();
-        Description(Type type);
-        Description(Type type, const SkPaint* paint);
+        Description(Type type, const Matrix4& transform, const SkPaint& paint);
         hash_t hash() const;
+        void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const;
     };
 
     struct ShadowDescription {
@@ -123,12 +121,12 @@
 
     // TODO: precache/get for Oval, Lines, Points, etc.
 
-    void precacheRoundRect(const Matrix4& transform,
-            float width, float height, float rx, float ry, const SkPaint* paint) {
-        getRoundRectBuffer(transform, width, height, rx, ry, paint);
+    void precacheRoundRect(const Matrix4& transform, const SkPaint& paint,
+            float width, float height, float rx, float ry) {
+        getRoundRectBuffer(transform, paint, width, height, rx, ry);
     }
-    const VertexBuffer* getRoundRect(const Matrix4& transform,
-            float width, float height, float rx, float ry, const SkPaint* paint);
+    const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
+            float width, float height, float rx, float ry);
 
     void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
             bool opaque, const SkPath* casterPerimeter,
@@ -146,14 +144,14 @@
     class TessellationTask;
     class TessellationProcessor;
 
+    typedef VertexBuffer* (*Tessellator)(const Description&);
 
-    typedef VertexBuffer* (*Tessellator)(const Description&, const SkPaint&);
+    Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint,
+            float width, float height);
+    Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint,
+            float width, float height, float rx, float ry);
 
-    Buffer* getRoundRectBuffer(const Matrix4& transform,
-            float width, float height, float rx, float ry, const SkPaint* paint);
-
-    Buffer* getOrCreateBuffer(const Description& entry,
-            Tessellator tessellator, const SkPaint* paint);
+    Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);
 
     uint32_t mSize;
     uint32_t mMaxSize;
diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h
index 9a211a2..30b6ff2 100644
--- a/libs/hwui/thread/Task.h
+++ b/libs/hwui/thread/Task.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_HWUI_TASK_H
 #define ANDROID_HWUI_TASK_H
 
-#define ATRACE_TAG ATRACE_TAG_VIEW
-
 #include <utils/RefBase.h>
 #include <utils/Trace.h>
 
@@ -40,7 +38,7 @@
     virtual ~Task() { }
 
     T getResult() const {
-        ATRACE_NAME("waitForTask");
+        ScopedTrace tracer(ATRACE_TAG_VIEW, "waitForTask");
         return mFuture->get();
     }