1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "Benchmark.h" 9 10 #include "SkCanvas.h" 11 #include "SkImage.h" 12 #include "SkRandom.h" 13 #include "SkSurface.h" 14 15 /** 16 * Simulates drawing layers images in a grid a la a tile based compositor. The layers are all 17 * untransformed. 18 */ 19 class CompositingImages : public Benchmark { 20 public: CompositingImages(SkISize tileSize,SkISize tileGridSize,int layerCnt,bool subpixelOffset)21 CompositingImages(SkISize tileSize, SkISize tileGridSize, int layerCnt, bool subpixelOffset) 22 : fTileSize(tileSize) 23 , fTileGridSize(tileGridSize) 24 , fLayerCnt(layerCnt) 25 , fSubpixelOffset(subpixelOffset) { 26 fName.appendf("compositing_images_tile_size_%dx%d_tile_cnt_%dx%d_layers_%d", 27 fTileSize.fWidth, fTileSize.fHeight, fTileGridSize.fWidth, 28 fTileGridSize.fHeight, fLayerCnt); 29 if (subpixelOffset) { 30 fName.append("_subpixel"); 31 } 32 } 33 isSuitableFor(Backend backend)34 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; } 35 36 protected: onGetName()37 const char* onGetName() override { return fName.c_str(); } 38 onPerCanvasPreDraw(SkCanvas * canvas)39 void onPerCanvasPreDraw(SkCanvas* canvas) override { 40 auto ii = SkImageInfo::Make(fTileSize.fWidth, fTileSize.fHeight, kRGBA_8888_SkColorType, 41 kPremul_SkAlphaType, nullptr); 42 SkRandom random; 43 int numImages = fLayerCnt * fTileGridSize.fWidth * fTileGridSize.fHeight; 44 fImages.reset(new sk_sp<SkImage>[numImages]); 45 for (int i = 0; i < numImages; ++i) { 46 auto surf = canvas->makeSurface(ii); 47 SkColor color = random.nextU(); 48 surf->getCanvas()->clear(color); 49 SkPaint paint; 50 paint.setColor(~color); 51 paint.setBlendMode(SkBlendMode::kSrc); 52 surf->getCanvas()->drawRect( 53 SkRect::MakeLTRB(3, 3, fTileSize.fWidth - 3, fTileSize.fHeight - 3), paint); 54 fImages[i] = surf->makeImageSnapshot(); 55 } 56 } 57 onPerCanvasPostDraw(SkCanvas *)58 void onPerCanvasPostDraw(SkCanvas*) override { fImages.reset(); } 59 onDraw(int loops,SkCanvas * canvas)60 void onDraw(int loops, SkCanvas* canvas) override { 61 SkScalar o = this->offset(); 62 63 SkPaint paint; 64 paint.setFilterQuality(kNone_SkFilterQuality); 65 // TODO: Use per-edge AA flags for tiles when API available. 66 paint.setAntiAlias(true); 67 for (int i = 0; i < loops; ++i) { 68 int imgIdx = 0; 69 for (int l = 0; l < fLayerCnt; ++l) { 70 for (int y = 0; y < fTileGridSize.fHeight; ++y) { 71 for (int x = 0; x < fTileGridSize.fWidth; ++x) { 72 canvas->drawImage(fImages[imgIdx++].get(), x * fTileSize.fWidth + o, 73 y * fTileSize.fHeight + o, &paint); 74 } 75 } 76 } 77 // Prevent any batching between composited "frames". 78 canvas->flush(); 79 } 80 } 81 82 private: offset() const83 SkScalar offset() const { 84 return fSubpixelOffset ? SK_ScalarHalf : 0.f; 85 } 86 onGetSize()87 SkIPoint onGetSize() override { 88 SkScalar o = this->offset(); 89 return SkIPoint::Make(SkScalarCeilToInt(fTileSize.fWidth * fTileGridSize.fWidth + o), 90 SkScalarCeilToInt(fTileSize.fHeight * fTileGridSize.fHeight + o)); 91 } 92 93 std::unique_ptr<sk_sp<SkImage>[]> fImages; 94 SkString fName; 95 SkISize fTileSize; 96 SkISize fTileGridSize; 97 int fLayerCnt; 98 bool fSubpixelOffset; 99 100 typedef Benchmark INHERITED; 101 }; 102 103 // Subpixel = false; all of the draw commands align with integer pixels so AA will be automatically 104 // turned off within the operation 105 DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 1, false)); 106 DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 1, false)); 107 DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 1, false)); 108 109 DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 4, false)); 110 DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 4, false)); 111 DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 4, false)); 112 113 DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 16, false)); 114 DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 16, false)); 115 DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 16, false)); 116 117 // Subpixel = true; force the draw commands to not align with pixels exactly so AA remains on 118 DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 1, true)); 119 DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 1, true)); 120 DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 1, true)); 121 122 DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 4, true)); 123 DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 4, true)); 124 DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 4, true)); 125 126 DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 16, true)); 127 DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 16, true)); 128 DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 16, true)); 129