• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "GrDefaultGeoProcFactory.h"
9 
10 #include "GrInvariantOutput.h"
11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
12 #include "glsl/GrGLSLGeometryProcessor.h"
13 #include "glsl/GrGLSLVertexShaderBuilder.h"
14 #include "glsl/GrGLSLVarying.h"
15 #include "glsl/GrGLSLUniformHandler.h"
16 #include "glsl/GrGLSLUtil.h"
17 
18 /*
19  * The default Geometry Processor simply takes position and multiplies it by the uniform view
20  * matrix. It also leaves coverage untouched.  Behind the scenes, we may add per vertex color or
21  * local coords.
22  */
23 
24 enum GPFlag {
25     kColor_GPFlag =                 0x1,
26     kLocalCoord_GPFlag =            0x2,
27     kCoverage_GPFlag=               0x4,
28     kTransformedLocalCoord_GPFlag = 0x8,
29 };
30 
31 class DefaultGeoProc : public GrGeometryProcessor {
32 public:
Create(uint32_t gpTypeFlags,GrColor color,const SkMatrix & viewMatrix,const SkMatrix & localMatrix,bool localCoordsWillBeRead,bool coverageWillBeIgnored,uint8_t coverage)33     static GrGeometryProcessor* Create(uint32_t gpTypeFlags,
34                                        GrColor color,
35                                        const SkMatrix& viewMatrix,
36                                        const SkMatrix& localMatrix,
37                                        bool localCoordsWillBeRead,
38                                        bool coverageWillBeIgnored,
39                                        uint8_t coverage) {
40         return new DefaultGeoProc(gpTypeFlags, color, viewMatrix, localMatrix, coverage,
41                                   localCoordsWillBeRead, coverageWillBeIgnored);
42     }
43 
name() const44     const char* name() const override { return "DefaultGeometryProcessor"; }
45 
inPosition() const46     const Attribute* inPosition() const { return fInPosition; }
inColor() const47     const Attribute* inColor() const { return fInColor; }
inLocalCoords() const48     const Attribute* inLocalCoords() const { return fInLocalCoords; }
inCoverage() const49     const Attribute* inCoverage() const { return fInCoverage; }
color() const50     GrColor color() const { return fColor; }
colorIgnored() const51     bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
hasVertexColor() const52     bool hasVertexColor() const { return SkToBool(fInColor); }
viewMatrix() const53     const SkMatrix& viewMatrix() const { return fViewMatrix; }
localMatrix() const54     const SkMatrix& localMatrix() const { return fLocalMatrix; }
localCoordsWillBeRead() const55     bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; }
coverage() const56     uint8_t coverage() const { return fCoverage; }
coverageWillBeIgnored() const57     bool coverageWillBeIgnored() const { return fCoverageWillBeIgnored; }
hasVertexCoverage() const58     bool hasVertexCoverage() const { return SkToBool(fInCoverage); }
59 
60     class GLSLProcessor : public GrGLSLGeometryProcessor {
61     public:
GLSLProcessor()62         GLSLProcessor()
63             : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverage(0xff) {}
64 
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)65         void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
66             const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
67             GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
68             GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
69             GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
70             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
71 
72             // emit attributes
73             varyingHandler->emitAttributes(gp);
74 
75             // Setup pass through color
76             if (!gp.colorIgnored()) {
77                 if (gp.hasVertexColor()) {
78                     varyingHandler->addPassThroughAttribute(gp.inColor(), args.fOutputColor);
79                 } else {
80                     this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
81                                             &fColorUniform);
82                 }
83             }
84 
85             // Setup position
86             this->setupPosition(vertBuilder,
87                                 uniformHandler,
88                                 gpArgs,
89                                 gp.inPosition()->fName,
90                                 gp.viewMatrix(),
91                                 &fViewMatrixUniform);
92 
93             if (gp.hasExplicitLocalCoords()) {
94                 // emit transforms with explicit local coords
95                 this->emitTransforms(vertBuilder,
96                                      varyingHandler,
97                                      uniformHandler,
98                                      gpArgs->fPositionVar,
99                                      gp.inLocalCoords()->fName,
100                                      gp.localMatrix(),
101                                      args.fTransformsIn,
102                                      args.fTransformsOut);
103             } else if(gp.hasTransformedLocalCoords()) {
104                 // transforms have already been applied to vertex attributes on the cpu
105                 this->emitTransforms(vertBuilder,
106                                      varyingHandler,
107                                      gp.inLocalCoords()->fName,
108                                      args.fTransformsIn,
109                                      args.fTransformsOut);
110             } else {
111                 // emit transforms with position
112                 this->emitTransforms(vertBuilder,
113                                      varyingHandler,
114                                      uniformHandler,
115                                      gpArgs->fPositionVar,
116                                      gp.inPosition()->fName,
117                                      gp.localMatrix(),
118                                      args.fTransformsIn,
119                                      args.fTransformsOut);
120             }
121 
122             // Setup coverage as pass through
123             if (!gp.coverageWillBeIgnored()) {
124                 if (gp.hasVertexCoverage()) {
125                     fragBuilder->codeAppendf("float alpha = 1.0;");
126                     varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
127                     fragBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
128                 } else if (gp.coverage() == 0xff) {
129                     fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
130                 } else {
131                     const char* fragCoverage;
132                     fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
133                                                                   kFloat_GrSLType,
134                                                                   kDefault_GrSLPrecision,
135                                                                   "Coverage",
136                                                                   &fragCoverage);
137                     fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, fragCoverage);
138                 }
139             }
140         }
141 
GenKey(const GrGeometryProcessor & gp,const GrGLSLCaps &,GrProcessorKeyBuilder * b)142         static inline void GenKey(const GrGeometryProcessor& gp,
143                                   const GrGLSLCaps&,
144                                   GrProcessorKeyBuilder* b) {
145             const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
146             uint32_t key = def.fFlags;
147             key |= def.colorIgnored() << 8;
148             key |= def.coverageWillBeIgnored() << 9;
149             key |= def.hasVertexColor() << 10;
150             key |= def.hasVertexCoverage() << 11;
151             key |= def.coverage() == 0xff ? 0x1 << 12 : 0;
152             key |= def.localCoordsWillBeRead() && def.localMatrix().hasPerspective() ? 0x1 << 24 :
153                                                                                        0x0;
154             key |= ComputePosKey(def.viewMatrix()) << 25;
155             b->add32(key);
156         }
157 
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & gp)158         void setData(const GrGLSLProgramDataManager& pdman,
159                      const GrPrimitiveProcessor& gp) override {
160             const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>();
161 
162             if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) {
163                 fViewMatrix = dgp.viewMatrix();
164                 float viewMatrix[3 * 3];
165                 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
166                 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
167             }
168 
169             if (dgp.color() != fColor && !dgp.hasVertexColor()) {
170                 float c[4];
171                 GrColorToRGBAFloat(dgp.color(), c);
172                 pdman.set4fv(fColorUniform, 1, c);
173                 fColor = dgp.color();
174             }
175 
176             if (!dgp.coverageWillBeIgnored() &&
177                 dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) {
178                 pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage()));
179                 fCoverage = dgp.coverage();
180             }
181         }
182 
setTransformData(const GrPrimitiveProcessor & primProc,const GrGLSLProgramDataManager & pdman,int index,const SkTArray<const GrCoordTransform *,true> & transforms)183         void setTransformData(const GrPrimitiveProcessor& primProc,
184                               const GrGLSLProgramDataManager& pdman,
185                               int index,
186                               const SkTArray<const GrCoordTransform*, true>& transforms) override {
187             this->setTransformDataHelper<DefaultGeoProc>(primProc, pdman, index, transforms);
188         }
189 
190     private:
191         SkMatrix fViewMatrix;
192         GrColor fColor;
193         uint8_t fCoverage;
194         UniformHandle fViewMatrixUniform;
195         UniformHandle fColorUniform;
196         UniformHandle fCoverageUniform;
197 
198         typedef GrGLSLGeometryProcessor INHERITED;
199     };
200 
getGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const201     void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
202         GLSLProcessor::GenKey(*this, caps, b);
203     }
204 
createGLSLInstance(const GrGLSLCaps &) const205     GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override {
206         return new GLSLProcessor();
207     }
208 
209 private:
DefaultGeoProc(uint32_t gpTypeFlags,GrColor color,const SkMatrix & viewMatrix,const SkMatrix & localMatrix,uint8_t coverage,bool localCoordsWillBeRead,bool coverageWillBeIgnored)210     DefaultGeoProc(uint32_t gpTypeFlags,
211                    GrColor color,
212                    const SkMatrix& viewMatrix,
213                    const SkMatrix& localMatrix,
214                    uint8_t coverage,
215                    bool localCoordsWillBeRead,
216                    bool coverageWillBeIgnored)
217         : fInPosition(nullptr)
218         , fInColor(nullptr)
219         , fInLocalCoords(nullptr)
220         , fInCoverage(nullptr)
221         , fColor(color)
222         , fViewMatrix(viewMatrix)
223         , fLocalMatrix(localMatrix)
224         , fCoverage(coverage)
225         , fFlags(gpTypeFlags)
226         , fLocalCoordsWillBeRead(localCoordsWillBeRead)
227         , fCoverageWillBeIgnored(coverageWillBeIgnored) {
228         this->initClassID<DefaultGeoProc>();
229         bool hasColor = SkToBool(gpTypeFlags & kColor_GPFlag);
230         bool hasExplicitLocalCoords = SkToBool(gpTypeFlags & kLocalCoord_GPFlag);
231         bool hasTransformedLocalCoords = SkToBool(gpTypeFlags & kTransformedLocalCoord_GPFlag);
232         bool hasLocalCoord = hasExplicitLocalCoords || hasTransformedLocalCoords;
233         bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPFlag);
234         fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
235                                                        kHigh_GrSLPrecision));
236         if (hasColor) {
237             fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
238         }
239         if (hasLocalCoord) {
240             fInLocalCoords = &this->addVertexAttrib(Attribute("inLocalCoord",
241                                                               kVec2f_GrVertexAttribType));
242             if (hasExplicitLocalCoords) {
243                 this->setHasExplicitLocalCoords();
244             } else {
245                 SkASSERT(hasTransformedLocalCoords);
246                 this->setHasTransformedLocalCoords();
247             }
248         }
249         if (hasCoverage) {
250             fInCoverage = &this->addVertexAttrib(Attribute("inCoverage",
251                                                            kFloat_GrVertexAttribType));
252         }
253     }
254 
255     const Attribute* fInPosition;
256     const Attribute* fInColor;
257     const Attribute* fInLocalCoords;
258     const Attribute* fInCoverage;
259     GrColor fColor;
260     SkMatrix fViewMatrix;
261     SkMatrix fLocalMatrix;
262     uint8_t fCoverage;
263     uint32_t fFlags;
264     bool fLocalCoordsWillBeRead;
265     bool fCoverageWillBeIgnored;
266 
267     GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
268 
269     typedef GrGeometryProcessor INHERITED;
270 };
271 
272 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc);
273 
TestCreate(GrProcessorTestData * d)274 const GrGeometryProcessor* DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
275     uint32_t flags = 0;
276     if (d->fRandom->nextBool()) {
277         flags |= kColor_GPFlag;
278     }
279     if (d->fRandom->nextBool()) {
280         flags |= kCoverage_GPFlag;
281     }
282     if (d->fRandom->nextBool()) {
283         flags |= kLocalCoord_GPFlag;
284     }
285     if (d->fRandom->nextBool()) {
286         flags |= kTransformedLocalCoord_GPFlag;
287     }
288 
289     return DefaultGeoProc::Create(flags,
290                                   GrRandomColor(d->fRandom),
291                                   GrTest::TestMatrix(d->fRandom),
292                                   GrTest::TestMatrix(d->fRandom),
293                                   d->fRandom->nextBool(),
294                                   d->fRandom->nextBool(),
295                                   GrRandomCoverage(d->fRandom));
296 }
297 
Create(const Color & color,const Coverage & coverage,const LocalCoords & localCoords,const SkMatrix & viewMatrix)298 const GrGeometryProcessor* GrDefaultGeoProcFactory::Create(const Color& color,
299                                                            const Coverage& coverage,
300                                                            const LocalCoords& localCoords,
301                                                            const SkMatrix& viewMatrix) {
302     uint32_t flags = 0;
303     flags |= color.fType == Color::kAttribute_Type ? kColor_GPFlag : 0;
304     flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverage_GPFlag : 0;
305     flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPFlag : 0;
306     flags |= localCoords.fType == LocalCoords::kHasTransformed_Type ?
307                                   kTransformedLocalCoord_GPFlag : 0;
308 
309     uint8_t inCoverage = coverage.fCoverage;
310     bool coverageWillBeIgnored = coverage.fType == Coverage::kNone_Type;
311     bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
312 
313     GrColor inColor = color.fColor;
314     return DefaultGeoProc::Create(flags,
315                                   inColor,
316                                   viewMatrix,
317                                   localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
318                                   localCoordsWillBeRead,
319                                   coverageWillBeIgnored,
320                                   inCoverage);
321 }
322 
CreateForDeviceSpace(const Color & color,const Coverage & coverage,const LocalCoords & localCoords,const SkMatrix & viewMatrix)323 const GrGeometryProcessor* GrDefaultGeoProcFactory::CreateForDeviceSpace(
324                                                                      const Color& color,
325                                                                      const Coverage& coverage,
326                                                                      const LocalCoords& localCoords,
327                                                                      const SkMatrix& viewMatrix) {
328     SkMatrix invert = SkMatrix::I();
329     if (LocalCoords::kUnused_Type != localCoords.fType) {
330         SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType);
331         if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
332             SkDebugf("Could not invert\n");
333             return nullptr;
334         }
335 
336         if (localCoords.hasLocalMatrix()) {
337             invert.preConcat(*localCoords.fMatrix);
338         }
339     }
340 
341     LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
342     return Create(color, coverage, inverted, SkMatrix::I());
343 }
344