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