7f8d041af88e013ce1785c06091ff6e01883d100
[platform/upstream/libSkiaSharp.git] / src / gpu / GrGeometryProcessor.h
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 GrGeometryProcessor_DEFINED
9 #define GrGeometryProcessor_DEFINED
10
11 #include "GrPrimitiveProcessor.h"
12
13 /**
14  * A GrGeometryProcessor is a flexible method for rendering a primitive.  The GrGeometryProcessor
15  * has complete control over vertex attributes and uniforms(aside from the render target) but it
16  * must obey the same contract as any GrPrimitiveProcessor, specifically it must emit a color and
17  * coverage into the fragment shader.  Where this color and coverage come from is completely the
18  * responsibility of the GrGeometryProcessor.
19  */
20 class GrGeometryProcessor : public GrPrimitiveProcessor {
21 public:
22     // TODO the Hint can be handled in a much more clean way when we have deferred geometry or
23     // atleast bundles
24     GrGeometryProcessor(GrColor color,
25                         const SkMatrix& viewMatrix = SkMatrix::I(),
26                         const SkMatrix& localMatrix = SkMatrix::I(),
27                         bool opaqueVertexColors = false)
28         : INHERITED(viewMatrix, localMatrix, false)
29         , fColor(color)
30         , fOpaqueVertexColors(opaqueVertexColors)
31         , fWillUseGeoShader(false)
32         , fHasVertexColor(false)
33         , fHasLocalCoords(false) {}
34
35     bool willUseGeoShader() const { return fWillUseGeoShader; }
36
37     /*
38      * In an ideal world, two GrGeometryProcessors with the same class id and texture accesses
39      * would ALWAYS be able to batch together.  If two GrGeometryProcesosrs are the same then we
40      * will only keep one of them.  The remaining GrGeometryProcessor then updates its
41      * GrBatchTracker to incorporate the draw information from the GrGeometryProcessor we discard.
42      * Any bundles associated with the discarded GrGeometryProcessor will be attached to the
43      * remaining GrGeometryProcessor.
44      */
45     bool canMakeEqual(const GrBatchTracker& mine,
46                       const GrPrimitiveProcessor& that,
47                       const GrBatchTracker& theirs) const SK_OVERRIDE {
48         if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
49             return false;
50         }
51
52         // TODO let the GPs decide this
53         if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) {
54             return false;
55         }
56
57         // TODO remove the hint
58         const GrGeometryProcessor& other = that.cast<GrGeometryProcessor>();
59         if (fHasVertexColor && fOpaqueVertexColors != other.fOpaqueVertexColors) {
60             return false;
61         }
62
63         // TODO this equality test should really be broken up, some of this can live on the batch
64         // tracker test and some of this should be in bundles
65         if (!this->onIsEqual(other)) {
66             return false;
67         }
68
69         return this->onCanMakeEqual(mine, other, theirs);
70     }
71     
72     // TODO we can remove color from the GrGeometryProcessor base class once we have bundles of
73     // primitive data
74     GrColor color() const { return fColor; }
75
76     // TODO this is a total hack until the gp can do deferred geometry
77     bool hasVertexColor() const { return fHasVertexColor; }
78
79     void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
80     void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
81
82 protected:
83     /*
84      * An optional simple helper function to determine by what means the GrGeometryProcessor should
85      * use to provide color.  If we are given an override color(ie the given overridecolor is NOT
86      * GrColor_ILLEGAL) then we must always emit that color(currently overrides are only supported
87      * via uniform, but with deferred Geometry we could use attributes).  Otherwise, if our color is
88      * ignored then we should not emit a color.  Lastly, if we don't have vertex colors then we must
89      * emit a color via uniform
90      * TODO this function changes quite a bit with deferred geometry.  There the GrGeometryProcessor
91      * can upload a new color via attribute if needed.
92      */
93     static GrGPInput GetColorInputType(GrColor* color, GrColor primitiveColor,
94                                        const GrPipelineInfo& init,
95                                        bool hasVertexColor) {
96         if (init.fColorIgnored) {
97             *color = GrColor_ILLEGAL;
98             return kIgnored_GrGPInput;
99         } else if (GrColor_ILLEGAL != init.fOverrideColor) {
100             *color = init.fOverrideColor;
101             return kUniform_GrGPInput;
102         }
103
104         *color = primitiveColor;
105         if (hasVertexColor) {
106             return kAttribute_GrGPInput;
107         } else {
108             return kUniform_GrGPInput;
109         }
110     }
111
112     /**
113      * Subclasses call this from their constructor to register vertex attributes.  Attributes
114      * will be padded to the nearest 4 bytes for performance reasons.
115      * TODO After deferred geometry, we should do all of this inline in GenerateGeometry alongside
116      * the struct used to actually populate the attributes.  This is all extremely fragile, vertex
117      * attributes have to be added in the order they will appear in the struct which maps memory.
118      * The processor key should reflect the vertex attributes, or there lack thereof in the
119      * GrGeometryProcessor.
120      */
121     const Attribute& addVertexAttrib(const Attribute& attribute) {
122         SkASSERT(fNumAttribs < kMaxVertexAttribs);
123         fVertexStride += attribute.fOffset;
124         fAttribs[fNumAttribs] = attribute;
125         return fAttribs[fNumAttribs++];
126     }
127
128     void setWillUseGeoShader() { fWillUseGeoShader = true; }
129
130     // TODO hack see above
131     void setHasVertexColor() { fHasVertexColor = true; }
132     void setHasLocalCoords() { fHasLocalCoords = true; }
133
134     virtual void onGetInvariantOutputColor(GrInitInvariantOutput*) const {}
135     virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const = 0;
136
137 private:
138     virtual bool onCanMakeEqual(const GrBatchTracker& mine,
139                                 const GrGeometryProcessor& that,
140                                 const GrBatchTracker& theirs) const = 0;
141
142     // TODO delete this when we have more advanced equality testing via bundles and the BT
143     virtual bool onIsEqual(const GrGeometryProcessor&) const = 0;
144
145     bool hasExplicitLocalCoords() const SK_OVERRIDE { return fHasLocalCoords; }
146
147     GrColor fColor;
148     bool fOpaqueVertexColors;
149     bool fWillUseGeoShader;
150     bool fHasVertexColor;
151     bool fHasLocalCoords;
152
153     typedef GrPrimitiveProcessor INHERITED;
154 };
155
156 #endif