1/*
2 * Copyright 2013 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 GrPrimitiveProcessor_DEFINED
9#define GrPrimitiveProcessor_DEFINED
10
11#include "GrColor.h"
12#include "GrProcessor.h"
13#include "GrShaderVar.h"
14
15/*
16 * The GrPrimitiveProcessor represents some kind of geometric primitive.  This includes the shape
17 * of the primitive and the inherent color of the primitive.  The GrPrimitiveProcessor is
18 * responsible for providing a color and coverage input into the Ganesh rendering pipeline.  Through
19 * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
20 * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
21 * functionality.
22 *
23 * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
24 * GrPrimitiveProcessor. These loops run on the CPU and to determine known properties of the final
25 * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
26 * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
27 * getProcessorAnalysisInputs implementation. These seed values are processed by the
28 * subsequent
29 * stages of the rendering pipeline and the output is then fed back into the GrDrawOp in
30 * the applyPipelineOptimizations call, where the op can use the information to inform decisions
31 * about GrPrimitiveProcessor creation.
32 */
33
34class GrGLSLPrimitiveProcessor;
35
36/*
37 * GrPrimitiveProcessor defines an interface which all subclasses must implement.  All
38 * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
39 * pipelines, and they must provide some notion of equality
40 */
41class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement {
42public:
43    struct Attribute {
44        enum class InputRate : bool {
45            kPerVertex,
46            kPerInstance
47        };
48        GrShaderVar asShaderVar() const {
49            return GrShaderVar(fName, GrVertexAttribTypeToSLType(fType),
50                               GrShaderVar::kIn_TypeModifier);
51        }
52        bool isInitialized() const { return SkToBool(fName); }
53        Attribute() = default;
54        Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate)
55                : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {}
56        const char*          fName = nullptr;
57        GrVertexAttribType   fType;
58        int                  fOffsetInRecord;
59        InputRate            fInputRate;
60    };
61
62    GrPrimitiveProcessor(ClassID classID)
63    : GrResourceIOProcessor(classID) {}
64
65    int numAttribs() const { return fAttribs.count(); }
66    const Attribute& getAttrib(int index) const { return fAttribs[index]; }
67
68    bool hasVertexAttribs() const { return SkToBool(fVertexStride); }
69    bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); }
70
71    /**
72     * These return the strides of the vertex and instance buffers. Attributes are expected to be
73     * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord
74     * indicates an attribute's location in bytes relative to the first attribute. (These are padded
75     * to the nearest 4 bytes for performance reasons.)
76     *
77     * A common practice is to populate the buffer's memory using an implicit array of structs. In
78     * this case, it is best to assert:
79     *
80     *     stride == sizeof(struct) and
81     *     offsetof(struct, field[i]) == attrib[i].fOffsetInRecord
82     *
83     * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses.
84     */
85    int getVertexStride() const { return fVertexStride; }
86    int getInstanceStride() const { return fInstanceStride; }
87
88    // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
89    // we put these calls on the base class to prevent having to cast
90    virtual bool willUseGeoShader() const = 0;
91
92    bool willUsePrimitiveRestart() const { return fWillUsePrimitiveRestart; }
93
94    /**
95     * Computes a transformKey from an array of coord transforms. Will only look at the first
96     * <numCoords> transforms in the array.
97     *
98     * TODO: A better name for this function  would be "compute" instead of "get".
99     */
100    uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
101                             int numCoords) const;
102
103    /**
104     * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
105     * processor's GL backend implementation.
106     *
107     * TODO: A better name for this function  would be "compute" instead of "get".
108     */
109    virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
110
111
112    /** Returns a new instance of the appropriate *GL* implementation class
113        for the given GrProcessor; caller is responsible for deleting
114        the object. */
115    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
116
117    virtual bool isPathRendering() const { return false; }
118
119    /**
120     * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor().
121     */
122    virtual const char* getDestColorOverride() const { return nullptr; }
123
124    virtual float getSampleShading() const {
125        return 0.0;
126    }
127
128protected:
129    /**
130     * Subclasses call these from their constructor to register vertex and instance attributes.
131     */
132    const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type) {
133        fAttribs.push_back() = {name, type, fVertexStride, Attribute::InputRate::kPerVertex};
134        fVertexStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
135        return fAttribs.back();
136    }
137    const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type) {
138        fAttribs.push_back() = {name, type, fInstanceStride, Attribute::InputRate::kPerInstance};
139        fInstanceStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
140        return fAttribs.back();
141    }
142
143    void setWillUsePrimitiveRestart() { fWillUsePrimitiveRestart = true; }
144
145private:
146    void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); }
147    void removeRefs() const override { GrResourceIOProcessor::removeRefs(); }
148    void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); }
149    void notifyRefCntIsZero() const final {}
150    virtual bool hasExplicitLocalCoords() const = 0;
151
152    SkSTArray<8, Attribute> fAttribs;
153    int fVertexStride = 0;
154    int fInstanceStride = 0;
155    bool fWillUsePrimitiveRestart = false;
156
157    typedef GrProcessor INHERITED;
158};
159
160#endif
161