xref: /aosp_15_r20/external/skia/bench/CompositingImagesBench.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2018 Google Inc.
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 <memory>
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "bench/GpuTools.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker enum class ClampingMode {
22*c8dee2aaSAndroid Build Coastguard Worker     // Submit image set entries with the fast constraint
23*c8dee2aaSAndroid Build Coastguard Worker     kAlwaysFast,
24*c8dee2aaSAndroid Build Coastguard Worker     // Submit image set entries with the strict constraint
25*c8dee2aaSAndroid Build Coastguard Worker     kAlwaysStrict,
26*c8dee2aaSAndroid Build Coastguard Worker     // Submit non-right/bottom tiles as fast, the bottom-right corner as strict, and bottom or right
27*c8dee2aaSAndroid Build Coastguard Worker     // edge tiles as strict with geometry modification to match content area. These will be
28*c8dee2aaSAndroid Build Coastguard Worker     // submitted from left-to-right, top-to-bottom so will necessarily be split into many batches.
29*c8dee2aaSAndroid Build Coastguard Worker     kChromeTiling_RowMajor,
30*c8dee2aaSAndroid Build Coastguard Worker     // As above, but group all fast tiles first, then bottom and right edge tiles in a second batch.
31*c8dee2aaSAndroid Build Coastguard Worker     kChromeTiling_Optimal
32*c8dee2aaSAndroid Build Coastguard Worker };
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker enum class TransformMode {
35*c8dee2aaSAndroid Build Coastguard Worker     // Tiles will be axis aligned on integer pixels
36*c8dee2aaSAndroid Build Coastguard Worker     kNone,
37*c8dee2aaSAndroid Build Coastguard Worker     // Subpixel, tiles will be axis aligned but adjusted to subpixel coordinates
38*c8dee2aaSAndroid Build Coastguard Worker     kSubpixel,
39*c8dee2aaSAndroid Build Coastguard Worker     // Rotated, tiles will be rotated globally; they won't overlap but their device space bounds may
40*c8dee2aaSAndroid Build Coastguard Worker     kRotated,
41*c8dee2aaSAndroid Build Coastguard Worker     // Perspective, tiles will have global perspective
42*c8dee2aaSAndroid Build Coastguard Worker     kPerspective
43*c8dee2aaSAndroid Build Coastguard Worker };
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker /**
46*c8dee2aaSAndroid Build Coastguard Worker  * Simulates drawing layers images in a grid a la a tile based compositor.
47*c8dee2aaSAndroid Build Coastguard Worker  */
48*c8dee2aaSAndroid Build Coastguard Worker class CompositingImages : public Benchmark {
49*c8dee2aaSAndroid Build Coastguard Worker public:
CompositingImages(SkISize imageSize,SkISize tileSize,SkISize tileGridSize,ClampingMode clampMode,TransformMode transformMode,int layerCnt)50*c8dee2aaSAndroid Build Coastguard Worker     CompositingImages(SkISize imageSize, SkISize tileSize, SkISize tileGridSize,
51*c8dee2aaSAndroid Build Coastguard Worker                       ClampingMode clampMode, TransformMode transformMode, int layerCnt)
52*c8dee2aaSAndroid Build Coastguard Worker             : fImageSize(imageSize)
53*c8dee2aaSAndroid Build Coastguard Worker             , fTileSize(tileSize)
54*c8dee2aaSAndroid Build Coastguard Worker             , fTileGridSize(tileGridSize)
55*c8dee2aaSAndroid Build Coastguard Worker             , fClampMode(clampMode)
56*c8dee2aaSAndroid Build Coastguard Worker             , fTransformMode(transformMode)
57*c8dee2aaSAndroid Build Coastguard Worker             , fLayerCnt(layerCnt) {
58*c8dee2aaSAndroid Build Coastguard Worker         fName.appendf("compositing_images_tile_size_%dx%d_grid_%dx%d_layers_%d",
59*c8dee2aaSAndroid Build Coastguard Worker                       fTileSize.fWidth, fTileSize.fHeight, fTileGridSize.fWidth,
60*c8dee2aaSAndroid Build Coastguard Worker                       fTileGridSize.fHeight, fLayerCnt);
61*c8dee2aaSAndroid Build Coastguard Worker         if (imageSize != tileSize) {
62*c8dee2aaSAndroid Build Coastguard Worker             fName.appendf("_image_%dx%d", imageSize.fWidth, imageSize.fHeight);
63*c8dee2aaSAndroid Build Coastguard Worker         }
64*c8dee2aaSAndroid Build Coastguard Worker         switch(clampMode) {
65*c8dee2aaSAndroid Build Coastguard Worker             case ClampingMode::kAlwaysFast:
66*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_fast");
67*c8dee2aaSAndroid Build Coastguard Worker                 break;
68*c8dee2aaSAndroid Build Coastguard Worker             case ClampingMode::kAlwaysStrict:
69*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_strict");
70*c8dee2aaSAndroid Build Coastguard Worker                 break;
71*c8dee2aaSAndroid Build Coastguard Worker             case ClampingMode::kChromeTiling_RowMajor:
72*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_chrome");
73*c8dee2aaSAndroid Build Coastguard Worker                 break;
74*c8dee2aaSAndroid Build Coastguard Worker             case ClampingMode::kChromeTiling_Optimal:
75*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_chrome_optimal");
76*c8dee2aaSAndroid Build Coastguard Worker                 break;
77*c8dee2aaSAndroid Build Coastguard Worker         }
78*c8dee2aaSAndroid Build Coastguard Worker         switch(transformMode) {
79*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kNone:
80*c8dee2aaSAndroid Build Coastguard Worker                 break;
81*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kSubpixel:
82*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_subpixel");
83*c8dee2aaSAndroid Build Coastguard Worker                 break;
84*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kRotated:
85*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_rotated");
86*c8dee2aaSAndroid Build Coastguard Worker                 break;
87*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kPerspective:
88*c8dee2aaSAndroid Build Coastguard Worker                 fName.append("_persp");
89*c8dee2aaSAndroid Build Coastguard Worker                 break;
90*c8dee2aaSAndroid Build Coastguard Worker         }
91*c8dee2aaSAndroid Build Coastguard Worker     }
92*c8dee2aaSAndroid Build Coastguard Worker 
isSuitableFor(Backend backend)93*c8dee2aaSAndroid Build Coastguard Worker     bool isSuitableFor(Backend backend) override { return Backend::kGanesh == backend; }
94*c8dee2aaSAndroid Build Coastguard Worker 
95*c8dee2aaSAndroid Build Coastguard Worker protected:
onGetName()96*c8dee2aaSAndroid Build Coastguard Worker     const char* onGetName() override { return fName.c_str(); }
97*c8dee2aaSAndroid Build Coastguard Worker 
onPerCanvasPreDraw(SkCanvas * canvas)98*c8dee2aaSAndroid Build Coastguard Worker     void onPerCanvasPreDraw(SkCanvas* canvas) override {
99*c8dee2aaSAndroid Build Coastguard Worker         // Use image size, which may be larger than the tile size (emulating how Chrome specifies
100*c8dee2aaSAndroid Build Coastguard Worker         // their tiles).
101*c8dee2aaSAndroid Build Coastguard Worker         auto ii = SkImageInfo::Make(fImageSize.fWidth, fImageSize.fHeight, kRGBA_8888_SkColorType,
102*c8dee2aaSAndroid Build Coastguard Worker                                     kPremul_SkAlphaType, nullptr);
103*c8dee2aaSAndroid Build Coastguard Worker         SkRandom random;
104*c8dee2aaSAndroid Build Coastguard Worker         int numImages = fLayerCnt * fTileGridSize.fWidth * fTileGridSize.fHeight;
105*c8dee2aaSAndroid Build Coastguard Worker         fImages = std::make_unique<sk_sp<SkImage>[]>(numImages);
106*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < numImages; ++i) {
107*c8dee2aaSAndroid Build Coastguard Worker             auto surf = canvas->makeSurface(ii);
108*c8dee2aaSAndroid Build Coastguard Worker             SkColor color = random.nextU();
109*c8dee2aaSAndroid Build Coastguard Worker             surf->getCanvas()->clear(color);
110*c8dee2aaSAndroid Build Coastguard Worker             SkPaint paint;
111*c8dee2aaSAndroid Build Coastguard Worker             paint.setColor(~color);
112*c8dee2aaSAndroid Build Coastguard Worker             paint.setBlendMode(SkBlendMode::kSrc);
113*c8dee2aaSAndroid Build Coastguard Worker             // While the image may be bigger than fTileSize, prepare its content as if fTileSize
114*c8dee2aaSAndroid Build Coastguard Worker             // is what will be visible.
115*c8dee2aaSAndroid Build Coastguard Worker             surf->getCanvas()->drawRect(
116*c8dee2aaSAndroid Build Coastguard Worker                     SkRect::MakeLTRB(3, 3, fTileSize.fWidth - 3, fTileSize.fHeight - 3), paint);
117*c8dee2aaSAndroid Build Coastguard Worker             fImages[i] = surf->makeImageSnapshot();
118*c8dee2aaSAndroid Build Coastguard Worker         }
119*c8dee2aaSAndroid Build Coastguard Worker     }
120*c8dee2aaSAndroid Build Coastguard Worker 
onPerCanvasPostDraw(SkCanvas *)121*c8dee2aaSAndroid Build Coastguard Worker     void onPerCanvasPostDraw(SkCanvas*) override { fImages.reset(); }
122*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(int loops,SkCanvas * canvas)123*c8dee2aaSAndroid Build Coastguard Worker     void onDraw(int loops, SkCanvas* canvas) override {
124*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
125*c8dee2aaSAndroid Build Coastguard Worker         paint.setAntiAlias(true);
126*c8dee2aaSAndroid Build Coastguard Worker         SkSamplingOptions sampling(SkFilterMode::kLinear);
127*c8dee2aaSAndroid Build Coastguard Worker 
128*c8dee2aaSAndroid Build Coastguard Worker         canvas->save();
129*c8dee2aaSAndroid Build Coastguard Worker         canvas->concat(this->getTransform());
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker         for (int loop = 0; loop < loops; ++loop) {
132*c8dee2aaSAndroid Build Coastguard Worker             for (int l = 0; l < fLayerCnt; ++l) {
133*c8dee2aaSAndroid Build Coastguard Worker                 AutoTArray<SkCanvas::ImageSetEntry> set(
134*c8dee2aaSAndroid Build Coastguard Worker                         fTileGridSize.fWidth * fTileGridSize.fHeight);
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker                 if (fClampMode == ClampingMode::kAlwaysFast ||
137*c8dee2aaSAndroid Build Coastguard Worker                     fClampMode == ClampingMode::kAlwaysStrict) {
138*c8dee2aaSAndroid Build Coastguard Worker                     // Simple 2D for loop, submit everything as a single batch
139*c8dee2aaSAndroid Build Coastguard Worker                     int i = 0;
140*c8dee2aaSAndroid Build Coastguard Worker                     for (int y = 0; y < fTileGridSize.fHeight; ++y) {
141*c8dee2aaSAndroid Build Coastguard Worker                         for (int x = 0; x < fTileGridSize.fWidth; ++x) {
142*c8dee2aaSAndroid Build Coastguard Worker                             set[i++] = this->getEntry(x, y, l);
143*c8dee2aaSAndroid Build Coastguard Worker                         }
144*c8dee2aaSAndroid Build Coastguard Worker                     }
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker                     SkCanvas::SrcRectConstraint constraint =
147*c8dee2aaSAndroid Build Coastguard Worker                             fClampMode == ClampingMode::kAlwaysFast
148*c8dee2aaSAndroid Build Coastguard Worker                                     ? SkCanvas::kFast_SrcRectConstraint
149*c8dee2aaSAndroid Build Coastguard Worker                                     : SkCanvas::kStrict_SrcRectConstraint;
150*c8dee2aaSAndroid Build Coastguard Worker                     canvas->experimental_DrawEdgeAAImageSet(set.get(), i, nullptr, nullptr,
151*c8dee2aaSAndroid Build Coastguard Worker                                                             sampling, &paint, constraint);
152*c8dee2aaSAndroid Build Coastguard Worker                 } else if (fClampMode == ClampingMode::kChromeTiling_RowMajor) {
153*c8dee2aaSAndroid Build Coastguard Worker                     // Same tile order, but break batching between fast and strict sections, and
154*c8dee2aaSAndroid Build Coastguard Worker                     // adjust bottom and right tiles to encode content area distinct from src rect.
155*c8dee2aaSAndroid Build Coastguard Worker                     int i = 0;
156*c8dee2aaSAndroid Build Coastguard Worker                     for (int y = 0; y < fTileGridSize.fHeight - 1; ++y) {
157*c8dee2aaSAndroid Build Coastguard Worker                         int rowStart = i;
158*c8dee2aaSAndroid Build Coastguard Worker                         for (int x = 0; x < fTileGridSize.fWidth - 1; ++x) {
159*c8dee2aaSAndroid Build Coastguard Worker                             set[i++] = this->getEntry(x, y, l);
160*c8dee2aaSAndroid Build Coastguard Worker                         }
161*c8dee2aaSAndroid Build Coastguard Worker                         // Flush "fast" horizontal row
162*c8dee2aaSAndroid Build Coastguard Worker                         canvas->experimental_DrawEdgeAAImageSet(set.get() + rowStart,
163*c8dee2aaSAndroid Build Coastguard Worker                                 fTileGridSize.fWidth - 1, nullptr, nullptr, sampling, &paint,
164*c8dee2aaSAndroid Build Coastguard Worker                                 SkCanvas::kFast_SrcRectConstraint);
165*c8dee2aaSAndroid Build Coastguard Worker                         // Then flush a single adjusted entry for the right edge
166*c8dee2aaSAndroid Build Coastguard Worker                         SkPoint dstQuad[4];
167*c8dee2aaSAndroid Build Coastguard Worker                         set[i++] = this->getAdjustedEntry(fTileGridSize.fWidth - 1, y, l, dstQuad);
168*c8dee2aaSAndroid Build Coastguard Worker                         canvas->experimental_DrawEdgeAAImageSet(
169*c8dee2aaSAndroid Build Coastguard Worker                                 set.get() + fTileGridSize.fWidth - 1, 1, dstQuad, nullptr, sampling,
170*c8dee2aaSAndroid Build Coastguard Worker                                 &paint, SkCanvas::kStrict_SrcRectConstraint);
171*c8dee2aaSAndroid Build Coastguard Worker                     }
172*c8dee2aaSAndroid Build Coastguard Worker                     // For last row, accumulate it as a single strict batch
173*c8dee2aaSAndroid Build Coastguard Worker                     int rowStart = i;
174*c8dee2aaSAndroid Build Coastguard Worker                     AutoTArray<SkPoint> dstQuads(4 * (fTileGridSize.fWidth - 1));
175*c8dee2aaSAndroid Build Coastguard Worker                     for (int x = 0; x < fTileGridSize.fWidth - 1; ++x) {
176*c8dee2aaSAndroid Build Coastguard Worker                         set[i++] = this->getAdjustedEntry(x, fTileGridSize.fHeight - 1, l,
177*c8dee2aaSAndroid Build Coastguard Worker                                                           dstQuads.get() + x * 4);
178*c8dee2aaSAndroid Build Coastguard Worker                     }
179*c8dee2aaSAndroid Build Coastguard Worker                     // The corner can use conventional strict mode without geometric adjustment
180*c8dee2aaSAndroid Build Coastguard Worker                     set[i++] = this->getEntry(
181*c8dee2aaSAndroid Build Coastguard Worker                             fTileGridSize.fWidth - 1, fTileGridSize.fHeight - 1, l);
182*c8dee2aaSAndroid Build Coastguard Worker                     canvas->experimental_DrawEdgeAAImageSet(set.get() + rowStart,
183*c8dee2aaSAndroid Build Coastguard Worker                             fTileGridSize.fWidth, dstQuads.get(), nullptr, sampling, &paint,
184*c8dee2aaSAndroid Build Coastguard Worker                             SkCanvas::kStrict_SrcRectConstraint);
185*c8dee2aaSAndroid Build Coastguard Worker                 } else {
186*c8dee2aaSAndroid Build Coastguard Worker                     SkASSERT(fClampMode == ClampingMode::kChromeTiling_Optimal);
187*c8dee2aaSAndroid Build Coastguard Worker                     int i = 0;
188*c8dee2aaSAndroid Build Coastguard Worker                     // Interior fast tiles
189*c8dee2aaSAndroid Build Coastguard Worker                     for (int y = 0; y < fTileGridSize.fHeight - 1; ++y) {
190*c8dee2aaSAndroid Build Coastguard Worker                         for (int x = 0; x < fTileGridSize.fWidth - 1; ++x) {
191*c8dee2aaSAndroid Build Coastguard Worker                             set[i++] = this->getEntry(x, y, l);
192*c8dee2aaSAndroid Build Coastguard Worker                         }
193*c8dee2aaSAndroid Build Coastguard Worker                     }
194*c8dee2aaSAndroid Build Coastguard Worker                     canvas->experimental_DrawEdgeAAImageSet(set.get(), i, nullptr, nullptr,
195*c8dee2aaSAndroid Build Coastguard Worker                                                             sampling, &paint,
196*c8dee2aaSAndroid Build Coastguard Worker                                                             SkCanvas::kFast_SrcRectConstraint);
197*c8dee2aaSAndroid Build Coastguard Worker 
198*c8dee2aaSAndroid Build Coastguard Worker                     // Right edge
199*c8dee2aaSAndroid Build Coastguard Worker                     int strictStart = i;
200*c8dee2aaSAndroid Build Coastguard Worker                     AutoTArray<SkPoint> dstQuads(
201*c8dee2aaSAndroid Build Coastguard Worker                             4 * (fTileGridSize.fWidth + fTileGridSize.fHeight - 2));
202*c8dee2aaSAndroid Build Coastguard Worker                     for (int y = 0; y < fTileGridSize.fHeight - 1; ++y) {
203*c8dee2aaSAndroid Build Coastguard Worker                         set[i++] = this->getAdjustedEntry(fTileGridSize.fWidth - 1, y, l,
204*c8dee2aaSAndroid Build Coastguard Worker                                                           dstQuads.get() + y * 4);
205*c8dee2aaSAndroid Build Coastguard Worker                     }
206*c8dee2aaSAndroid Build Coastguard Worker                     canvas->experimental_DrawEdgeAAImageSet(set.get() + strictStart,
207*c8dee2aaSAndroid Build Coastguard Worker                             i - strictStart, dstQuads.get(), nullptr, sampling, &paint,
208*c8dee2aaSAndroid Build Coastguard Worker                             SkCanvas::kStrict_SrcRectConstraint);
209*c8dee2aaSAndroid Build Coastguard Worker                     int quadStart = 4 * (fTileGridSize.fHeight - 1);
210*c8dee2aaSAndroid Build Coastguard Worker                     strictStart = i;
211*c8dee2aaSAndroid Build Coastguard Worker                     for (int x = 0; x < fTileGridSize.fWidth - 1; ++x) {
212*c8dee2aaSAndroid Build Coastguard Worker                         set[i++] = this->getAdjustedEntry(x, fTileGridSize.fHeight - 1, l,
213*c8dee2aaSAndroid Build Coastguard Worker                                                           dstQuads.get() + quadStart + x * 4);
214*c8dee2aaSAndroid Build Coastguard Worker                     }
215*c8dee2aaSAndroid Build Coastguard Worker                     set[i++] = this->getEntry(
216*c8dee2aaSAndroid Build Coastguard Worker                             fTileGridSize.fWidth - 1, fTileGridSize.fHeight - 1, l);
217*c8dee2aaSAndroid Build Coastguard Worker                     canvas->experimental_DrawEdgeAAImageSet(set.get() + strictStart,
218*c8dee2aaSAndroid Build Coastguard Worker                             i - strictStart, dstQuads.get() + quadStart, nullptr, sampling, &paint,
219*c8dee2aaSAndroid Build Coastguard Worker                             SkCanvas::kStrict_SrcRectConstraint);
220*c8dee2aaSAndroid Build Coastguard Worker                 }
221*c8dee2aaSAndroid Build Coastguard Worker             }
222*c8dee2aaSAndroid Build Coastguard Worker             // Prevent any batching between composited "frames".
223*c8dee2aaSAndroid Build Coastguard Worker             skgpu::Flush(canvas->getSurface());
224*c8dee2aaSAndroid Build Coastguard Worker         }
225*c8dee2aaSAndroid Build Coastguard Worker         canvas->restore();
226*c8dee2aaSAndroid Build Coastguard Worker     }
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker private:
getTransform() const229*c8dee2aaSAndroid Build Coastguard Worker     SkMatrix getTransform() const {
230*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix m;
231*c8dee2aaSAndroid Build Coastguard Worker         switch(fTransformMode) {
232*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kNone:
233*c8dee2aaSAndroid Build Coastguard Worker                 m.setIdentity();
234*c8dee2aaSAndroid Build Coastguard Worker                 break;
235*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kSubpixel:
236*c8dee2aaSAndroid Build Coastguard Worker                 m.setTranslate(0.5f, 0.5f);
237*c8dee2aaSAndroid Build Coastguard Worker                 break;
238*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kRotated:
239*c8dee2aaSAndroid Build Coastguard Worker                 m.setRotate(15.f);
240*c8dee2aaSAndroid Build Coastguard Worker                 break;
241*c8dee2aaSAndroid Build Coastguard Worker             case TransformMode::kPerspective: {
242*c8dee2aaSAndroid Build Coastguard Worker                 m.setIdentity();
243*c8dee2aaSAndroid Build Coastguard Worker                 m.setPerspY(0.001f);
244*c8dee2aaSAndroid Build Coastguard Worker                 m.setSkewX(SkIntToScalar(8) / 25);
245*c8dee2aaSAndroid Build Coastguard Worker                 break;
246*c8dee2aaSAndroid Build Coastguard Worker             }
247*c8dee2aaSAndroid Build Coastguard Worker         }
248*c8dee2aaSAndroid Build Coastguard Worker         return m;
249*c8dee2aaSAndroid Build Coastguard Worker     }
250*c8dee2aaSAndroid Build Coastguard Worker 
onGetSize()251*c8dee2aaSAndroid Build Coastguard Worker     SkISize onGetSize() override {
252*c8dee2aaSAndroid Build Coastguard Worker         SkRect size = SkRect::MakeWH(1.25f * fTileSize.fWidth * fTileGridSize.fWidth,
253*c8dee2aaSAndroid Build Coastguard Worker                                      1.25f * fTileSize.fHeight * fTileGridSize.fHeight);
254*c8dee2aaSAndroid Build Coastguard Worker         this->getTransform().mapRect(&size);
255*c8dee2aaSAndroid Build Coastguard Worker         return SkISize::Make(SkScalarCeilToInt(size.width()), SkScalarCeilToInt(size.height()));
256*c8dee2aaSAndroid Build Coastguard Worker     }
257*c8dee2aaSAndroid Build Coastguard Worker 
getEdgeFlags(int x,int y) const258*c8dee2aaSAndroid Build Coastguard Worker     unsigned getEdgeFlags(int x, int y) const {
259*c8dee2aaSAndroid Build Coastguard Worker         unsigned flags = SkCanvas::kNone_QuadAAFlags;
260*c8dee2aaSAndroid Build Coastguard Worker         if (x == 0) {
261*c8dee2aaSAndroid Build Coastguard Worker             flags |= SkCanvas::kLeft_QuadAAFlag;
262*c8dee2aaSAndroid Build Coastguard Worker         } else if (x == fTileGridSize.fWidth - 1) {
263*c8dee2aaSAndroid Build Coastguard Worker             flags |= SkCanvas::kRight_QuadAAFlag;
264*c8dee2aaSAndroid Build Coastguard Worker         }
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker         if (y == 0) {
267*c8dee2aaSAndroid Build Coastguard Worker             flags |= SkCanvas::kTop_QuadAAFlag;
268*c8dee2aaSAndroid Build Coastguard Worker         } else if (y == fTileGridSize.fHeight - 1) {
269*c8dee2aaSAndroid Build Coastguard Worker             flags |= SkCanvas::kBottom_QuadAAFlag;
270*c8dee2aaSAndroid Build Coastguard Worker         }
271*c8dee2aaSAndroid Build Coastguard Worker         return flags;
272*c8dee2aaSAndroid Build Coastguard Worker     }
273*c8dee2aaSAndroid Build Coastguard Worker 
getEntry(int x,int y,int layer) const274*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas::ImageSetEntry getEntry(int x, int y, int layer) const {
275*c8dee2aaSAndroid Build Coastguard Worker         int imageIdx =
276*c8dee2aaSAndroid Build Coastguard Worker                 fTileGridSize.fWidth * fTileGridSize.fHeight * layer + fTileGridSize.fWidth * y + x;
277*c8dee2aaSAndroid Build Coastguard Worker         SkRect srcRect = SkRect::Make(fTileSize);
278*c8dee2aaSAndroid Build Coastguard Worker         // Make a non-identity transform between src and dst so bilerp isn't disabled.
279*c8dee2aaSAndroid Build Coastguard Worker         float dstWidth = srcRect.width() * 1.25f;
280*c8dee2aaSAndroid Build Coastguard Worker         float dstHeight = srcRect.height() * 1.25f;
281*c8dee2aaSAndroid Build Coastguard Worker         SkRect dstRect = SkRect::MakeXYWH(dstWidth * x, dstHeight * y, dstWidth, dstHeight);
282*c8dee2aaSAndroid Build Coastguard Worker         return SkCanvas::ImageSetEntry(fImages[imageIdx], srcRect, dstRect, 1.f,
283*c8dee2aaSAndroid Build Coastguard Worker                                        this->getEdgeFlags(x, y));
284*c8dee2aaSAndroid Build Coastguard Worker     }
285*c8dee2aaSAndroid Build Coastguard Worker 
getAdjustedEntry(int x,int y,int layer,SkPoint dstQuad[4]) const286*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas::ImageSetEntry getAdjustedEntry(int x, int y, int layer, SkPoint dstQuad[4]) const {
287*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(x == fTileGridSize.fWidth - 1 || y == fTileGridSize.fHeight - 1);
288*c8dee2aaSAndroid Build Coastguard Worker 
289*c8dee2aaSAndroid Build Coastguard Worker         SkCanvas::ImageSetEntry entry = this->getEntry(x, y, layer);
290*c8dee2aaSAndroid Build Coastguard Worker         SkRect contentRect = SkRect::Make(fImageSize);
291*c8dee2aaSAndroid Build Coastguard Worker         if (x == fTileGridSize.fWidth - 1) {
292*c8dee2aaSAndroid Build Coastguard Worker             // Right edge, so restrict horizontal content to tile width
293*c8dee2aaSAndroid Build Coastguard Worker             contentRect.fRight = fTileSize.fWidth;
294*c8dee2aaSAndroid Build Coastguard Worker         }
295*c8dee2aaSAndroid Build Coastguard Worker         if (y == fTileGridSize.fHeight - 1) {
296*c8dee2aaSAndroid Build Coastguard Worker             // Bottom edge, so restrict vertical content to tile height
297*c8dee2aaSAndroid Build Coastguard Worker             contentRect.fBottom = fTileSize.fHeight;
298*c8dee2aaSAndroid Build Coastguard Worker         }
299*c8dee2aaSAndroid Build Coastguard Worker 
300*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix srcToDst = SkMatrix::RectToRect(entry.fSrcRect, entry.fDstRect);
301*c8dee2aaSAndroid Build Coastguard Worker 
302*c8dee2aaSAndroid Build Coastguard Worker         // Story entry's dstRect into dstQuad, and use contentRect and contentDst as its src and dst
303*c8dee2aaSAndroid Build Coastguard Worker         entry.fDstRect.toQuad(dstQuad);
304*c8dee2aaSAndroid Build Coastguard Worker         entry.fSrcRect = contentRect;
305*c8dee2aaSAndroid Build Coastguard Worker         entry.fDstRect = srcToDst.mapRect(contentRect);
306*c8dee2aaSAndroid Build Coastguard Worker         entry.fHasClip = true;
307*c8dee2aaSAndroid Build Coastguard Worker 
308*c8dee2aaSAndroid Build Coastguard Worker         return entry;
309*c8dee2aaSAndroid Build Coastguard Worker     }
310*c8dee2aaSAndroid Build Coastguard Worker 
311*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<sk_sp<SkImage>[]> fImages;
312*c8dee2aaSAndroid Build Coastguard Worker     SkString fName;
313*c8dee2aaSAndroid Build Coastguard Worker     SkISize fImageSize;
314*c8dee2aaSAndroid Build Coastguard Worker     SkISize fTileSize;
315*c8dee2aaSAndroid Build Coastguard Worker     SkISize fTileGridSize;
316*c8dee2aaSAndroid Build Coastguard Worker     ClampingMode fClampMode;
317*c8dee2aaSAndroid Build Coastguard Worker     TransformMode fTransformMode;
318*c8dee2aaSAndroid Build Coastguard Worker     int fLayerCnt;
319*c8dee2aaSAndroid Build Coastguard Worker 
320*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = Benchmark;
321*c8dee2aaSAndroid Build Coastguard Worker };
322*c8dee2aaSAndroid Build Coastguard Worker 
323*c8dee2aaSAndroid Build Coastguard Worker // Subpixel = false; all of the draw commands align with integer pixels so AA will be automatically
324*c8dee2aaSAndroid Build Coastguard Worker // turned off within the operation
325*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({256, 256}, {256, 256}, {8, 8}, ClampingMode::kAlwaysFast, TransformMode::kNone, 1));
326*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {512, 512}, {4, 4}, ClampingMode::kAlwaysFast, TransformMode::kNone, 1));
327*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({1024, 512}, {1024, 512}, {2, 4}, ClampingMode::kAlwaysFast, TransformMode::kNone, 1));
328*c8dee2aaSAndroid Build Coastguard Worker 
329*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({256, 256}, {256, 256}, {8, 8}, ClampingMode::kAlwaysFast, TransformMode::kNone, 4));
330*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {512, 512}, {4, 4}, ClampingMode::kAlwaysFast, TransformMode::kNone, 4));
331*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({1024, 512}, {1024, 512}, {2, 4}, ClampingMode::kAlwaysFast, TransformMode::kNone, 4));
332*c8dee2aaSAndroid Build Coastguard Worker 
333*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({256, 256}, {256, 256}, {8, 8}, ClampingMode::kAlwaysFast, TransformMode::kNone, 16));
334*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {512, 512}, {4, 4}, ClampingMode::kAlwaysFast, TransformMode::kNone, 16));
335*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({1024, 512}, {1024, 512}, {2, 4}, ClampingMode::kAlwaysFast, TransformMode::kNone, 16));
336*c8dee2aaSAndroid Build Coastguard Worker 
337*c8dee2aaSAndroid Build Coastguard Worker // Subpixel = true; force the draw commands to not align with pixels exactly so AA remains on
338*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({256, 256}, {256, 256}, {8, 8}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 1));
339*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {512, 512}, {4, 4}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 1));
340*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({1024, 512}, {1024, 512}, {2, 4}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 1));
341*c8dee2aaSAndroid Build Coastguard Worker 
342*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({256, 256}, {256, 256}, {8, 8}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 4));
343*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {512, 512}, {4, 4}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 4));
344*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({1024, 512}, {1024, 512}, {2, 4}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 4));
345*c8dee2aaSAndroid Build Coastguard Worker 
346*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({256, 256}, {256, 256}, {8, 8}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 16));
347*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {512, 512}, {4, 4}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 16));
348*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({1024, 512}, {1024, 512}, {2, 4}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 16));
349*c8dee2aaSAndroid Build Coastguard Worker 
350*c8dee2aaSAndroid Build Coastguard Worker // Test different tiling scenarios inspired by Chrome's compositor
351*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysFast, TransformMode::kNone, 1));
352*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysStrict, TransformMode::kNone, 1));
353*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_RowMajor, TransformMode::kNone, 1));
354*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_Optimal, TransformMode::kNone, 1));
355*c8dee2aaSAndroid Build Coastguard Worker 
356*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysFast, TransformMode::kSubpixel, 1));
357*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysStrict, TransformMode::kSubpixel, 1));
358*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_RowMajor, TransformMode::kSubpixel, 1));
359*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_Optimal, TransformMode::kSubpixel, 1));
360*c8dee2aaSAndroid Build Coastguard Worker 
361*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysFast, TransformMode::kRotated, 1));
362*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysStrict, TransformMode::kRotated, 1));
363*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_RowMajor, TransformMode::kRotated, 1));
364*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_Optimal, TransformMode::kRotated, 1));
365*c8dee2aaSAndroid Build Coastguard Worker 
366*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysFast, TransformMode::kPerspective, 1));
367*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kAlwaysStrict, TransformMode::kPerspective, 1));
368*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_RowMajor, TransformMode::kPerspective, 1));
369*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CompositingImages({512, 512}, {380, 380}, {5, 5}, ClampingMode::kChromeTiling_Optimal, TransformMode::kPerspective, 1));
370