blob: 00e07cbbd48cb5befda50585d47dc8b7034ddb27 [file] [log] [blame]
Brian Salomon7eae3e02018-08-07 14:02:38 +00001/*
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 */
19class CompositingImages : public Benchmark {
20public:
Michael Ludwigeb356502018-11-20 09:43:17 -050021 CompositingImages(SkISize tileSize, SkISize tileGridSize, int layerCnt, bool subpixelOffset)
22 : fTileSize(tileSize)
23 , fTileGridSize(tileGridSize)
24 , fLayerCnt(layerCnt)
25 , fSubpixelOffset(subpixelOffset) {
Brian Salomon7eae3e02018-08-07 14:02:38 +000026 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);
Michael Ludwigeb356502018-11-20 09:43:17 -050029 if (subpixelOffset) {
30 fName.append("_subpixel");
31 }
Brian Salomon7eae3e02018-08-07 14:02:38 +000032 }
33
34 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
35
36protected:
37 const char* onGetName() override { return fName.c_str(); }
38
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
58 void onPerCanvasPostDraw(SkCanvas*) override { fImages.reset(); }
59
60 void onDraw(int loops, SkCanvas* canvas) override {
Michael Ludwigeb356502018-11-20 09:43:17 -050061 SkScalar o = this->offset();
62
Brian Salomon7eae3e02018-08-07 14:02:38 +000063 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) {
Michael Ludwigeb356502018-11-20 09:43:17 -050072 canvas->drawImage(fImages[imgIdx++].get(), x * fTileSize.fWidth + o,
73 y * fTileSize.fHeight + o, &paint);
Brian Salomon7eae3e02018-08-07 14:02:38 +000074 }
75 }
76 }
77 // Prevent any batching between composited "frames".
78 canvas->flush();
79 }
80 }
81
82private:
Michael Ludwigeb356502018-11-20 09:43:17 -050083 SkScalar offset() const {
84 return fSubpixelOffset ? SK_ScalarHalf : 0.f;
85 }
86
Brian Salomon7eae3e02018-08-07 14:02:38 +000087 SkIPoint onGetSize() override {
Michael Ludwigeb356502018-11-20 09:43:17 -050088 SkScalar o = this->offset();
89 return SkIPoint::Make(SkScalarCeilToInt(fTileSize.fWidth * fTileGridSize.fWidth + o),
90 SkScalarCeilToInt(fTileSize.fHeight * fTileGridSize.fHeight + o));
Brian Salomon7eae3e02018-08-07 14:02:38 +000091 }
92
93 std::unique_ptr<sk_sp<SkImage>[]> fImages;
94 SkString fName;
95 SkISize fTileSize;
96 SkISize fTileGridSize;
97 int fLayerCnt;
Michael Ludwigeb356502018-11-20 09:43:17 -050098 bool fSubpixelOffset;
Brian Salomon7eae3e02018-08-07 14:02:38 +000099
100 typedef Benchmark INHERITED;
101};
102
Michael Ludwigeb356502018-11-20 09:43:17 -0500103// Subpixel = false; all of the draw commands align with integer pixels so AA will be automatically
104// turned off within the operation
105DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 1, false));
106DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 1, false));
107DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 1, false));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000108
Michael Ludwigeb356502018-11-20 09:43:17 -0500109DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 4, false));
110DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 4, false));
111DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 4, false));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000112
Michael Ludwigeb356502018-11-20 09:43:17 -0500113DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 16, false));
114DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 16, false));
115DEF_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
118DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 1, true));
119DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 1, true));
120DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 1, true));
121
122DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 4, true));
123DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 4, true));
124DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 4, true));
125
126DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 16, true));
127DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 16, true));
128DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 16, true));