1/*
2 * Copyright 2012 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 "gm.h"
9#include "SkBlurMaskFilter.h"
10#include "SkCanvas.h"
11#include "SkPath.h"
12#include "SkShader.h"
13
14namespace skiagm {
15
16/**
17 * Stress test the GPU samplers by rendering a textured glyph with a mask and
18 * an AA clip
19 */
20class SamplerStressGM : public GM {
21public:
22    SamplerStressGM()
23    : fTextureCreated(false)
24    , fShader(nullptr)
25    , fMaskFilter(nullptr) {
26    }
27
28    virtual ~SamplerStressGM() {
29    }
30
31protected:
32
33    SkString onShortName() override {
34        return SkString("gpusamplerstress");
35    }
36
37    SkISize onISize() override {
38        return SkISize::Make(640, 480);
39    }
40
41    /**
42     * Create a red & green stripes on black texture
43     */
44    void createTexture() {
45        if (fTextureCreated) {
46            return;
47        }
48
49        static const int xSize = 16;
50        static const int ySize = 16;
51
52        fTexture.allocN32Pixels(xSize, ySize);
53        SkPMColor* addr = fTexture.getAddr32(0, 0);
54
55        for (int y = 0; y < ySize; ++y) {
56            for (int x = 0; x < xSize; ++x) {
57                addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorBLACK);
58
59                if ((y % 5) == 0) {
60                    addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorRED);
61                }
62                if ((x % 7) == 0) {
63                    addr[y*xSize+x] = SkPreMultiplyColor(SK_ColorGREEN);
64                }
65            }
66        }
67
68        fTextureCreated = true;
69    }
70
71    void createShader() {
72        if (fShader.get()) {
73            return;
74        }
75
76        createTexture();
77
78        fShader.reset(SkShader::CreateBitmapShader(fTexture,
79                                                   SkShader::kRepeat_TileMode,
80                                                   SkShader::kRepeat_TileMode));
81    }
82
83    void createMaskFilter() {
84        if (fMaskFilter.get()) {
85            return;
86        }
87
88        const SkScalar sigma = 1;
89        fMaskFilter.reset(SkBlurMaskFilter::Create(kNormal_SkBlurStyle, sigma));
90    }
91
92    void onDraw(SkCanvas* canvas) override {
93        createShader();
94        createMaskFilter();
95
96        canvas->save();
97
98        // draw a letter "M" with a green & red striped texture and a
99        // stipple mask with a round rect soft clip
100        SkPaint paint;
101        paint.setAntiAlias(true);
102        paint.setTextSize(72);
103        paint.setShader(fShader.get());
104        paint.setMaskFilter(fMaskFilter.get());
105        sk_tool_utils::set_portable_typeface(&paint);
106
107        SkRect temp;
108        temp.set(SkIntToScalar(115),
109                 SkIntToScalar(75),
110                 SkIntToScalar(144),
111                 SkIntToScalar(110));
112
113        SkPath path;
114        path.addRoundRect(temp, SkIntToScalar(5), SkIntToScalar(5));
115
116        canvas->clipPath(path, SkRegion::kReplace_Op, true); // AA is on
117
118        canvas->drawText("M", 1,
119                         SkIntToScalar(100), SkIntToScalar(100),
120                         paint);
121
122        canvas->restore();
123
124        // Now draw stroked versions of the "M" and the round rect so we can
125        // see what is going on
126        SkPaint paint2;
127        paint2.setColor(SK_ColorBLACK);
128        paint2.setAntiAlias(true);
129        paint2.setTextSize(72);
130        paint2.setStyle(SkPaint::kStroke_Style);
131        paint2.setStrokeWidth(1);
132        sk_tool_utils::set_portable_typeface(&paint2);
133        canvas->drawText("M", 1,
134                         SkIntToScalar(100), SkIntToScalar(100),
135                         paint2);
136
137        paint2.setColor(sk_tool_utils::color_to_565(SK_ColorGRAY));
138
139        canvas->drawPath(path, paint2);
140    }
141
142private:
143    SkBitmap      fTexture;
144    bool          fTextureCreated;
145    SkAutoTUnref<SkShader>     fShader;
146    SkAutoTUnref<SkMaskFilter> fMaskFilter;
147
148    typedef GM INHERITED;
149};
150
151//////////////////////////////////////////////////////////////////////////////
152
153static GM* MyFactory(void*) { return new SamplerStressGM; }
154static GMRegistry reg(MyFactory);
155
156}
157