Add canvas ops 3

Added the following
--DrawPoint
--DrawPath
--DrawRegion
--DrawDoubleRoundRect
--DrawLine
--DrawVertices

Test: Added tests to CanvasOpTests
Change-Id: I5844c61bc8d2dacf74e504f7bac7946398174ed2
diff --git a/libs/hwui/canvas/CanvasOpTypes.h b/libs/hwui/canvas/CanvasOpTypes.h
index 895c6d0..efcb373 100644
--- a/libs/hwui/canvas/CanvasOpTypes.h
+++ b/libs/hwui/canvas/CanvasOpTypes.h
@@ -37,13 +37,19 @@
     // Drawing ops
     DrawColor,
     DrawRect,
+    DrawRegion,
     DrawRoundRect,
     DrawRoundRectProperty,
+    DrawDoubleRoundRect,
     DrawCircleProperty,
     DrawCircle,
     DrawOval,
     DrawArc,
     DrawPaint,
+    DrawPoint,
+    DrawPath,
+    DrawLine,
+    DrawVertices,
 
 
     // TODO: Rest
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index afd88c0..6a76539 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -19,6 +19,8 @@
 #include <SkAndroidFrameworkUtils.h>
 #include <SkCanvas.h>
 #include <SkPath.h>
+#include <SkRegion.h>
+#include <SkVertices.h>
 #include <log/log.h>
 #include "CanvasProperty.h"
 
@@ -150,6 +152,15 @@
 };
 
 template <>
+struct CanvasOp<CanvasOpType::DrawPoint> {
+    float x;
+    float y;
+    SkPaint paint;
+    void draw(SkCanvas* canvas) const { canvas->drawPoint(x, y, paint); }
+    ASSERT_DRAWABLE()
+};
+
+template <>
 struct CanvasOp<CanvasOpType::DrawRect> {
     SkRect rect;
     SkPaint paint;
@@ -157,6 +168,14 @@
     ASSERT_DRAWABLE()
 };
 
+template <>
+struct CanvasOp<CanvasOpType::DrawRegion> {
+    SkRegion region;
+    SkPaint paint;
+    void draw(SkCanvas* canvas) const { canvas->drawRegion(region, paint); }
+    ASSERT_DRAWABLE()
+};
+
 template<>
 struct CanvasOp<CanvasOpType::DrawRoundRect> {
     SkRect rect;
@@ -170,6 +189,17 @@
 };
 
 template<>
+struct CanvasOp<CanvasOpType::DrawDoubleRoundRect> {
+    SkRRect outer;
+    SkRRect inner;
+    SkPaint paint;
+    void draw(SkCanvas* canvas) const {
+        canvas->drawDRRect(outer, inner, paint);
+    }
+    ASSERT_DRAWABLE()
+};
+
+template<>
 struct CanvasOp<CanvasOpType::DrawCircle> {
     SkScalar cx;
     SkScalar cy;
@@ -205,7 +235,41 @@
     ASSERT_DRAWABLE()
 };
 
+template<>
+struct CanvasOp<CanvasOpType::DrawPath> {
+    SkPath path;
+    SkPaint paint;
+
+    void draw(SkCanvas* canvas) const { canvas->drawPath(path, paint); }
+    ASSERT_DRAWABLE()
+};
+
+template<>
+struct CanvasOp<CanvasOpType::DrawLine> {
+    float startX;
+    float startY;
+    float endX;
+    float endY;
+    SkPaint paint;
+
+    void draw(SkCanvas* canvas) const {
+        canvas->drawLine(startX, startY, endX, endY, paint);
+    }
+    ASSERT_DRAWABLE()
+};
+
+template<>
+struct CanvasOp<CanvasOpType::DrawVertices> {
+    sk_sp<SkVertices> vertices;
+    SkBlendMode mode;
+    SkPaint paint;
+    void draw(SkCanvas* canvas) const {
+        canvas->drawVertices(vertices, mode, paint);
+    }
+    ASSERT_DRAWABLE()
+};
+
 // cleanup our macros
 #undef ASSERT_DRAWABLE
 
