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#ifndef GrConvexPolyEffect_DEFINED
9#define GrConvexPolyEffect_DEFINED
10
11#include "GrDrawTargetCaps.h"
12#include "GrFragmentProcessor.h"
13#include "GrProcessor.h"
14#include "GrTypesPriv.h"
15
16class GrInvariantOutput;
17class SkPath;
18
19/**
20 * An effect that renders a convex polygon. It is intended to be used as a coverage effect.
21 * Bounding geometry is rendered and the effect computes coverage based on the fragment's
22 * position relative to the polygon.
23 */
24class GrConvexPolyEffect : public GrFragmentProcessor {
25public:
26    enum {
27        kMaxEdges = 8,
28    };
29
30    /**
31     * edges is a set of n edge equations where n is limited to kMaxEdges. It contains 3*n values.
32     * The edges should form a convex polygon. The positive half-plane is considered to be the
33     * inside. The equations should be normalized such that the first two coefficients are a unit
34     * 2d vector.
35     *
36     * Currently the edges are specified in device space. In the future we may prefer to specify
37     * them in src space. There are a number of ways this could be accomplished but we'd probably
38     * have to modify the effect/shaderbuilder interface to make it possible (e.g. give access
39     * to the view matrix or untransformed positions in the fragment shader).
40     */
41    static GrFragmentProcessor* Create(GrPrimitiveEdgeType edgeType, int n,
42                                       const SkScalar edges[]) {
43        if (n <= 0 || n > kMaxEdges || kHairlineAA_GrProcessorEdgeType == edgeType) {
44            return NULL;
45        }
46        return SkNEW_ARGS(GrConvexPolyEffect, (edgeType, n, edges));
47    }
48
49    /**
50     * Creates an effect that clips against the path. If the path is not a convex polygon, is
51     * inverse filled, or has too many edges, this will return NULL. If offset is non-NULL, then
52     * the path is translated by the vector.
53     */
54    static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPath&,
55                                       const SkVector* offset = NULL);
56
57    /**
58     * Creates an effect that fills inside the rect with AA edges..
59     */
60    static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkRect&);
61
62    virtual ~GrConvexPolyEffect();
63
64    const char* name() const override { return "ConvexPoly"; }
65
66    GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
67
68    int getEdgeCount() const { return fEdgeCount; }
69
70    const SkScalar* getEdges() const { return fEdges; }
71
72    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
73
74    GrGLFragmentProcessor* createGLInstance() const override;
75
76private:
77    GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[]);
78
79    bool onIsEqual(const GrFragmentProcessor& other) const override;
80
81    void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
82
83    GrPrimitiveEdgeType    fEdgeType;
84    int                    fEdgeCount;
85    SkScalar               fEdges[3 * kMaxEdges];
86
87    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
88
89    typedef GrFragmentProcessor INHERITED;
90};
91
92
93#endif
94