diff options
| author | 2020-11-09 17:27:36 -0800 | |
|---|---|---|
| committer | 2020-11-12 12:57:24 -0800 | |
| commit | da9248cefa41a3641181bb177f4d878695c84ef5 (patch) | |
| tree | 7f4b59dc4b7b6822b6c7b7c77f42d6f174ea5320 | |
| parent | fb1e7f1b6aa772c0d579cc8f2d21791f421cba54 (diff) | |
Add more canvas ops 5
Added:
--DrawImage
--DrawImageRect
--DrawImageNine
--DrawPicture
--DrawImageLattice
Test: Added tests to CanvasOpTests
Change-Id: I9997d9fadd8738aa5fef4288dbcf92864da9fe74
| -rw-r--r-- | libs/hwui/canvas/CanvasOpTypes.h | 6 | ||||
| -rw-r--r-- | libs/hwui/canvas/CanvasOps.h | 95 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/CanvasOpTests.cpp | 136 |
3 files changed, 221 insertions, 16 deletions
diff --git a/libs/hwui/canvas/CanvasOpTypes.h b/libs/hwui/canvas/CanvasOpTypes.h index efcb3739ab5d..f9df2f7aa5ba 100644 --- a/libs/hwui/canvas/CanvasOpTypes.h +++ b/libs/hwui/canvas/CanvasOpTypes.h @@ -50,7 +50,11 @@ enum class CanvasOpType : int8_t { DrawPath, DrawLine, DrawVertices, - + DrawImage, + DrawImageRect, + // DrawImageLattice also used to draw 9 patches + DrawImageLattice, + DrawPicture, // TODO: Rest diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index 6a7653958981..8c7113d5d075 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -21,12 +21,16 @@ #include <SkPath.h> #include <SkRegion.h> #include <SkVertices.h> +#include <SkImage.h> +#include <SkPicture.h> +#include <hwui/Bitmap.h> #include <log/log.h> #include "CanvasProperty.h" #include "CanvasOpTypes.h" #include <experimental/type_traits> +#include <utility> namespace android::uirenderer { @@ -269,6 +273,97 @@ struct CanvasOp<CanvasOpType::DrawVertices> { ASSERT_DRAWABLE() }; +template<> +struct CanvasOp<CanvasOpType::DrawImage> { + + CanvasOp<CanvasOpType::DrawImageRect>( + const sk_sp<Bitmap>& bitmap, + float left, + float top, + SkPaint paint + ) : left(left), + top(top), + paint(std::move(paint)), + bitmap(bitmap), + image(bitmap->makeImage()) { } + + float left; + float top; + SkPaint paint; + sk_sp<Bitmap> bitmap; + sk_sp<SkImage> image; + + void draw(SkCanvas* canvas) const { + canvas->drawImage(image, left, top, &paint); + } + ASSERT_DRAWABLE() +}; + +template<> +struct CanvasOp<CanvasOpType::DrawImageRect> { + + CanvasOp<CanvasOpType::DrawImageRect>( + const sk_sp<Bitmap>& bitmap, + SkRect src, + SkRect dst, + SkPaint paint + ) : src(src), + dst(dst), + paint(std::move(paint)), + bitmap(bitmap), + image(bitmap->makeImage()) { } + + SkRect src; + SkRect dst; + SkPaint paint; + sk_sp<Bitmap> bitmap; + sk_sp<SkImage> image; + + void draw(SkCanvas* canvas) const { + canvas->drawImageRect(image, + src, + dst, + &paint, + SkCanvas::kFast_SrcRectConstraint + ); + } + ASSERT_DRAWABLE() +}; + +template<> +struct CanvasOp<CanvasOpType::DrawImageLattice> { + + CanvasOp<CanvasOpType::DrawImageLattice>( + const sk_sp<Bitmap>& bitmap, + SkRect dst, + SkCanvas::Lattice lattice, + SkPaint paint + ): dst(dst), + lattice(lattice), + bitmap(bitmap), + image(bitmap->makeImage()), + paint(std::move(paint)) {} + + SkRect dst; + SkCanvas::Lattice lattice; + const sk_sp<Bitmap> bitmap; + const sk_sp<SkImage> image; + + SkPaint paint; + void draw(SkCanvas* canvas) const { + canvas->drawImageLattice(image.get(), lattice, dst, &paint); + } + ASSERT_DRAWABLE() +}; + +template<> +struct CanvasOp<CanvasOpType::DrawPicture> { + sk_sp<SkPicture> picture; + void draw(SkCanvas* canvas) const { + picture->playback(canvas); + } +}; + // cleanup our macros #undef ASSERT_DRAWABLE diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp index 60c8628ea966..50d3cb1483dd 100644 --- a/libs/hwui/tests/unit/CanvasOpTests.cpp +++ b/libs/hwui/tests/unit/CanvasOpTests.cpp @@ -22,7 +22,9 @@ #include <tests/common/CallCountingCanvas.h> +#include "SkPictureRecorder.h" #include "SkColor.h" +#include "SkLatticeIter.h" #include "pipeline/skia/AnimatedDrawables.h" using namespace android; @@ -184,7 +186,7 @@ TEST(CanvasOp, simplePush) { TEST(CanvasOp, simpleDrawPaint) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawColor> { + buffer.push<Op::DrawColor> ({ .color = SkColor4f{1, 1, 1, 1}, .mode = SkBlendMode::kSrcIn }); @@ -199,7 +201,7 @@ TEST(CanvasOp, simpleDrawPaint) { TEST(CanvasOp, simpleDrawPoint) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawPoint> { + buffer.push<Op::DrawPoint> ({ .x = 12, .y = 42, .paint = SkPaint{} @@ -215,7 +217,7 @@ TEST(CanvasOp, simpleDrawPoint) { TEST(CanvasOp, simpleDrawLine) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawLine> { + buffer.push<Op::DrawLine> ({ .startX = 16, .startY = 28, .endX = 12, @@ -233,7 +235,7 @@ TEST(CanvasOp, simpleDrawLine) { TEST(CanvasOp, simpleDrawRect) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawRect> { + buffer.push<Op::DrawRect> ({ .paint = SkPaint{}, .rect = SkRect::MakeEmpty() }); @@ -250,7 +252,7 @@ TEST(CanvasOp, simpleDrawRegionRect) { EXPECT_EQ(buffer.size(), 0); SkRegion region; region.setRect(SkIRect::MakeWH(12, 50)); - buffer.push(CanvasOp<Op::DrawRegion> { + buffer.push<Op::DrawRegion> ({ .paint = SkPaint{}, .region = region }); @@ -272,7 +274,7 @@ TEST(CanvasOp, simpleDrawRegionPath) { clip.setRect(SkIRect::MakeWH(100, 100)); SkRegion region; region.setPath(path, clip); - buffer.push(CanvasOp<Op::DrawRegion> { + buffer.push<Op::DrawRegion> ({ .paint = SkPaint{}, .region = region }); @@ -287,7 +289,7 @@ TEST(CanvasOp, simpleDrawRegionPath) { TEST(CanvasOp, simpleDrawRoundRect) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawRoundRect> { + buffer.push<Op::DrawRoundRect> ({ .paint = SkPaint{}, .rect = SkRect::MakeEmpty(), .rx = 10, @@ -326,7 +328,7 @@ TEST(CanvasOp, simpleDrawDoubleRoundRect) { innerPts[3].set(10, 10); innerRRect.setRectRadii(inner, innerPts.get()); - buffer.push(CanvasOp<Op::DrawDoubleRoundRect> { + buffer.push<Op::DrawDoubleRoundRect> ({ .outer = outerRRect, .inner = innerRRect, .paint = SkPaint{} @@ -342,7 +344,7 @@ TEST(CanvasOp, simpleDrawDoubleRoundRect) { TEST(CanvasOp, simpleDrawCircle) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawCircle> { + buffer.push<Op::DrawCircle>({ .cx = 5, .cy = 7, .radius = 10, @@ -359,7 +361,7 @@ TEST(CanvasOp, simpleDrawCircle) { TEST(CanvasOp, simpleDrawOval) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawOval> { + buffer.push<Op::DrawOval> ({ .oval = SkRect::MakeEmpty(), .paint = SkPaint{} }); @@ -374,7 +376,7 @@ TEST(CanvasOp, simpleDrawOval) { TEST(CanvasOp, simpleDrawArc) { CanvasOpBuffer buffer; EXPECT_EQ(buffer.size(), 0); - buffer.push(CanvasOp<Op::DrawArc> { + buffer.push<Op::DrawArc>({ .oval = SkRect::MakeWH(100, 100), .startAngle = 120, .sweepAngle = 70, @@ -394,7 +396,7 @@ TEST(CanvasOp, simpleDrawPath) { EXPECT_EQ(buffer.size(), 0); SkPath path; path.addCircle(50, 50, 30); - buffer.push(CanvasOp<Op::DrawPath> { + buffer.push<Op::DrawPath> ({ .path = path, .paint = SkPaint{} }); @@ -419,7 +421,7 @@ TEST(CanvasOp, simpleDrawRoundRectProperty) { auto propertyPaint = sp<uirenderer::CanvasPropertyPaint>(new uirenderer::CanvasPropertyPaint(SkPaint{})); - buffer.push(CanvasOp<Op::DrawRoundRectProperty> { + buffer.push<Op::DrawRoundRectProperty> ({ .left = left, .top = top, .right = right, @@ -446,7 +448,7 @@ TEST(CanvasOp, simpleDrawCircleProperty) { auto propertyPaint = sp<uirenderer::CanvasPropertyPaint>(new uirenderer::CanvasPropertyPaint(SkPaint{})); - buffer.push(CanvasOp<Op::DrawCircleProperty> { + buffer.push<Op::DrawCircleProperty> ({ .x = x, .y = y, .radius = radius, @@ -468,7 +470,7 @@ TEST(CanvasOp, simpleDrawVertices) { 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> { + buffer.push<Op::DrawVertices> ({ .vertices = vertices, .mode = SkBlendMode::kSrcOver, .paint = SkPaint{} @@ -481,6 +483,110 @@ TEST(CanvasOp, simpleDrawVertices) { EXPECT_EQ(1, canvas.sumTotalDrawCalls()); } +TEST(CanvasOp, simpleDrawImage) { + CanvasOpBuffer buffer; + EXPECT_EQ(buffer.size(), 0); + + SkImageInfo info =SkImageInfo::Make(5, 1, + kGray_8_SkColorType, kOpaque_SkAlphaType); + sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info); + buffer.push<Op::DrawImage> ({ + bitmap, + 7, + 19, + SkPaint{} + } + ); + + CallCountingCanvas canvas; + EXPECT_EQ(0, canvas.sumTotalDrawCalls()); + rasterizeCanvasBuffer(buffer, &canvas); + EXPECT_EQ(1, canvas.drawImageCount); + EXPECT_EQ(1, canvas.sumTotalDrawCalls()); +} + +TEST(CanvasOp, simpleDrawImageRect) { + CanvasOpBuffer buffer; + EXPECT_EQ(buffer.size(), 0); + + SkImageInfo info = SkImageInfo::Make(5, 1, + kGray_8_SkColorType, kOpaque_SkAlphaType); + + sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info); + buffer.push<Op::DrawImageRect> ({ + bitmap, SkRect::MakeWH(100, 100), + SkRect::MakeLTRB(120, 110, 220, 210), + SkPaint{} + } + ); + + CallCountingCanvas canvas; + EXPECT_EQ(0, canvas.sumTotalDrawCalls()); + rasterizeCanvasBuffer(buffer, &canvas); + EXPECT_EQ(1, canvas.drawImageRectCount); + EXPECT_EQ(1, canvas.sumTotalDrawCalls()); +} + +TEST(CanvasOp, simpleDrawImageLattice) { + CanvasOpBuffer buffer; + EXPECT_EQ(buffer.size(), 0); + + SkBitmap skBitmap; + skBitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); + + const int xDivs[] = { 20, 50 }; + const int yDivs[] = { 10, 40 }; + SkCanvas::Lattice::RectType fillTypes[3][3]; + memset(fillTypes, 0, sizeof(fillTypes)); + fillTypes[1][1] = SkCanvas::Lattice::kTransparent; + SkColor colors[9]; + SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], 2, + 2, nullptr, colors }; + sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(&skBitmap); + buffer.push<Op::DrawImageLattice>( + { + bitmap, + SkRect::MakeWH(5, 1), + lattice, + SkPaint{} + } + ); + + CallCountingCanvas canvas; + EXPECT_EQ(0, canvas.sumTotalDrawCalls()); + rasterizeCanvasBuffer(buffer, &canvas); + EXPECT_EQ(1, canvas.drawImageLatticeCount); + EXPECT_EQ(1, canvas.sumTotalDrawCalls()); +} + +TEST(CanvasOp, simpleDrawPicture) { + CanvasOpBuffer buffer; + EXPECT_EQ(buffer.size(), 0); + + SkPictureRecorder recorder; + SkCanvas* pictureCanvas = recorder.beginRecording({64, 64, 192, 192}); + SkPaint paint; + pictureCanvas->drawRect(SkRect::MakeWH(200, 200), paint); + paint.setColor(SK_ColorWHITE); + pictureCanvas->drawRect(SkRect::MakeLTRB(20, 20, 180, 180), paint); + sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); + buffer.push<Op::DrawPicture> ({ + .picture = picture + }); + + CallCountingCanvas canvas; + EXPECT_EQ(0, canvas.sumTotalDrawCalls()); + rasterizeCanvasBuffer(buffer, &canvas); + // Note because we are explicitly issuing 2 drawRect calls + // in the picture recorder above, when it is played back into + // CallCountingCanvas we will see 2 calls to drawRect instead of 1 + // call to drawPicture. + // This is because SkiaCanvas::drawPicture uses picture.playback(canvas) + // instead of canvas->drawPicture. + EXPECT_EQ(2, canvas.drawRectCount); + EXPECT_EQ(2, canvas.sumTotalDrawCalls()); +} + TEST(CanvasOp, immediateRendering) { auto canvas = std::make_shared<CallCountingCanvas>(); |