1 /* 2 * Copyright 2013 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 "SkCanvas.h" 10 #include "SkLayerDrawLooper.h" 11 #include "SkMaskFilter.h" 12 #include "SkPaint.h" 13 #include "SkPath.h" 14 #include "SkRandom.h" 15 16 // This bench replicates a problematic use case of a draw looper used 17 // to create an inner blurred rect 18 class RectoriBench : public Benchmark { 19 public: 20 RectoriBench() {} 21 22 protected: 23 24 const char* onGetName() override { 25 return "rectori"; 26 } 27 28 void onDraw(int loops, SkCanvas* canvas) override { 29 SkRandom Random; 30 31 for (int i = 0; i < loops; i++) { 32 SkScalar blurSigma = Random.nextRangeScalar(1.5f, 25.0f); 33 SkScalar size = Random.nextRangeScalar(20*blurSigma, 50*blurSigma); 34 35 SkScalar x = Random.nextRangeScalar(0.0f, W - size); 36 SkScalar y = Random.nextRangeScalar(0.0f, H - size); 37 38 SkRect inner = { x, y, x + size, y + size }; 39 40 SkRect outer(inner); 41 // outer is always outset either 2x or 4x the blur radius (we go with 2x) 42 outer.outset(2*blurSigma, 2*blurSigma); 43 44 SkPath p; 45 46 p.addRect(outer); 47 p.addRect(inner); 48 p.setFillType(SkPath::kEvenOdd_FillType); 49 50 // This will be used to translate the normal draw outside the 51 // clip rect and translate the blurred version back inside 52 SkScalar translate = 2.0f * size; 53 54 SkPaint paint; 55 paint.setLooper(this->createLooper(-translate, blurSigma)); 56 paint.setColor(0xff000000 | Random.nextU()); 57 paint.setAntiAlias(true); 58 59 canvas->save(); 60 // clip always equals inner rect so we get the inside blur 61 canvas->clipRect(inner); 62 canvas->translate(translate, 0); 63 canvas->drawPath(p, paint); 64 canvas->restore(); 65 } 66 } 67 68 private: 69 enum { 70 W = 640, 71 H = 480, 72 }; 73 74 sk_sp<SkDrawLooper> createLooper(SkScalar xOff, SkScalar sigma) { 75 SkLayerDrawLooper::Builder looperBuilder; 76 77 //----------------------------------------------- 78 SkLayerDrawLooper::LayerInfo info; 79 80 // TODO: add a color filter to better match what is seen in the wild 81 info.fPaintBits = /* SkLayerDrawLooper::kColorFilter_Bit |*/ 82 SkLayerDrawLooper::kMaskFilter_Bit; 83 info.fColorMode = SkBlendMode::kDst; 84 info.fOffset.set(xOff, 0); 85 info.fPostTranslate = false; 86 87 SkPaint* paint = looperBuilder.addLayer(info); 88 89 paint->setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma)); 90 91 //----------------------------------------------- 92 info.fPaintBits = 0; 93 info.fOffset.set(0, 0); 94 95 paint = looperBuilder.addLayer(info); 96 return looperBuilder.detach(); 97 } 98 99 typedef Benchmark INHERITED; 100 }; 101 102 DEF_BENCH(return new RectoriBench();) 103