ImageCycleBench.cpp 3.6 KB

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