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