• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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