| /* | 
 |  * Copyright 2017 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 "GrContextOptions.h" | 
 | #include "SkCanvas.h" | 
 | #include "SkImage.h" | 
 | #include "SkRandom.h" | 
 | #include "SkSurface.h" | 
 |  | 
 | class MultitextureImages : public Benchmark { | 
 | public: | 
 |     MultitextureImages(int imageSize, int dstRectSize, bool disableMultitexturing, bool aa) | 
 |             : fImageSize(imageSize) | 
 |             , fDstRectSize(dstRectSize) | 
 |             , fDisableMultitexturing(disableMultitexturing) | 
 |             , fAA(aa) { | 
 |         fName.appendf("multitexture_images_%dx%d_image_%dx%d_rect", imageSize, imageSize, | 
 |                       dstRectSize, dstRectSize); | 
 |         if (aa) { | 
 |             fName.append("_aa"); | 
 |         } | 
 |         if (disableMultitexturing) { | 
 |             fName.append("_disable_multitexturing"); | 
 |         } | 
 |     } | 
 |  | 
 |     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(fImageSize, fImageSize, kRGBA_8888_SkColorType, | 
 |                                     kPremul_SkAlphaType, nullptr); | 
 |         SkRandom random; | 
 |         for (int i = 0; i < kNumImages; ++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, fImageSize - 3, fImageSize - 3), | 
 |                                         paint); | 
 |             fImages[i] = surf->makeImageSnapshot(); | 
 |         } | 
 |     } | 
 |  | 
 |     void onPerCanvasPostDraw(SkCanvas*) override { | 
 |         for (int i = 0; i < kNumImages; ++i) { | 
 |             fImages[i].reset(); | 
 |         } | 
 |     } | 
 |  | 
 |     void onDraw(int loops, SkCanvas* canvas) override { | 
 |         SkRect rect = SkRect::MakeWH(fDstRectSize, fDstRectSize); | 
 |         SkPaint paint; | 
 |         paint.setAlpha(0x40); | 
 |         paint.setFilterQuality(kLow_SkFilterQuality); | 
 |         paint.setAntiAlias(fAA); | 
 |         for (int i = 0; i < loops; i++) { | 
 |             for (int j = 0; j < kNumImages; ++j) { | 
 |                 SkVector translate = this->translation(i * kNumImages + j); | 
 |                 canvas->drawImageRect(fImages[j].get(), rect.makeOffset(translate.fX, translate.fY), | 
 |                                       &paint); | 
 |             } | 
 |             // Prevent any batching except without multitexturing since we're trying to measure | 
 |             // drawing distinct images and just repeating images here to increase the workload for | 
 |             // timing reasons. | 
 |             canvas->flush(); | 
 |         } | 
 |     } | 
 |  | 
 |     void modifyGrContextOptions(GrContextOptions* options) override { | 
 |         options->fDisableImageMultitexturing = fDisableMultitexturing; | 
 |     } | 
 |  | 
 | private: | 
 |     SkIPoint onGetSize() override { | 
 |         // The rows and columns are spaced by kTranslate, but the images may overlap if they are | 
 |         // larger than kTranslate and extend beyond the last row/column. | 
 |         return SkIPoint::Make(kTranslate * (kNumColumns - 1) + fDstRectSize, | 
 |                               kTranslate * (kNumRows - 1) + fDstRectSize); | 
 |     } | 
 |  | 
 |     SkVector translation(int i) const { | 
 |         SkVector offset; | 
 |         // Fractional offsets to ensure we can't ignore antialiasing. | 
 |         offset.fX = i % kNumColumns * kTranslate + 0.1f; | 
 |         offset.fY = (i / kNumColumns) % kNumRows * kTranslate + 0.1f; | 
 |         return offset; | 
 |     } | 
 |  | 
 |     static const int kTranslate = 200; | 
 |     static const int kNumColumns = 5; | 
 |     static const int kNumRows = 5; | 
 |     static const int kNumImages = 8; | 
 |  | 
 |     sk_sp<SkImage> fImages[kNumImages]; | 
 |     SkString fName; | 
 |     int fImageSize; | 
 |     int fDstRectSize; | 
 |     bool fDisableMultitexturing; | 
 |     bool fAA; | 
 |  | 
 |     typedef Benchmark INHERITED; | 
 | }; | 
 |  | 
 | // Non-AA | 
 | DEF_BENCH(return new MultitextureImages(128, 32, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(128, 32, true, false)); | 
 | DEF_BENCH(return new MultitextureImages(128, 128, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(128, 128, true, false)); | 
 | DEF_BENCH(return new MultitextureImages(128, 256, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(128, 256, true, false)); | 
 |  | 
 | DEF_BENCH(return new MultitextureImages(512, 32, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 32, true, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 128, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 128, true, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 256, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 256, true, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 512, false, false)); | 
 | DEF_BENCH(return new MultitextureImages(512, 512, true, false)); | 
 |  | 
 | // AA | 
 | DEF_BENCH(return new MultitextureImages(512, 512, true, true)); | 
 | DEF_BENCH(return new MultitextureImages(512, 512, false, true)); | 
 | DEF_BENCH(return new MultitextureImages(128, 32, true, true)); | 
 | DEF_BENCH(return new MultitextureImages(128, 32, false, true)); |