Home | History | Annotate | Download | only in bench
      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  * Draws a small set of small images multiple times each with no overlaps so that each image could
     17  * be batched. This was originally added to detect regressions as GrTextureOp is refactored to
     18  * use "dynamic state" for texture bindings. Everything is kept small as we're mostly interested in
     19  * CPU overhead.
     20  */
     21 class ImageCycle : public Benchmark {
     22 public:
     23     /**
     24      * imageCnt is the number of images and repeat cnt is how many times each image is drawn per
     25      * logical "frame."
     26      */
     27     ImageCycle(int imageCnt, int repeatCnt) : fImageCnt(imageCnt), fRepeatCnt(repeatCnt) {
     28         fName.appendf("image_cycle_image_cnt_%d_repeat_cnt_%d", fImageCnt, fRepeatCnt);
     29     }
     30 
     31     bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
     32 
     33 protected:
     34     const char* onGetName() override { return fName.c_str(); }
     35 
     36     void onPerCanvasPreDraw(SkCanvas* canvas) override {
     37         auto ii = SkImageInfo::Make(kImageSize.fWidth, kImageSize.fHeight, kRGBA_8888_SkColorType,
     38                                     kPremul_SkAlphaType, nullptr);
     39         SkRandom random;
     40         fImages.reset(new sk_sp<SkImage>[fImageCnt]);
     41         for (int i = 0; i < fImageCnt; ++i) {
     42             auto surf = canvas->makeSurface(ii);
     43             SkColor color = random.nextU();
     44             surf->getCanvas()->clear(color);
     45             SkPaint paint;
     46             paint.setColor(~color);
     47             paint.setBlendMode(SkBlendMode::kSrc);
     48             surf->getCanvas()->drawRect(
     49                     SkRect::MakeLTRB(1, 1, kImageSize.fWidth - 1, kImageSize.fHeight - 1), paint);
     50             fImages[i] = surf->makeImageSnapshot();
     51         }
     52     }
     53 
     54     void onPerCanvasPostDraw(SkCanvas*) override { fImages.reset(); }
     55 
     56     void onDraw(int loops, SkCanvas* canvas) override {
     57         SkPaint paint;
     58         paint.setFilterQuality(kNone_SkFilterQuality);
     59         paint.setAntiAlias(true);
     60         static constexpr SkScalar kPad = 2;
     61         // To avoid tripping up bounds tracking we position the draws such that all the
     62         // draws of image 0 are above those of image 1, etc.
     63         static const int imagesPerRow =
     64                 SkScalarFloorToInt(kDeviceSize.fWidth / (kImageSize.fWidth + kPad));
     65         int rowsPerImage = SkScalarCeilToInt((SkScalar)fRepeatCnt / imagesPerRow);
     66         for (int l = 0; l < loops; ++l) {
     67             for (int r = 0; r < fRepeatCnt; ++r) {
     68                 for (int i = 0; i < fImageCnt; ++i) {
     69                     SkScalar imageYOffset = i * rowsPerImage * (kImageSize.fHeight + kPad);
     70                     SkScalar rowYOffset = (r / imagesPerRow) * (kImageSize.fHeight + kPad);
     71                     SkScalar x = (r % imagesPerRow) * (kImageSize.fWidth + kPad);
     72                     canvas->drawImage(fImages[i].get(), x, imageYOffset + rowYOffset, &paint);
     73                 }
     74             }
     75             // Prevent any batching between "frames".
     76             canvas->flush();
     77         }
     78     }
     79 
     80 private:
     81     SkIPoint onGetSize() override { return {kDeviceSize.fWidth, kDeviceSize.fHeight}; }
     82 
     83     static constexpr SkISize kImageSize{4, 4};
     84     static constexpr SkISize kDeviceSize{64, 64};
     85 
     86     std::unique_ptr<sk_sp<SkImage>[]> fImages;
     87     SkString fName;
     88     int fImageCnt;
     89     int fRepeatCnt;
     90 
     91     typedef Benchmark INHERITED;
     92 };
     93 
     94 DEF_BENCH(return new ImageCycle(5, 10));
     95