-}  // namespace android::uirenderer
\ No newline at end of file
+}  // namespace android::uirenderer
diff --git a/libs/hwui/tests/common/CallCountingCanvas.h b/libs/hwui/tests/common/CallCountingCanvas.h
index a965571..594afd0 100644
--- a/libs/hwui/tests/common/CallCountingCanvas.h
+++ b/libs/hwui/tests/common/CallCountingCanvas.h
@@ -80,7 +80,7 @@
 
     int drawPathCount = 0;
     void onDrawPath(const SkPath& path, const SkPaint& paint) override {
-        drawPaintCount++;
+        drawPathCount++;
     }
 
     int drawRegionCount = 0;
@@ -159,6 +159,12 @@
         drawPictureCount++;
     }
 
+    int drawVerticesCount = 0;
+    void onDrawVerticesObject (const SkVertices *vertices, SkBlendMode mode,
+                        const SkPaint &paint) override {
+        drawVerticesCount++;
+    }
+
 private:
     int END_MARKER;
 };
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index 2311924..60c8628 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -196,6 +196,40 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawPoint) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    buffer.push(CanvasOp<Op::DrawPoint> {
+        .x = 12,
+        .y = 42,
+        .paint = SkPaint{}
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawPoints);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
+TEST(CanvasOp, simpleDrawLine) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    buffer.push(CanvasOp<Op::DrawLine> {
+        .startX = 16,
+        .startY = 28,
+        .endX = 12,
+        .endY = 30,
+        .paint = SkPaint{}
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawPoints);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, simpleDrawRect) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
@@ -211,6 +245,45 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawRegionRect) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    SkRegion region;
+    region.setRect(SkIRect::MakeWH(12, 50));
+    buffer.push(CanvasOp<Op::DrawRegion> {
+        .paint = SkPaint{},
+        .region = region
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    // If the region is a rectangle, drawRegion calls into drawRect as a fast path
+    EXPECT_EQ(1, canvas.drawRectCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
+TEST(CanvasOp, simpleDrawRegionPath) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    SkPath path;
+    path.addCircle(50, 50, 50);
+    SkRegion clip;
+    clip.setRect(SkIRect::MakeWH(100, 100));
+    SkRegion region;
+    region.setPath(path, clip);
+    buffer.push(CanvasOp<Op::DrawRegion> {
+        .paint = SkPaint{},
+        .region = region
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawRegionCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, simpleDrawRoundRect) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
@@ -228,6 +301,44 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawDoubleRoundRect) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    SkRect outer = SkRect::MakeLTRB(0, 0, 100, 100);
+    SkRect inner = SkRect::MakeLTRB(20, 20, 80, 80);
+
+    const int numPts = 4;
+    SkRRect outerRRect;
+
+    auto outerPts = std::make_unique<SkVector[]>(numPts);
+    outerPts[0].set(32, 16);
+    outerPts[1].set(48, 48);
+    outerPts[2].set(16, 32);
+    outerPts[3].set(20, 20);
+    outerRRect.setRectRadii(outer, outerPts.get());
+    outerRRect.setRect(outer);
+
+    SkRRect innerRRect;
+    auto innerPts = std::make_unique<SkVector[]>(numPts);
+    innerPts[0].set(16, 8);
+    innerPts[1].set(24, 24);
+    innerPts[2].set(8, 16);
+    innerPts[3].set(10, 10);
+    innerRRect.setRectRadii(inner, innerPts.get());
+
+    buffer.push(CanvasOp<Op::DrawDoubleRoundRect> {
+        .outer = outerRRect,
+        .inner = innerRRect,
+        .paint = SkPaint{}
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawDRRectCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, simpleDrawCircle) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
@@ -278,6 +389,23 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawPath) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+    SkPath path;
+    path.addCircle(50, 50, 30);
+    buffer.push(CanvasOp<Op::DrawPath> {
+        .path = path,
+        .paint = SkPaint{}
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawPathCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, simpleDrawRoundRectProperty) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
@@ -332,6 +460,27 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawVertices) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+
+    SkPoint pts[3] = {{64, 32}, {0, 224}, {128, 224}};
+    SkColor colors[3] = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN};
+    sk_sp<SkVertices> vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts,
+            nullptr, colors);
+    buffer.push(CanvasOp<Op::DrawVertices> {
+        .vertices = vertices,
+        .mode = SkBlendMode::kSrcOver,
+        .paint = SkPaint{}
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawVerticesCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, immediateRendering) {
     auto canvas = std::make_shared<CallCountingCanvas>();