| /* | |
| * Copyright 2018 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "Benchmark.h" | |
| #include "SkCanvas.h" | |
| #include "SkImage.h" | |
| #include "SkRandom.h" | |
| #include "SkSurface.h" | |
| /** | |
| * Simulates drawing layers images in a grid a la a tile based compositor. The layers are all | |
| * untransformed. | |
| */ | |
| class CompositingImages : public Benchmark { | |
| public: | |
| CompositingImages(SkISize tileSize, SkISize tileGridSize, int layerCnt, bool subpixelOffset) | |
| : fTileSize(tileSize) | |
| , fTileGridSize(tileGridSize) | |
| , fLayerCnt(layerCnt) | |
| , fSubpixelOffset(subpixelOffset) { | |
| fName.appendf("compositing_images_tile_size_%dx%d_tile_cnt_%dx%d_layers_%d", | |
| fTileSize.fWidth, fTileSize.fHeight, fTileGridSize.fWidth, | |
| fTileGridSize.fHeight, fLayerCnt); | |
| if (subpixelOffset) { | |
| fName.append("_subpixel"); | |
| } | |
| } | |
| bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; } | |
| protected: | |
| const char* onGetName() override { return fName.c_str(); } | |
| void onPerCanvasPreDraw(SkCanvas* canvas) override { | |
| auto ii = SkImageInfo::Make(fTileSize.fWidth, fTileSize.fHeight, kRGBA_8888_SkColorType, | |
| kPremul_SkAlphaType, nullptr); | |
| SkRandom random; | |
| int numImages = fLayerCnt * fTileGridSize.fWidth * fTileGridSize.fHeight; | |
| fImages.reset(new sk_sp<SkImage>[numImages]); | |
| for (int i = 0; i < numImages; ++i) { | |
| auto surf = canvas->makeSurface(ii); | |
| SkColor color = random.nextU(); | |
| surf->getCanvas()->clear(color); | |
| SkPaint paint; | |
| paint.setColor(~color); | |
| paint.setBlendMode(SkBlendMode::kSrc); | |
| surf->getCanvas()->drawRect( | |
| SkRect::MakeLTRB(3, 3, fTileSize.fWidth - 3, fTileSize.fHeight - 3), paint); | |
| fImages[i] = surf->makeImageSnapshot(); | |
| } | |
| } | |
| void onPerCanvasPostDraw(SkCanvas*) override { fImages.reset(); } | |
| void onDraw(int loops, SkCanvas* canvas) override { | |
| SkScalar o = this->offset(); | |
| SkPaint paint; | |
| paint.setFilterQuality(kNone_SkFilterQuality); | |
| // TODO: Use per-edge AA flags for tiles when API available. | |
| paint.setAntiAlias(true); | |
| for (int i = 0; i < loops; ++i) { | |
| int imgIdx = 0; | |
| for (int l = 0; l < fLayerCnt; ++l) { | |
| for (int y = 0; y < fTileGridSize.fHeight; ++y) { | |
| for (int x = 0; x < fTileGridSize.fWidth; ++x) { | |
| canvas->drawImage(fImages[imgIdx++].get(), x * fTileSize.fWidth + o, | |
| y * fTileSize.fHeight + o, &paint); | |
| } | |
| } | |
| } | |
| // Prevent any batching between composited "frames". | |
| canvas->flush(); | |
| } | |
| } | |
| private: | |
| SkScalar offset() const { | |
| return fSubpixelOffset ? SK_ScalarHalf : 0.f; | |
| } | |
| SkIPoint onGetSize() override { | |
| SkScalar o = this->offset(); | |
| return SkIPoint::Make(SkScalarCeilToInt(fTileSize.fWidth * fTileGridSize.fWidth + o), | |
| SkScalarCeilToInt(fTileSize.fHeight * fTileGridSize.fHeight + o)); | |
| } | |
| std::unique_ptr<sk_sp<SkImage>[]> fImages; | |
| SkString fName; | |
| SkISize fTileSize; | |
| SkISize fTileGridSize; | |
| int fLayerCnt; | |
| bool fSubpixelOffset; | |
| typedef Benchmark INHERITED; | |
| }; | |
| // Subpixel = false; all of the draw commands align with integer pixels so AA will be automatically | |
| // turned off within the operation | |
| DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 1, false)); | |
| DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 1, false)); | |
| DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 1, false)); | |
| DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 4, false)); | |
| DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 4, false)); | |
| DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 4, false)); | |
| DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 16, false)); | |
| DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 16, false)); | |
| DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 16, false)); | |
| // Subpixel = true; force the draw commands to not align with pixels exactly so AA remains on | |
| DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 1, true)); | |
| DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 1, true)); | |
| DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 1, true)); | |
| DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 4, true)); | |
| DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 4, true)); | |
| DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 4, true)); | |
| DEF_BENCH(return new CompositingImages({256, 256}, {8, 8}, 16, true)); | |
| DEF_BENCH(return new CompositingImages({512, 512}, {4, 4}, 16, true)); | |
| DEF_BENCH(return new CompositingImages({1024, 512}, {2, 4}, 16, true)); |