blob: d2b1ef91a89870e47716561aaadbf1abba0192e8 [file] [log] [blame]
John Reck013127b2020-10-29 20:53:51 -04001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
John Reckdc95f102020-11-16 12:35:02 -050019#include <canvas/CanvasFrontend.h>
John Reck013127b2020-10-29 20:53:51 -040020#include <canvas/CanvasOpBuffer.h>
21#include <canvas/CanvasOps.h>
22#include <canvas/CanvasOpRasterizer.h>
23
24#include <tests/common/CallCountingCanvas.h>
25
Kevin Lubick856848e2022-02-24 16:24:09 +000026#include "SkBitmap.h"
27#include "SkCanvas.h"
Nader Jawadde3ce842020-11-06 16:54:48 -080028#include "SkColor.h"
Kevin Lubick856848e2022-02-24 16:24:09 +000029#include "SkImageInfo.h"
Nader Jawadda9248c2020-11-09 17:27:36 -080030#include "SkLatticeIter.h"
Kevin Lubick856848e2022-02-24 16:24:09 +000031#include "SkPaint.h"
32#include "SkPath.h"
33#include "SkPictureRecorder.h"
34#include "SkRRect.h"
35#include "SkRect.h"
36#include "SkRegion.h"
Nader Jawadde3ce842020-11-06 16:54:48 -080037#include "pipeline/skia/AnimatedDrawables.h"
John Reckdc95f102020-11-16 12:35:02 -050038#include <SkNoDrawCanvas.h>
Nader Jawadde3ce842020-11-06 16:54:48 -080039
John Reck013127b2020-10-29 20:53:51 -040040using namespace android;
41using namespace android::uirenderer;
Lucas Dupin00af5272021-04-29 20:30:01 -070042using namespace android::uirenderer::skiapipeline;
John Reck013127b2020-10-29 20:53:51 -040043using namespace android::uirenderer::test;
44
45// We lazy
46using Op = CanvasOpType;
47
John Reckdc95f102020-11-16 12:35:02 -050048class CanvasOpCountingReceiver {
49public:
50 template <CanvasOpType T>
51 void push_container(CanvasOpContainer<T>&& op) {
52 mOpCounts[static_cast<size_t>(T)] += 1;
53 }
54
55 int operator[](CanvasOpType op) const {
56 return mOpCounts[static_cast<size_t>(op)];
57 }
58
59private:
60 std::array<int, static_cast<size_t>(CanvasOpType::COUNT)> mOpCounts;
61};
62
John Reck013127b2020-10-29 20:53:51 -040063template<typename T>
64static int countItems(const T& t) {
65 int count = 0;
66 t.for_each([&](auto i) {
67 count++;
68 });
69 return count;
70}
71
John Reck90b0a1c2020-11-12 12:37:30 -050072TEST(CanvasOp, verifyConst) {
73 CanvasOpBuffer buffer;
74 buffer.push<Op::DrawColor>({
75 .color = SkColors::kBlack,
76 .mode = SkBlendMode::kSrcOver,
77 });
78 buffer.for_each([](auto op) {
79 static_assert(std::is_const_v<std::remove_reference_t<decltype(*op)>>,
80 "Expected container to be const");
81 static_assert(std::is_const_v<std::remove_reference_t<decltype(op->op())>>,
82 "Expected op to be const");
83 });
84}
85
John Reck013127b2020-10-29 20:53:51 -040086TEST(CanvasOp, simplePush) {
87 CanvasOpBuffer buffer;
88 EXPECT_EQ(buffer.size(), 0);
89 buffer.push<Op::Save>({});
90 buffer.push<Op::Save>({});
91 buffer.push<Op::Restore>({});
92 EXPECT_GT(buffer.size(), 0);
93
94 int saveCount = 0;
95 int restoreCount = 0;
96 int otherCount = 0;
97
98 buffer.for_each([&](auto op) {
99 switch (op->type()) {
100 case Op::Save:
101 saveCount++;
102 break;
103 case Op::Restore:
104 restoreCount++;
105 break;
106 default:
107 otherCount++;
108 break;
109 }
110 });
111
112 EXPECT_EQ(saveCount, 2);
113 EXPECT_EQ(restoreCount, 1);
114 EXPECT_EQ(otherCount, 0);
115
116 buffer.clear();
117 int itemCount = 0;
118 buffer.for_each([&](auto op) {
119 itemCount++;
120 });
121 EXPECT_EQ(itemCount, 0);
122 buffer.resize(0);
123 EXPECT_EQ(buffer.size(), 0);
124}
125
Nader Jawadde3ce842020-11-06 16:54:48 -0800126TEST(CanvasOp, simpleDrawPaint) {
127 CanvasOpBuffer buffer;
128 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800129 buffer.push<Op::DrawColor> ({
Nader Jawadde3ce842020-11-06 16:54:48 -0800130 .color = SkColor4f{1, 1, 1, 1},
131 .mode = SkBlendMode::kSrcIn
132 });
133
134 CallCountingCanvas canvas;
135 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
136 rasterizeCanvasBuffer(buffer, &canvas);
137 EXPECT_EQ(1, canvas.drawPaintCount);
138 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
139}
140
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800141TEST(CanvasOp, simpleDrawPoint) {
142 CanvasOpBuffer buffer;
143 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800144 buffer.push<Op::DrawPoint> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800145 .x = 12,
146 .y = 42,
147 .paint = SkPaint{}
148 });
149
150 CallCountingCanvas canvas;
151 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
152 rasterizeCanvasBuffer(buffer, &canvas);
153 EXPECT_EQ(1, canvas.drawPoints);
154 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
155}
156
Nader Jawad4285c8a2020-11-06 22:49:42 -0800157TEST(CanvasOp, simpleDrawPoints) {
158 CanvasOpBuffer buffer;
159 EXPECT_EQ(buffer.size(), 0);
160 size_t numPts = 3;
John Reck064650b2021-01-19 21:29:24 -0500161 auto pts = sk_sp<Points>(
Nader Jawad4285c8a2020-11-06 22:49:42 -0800162 new Points({
163 {32, 16},
164 {48, 48},
165 {16, 32}
166 })
167 );
168
169 buffer.push(CanvasOp<Op::DrawPoints> {
170 .count = numPts,
171 .paint = SkPaint{},
172 .points = pts
173 });
174
175 CallCountingCanvas canvas;
176 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
177 rasterizeCanvasBuffer(buffer, &canvas);
178 EXPECT_EQ(1, canvas.drawPoints);
179 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
180}
181
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800182TEST(CanvasOp, simpleDrawLine) {
183 CanvasOpBuffer buffer;
184 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800185 buffer.push<Op::DrawLine> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800186 .startX = 16,
187 .startY = 28,
188 .endX = 12,
189 .endY = 30,
190 .paint = SkPaint{}
191 });
192
193 CallCountingCanvas canvas;
194 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
195 rasterizeCanvasBuffer(buffer, &canvas);
196 EXPECT_EQ(1, canvas.drawPoints);
197 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
198}
199
Nader Jawad4285c8a2020-11-06 22:49:42 -0800200TEST(CanvasOp, simpleDrawLines) {
201 CanvasOpBuffer buffer;
202 EXPECT_EQ(buffer.size(), 0);
203 size_t numPts = 3;
John Reck064650b2021-01-19 21:29:24 -0500204 auto pts = sk_sp<Points>(
Nader Jawad4285c8a2020-11-06 22:49:42 -0800205 new Points({
206 {32, 16},
207 {48, 48},
208 {16, 32}
209 })
210 );
211 buffer.push(CanvasOp<Op::DrawLines> {
212 .count = numPts,
213 .paint = SkPaint{},
214 .points = pts
215 });
216
217 CallCountingCanvas canvas;
218 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
219 rasterizeCanvasBuffer(buffer, &canvas);
220 EXPECT_EQ(1, canvas.drawPoints);
221 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
222}
223
John Reck013127b2020-10-29 20:53:51 -0400224TEST(CanvasOp, simpleDrawRect) {
225 CanvasOpBuffer buffer;
226 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800227 buffer.push<Op::DrawRect> ({
John Reck013127b2020-10-29 20:53:51 -0400228 .paint = SkPaint{},
229 .rect = SkRect::MakeEmpty()
230 });
231
232 CallCountingCanvas canvas;
233 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
234 rasterizeCanvasBuffer(buffer, &canvas);
235 EXPECT_EQ(1, canvas.drawRectCount);
236 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
237}
238
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800239TEST(CanvasOp, simpleDrawRegionRect) {
240 CanvasOpBuffer buffer;
241 EXPECT_EQ(buffer.size(), 0);
242 SkRegion region;
243 region.setRect(SkIRect::MakeWH(12, 50));
Nader Jawadda9248c2020-11-09 17:27:36 -0800244 buffer.push<Op::DrawRegion> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800245 .paint = SkPaint{},
246 .region = region
247 });
248
249 CallCountingCanvas canvas;
250 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
251 rasterizeCanvasBuffer(buffer, &canvas);
252 // If the region is a rectangle, drawRegion calls into drawRect as a fast path
253 EXPECT_EQ(1, canvas.drawRectCount);
254 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
255}
256
257TEST(CanvasOp, simpleDrawRegionPath) {
258 CanvasOpBuffer buffer;
259 EXPECT_EQ(buffer.size(), 0);
260 SkPath path;
261 path.addCircle(50, 50, 50);
262 SkRegion clip;
263 clip.setRect(SkIRect::MakeWH(100, 100));
264 SkRegion region;
265 region.setPath(path, clip);
Nader Jawadda9248c2020-11-09 17:27:36 -0800266 buffer.push<Op::DrawRegion> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800267 .paint = SkPaint{},
268 .region = region
269 });
270
271 CallCountingCanvas canvas;
272 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
273 rasterizeCanvasBuffer(buffer, &canvas);
274 EXPECT_EQ(1, canvas.drawRegionCount);
275 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
276}
277
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800278TEST(CanvasOp, simpleDrawRoundRect) {
279 CanvasOpBuffer buffer;
280 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800281 buffer.push<Op::DrawRoundRect> ({
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800282 .paint = SkPaint{},
283 .rect = SkRect::MakeEmpty(),
284 .rx = 10,
285 .ry = 10
286 });
287
288 CallCountingCanvas canvas;
289 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
290 rasterizeCanvasBuffer(buffer, &canvas);
291 EXPECT_EQ(1, canvas.drawRRectCount);
292 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
293}
294
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800295TEST(CanvasOp, simpleDrawDoubleRoundRect) {
296 CanvasOpBuffer buffer;
297 EXPECT_EQ(buffer.size(), 0);
298 SkRect outer = SkRect::MakeLTRB(0, 0, 100, 100);
299 SkRect inner = SkRect::MakeLTRB(20, 20, 80, 80);
300
301 const int numPts = 4;
302 SkRRect outerRRect;
303
304 auto outerPts = std::make_unique<SkVector[]>(numPts);
305 outerPts[0].set(32, 16);
306 outerPts[1].set(48, 48);
307 outerPts[2].set(16, 32);
308 outerPts[3].set(20, 20);
309 outerRRect.setRectRadii(outer, outerPts.get());
310 outerRRect.setRect(outer);
311
312 SkRRect innerRRect;
313 auto innerPts = std::make_unique<SkVector[]>(numPts);
314 innerPts[0].set(16, 8);
315 innerPts[1].set(24, 24);
316 innerPts[2].set(8, 16);
317 innerPts[3].set(10, 10);
318 innerRRect.setRectRadii(inner, innerPts.get());
319
Nader Jawadda9248c2020-11-09 17:27:36 -0800320 buffer.push<Op::DrawDoubleRoundRect> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800321 .outer = outerRRect,
322 .inner = innerRRect,
323 .paint = SkPaint{}
324 });
325
326 CallCountingCanvas canvas;
327 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
328 rasterizeCanvasBuffer(buffer, &canvas);
329 EXPECT_EQ(1, canvas.drawDRRectCount);
330 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
331}
332
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800333TEST(CanvasOp, simpleDrawCircle) {
334 CanvasOpBuffer buffer;
335 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800336 buffer.push<Op::DrawCircle>({
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800337 .cx = 5,
338 .cy = 7,
339 .radius = 10,
340 .paint = SkPaint{}
341 });
342
343 CallCountingCanvas canvas;
344 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
345 rasterizeCanvasBuffer(buffer, &canvas);
346 EXPECT_EQ(1, canvas.drawOvalCount);
347 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
348}
349
350TEST(CanvasOp, simpleDrawOval) {
351 CanvasOpBuffer buffer;
352 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800353 buffer.push<Op::DrawOval> ({
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800354 .oval = SkRect::MakeEmpty(),
355 .paint = SkPaint{}
356 });
357
358 CallCountingCanvas canvas;
359 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
360 rasterizeCanvasBuffer(buffer, &canvas);
361 EXPECT_EQ(1, canvas.drawOvalCount);
362 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
363}
364
365TEST(CanvasOp, simpleDrawArc) {
366 CanvasOpBuffer buffer;
367 EXPECT_EQ(buffer.size(), 0);
Nader Jawadda9248c2020-11-09 17:27:36 -0800368 buffer.push<Op::DrawArc>({
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800369 .oval = SkRect::MakeWH(100, 100),
370 .startAngle = 120,
371 .sweepAngle = 70,
372 .useCenter = true,
373 .paint = SkPaint{}
374 });
375
376 CallCountingCanvas canvas;
377 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
378 rasterizeCanvasBuffer(buffer, &canvas);
379 EXPECT_EQ(1, canvas.drawArcCount);
380 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
381}
382
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800383TEST(CanvasOp, simpleDrawPath) {
384 CanvasOpBuffer buffer;
385 EXPECT_EQ(buffer.size(), 0);
386 SkPath path;
387 path.addCircle(50, 50, 30);
Nader Jawadda9248c2020-11-09 17:27:36 -0800388 buffer.push<Op::DrawPath> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800389 .path = path,
390 .paint = SkPaint{}
391 });
392
393 CallCountingCanvas canvas;
394 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
395 rasterizeCanvasBuffer(buffer, &canvas);
396 EXPECT_EQ(1, canvas.drawPathCount);
397 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
398}
399
Nader Jawadde3ce842020-11-06 16:54:48 -0800400TEST(CanvasOp, simpleDrawRoundRectProperty) {
401 CanvasOpBuffer buffer;
402 EXPECT_EQ(buffer.size(), 0);
403
404 auto left = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(1));
405 auto top = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(2));
406 auto right = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(3));
407 auto bottom = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(4));
408 auto radiusX = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(5));
409 auto radiusY = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(6));
410 auto propertyPaint =
411 sp<uirenderer::CanvasPropertyPaint>(new uirenderer::CanvasPropertyPaint(SkPaint{}));
412
Nader Jawadda9248c2020-11-09 17:27:36 -0800413 buffer.push<Op::DrawRoundRectProperty> ({
Nader Jawadde3ce842020-11-06 16:54:48 -0800414 .left = left,
415 .top = top,
416 .right = right,
417 .bottom = bottom,
418 .rx = radiusX,
419 .ry = radiusY,
420 .paint = propertyPaint
421 });
422
423 CallCountingCanvas canvas;
424 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
425 rasterizeCanvasBuffer(buffer, &canvas);
426 EXPECT_EQ(1, canvas.drawRRectCount);
427 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
428}
429
430TEST(CanvasOp, simpleDrawCircleProperty) {
431 CanvasOpBuffer buffer;
432 EXPECT_EQ(buffer.size(), 0);
433
434 auto x = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(1));
435 auto y = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(2));
436 auto radius = sp<CanvasPropertyPrimitive>(new uirenderer::CanvasPropertyPrimitive(5));
437 auto propertyPaint =
438 sp<uirenderer::CanvasPropertyPaint>(new uirenderer::CanvasPropertyPaint(SkPaint{}));
439
Nader Jawadda9248c2020-11-09 17:27:36 -0800440 buffer.push<Op::DrawCircleProperty> ({
Nader Jawadde3ce842020-11-06 16:54:48 -0800441 .x = x,
442 .y = y,
443 .radius = radius,
444 .paint = propertyPaint
445 });
446
447 CallCountingCanvas canvas;
448 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
449 rasterizeCanvasBuffer(buffer, &canvas);
450 EXPECT_EQ(1, canvas.drawOvalCount);
451 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
452}
453
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800454TEST(CanvasOp, simpleDrawVertices) {
455 CanvasOpBuffer buffer;
456 EXPECT_EQ(buffer.size(), 0);
457
458 SkPoint pts[3] = {{64, 32}, {0, 224}, {128, 224}};
459 SkColor colors[3] = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN};
460 sk_sp<SkVertices> vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts,
461 nullptr, colors);
Nader Jawadda9248c2020-11-09 17:27:36 -0800462 buffer.push<Op::DrawVertices> ({
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800463 .vertices = vertices,
464 .mode = SkBlendMode::kSrcOver,
465 .paint = SkPaint{}
466 });
467
468 CallCountingCanvas canvas;
469 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
470 rasterizeCanvasBuffer(buffer, &canvas);
471 EXPECT_EQ(1, canvas.drawVerticesCount);
472 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
473}
474
Nader Jawadda9248c2020-11-09 17:27:36 -0800475TEST(CanvasOp, simpleDrawImage) {
476 CanvasOpBuffer buffer;
477 EXPECT_EQ(buffer.size(), 0);
478
479 SkImageInfo info =SkImageInfo::Make(5, 1,
480 kGray_8_SkColorType, kOpaque_SkAlphaType);
481 sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
482 buffer.push<Op::DrawImage> ({
483 bitmap,
484 7,
485 19,
Mike Reed7994a312021-01-28 18:06:26 -0500486 SkFilterMode::kNearest,
Nader Jawadda9248c2020-11-09 17:27:36 -0800487 SkPaint{}
488 }
489 );
490
491 CallCountingCanvas canvas;
492 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
493 rasterizeCanvasBuffer(buffer, &canvas);
494 EXPECT_EQ(1, canvas.drawImageCount);
495 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
496}
497
498TEST(CanvasOp, simpleDrawImageRect) {
499 CanvasOpBuffer buffer;
500 EXPECT_EQ(buffer.size(), 0);
501
502 SkImageInfo info = SkImageInfo::Make(5, 1,
503 kGray_8_SkColorType, kOpaque_SkAlphaType);
504
505 sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
506 buffer.push<Op::DrawImageRect> ({
507 bitmap, SkRect::MakeWH(100, 100),
508 SkRect::MakeLTRB(120, 110, 220, 210),
Mike Reed7994a312021-01-28 18:06:26 -0500509 SkFilterMode::kNearest, SkPaint{}
Nader Jawadda9248c2020-11-09 17:27:36 -0800510 }
511 );
512
513 CallCountingCanvas canvas;
514 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
515 rasterizeCanvasBuffer(buffer, &canvas);
516 EXPECT_EQ(1, canvas.drawImageRectCount);
517 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
518}
519
520TEST(CanvasOp, simpleDrawImageLattice) {
521 CanvasOpBuffer buffer;
522 EXPECT_EQ(buffer.size(), 0);
523
524 SkBitmap skBitmap;
525 skBitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
526
527 const int xDivs[] = { 20, 50 };
528 const int yDivs[] = { 10, 40 };
529 SkCanvas::Lattice::RectType fillTypes[3][3];
530 memset(fillTypes, 0, sizeof(fillTypes));
531 fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
532 SkColor colors[9];
533 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], 2,
534 2, nullptr, colors };
535 sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(&skBitmap);
536 buffer.push<Op::DrawImageLattice>(
537 {
538 bitmap,
539 SkRect::MakeWH(5, 1),
540 lattice,
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500541 SkFilterMode::kNearest,
Nader Jawadda9248c2020-11-09 17:27:36 -0800542 SkPaint{}
543 }
544 );
545
546 CallCountingCanvas canvas;
547 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
548 rasterizeCanvasBuffer(buffer, &canvas);
549 EXPECT_EQ(1, canvas.drawImageLatticeCount);
550 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
551}
552
553TEST(CanvasOp, simpleDrawPicture) {
554 CanvasOpBuffer buffer;
555 EXPECT_EQ(buffer.size(), 0);
556
557 SkPictureRecorder recorder;
558 SkCanvas* pictureCanvas = recorder.beginRecording({64, 64, 192, 192});
559 SkPaint paint;
560 pictureCanvas->drawRect(SkRect::MakeWH(200, 200), paint);
561 paint.setColor(SK_ColorWHITE);
562 pictureCanvas->drawRect(SkRect::MakeLTRB(20, 20, 180, 180), paint);
563 sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
564 buffer.push<Op::DrawPicture> ({
565 .picture = picture
566 });
567
568 CallCountingCanvas canvas;
569 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
570 rasterizeCanvasBuffer(buffer, &canvas);
571 // Note because we are explicitly issuing 2 drawRect calls
572 // in the picture recorder above, when it is played back into
573 // CallCountingCanvas we will see 2 calls to drawRect instead of 1
574 // call to drawPicture.
575 // This is because SkiaCanvas::drawPicture uses picture.playback(canvas)
576 // instead of canvas->drawPicture.
577 EXPECT_EQ(2, canvas.drawRectCount);
578 EXPECT_EQ(2, canvas.sumTotalDrawCalls());
579}
580
Lucas Dupin00af5272021-04-29 20:30:01 -0700581TEST(CanvasOp, simpleDrawRipple) {
582 CanvasOpBuffer buffer;
583 EXPECT_EQ(buffer.size(), 0);
584
585 const char* sksl =
586 "half4 main(float2 coord) {"
587 " return half4(1.);"
588 "}";
589 auto [effect, error] = SkRuntimeEffect::MakeForShader(SkString(sksl));
590 auto params = RippleDrawableParams{
591 .x = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(100)),
592 .y = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(200)),
593 .radius = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(50)),
594 .progress = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(0.5)),
595 .turbulencePhase = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(1)),
596 .color = 0xff00ff,
597 .paint = sp<CanvasPropertyPaint>(new CanvasPropertyPaint(SkPaint{})),
598 .effectBuilder = SkRuntimeShaderBuilder(effect)};
599 buffer.push<Op::DrawRippleDrawable>({.params = params});
600
601 CallCountingCanvas canvas;
602 EXPECT_EQ(0, canvas.sumTotalDrawCalls());
603 rasterizeCanvasBuffer(buffer, &canvas);
604 EXPECT_EQ(1, canvas.drawOvalCount);
605 EXPECT_EQ(1, canvas.sumTotalDrawCalls());
606}
607
John Reck013127b2020-10-29 20:53:51 -0400608TEST(CanvasOp, immediateRendering) {
609 auto canvas = std::make_shared<CallCountingCanvas>();
610
611 EXPECT_EQ(0, canvas->sumTotalDrawCalls());
612 ImmediateModeRasterizer rasterizer{canvas};
613 auto op = CanvasOp<Op::DrawRect> {
614 .paint = SkPaint{},
615 .rect = SkRect::MakeEmpty()
616 };
617 EXPECT_TRUE(CanvasOpTraits::can_draw<decltype(op)>);
618 rasterizer.draw(op);
619 EXPECT_EQ(1, canvas->drawRectCount);
620 EXPECT_EQ(1, canvas->sumTotalDrawCalls());
John Reckdc95f102020-11-16 12:35:02 -0500621}
622
623TEST(CanvasOp, frontendSaveCount) {
624 SkNoDrawCanvas skiaCanvas(100, 100);
625 CanvasFrontend<CanvasOpCountingReceiver> opCanvas(100, 100);
626 const auto& receiver = opCanvas.receiver();
627
628 EXPECT_EQ(1, skiaCanvas.getSaveCount());
629 EXPECT_EQ(1, opCanvas.saveCount());
630
631 skiaCanvas.save();
632 opCanvas.save(SaveFlags::MatrixClip);
633 EXPECT_EQ(2, skiaCanvas.getSaveCount());
634 EXPECT_EQ(2, opCanvas.saveCount());
635
636 skiaCanvas.restore();
637 opCanvas.restore();
638 EXPECT_EQ(1, skiaCanvas.getSaveCount());
639 EXPECT_EQ(1, opCanvas.saveCount());
640
641 skiaCanvas.restore();
642 opCanvas.restore();
643 EXPECT_EQ(1, skiaCanvas.getSaveCount());
644 EXPECT_EQ(1, opCanvas.saveCount());
645
646 EXPECT_EQ(1, receiver[Op::Save]);
647 EXPECT_EQ(1, receiver[Op::Restore]);
648}