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