aboutsummaryrefslogtreecommitdiffhomepage
path: root/bench/ImageFilterDAGBench.cpp
blob: 76b091f3f4fdcd29f5210d7a81c823599870334c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Benchmark.h"
#include "Resources.h"
#include "SkBlurImageFilter.h"
#include "SkCanvas.h"
#include "SkDisplacementMapEffect.h"
#include "SkImage.h"
#include "SkMergeImageFilter.h"
#include "SkOffsetImageFilter.h"
#include "SkXfermodeImageFilter.h"

// Exercise a blur filter connected to 5 inputs of the same merge filter.
// This bench shows an improvement in performance once cacheing of re-used
// nodes is implemented, since the DAG is no longer flattened to a tree.
class ImageFilterDAGBench : public Benchmark {
public:
    ImageFilterDAGBench() {}

protected:
    const char* onGetName() override {
        return "image_filter_dag";
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        const SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));

        for (int j = 0; j < loops; j++) {
            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr));
            sk_sp<SkImageFilter> inputs[kNumInputs];
            for (int i = 0; i < kNumInputs; ++i) {
                inputs[i] = blur;
            }
            SkPaint paint;
            paint.setImageFilter(SkMergeImageFilter::Make(inputs, kNumInputs));
            canvas->drawRect(rect, paint);
        }
    }

private:
    static const int kNumInputs = 5;

    typedef Benchmark INHERITED;
};

class ImageMakeWithFilterDAGBench : public Benchmark {
public:
    ImageMakeWithFilterDAGBench() {}

protected:
    const char* onGetName() override {
        return "image_make_with_filter_dag";
    }

    void onDelayedSetup() override {
        fImage = GetResourceAsImage("images/mandrill_512.png");
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        SkIRect subset = SkIRect::MakeSize(fImage->dimensions());
        SkIPoint offset = SkIPoint::Make(0, 0);
        SkIRect discardSubset;
        sk_sp<SkImage> image = fImage;

        for (int j = 0; j < loops; j++) {
            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr));
            sk_sp<SkImageFilter> inputs[kNumInputs];
            for (int i = 0; i < kNumInputs; ++i) {
                inputs[i] = blur;
            }
            sk_sp<SkImageFilter> mergeFilter = SkMergeImageFilter::Make(inputs, kNumInputs);
            image = image->makeWithFilter(mergeFilter.get(), subset, subset, &discardSubset,
                                          &offset);
            SkASSERT(image && image->dimensions() == fImage->dimensions());
        }
    }

private:
    static const int kNumInputs = 5;
    sk_sp<SkImage> fImage;

    typedef Benchmark INHERITED;
};

// Exercise a blur filter connected to both inputs of an SkDisplacementMapEffect.

class ImageFilterDisplacedBlur : public Benchmark {
public:
    ImageFilterDisplacedBlur() {}

protected:
    const char* onGetName() override {
        return "image_filter_displaced_blur";
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        for (int j = 0; j < loops; j++) {
            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(4.0f, 4.0f, nullptr));
            auto xSelector = SkDisplacementMapEffect::kR_ChannelSelectorType;
            auto ySelector = SkDisplacementMapEffect::kB_ChannelSelectorType;
            SkScalar scale = 2;

            SkPaint paint;
            paint.setImageFilter(SkDisplacementMapEffect::Make(xSelector, ySelector, scale,
                                                               blur, blur));

            SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));
            canvas->drawRect(rect, paint);
        }
    }

private:
    typedef Benchmark INHERITED;
};

// Exercise an Xfermode kSrcIn filter compositing two inputs which have a small intersection.
class ImageFilterXfermodeIn : public Benchmark {
public:
    ImageFilterXfermodeIn() {}

protected:
    const char* onGetName() override { return "image_filter_xfermode_in"; }

    void onDraw(int loops, SkCanvas* canvas) override {
        for (int j = 0; j < loops; j++) {
            auto blur = SkBlurImageFilter::Make(20.0f, 20.0f, nullptr);
            auto offset1 = SkOffsetImageFilter::Make(100.0f, 100.0f, blur);
            auto offset2 = SkOffsetImageFilter::Make(-100.0f, -100.0f, blur);
            auto xfermode =
                    SkXfermodeImageFilter::Make(SkBlendMode::kSrcIn, offset1, offset2, nullptr);

            SkPaint paint;
            paint.setImageFilter(xfermode);
            canvas->drawRect(SkRect::MakeWH(200.0f, 200.0f), paint);
        }
    }

private:
    typedef Benchmark INHERITED;
};

DEF_BENCH(return new ImageFilterDAGBench;)
DEF_BENCH(return new ImageMakeWithFilterDAGBench;)
DEF_BENCH(return new ImageFilterDisplacedBlur;)
DEF_BENCH(return new ImageFilterXfermodeIn;)