1 /* 2 * Copyright 2014 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 #include "Resources.h" 10 #include "SkBlurImageFilter.h" 11 #include "SkCanvas.h" 12 #include "SkDisplacementMapEffect.h" 13 #include "SkImage.h" 14 #include "SkMergeImageFilter.h" 15 #include "SkOffsetImageFilter.h" 16 #include "SkXfermodeImageFilter.h" 17 18 // Exercise a blur filter connected to 5 inputs of the same merge filter. 19 // This bench shows an improvement in performance once cacheing of re-used 20 // nodes is implemented, since the DAG is no longer flattened to a tree. 21 class ImageFilterDAGBench : public Benchmark { 22 public: 23 ImageFilterDAGBench() {} 24 25 protected: 26 const char* onGetName() override { 27 return "image_filter_dag"; 28 } 29 30 void onDraw(int loops, SkCanvas* canvas) override { 31 const SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400)); 32 33 for (int j = 0; j < loops; j++) { 34 sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr)); 35 sk_sp<SkImageFilter> inputs[kNumInputs]; 36 for (int i = 0; i < kNumInputs; ++i) { 37 inputs[i] = blur; 38 } 39 SkPaint paint; 40 paint.setImageFilter(SkMergeImageFilter::Make(inputs, kNumInputs)); 41 canvas->drawRect(rect, paint); 42 } 43 } 44 45 private: 46 static const int kNumInputs = 5; 47 48 typedef Benchmark INHERITED; 49 }; 50 51 class ImageMakeWithFilterDAGBench : public Benchmark { 52 public: 53 ImageMakeWithFilterDAGBench() {} 54 55 protected: 56 const char* onGetName() override { 57 return "image_make_with_filter_dag"; 58 } 59 60 void onDelayedSetup() override { 61 fImage = GetResourceAsImage("images/mandrill_512.png"); 62 } 63 64 void onDraw(int loops, SkCanvas* canvas) override { 65 SkIRect subset = SkIRect::MakeSize(fImage->dimensions()); 66 SkIPoint offset = SkIPoint::Make(0, 0); 67 SkIRect discardSubset; 68 sk_sp<SkImage> image = fImage; 69 70 for (int j = 0; j < loops; j++) { 71 sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr)); 72 sk_sp<SkImageFilter> inputs[kNumInputs]; 73 for (int i = 0; i < kNumInputs; ++i) { 74 inputs[i] = blur; 75 } 76 sk_sp<SkImageFilter> mergeFilter = SkMergeImageFilter::Make(inputs, kNumInputs); 77 image = image->makeWithFilter(mergeFilter.get(), subset, subset, &discardSubset, 78 &offset); 79 SkASSERT(image && image->dimensions() == fImage->dimensions()); 80 } 81 } 82 83 private: 84 static const int kNumInputs = 5; 85 sk_sp<SkImage> fImage; 86 87 typedef Benchmark INHERITED; 88 }; 89 90 // Exercise a blur filter connected to both inputs of an SkDisplacementMapEffect. 91 92 class ImageFilterDisplacedBlur : public Benchmark { 93 public: 94 ImageFilterDisplacedBlur() {} 95 96 protected: 97 const char* onGetName() override { 98 return "image_filter_displaced_blur"; 99 } 100 101 void onDraw(int loops, SkCanvas* canvas) override { 102 for (int j = 0; j < loops; j++) { 103 sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(4.0f, 4.0f, nullptr)); 104 auto xSelector = SkDisplacementMapEffect::kR_ChannelSelectorType; 105 auto ySelector = SkDisplacementMapEffect::kB_ChannelSelectorType; 106 SkScalar scale = 2; 107 108 SkPaint paint; 109 paint.setImageFilter(SkDisplacementMapEffect::Make(xSelector, ySelector, scale, 110 blur, blur)); 111 112 SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400)); 113 canvas->drawRect(rect, paint); 114 } 115 } 116 117 private: 118 typedef Benchmark INHERITED; 119 }; 120 121 // Exercise an Xfermode kSrcIn filter compositing two inputs which have a small intersection. 122 class ImageFilterXfermodeIn : public Benchmark { 123 public: 124 ImageFilterXfermodeIn() {} 125 126 protected: 127 const char* onGetName() override { return "image_filter_xfermode_in"; } 128 129 void onDraw(int loops, SkCanvas* canvas) override { 130 for (int j = 0; j < loops; j++) { 131 auto blur = SkBlurImageFilter::Make(20.0f, 20.0f, nullptr); 132 auto offset1 = SkOffsetImageFilter::Make(100.0f, 100.0f, blur); 133 auto offset2 = SkOffsetImageFilter::Make(-100.0f, -100.0f, blur); 134 auto xfermode = 135 SkXfermodeImageFilter::Make(SkBlendMode::kSrcIn, offset1, offset2, nullptr); 136 137 SkPaint paint; 138 paint.setImageFilter(xfermode); 139 canvas->drawRect(SkRect::MakeWH(200.0f, 200.0f), paint); 140 } 141 } 142 143 private: 144 typedef Benchmark INHERITED; 145 }; 146 147 DEF_BENCH(return new ImageFilterDAGBench;) 148 DEF_BENCH(return new ImageMakeWithFilterDAGBench;) 149 DEF_BENCH(return new ImageFilterDisplacedBlur;) 150 DEF_BENCH(return new ImageFilterXfermodeIn;) 151