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. 21class ImageFilterDAGBench : public Benchmark { 22public: 23 ImageFilterDAGBench() {} 24 25protected: 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 45private: 46 static const int kNumInputs = 5; 47 48 typedef Benchmark INHERITED; 49}; 50 51class ImageMakeWithFilterDAGBench : public Benchmark { 52public: 53 ImageMakeWithFilterDAGBench() {} 54 55protected: 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 83private: 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 92class ImageFilterDisplacedBlur : public Benchmark { 93public: 94 ImageFilterDisplacedBlur() {} 95 96protected: 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 117private: 118 typedef Benchmark INHERITED; 119}; 120 121// Exercise an Xfermode kSrcIn filter compositing two inputs which have a small intersection. 122class ImageFilterXfermodeIn : public Benchmark { 123public: 124 ImageFilterXfermodeIn() {} 125 126protected: 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 143private: 144 typedef Benchmark INHERITED; 145}; 146 147DEF_BENCH(return new ImageFilterDAGBench;) 148DEF_BENCH(return new ImageMakeWithFilterDAGBench;) 149DEF_BENCH(return new ImageFilterDisplacedBlur;) 150DEF_BENCH(return new ImageFilterXfermodeIn;) 151