2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrGeometryProcessor_DEFINED
9 #define GrGeometryProcessor_DEFINED
11 #include "GrPrimitiveProcessor.h"
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.
20 class GrGeometryProcessor : public GrPrimitiveProcessor {
22 // TODO the Hint can be handled in a much more clean way when we have deferred geometry or
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)
30 , fOpaqueVertexColors(opaqueVertexColors)
31 , fWillUseGeoShader(false)
32 , fHasVertexColor(false)
33 , fHasLocalCoords(false) {}
35 bool willUseGeoShader() const { return fWillUseGeoShader; }
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.
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)) {
52 // TODO let the GPs decide this
53 if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) {
57 // TODO remove the hint
58 const GrGeometryProcessor& other = that.cast<GrGeometryProcessor>();
59 if (fHasVertexColor && fOpaqueVertexColors != other.fOpaqueVertexColors) {
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)) {
69 return this->onCanMakeEqual(mine, other, theirs);
72 // TODO we can remove color from the GrGeometryProcessor base class once we have bundles of
74 GrColor color() const { return fColor; }
76 // TODO this is a total hack until the gp can do deferred geometry
77 bool hasVertexColor() const { return fHasVertexColor; }
79 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
80 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
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.
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;
104 *color = primitiveColor;
105 if (hasVertexColor) {
106 return kAttribute_GrGPInput;
108 return kUniform_GrGPInput;
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.
121 const Attribute& addVertexAttrib(const Attribute& attribute) {
122 SkASSERT(fNumAttribs < kMaxVertexAttribs);
123 fVertexStride += attribute.fOffset;
124 fAttribs[fNumAttribs] = attribute;
125 return fAttribs[fNumAttribs++];
128 void setWillUseGeoShader() { fWillUseGeoShader = true; }
130 // TODO hack see above
131 void setHasVertexColor() { fHasVertexColor = true; }
132 void setHasLocalCoords() { fHasLocalCoords = true; }
134 virtual void onGetInvariantOutputColor(GrInitInvariantOutput*) const {}
135 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const = 0;
138 virtual bool onCanMakeEqual(const GrBatchTracker& mine,
139 const GrGeometryProcessor& that,
140 const GrBatchTracker& theirs) const = 0;
142 // TODO delete this when we have more advanced equality testing via bundles and the BT
143 virtual bool onIsEqual(const GrGeometryProcessor&) const = 0;
145 bool hasExplicitLocalCoords() const SK_OVERRIDE { return fHasLocalCoords; }
148 bool fOpaqueVertexColors;
149 bool fWillUseGeoShader;
150 bool fHasVertexColor;
151 bool fHasLocalCoords;
153 typedef GrPrimitiveProcessor INHERITED;