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>();