xref: /aosp_15_r20/external/skia/bench/BulkRectBench.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2019 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkImageGanesh.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCanvasPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCanvas.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpsTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SkGr.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker // Benchmarks that exercise the bulk image and solid color quad APIs, under a variety of patterns:
23*c8dee2aaSAndroid Build Coastguard Worker enum class ImageMode {
24*c8dee2aaSAndroid Build Coastguard Worker     kShared, // 1. One shared image referenced by every rectangle
25*c8dee2aaSAndroid Build Coastguard Worker     kUnique, // 2. Unique image for every rectangle
26*c8dee2aaSAndroid Build Coastguard Worker     kNone    // 3. No image, solid color shading per rectangle
27*c8dee2aaSAndroid Build Coastguard Worker };
28*c8dee2aaSAndroid Build Coastguard Worker //   X
29*c8dee2aaSAndroid Build Coastguard Worker enum class DrawMode {
30*c8dee2aaSAndroid Build Coastguard Worker     kBatch,  // Bulk API submission, one call to draw every rectangle
31*c8dee2aaSAndroid Build Coastguard Worker     kRef,    // One standard SkCanvas draw call per rectangle
32*c8dee2aaSAndroid Build Coastguard Worker     kQuad    // One experimental draw call per rectangle, only for solid color draws
33*c8dee2aaSAndroid Build Coastguard Worker };
34*c8dee2aaSAndroid Build Coastguard Worker //   X
35*c8dee2aaSAndroid Build Coastguard Worker enum class RectangleLayout {
36*c8dee2aaSAndroid Build Coastguard Worker     kRandom,  // Random overlapping rectangles
37*c8dee2aaSAndroid Build Coastguard Worker     kGrid     // Small, non-overlapping rectangles in a grid covering the output surface
38*c8dee2aaSAndroid Build Coastguard Worker };
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker // Benchmark runner that can be configured by template arguments.
41*c8dee2aaSAndroid Build Coastguard Worker template<int kRectCount, RectangleLayout kLayout, ImageMode kImageMode, DrawMode kDrawMode>
42*c8dee2aaSAndroid Build Coastguard Worker class BulkRectBench : public Benchmark {
43*c8dee2aaSAndroid Build Coastguard Worker public:
44*c8dee2aaSAndroid Build Coastguard Worker     static_assert(kImageMode == ImageMode::kNone || kDrawMode != DrawMode::kQuad,
45*c8dee2aaSAndroid Build Coastguard Worker                   "kQuad only supported for solid color draws");
46*c8dee2aaSAndroid Build Coastguard Worker 
47*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kWidth      = 1024;
48*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kHeight     = 1024;
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker     // There will either be 0 images, 1 image, or 1 image per rect
51*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kImageCount = kImageMode == ImageMode::kShared ?
52*c8dee2aaSAndroid Build Coastguard Worker             1 : (kImageMode == ImageMode::kNone ? 0 : kRectCount);
53*c8dee2aaSAndroid Build Coastguard Worker 
isSuitableFor(Backend backend)54*c8dee2aaSAndroid Build Coastguard Worker     bool isSuitableFor(Backend backend) override {
55*c8dee2aaSAndroid Build Coastguard Worker         if (kDrawMode == DrawMode::kBatch && kImageMode == ImageMode::kNone) {
56*c8dee2aaSAndroid Build Coastguard Worker             // Currently the bulk color quad API is only available on
57*c8dee2aaSAndroid Build Coastguard Worker             // skgpu::ganesh::SurfaceDrawContext
58*c8dee2aaSAndroid Build Coastguard Worker             return backend == Backend::kGanesh;
59*c8dee2aaSAndroid Build Coastguard Worker         } else {
60*c8dee2aaSAndroid Build Coastguard Worker             return this->INHERITED::isSuitableFor(backend);
61*c8dee2aaSAndroid Build Coastguard Worker         }
62*c8dee2aaSAndroid Build Coastguard Worker     }
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker protected:
65*c8dee2aaSAndroid Build Coastguard Worker     SkRect         fRects[kRectCount];
66*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> fImages[kImageCount > 0 ? kImageCount : 1];
67*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f      fColors[kRectCount];
68*c8dee2aaSAndroid Build Coastguard Worker     SkString       fName;
69*c8dee2aaSAndroid Build Coastguard Worker 
computeName()70*c8dee2aaSAndroid Build Coastguard Worker     void computeName()  {
71*c8dee2aaSAndroid Build Coastguard Worker         fName = "bulkrect";
72*c8dee2aaSAndroid Build Coastguard Worker         fName.appendf("_%d", kRectCount);
73*c8dee2aaSAndroid Build Coastguard Worker         if (kLayout == RectangleLayout::kRandom) {
74*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_random");
75*c8dee2aaSAndroid Build Coastguard Worker         } else {
76*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_grid");
77*c8dee2aaSAndroid Build Coastguard Worker         }
78*c8dee2aaSAndroid Build Coastguard Worker         if (kImageMode == ImageMode::kShared) {
79*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_sharedimage");
80*c8dee2aaSAndroid Build Coastguard Worker         } else if (kImageMode == ImageMode::kUnique) {
81*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_uniqueimages");
82*c8dee2aaSAndroid Build Coastguard Worker         } else {
83*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_solidcolor");
84*c8dee2aaSAndroid Build Coastguard Worker         }
85*c8dee2aaSAndroid Build Coastguard Worker         if (kDrawMode == DrawMode::kBatch) {
86*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_batch");
87*c8dee2aaSAndroid Build Coastguard Worker         } else if (kDrawMode == DrawMode::kRef) {
88*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_ref");
89*c8dee2aaSAndroid Build Coastguard Worker         } else {
90*c8dee2aaSAndroid Build Coastguard Worker             fName.append("_quad");
91*c8dee2aaSAndroid Build Coastguard Worker         }
92*c8dee2aaSAndroid Build Coastguard Worker     }
93*c8dee2aaSAndroid Build Coastguard Worker 
drawImagesBatch(SkCanvas * canvas) const94*c8dee2aaSAndroid Build Coastguard Worker     void drawImagesBatch(SkCanvas* canvas) const {
95*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kImageMode != ImageMode::kNone);
96*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kDrawMode == DrawMode::kBatch);
97*c8dee2aaSAndroid Build Coastguard Worker 
98*c8dee2aaSAndroid Build Coastguard Worker         SkCanvas::ImageSetEntry batch[kRectCount];
99*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kRectCount; ++i) {
100*c8dee2aaSAndroid Build Coastguard Worker             int imageIndex = kImageMode == ImageMode::kShared ? 0 : i;
101*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fImage = fImages[imageIndex];
102*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fSrcRect = SkRect::MakeIWH(fImages[imageIndex]->width(),
103*c8dee2aaSAndroid Build Coastguard Worker                                                 fImages[imageIndex]->height());
104*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fDstRect = fRects[i];
105*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fAAFlags = SkCanvas::kAll_QuadAAFlags;
106*c8dee2aaSAndroid Build Coastguard Worker         }
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
109*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
110*c8dee2aaSAndroid Build Coastguard Worker 
111*c8dee2aaSAndroid Build Coastguard Worker         canvas->experimental_DrawEdgeAAImageSet(batch, kRectCount, nullptr, nullptr,
112*c8dee2aaSAndroid Build Coastguard Worker                                                 SkSamplingOptions(SkFilterMode::kLinear), &paint,
113*c8dee2aaSAndroid Build Coastguard Worker                                                 SkCanvas::kFast_SrcRectConstraint);
114*c8dee2aaSAndroid Build Coastguard Worker     }
115*c8dee2aaSAndroid Build Coastguard Worker 
drawImagesRef(SkCanvas * canvas) const116*c8dee2aaSAndroid Build Coastguard Worker     void drawImagesRef(SkCanvas* canvas) const {
117*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kImageMode != ImageMode::kNone);
118*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kDrawMode == DrawMode::kRef);
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
121*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kRectCount; ++i) {
124*c8dee2aaSAndroid Build Coastguard Worker             int imageIndex = kImageMode == ImageMode::kShared ? 0 : i;
125*c8dee2aaSAndroid Build Coastguard Worker             SkRect srcRect = SkRect::MakeIWH(fImages[imageIndex]->width(),
126*c8dee2aaSAndroid Build Coastguard Worker                                              fImages[imageIndex]->height());
127*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawImageRect(fImages[imageIndex].get(), srcRect, fRects[i],
128*c8dee2aaSAndroid Build Coastguard Worker                                   SkSamplingOptions(SkFilterMode::kLinear), &paint,
129*c8dee2aaSAndroid Build Coastguard Worker                                   SkCanvas::kFast_SrcRectConstraint);
130*c8dee2aaSAndroid Build Coastguard Worker         }
131*c8dee2aaSAndroid Build Coastguard Worker     }
132*c8dee2aaSAndroid Build Coastguard Worker 
drawSolidColorsBatch(SkCanvas * canvas) const133*c8dee2aaSAndroid Build Coastguard Worker     void drawSolidColorsBatch(SkCanvas* canvas) const {
134*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kImageMode == ImageMode::kNone);
135*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kDrawMode == DrawMode::kBatch);
136*c8dee2aaSAndroid Build Coastguard Worker 
137*c8dee2aaSAndroid Build Coastguard Worker         auto context = canvas->recordingContext();
138*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(context);
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker         GrQuadSetEntry batch[kRectCount];
141*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kRectCount; ++i) {
142*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fRect = fRects[i];
143*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fColor = fColors[i].premul();
144*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fLocalMatrix = SkMatrix::I();
145*c8dee2aaSAndroid Build Coastguard Worker             batch[i].fAAFlags = GrQuadAAFlags::kAll;
146*c8dee2aaSAndroid Build Coastguard Worker         }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
149*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorWHITE);
150*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker         auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas);
153*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix view = canvas->getLocalToDeviceAs3x3();
154*c8dee2aaSAndroid Build Coastguard Worker         SkSurfaceProps props;
155*c8dee2aaSAndroid Build Coastguard Worker         GrPaint grPaint;
156*c8dee2aaSAndroid Build Coastguard Worker         SkPaintToGrPaint(context, sdc->colorInfo(), paint, view, props, &grPaint);
157*c8dee2aaSAndroid Build Coastguard Worker         sdc->drawQuadSet(nullptr, std::move(grPaint), view, batch, kRectCount);
158*c8dee2aaSAndroid Build Coastguard Worker     }
159*c8dee2aaSAndroid Build Coastguard Worker 
drawSolidColorsRef(SkCanvas * canvas) const160*c8dee2aaSAndroid Build Coastguard Worker     void drawSolidColorsRef(SkCanvas* canvas) const {
161*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kImageMode == ImageMode::kNone);
162*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kDrawMode == DrawMode::kRef || kDrawMode == DrawMode::kQuad);
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
165*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
166*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kRectCount; ++i) {
167*c8dee2aaSAndroid Build Coastguard Worker             if (kDrawMode == DrawMode::kRef) {
168*c8dee2aaSAndroid Build Coastguard Worker                 paint.setColor4f(fColors[i]);
169*c8dee2aaSAndroid Build Coastguard Worker                 canvas->drawRect(fRects[i], paint);
170*c8dee2aaSAndroid Build Coastguard Worker             } else {
171*c8dee2aaSAndroid Build Coastguard Worker                 canvas->experimental_DrawEdgeAAQuad(fRects[i], nullptr, SkCanvas::kAll_QuadAAFlags,
172*c8dee2aaSAndroid Build Coastguard Worker                                                     fColors[i], SkBlendMode::kSrcOver);
173*c8dee2aaSAndroid Build Coastguard Worker             }
174*c8dee2aaSAndroid Build Coastguard Worker         }
175*c8dee2aaSAndroid Build Coastguard Worker     }
176*c8dee2aaSAndroid Build Coastguard Worker 
onGetName()177*c8dee2aaSAndroid Build Coastguard Worker     const char* onGetName() override {
178*c8dee2aaSAndroid Build Coastguard Worker         if (fName.isEmpty()) {
179*c8dee2aaSAndroid Build Coastguard Worker             this->computeName();
180*c8dee2aaSAndroid Build Coastguard Worker         }
181*c8dee2aaSAndroid Build Coastguard Worker         return fName.c_str();
182*c8dee2aaSAndroid Build Coastguard Worker     }
183*c8dee2aaSAndroid Build Coastguard Worker 
onDelayedSetup()184*c8dee2aaSAndroid Build Coastguard Worker     void onDelayedSetup() override {
185*c8dee2aaSAndroid Build Coastguard Worker         static constexpr SkScalar kMinRectSize = 0.2f;
186*c8dee2aaSAndroid Build Coastguard Worker         static constexpr SkScalar kMaxRectSize = 300.f;
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker         SkRandom rand;
189*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kRectCount; i++) {
190*c8dee2aaSAndroid Build Coastguard Worker             if (kLayout == RectangleLayout::kRandom) {
191*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar w = rand.nextF() * (kMaxRectSize - kMinRectSize) + kMinRectSize;
192*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar h = rand.nextF() * (kMaxRectSize - kMinRectSize) + kMinRectSize;
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar x = rand.nextF() * (kWidth - w);
195*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar y = rand.nextF() * (kHeight - h);
196*c8dee2aaSAndroid Build Coastguard Worker 
197*c8dee2aaSAndroid Build Coastguard Worker                 fRects[i].setXYWH(x, y, w, h);
198*c8dee2aaSAndroid Build Coastguard Worker             } else {
199*c8dee2aaSAndroid Build Coastguard Worker                 int gridSize = SkScalarCeilToInt(SkScalarSqrt(kRectCount));
200*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(gridSize * gridSize >= kRectCount);
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar w = (kWidth - 1.f) / gridSize;
203*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar h = (kHeight - 1.f) / gridSize;
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar x = (i % gridSize) * w + 0.5f; // Offset to ensure AA doesn't get disabled
206*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar y = (i / gridSize) * h + 0.5f;
207*c8dee2aaSAndroid Build Coastguard Worker 
208*c8dee2aaSAndroid Build Coastguard Worker                 fRects[i].setXYWH(x, y, w, h);
209*c8dee2aaSAndroid Build Coastguard Worker             }
210*c8dee2aaSAndroid Build Coastguard Worker 
211*c8dee2aaSAndroid Build Coastguard Worker             // Make sure we don't extend outside the render target, don't want to include clipping
212*c8dee2aaSAndroid Build Coastguard Worker             // in the benchmark.
213*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(SkRect::MakeWH(kWidth, kHeight).contains(fRects[i]));
214*c8dee2aaSAndroid Build Coastguard Worker 
215*c8dee2aaSAndroid Build Coastguard Worker             fColors[i] = {rand.nextF(), rand.nextF(), rand.nextF(), 1.f};
216*c8dee2aaSAndroid Build Coastguard Worker         }
217*c8dee2aaSAndroid Build Coastguard Worker     }
218*c8dee2aaSAndroid Build Coastguard Worker 
onPerCanvasPreDraw(SkCanvas * canvas)219*c8dee2aaSAndroid Build Coastguard Worker     void onPerCanvasPreDraw(SkCanvas* canvas) override {
220*c8dee2aaSAndroid Build Coastguard Worker         // Push the skimages to the GPU when using the GPU backend so that the texture creation is
221*c8dee2aaSAndroid Build Coastguard Worker         // not part of the bench measurements. Always remake the images since they are so simple,
222*c8dee2aaSAndroid Build Coastguard Worker         // and since they are context-specific, this works when the bench runs multiple GPU backends
223*c8dee2aaSAndroid Build Coastguard Worker         auto direct = GrAsDirectContext(canvas->recordingContext());
224*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kImageCount; ++i) {
225*c8dee2aaSAndroid Build Coastguard Worker             SkBitmap bm;
226*c8dee2aaSAndroid Build Coastguard Worker             bm.allocN32Pixels(256, 256);
227*c8dee2aaSAndroid Build Coastguard Worker             bm.eraseColor(fColors[i].toSkColor());
228*c8dee2aaSAndroid Build Coastguard Worker             auto image = bm.asImage();
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker             if (direct) {
231*c8dee2aaSAndroid Build Coastguard Worker                 fImages[i] = SkImages::TextureFromImage(direct, image);
232*c8dee2aaSAndroid Build Coastguard Worker             } else {
233*c8dee2aaSAndroid Build Coastguard Worker                 fImages[i] = std::move(image);
234*c8dee2aaSAndroid Build Coastguard Worker             }
235*c8dee2aaSAndroid Build Coastguard Worker         }
236*c8dee2aaSAndroid Build Coastguard Worker     }
237*c8dee2aaSAndroid Build Coastguard Worker 
onPerCanvasPostDraw(SkCanvas * canvas)238*c8dee2aaSAndroid Build Coastguard Worker     void onPerCanvasPostDraw(SkCanvas* canvas) override {
239*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < kImageCount; ++i) {
240*c8dee2aaSAndroid Build Coastguard Worker             // For Vulkan we need to make sure the bench isn't holding onto any refs to the
241*c8dee2aaSAndroid Build Coastguard Worker             // GrContext when we go to delete the vulkan context (which happens before the bench is
242*c8dee2aaSAndroid Build Coastguard Worker             // deleted). So reset all the images here so they aren't holding GrContext refs.
243*c8dee2aaSAndroid Build Coastguard Worker             fImages[i].reset();
244*c8dee2aaSAndroid Build Coastguard Worker         }
245*c8dee2aaSAndroid Build Coastguard Worker     }
246*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(int loops,SkCanvas * canvas)247*c8dee2aaSAndroid Build Coastguard Worker     void onDraw(int loops, SkCanvas* canvas) override {
248*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < loops; i++) {
249*c8dee2aaSAndroid Build Coastguard Worker             if (kImageMode == ImageMode::kNone) {
250*c8dee2aaSAndroid Build Coastguard Worker                 if (kDrawMode == DrawMode::kBatch) {
251*c8dee2aaSAndroid Build Coastguard Worker                     this->drawSolidColorsBatch(canvas);
252*c8dee2aaSAndroid Build Coastguard Worker                 } else {
253*c8dee2aaSAndroid Build Coastguard Worker                     this->drawSolidColorsRef(canvas);
254*c8dee2aaSAndroid Build Coastguard Worker                 }
255*c8dee2aaSAndroid Build Coastguard Worker             } else {
256*c8dee2aaSAndroid Build Coastguard Worker                 if (kDrawMode == DrawMode::kBatch) {
257*c8dee2aaSAndroid Build Coastguard Worker                     this->drawImagesBatch(canvas);
258*c8dee2aaSAndroid Build Coastguard Worker                 } else {
259*c8dee2aaSAndroid Build Coastguard Worker                     this->drawImagesRef(canvas);
260*c8dee2aaSAndroid Build Coastguard Worker                 }
261*c8dee2aaSAndroid Build Coastguard Worker             }
262*c8dee2aaSAndroid Build Coastguard Worker         }
263*c8dee2aaSAndroid Build Coastguard Worker     }
264*c8dee2aaSAndroid Build Coastguard Worker 
onGetSize()265*c8dee2aaSAndroid Build Coastguard Worker     SkISize onGetSize() override {
266*c8dee2aaSAndroid Build Coastguard Worker         return { kWidth, kHeight };
267*c8dee2aaSAndroid Build Coastguard Worker     }
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = Benchmark;
270*c8dee2aaSAndroid Build Coastguard Worker };
271*c8dee2aaSAndroid Build Coastguard Worker 
272*c8dee2aaSAndroid Build Coastguard Worker // constructor call is wrapped in () so the macro doesn't break parsing the commas in the template
273*c8dee2aaSAndroid Build Coastguard Worker #define ADD_BENCH(n, layout, imageMode, drawMode)                              \
274*c8dee2aaSAndroid Build Coastguard Worker     DEF_BENCH( return (new BulkRectBench<n, layout, imageMode, drawMode>()); )
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker #define ADD_BENCH_FAMILY(n, layout)                                            \
277*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kShared, DrawMode::kBatch)                 \
278*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kShared, DrawMode::kRef)                   \
279*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kUnique, DrawMode::kBatch)                 \
280*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kUnique, DrawMode::kRef)                   \
281*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kNone,   DrawMode::kBatch)                 \
282*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kNone,   DrawMode::kRef)                   \
283*c8dee2aaSAndroid Build Coastguard Worker     ADD_BENCH(n, layout, ImageMode::kNone,   DrawMode::kQuad)
284*c8dee2aaSAndroid Build Coastguard Worker 
285*c8dee2aaSAndroid Build Coastguard Worker ADD_BENCH_FAMILY(1000,  RectangleLayout::kRandom)
286*c8dee2aaSAndroid Build Coastguard Worker ADD_BENCH_FAMILY(1000,  RectangleLayout::kGrid)
287*c8dee2aaSAndroid Build Coastguard Worker 
288*c8dee2aaSAndroid Build Coastguard Worker #undef ADD_BENCH_FAMILY
289*c8dee2aaSAndroid Build Coastguard Worker #undef ADD_BENCH
290