RectoriBench.cpp revision b7061176c7f414616fe2e79e832b3e0abe326af6
19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Copyright 2013 Google Inc.
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Use of this source code is governed by a BSD-style license that can be
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * found in the LICENSE file.
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SkBenchmark.h"
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SkCanvas.h"
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SkPaint.h"
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SkRandom.h"
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SkBlurMaskFilter.h"
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SkLayerDrawLooper.h"
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall// This bench replicates a problematic use case of a draw looper used
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall// to create an inner blurred rect
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallclass RectoriBench : public SkBenchmark {
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallpublic:
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    RectoriBench(void* param) : INHERITED(param) {}
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallprotected:
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    virtual const char* onGetName() {
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return "rectori";
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SkMWCRandom Random;
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        for (int i = 0; i < N; i++) {
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkScalar blurSigma = Random.nextRangeScalar(1.5f, 25.0f);
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkScalar size = Random.nextRangeScalar(20*blurSigma, 50*blurSigma);
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkScalar x = Random.nextRangeScalar(0.0f, W - size);
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkScalar y = Random.nextRangeScalar(0.0f, H - size);
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkRect inner = { x, y, x + size, y + size };
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkRect outer(inner);
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            // outer is always outset either 2x or 4x the blur radius (we go with 2x)
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            outer.outset(2*blurSigma, 2*blurSigma);
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkPath p;
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            p.addRect(outer);
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            p.addRect(inner);
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            p.setFillType(SkPath::kEvenOdd_FillType);
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            // This will be used to translate the normal draw outside the
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            // clip rect and translate the blurred version back inside
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkScalar translate = 2.0f * size;
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SkPaint paint;
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            paint.setLooper(this->createLooper(-translate, blurSigma))->unref();
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            paint.setColor(0xff000000 | Random.nextU());
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            paint.setAntiAlias(true);
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            canvas->save();
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            // clip always equals inner rect so we get the inside blur
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            canvas->clipRect(inner);
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            canvas->translate(translate, 0);
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            canvas->drawPath(p, paint);
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            canvas->restore();
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallprivate:
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    enum {
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        W = 640,
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        H = 480,
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    };
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    enum { N = SkBENCHLOOP(100) };
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SkLayerDrawLooper* createLooper(SkScalar xOff, SkScalar sigma) {
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SkLayerDrawLooper* looper = new SkLayerDrawLooper;
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        //-----------------------------------------------
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SkLayerDrawLooper::LayerInfo info;
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fFlagsMask = 0;
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        // TODO: add a color filter to better match what is seen in the wild
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fPaintBits = /* SkLayerDrawLooper::kColorFilter_Bit |*/
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                          SkLayerDrawLooper::kMaskFilter_Bit;
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fColorMode = SkXfermode::kDst_Mode;
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fOffset.set(xOff, 0);
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fPostTranslate = false;
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SkPaint* paint = looper->addLayer(info);
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SkMaskFilter* mf = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                                    sigma,
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                                    SkBlurMaskFilter::kHighQuality_BlurFlag);
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        paint->setMaskFilter(mf)->unref();
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        //-----------------------------------------------
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fPaintBits = 0;
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        info.fOffset.set(0, 0);
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        paint = looper->addLayer(info);
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return looper;
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    typedef SkBenchmark INHERITED;
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallDEF_BENCH( return SkNEW_ARGS(RectoriBench, (p)); )
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall