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
49        const char*          fName;
50        GrVertexAttribType   fType;
51        int                  fOffsetInRecord;
52        GrSLPrecision        fPrecision;
53        InputRate            fInputRate;
54    };
55
56    int numAttribs() const { return fAttribs.count(); }
57    const Attribute& getAttrib(int index) const { return fAttribs[index]; }
58
59    bool hasVertexAttribs() const { return SkToBool(fVertexStride); }
60    bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); }
61
62    /**
63     * These return the strides of the vertex and instance buffers. Attributes are expected to be
64     * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord
65     * indicates an attribute's location in bytes relative to the first attribute. (These are padded
66     * to the nearest 4 bytes for performance reasons.)
67     *
68     * A common practice is to populate the buffer's memory using an implicit array of structs. In
69     * this case, it is best to assert:
70     *
71     *     stride == sizeof(struct) and
72     *     offsetof(struct, field[i]) == attrib[i].fOffsetInRecord
73     *
74     * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses.
75     */
76    int getVertexStride() const { return fVertexStride; }
77    int getInstanceStride() const { return fInstanceStride; }
78
79    // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
80    // we put these calls on the base class to prevent having to cast
81    virtual bool willUseGeoShader() const = 0;
82
83    /**
84     * Computes a transformKey from an array of coord transforms. Will only look at the first
85     * <numCoords> transforms in the array.
86     *
87     * TODO: A better name for this function  would be "compute" instead of "get".
88     */
89    uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
90                             int numCoords) const;
91
92    /**
93     * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
94     * processor's GL backend implementation.
95     *
96     * TODO: A better name for this function  would be "compute" instead of "get".
97     */
98    virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
99
100
101    /** Returns a new instance of the appropriate *GL* implementation class
102        for the given GrProcessor; caller is responsible for deleting
103        the object. */
104    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
105
106    virtual bool isPathRendering() const { return false; }
107
108    /**
109     * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor().
110     */
111    virtual const char* getDestColorOverride() const { return nullptr; }
112
113    virtual float getSampleShading() const {
114        return 0.0;
115    }
116
117protected:
118    /**
119     * Subclasses call these from their constructor to register vertex and instance attributes.
120     */
121    const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type,
122                                     GrSLPrecision precision = kDefault_GrSLPrecision) {
123        precision = (kDefault_GrSLPrecision == precision) ? kMedium_GrSLPrecision : precision;
124        fAttribs.push_back() = {name, type, fVertexStride, precision,
125                                Attribute::InputRate::kPerVertex};
126        fVertexStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
127        return fAttribs.back();
128    }
129    const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type,
130                                       GrSLPrecision precision = kDefault_GrSLPrecision) {
131        precision = (kDefault_GrSLPrecision == precision) ? kMedium_GrSLPrecision : precision;
132        fAttribs.push_back() = {name, type, fInstanceStride, precision,
133                                Attribute::InputRate::kPerInstance};
134        fInstanceStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
135        return fAttribs.back();
136    }
137
138private:
139    void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); }
140    void removeRefs() const override { GrResourceIOProcessor::removeRefs(); }
141    void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); }
142    void notifyRefCntIsZero() const final {}
143    virtual bool hasExplicitLocalCoords() const = 0;
144
145    SkSTArray<8, Attribute>   fAttribs;
146    int                       fVertexStride = 0;
147    int                       fInstanceStride = 0;
148
149    typedef GrProcessor INHERITED;
150};
151
152#endif
153