1/*
2 * Copyright 2014 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 "GrConvexPolyEffect.h"
9#include "SkPathPriv.h"
10#include "effects/GrConstColorProcessor.h"
11#include "glsl/GrGLSLFragmentProcessor.h"
12#include "glsl/GrGLSLFragmentShaderBuilder.h"
13#include "glsl/GrGLSLProgramDataManager.h"
14#include "glsl/GrGLSLUniformHandler.h"
15#include "../private/GrGLSL.h"
16
17//////////////////////////////////////////////////////////////////////////////
18class AARectEffect : public GrFragmentProcessor {
19public:
20    const SkRect& getRect() const { return fRect; }
21
22    static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
23        return sk_sp<GrFragmentProcessor>(new AARectEffect(edgeType, rect));
24    }
25
26    GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
27
28    const char* name() const override { return "AARect"; }
29
30    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
31
32private:
33    AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
34            : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
35            , fRect(rect)
36            , fEdgeType(edgeType) {
37        this->initClassID<AARectEffect>();
38    }
39
40    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
41
42    bool onIsEqual(const GrFragmentProcessor& other) const override {
43        const AARectEffect& aare = other.cast<AARectEffect>();
44        return fRect == aare.fRect;
45    }
46
47    SkRect              fRect;
48    GrPrimitiveEdgeType fEdgeType;
49
50    typedef GrFragmentProcessor INHERITED;
51
52    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
53
54};
55
56GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect);
57
58#if GR_TEST_UTILS
59sk_sp<GrFragmentProcessor> AARectEffect::TestCreate(GrProcessorTestData* d) {
60    SkRect rect = SkRect::MakeLTRB(d->fRandom->nextSScalar1(),
61                                   d->fRandom->nextSScalar1(),
62                                   d->fRandom->nextSScalar1(),
63                                   d->fRandom->nextSScalar1());
64    sk_sp<GrFragmentProcessor> fp;
65    do {
66        GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
67                d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
68
69        fp = AARectEffect::Make(edgeType, rect);
70    } while (nullptr == fp);
71    return fp;
72}
73#endif
74
75//////////////////////////////////////////////////////////////////////////////
76
77class GLAARectEffect : public GrGLSLFragmentProcessor {
78public:
79    GLAARectEffect() {
80        fPrevRect.fLeft = SK_ScalarNaN;
81    }
82
83    void emitCode(EmitArgs&) override;
84
85    static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
86
87protected:
88    void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
89
90private:
91    GrGLSLProgramDataManager::UniformHandle fRectUniform;
92    SkRect                                  fPrevRect;
93
94    typedef GrGLSLFragmentProcessor INHERITED;
95};
96
97void GLAARectEffect::emitCode(EmitArgs& args) {
98    const AARectEffect& aare = args.fFp.cast<AARectEffect>();
99    const char *rectName;
100    // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
101    // respectively.
102    fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
103                                                    kVec4f_GrSLType,
104                                                    kDefault_GrSLPrecision,
105                                                    "rect",
106                                                    &rectName);
107
108    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
109    if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
110        // The amount of coverage removed in x and y by the edges is computed as a pair of negative
111        // numbers, xSub and ySub.
112        fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
113        fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName);
114        fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName);
115        fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName);
116        fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName);
117        // Now compute coverage in x and y and multiply them to get the fraction of the pixel
118        // covered.
119        fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
120    } else {
121        fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
122        fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n",
123                                 rectName);
124        fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n",
125                                 rectName);
126        fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.y - %s.y) > -0.5 ? 1.0 : 0.0;\n",
127                                 rectName);
128        fragBuilder->codeAppendf("\t\talpha *= (%s.w - sk_FragCoord.y) > -0.5 ? 1.0 : 0.0;\n",
129                                 rectName);
130    }
131
132    if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
133        fragBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
134    }
135    fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
136                             (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
137}
138
139void GLAARectEffect::onSetData(const GrGLSLProgramDataManager& pdman,
140                               const GrProcessor& processor) {
141    const AARectEffect& aare = processor.cast<AARectEffect>();
142    const SkRect& rect = aare.getRect();
143    if (rect != fPrevRect) {
144        pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
145                   rect.fRight - 0.5f, rect.fBottom - 0.5f);
146        fPrevRect = rect;
147    }
148}
149
150void GLAARectEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
151                            GrProcessorKeyBuilder* b) {
152    const AARectEffect& aare = processor.cast<AARectEffect>();
153    b->add32(aare.getEdgeType());
154}
155
156void AARectEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
157    GLAARectEffect::GenKey(*this, caps, b);
158}
159
160GrGLSLFragmentProcessor* AARectEffect::onCreateGLSLInstance() const  {
161    return new GLAARectEffect;
162}
163
164//////////////////////////////////////////////////////////////////////////////
165
166class GrGLConvexPolyEffect : public GrGLSLFragmentProcessor {
167public:
168    GrGLConvexPolyEffect() {
169        for (size_t i = 0; i < SK_ARRAY_COUNT(fPrevEdges); ++i) {
170            fPrevEdges[i] = SK_ScalarNaN;
171        }
172    }
173
174    void emitCode(EmitArgs&) override;
175
176    static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
177
178protected:
179    void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
180
181private:
182    GrGLSLProgramDataManager::UniformHandle fEdgeUniform;
183    SkScalar                                fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
184    typedef GrGLSLFragmentProcessor INHERITED;
185};
186
187void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
188    const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();
189
190    const char *edgeArrayName;
191    fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
192                                                         kVec3f_GrSLType,
193                                                         kDefault_GrSLPrecision,
194                                                         "edges",
195                                                         cpe.getEdgeCount(),
196                                                         &edgeArrayName);
197    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
198    fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
199    fragBuilder->codeAppend("\t\tfloat edge;\n");
200    for (int i = 0; i < cpe.getEdgeCount(); ++i) {
201        fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(sk_FragCoord.x, sk_FragCoord.y, "
202                                                             "1));\n",
203                                 edgeArrayName, i);
204        if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
205            fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
206        } else {
207            fragBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
208        }
209        fragBuilder->codeAppend("\t\talpha *= edge;\n");
210    }
211
212    if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
213        fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
214    }
215    fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
216                             (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
217}
218
219void GrGLConvexPolyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
220                                     const GrProcessor& effect) {
221    const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>();
222    size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
223    if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
224        pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
225        memcpy(fPrevEdges, cpe.getEdges(), byteSize);
226    }
227}
228
229void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
230                                  GrProcessorKeyBuilder* b) {
231    const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>();
232    GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
233    uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
234    b->add32(key);
235}
236
237//////////////////////////////////////////////////////////////////////////////
238
239sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType type, const SkPath& path) {
240    if (kHairlineAA_GrProcessorEdgeType == type) {
241        return nullptr;
242    }
243    if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
244        !path.isConvex()) {
245        return nullptr;
246    }
247
248    SkPathPriv::FirstDirection dir;
249    // The only way this should fail is if the clip is effectively a infinitely thin line. In that
250    // case nothing is inside the clip. It'd be nice to detect this at a higher level and either
251    // skip the draw or omit the clip element.
252    if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
253        if (GrProcessorEdgeTypeIsInverseFill(type)) {
254            return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
255                                               GrConstColorProcessor::kModulateRGBA_InputMode);
256        }
257        // This could use kIgnore instead of kModulateRGBA but it would trigger a debug print
258        // about a coverage processor not being compatible with the alpha-as-coverage optimization.
259        // We don't really care about this unlikely case so we just use kModulateRGBA to suppress
260        // the print.
261        return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
262                                           GrConstColorProcessor::kModulateRGBA_InputMode);
263    }
264
265    SkScalar        edges[3 * kMaxEdges];
266    SkPoint         pts[4];
267    SkPath::Verb    verb;
268    SkPath::Iter    iter(path, true);
269
270    // SkPath considers itself convex so long as there is a convex contour within it,
271    // regardless of any degenerate contours such as a string of moveTos before it.
272    // Iterate here to consume any degenerate contours and only process the points
273    // on the actual convex contour.
274    int n = 0;
275    while ((verb = iter.next(pts, true, true)) != SkPath::kDone_Verb) {
276        switch (verb) {
277            case SkPath::kMove_Verb:
278                SkASSERT(n == 0);
279            case SkPath::kClose_Verb:
280                break;
281            case SkPath::kLine_Verb: {
282                if (n >= kMaxEdges) {
283                    return nullptr;
284                }
285                SkVector v = pts[1] - pts[0];
286                v.normalize();
287                if (SkPathPriv::kCCW_FirstDirection == dir) {
288                    edges[3 * n] = v.fY;
289                    edges[3 * n + 1] = -v.fX;
290                } else {
291                    edges[3 * n] = -v.fY;
292                    edges[3 * n + 1] = v.fX;
293                }
294                edges[3 * n + 2] = -(edges[3 * n] * pts[1].fX + edges[3 * n + 1] * pts[1].fY);
295                ++n;
296                break;
297            }
298            default:
299                return nullptr;
300        }
301    }
302
303    if (path.isInverseFillType()) {
304        type = GrInvertProcessorEdgeType(type);
305    }
306    return Make(type, n, edges);
307}
308
309sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType edgeType,
310                                                    const SkRect& rect) {
311    if (kHairlineAA_GrProcessorEdgeType == edgeType){
312        return nullptr;
313    }
314    return AARectEffect::Make(edgeType, rect);
315}
316
317GrConvexPolyEffect::~GrConvexPolyEffect() {}
318
319void GrConvexPolyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
320                                               GrProcessorKeyBuilder* b) const {
321    GrGLConvexPolyEffect::GenKey(*this, caps, b);
322}
323
324GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const  {
325    return new GrGLConvexPolyEffect;
326}
327
328GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
329        : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
330        , fEdgeType(edgeType)
331        , fEdgeCount(n) {
332    this->initClassID<GrConvexPolyEffect>();
333    // Factory function should have already ensured this.
334    SkASSERT(n <= kMaxEdges);
335    memcpy(fEdges, edges, 3 * n * sizeof(SkScalar));
336    // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case
337    // and 100% covered in the non-AA case.
338    for (int i = 0; i < n; ++i) {
339        fEdges[3 * i + 2] += SK_ScalarHalf;
340    }
341}
342
343bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const {
344    const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>();
345    // ignore the fact that 0 == -0 and just use memcmp.
346    return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount &&
347            0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar)));
348}
349
350//////////////////////////////////////////////////////////////////////////////
351
352GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect);
353
354#if GR_TEST_UTILS
355sk_sp<GrFragmentProcessor> GrConvexPolyEffect::TestCreate(GrProcessorTestData* d) {
356    int count = d->fRandom->nextULessThan(kMaxEdges) + 1;
357    SkScalar edges[kMaxEdges * 3];
358    for (int i = 0; i < 3 * count; ++i) {
359        edges[i] = d->fRandom->nextSScalar1();
360    }
361
362    sk_sp<GrFragmentProcessor> fp;
363    do {
364        GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
365                d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
366        fp = GrConvexPolyEffect::Make(edgeType, count, edges);
367    } while (nullptr == fp);
368    return fp;
369}
370#endif
371