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 "src/gpu/GrDefaultGeoProcFactory.h" |
9 | |
10 | #include "include/core/SkRefCnt.h" |
11 | #include "src/core/SkArenaAlloc.h" |
12 | #include "src/gpu/GrCaps.h" |
13 | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" |
14 | #include "src/gpu/glsl/GrGLSLGeometryProcessor.h" |
15 | #include "src/gpu/glsl/GrGLSLUniformHandler.h" |
16 | #include "src/gpu/glsl/GrGLSLVarying.h" |
17 | #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" |
18 | |
19 | /* |
20 | * The default Geometry Processor simply takes position and multiplies it by the uniform view |
21 | * matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or |
22 | * local coords. |
23 | */ |
24 | |
25 | enum GPFlag { |
26 | kColorAttribute_GPFlag = 0x1, |
27 | kColorAttributeIsWide_GPFlag = 0x2, |
28 | kLocalCoordAttribute_GPFlag = 0x4, |
29 | kCoverageAttribute_GPFlag = 0x8, |
30 | kCoverageAttributeTweak_GPFlag = 0x10, |
31 | }; |
32 | |
33 | class DefaultGeoProc : public GrGeometryProcessor { |
34 | public: |
35 | static GrGeometryProcessor* Make(SkArenaAlloc* arena, |
36 | uint32_t gpTypeFlags, |
37 | const SkPMColor4f& color, |
38 | const SkMatrix& viewMatrix, |
39 | const SkMatrix& localMatrix, |
40 | bool localCoordsWillBeRead, |
41 | uint8_t coverage) { |
42 | return arena->make<DefaultGeoProc>(gpTypeFlags, color, viewMatrix, localMatrix, coverage, |
43 | localCoordsWillBeRead); |
44 | } |
45 | |
46 | const char* name() const override { return "DefaultGeometryProcessor" ; } |
47 | |
48 | const SkPMColor4f& color() const { return fColor; } |
49 | bool hasVertexColor() const { return fInColor.isInitialized(); } |
50 | const SkMatrix& viewMatrix() const { return fViewMatrix; } |
51 | const SkMatrix& localMatrix() const { return fLocalMatrix; } |
52 | bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; } |
53 | uint8_t coverage() const { return fCoverage; } |
54 | bool hasVertexCoverage() const { return fInCoverage.isInitialized(); } |
55 | |
56 | class GLSLProcessor : public GrGLSLGeometryProcessor { |
57 | public: |
58 | GLSLProcessor() |
59 | : fViewMatrix(SkMatrix::InvalidMatrix()) |
60 | , fLocalMatrix(SkMatrix::InvalidMatrix()) |
61 | , fColor(SK_PMColor4fILLEGAL) |
62 | , fCoverage(0xff) {} |
63 | |
64 | void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { |
65 | const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>(); |
66 | GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; |
67 | GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
68 | GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; |
69 | GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
70 | |
71 | // emit attributes |
72 | varyingHandler->emitAttributes(gp); |
73 | |
74 | bool tweakAlpha = SkToBool(gp.fFlags & kCoverageAttributeTweak_GPFlag); |
75 | SkASSERT(!tweakAlpha || gp.hasVertexCoverage()); |
76 | |
77 | // Setup pass through color |
78 | if (gp.hasVertexColor() || tweakAlpha) { |
79 | GrGLSLVarying varying(kHalf4_GrSLType); |
80 | varyingHandler->addVarying("color" , &varying); |
81 | |
82 | // Start with the attribute or with uniform color |
83 | if (gp.hasVertexColor()) { |
84 | vertBuilder->codeAppendf("half4 color = %s;" , gp.fInColor.name()); |
85 | } else { |
86 | const char* colorUniformName; |
87 | fColorUniform = uniformHandler->addUniform(nullptr, |
88 | kVertex_GrShaderFlag, |
89 | kHalf4_GrSLType, |
90 | "Color" , |
91 | &colorUniformName); |
92 | vertBuilder->codeAppendf("half4 color = %s;" , colorUniformName); |
93 | } |
94 | |
95 | // Optionally fold coverage into alpha (color). |
96 | if (tweakAlpha) { |
97 | vertBuilder->codeAppendf("color = color * %s;" , gp.fInCoverage.name()); |
98 | } |
99 | vertBuilder->codeAppendf("%s = color;\n" , varying.vsOut()); |
100 | fragBuilder->codeAppendf("%s = %s;" , args.fOutputColor, varying.fsIn()); |
101 | } else { |
102 | this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, |
103 | &fColorUniform); |
104 | } |
105 | |
106 | // Setup position |
107 | this->writeOutputPosition(vertBuilder, |
108 | uniformHandler, |
109 | gpArgs, |
110 | gp.fInPosition.name(), |
111 | gp.viewMatrix(), |
112 | &fViewMatrixUniform); |
113 | |
114 | // emit transforms using either explicit local coords or positions |
115 | if (gp.fInLocalCoords.isInitialized()) { |
116 | SkASSERT(gp.localMatrix().isIdentity()); |
117 | gpArgs->fLocalCoordVar = gp.fInLocalCoords.asShaderVar(); |
118 | } else if (gp.fLocalCoordsWillBeRead) { |
119 | this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, |
120 | gp.fInPosition.asShaderVar(), gp.localMatrix(), |
121 | &fLocalMatrixUniform); |
122 | } |
123 | |
124 | // Setup coverage as pass through |
125 | if (gp.hasVertexCoverage() && !tweakAlpha) { |
126 | fragBuilder->codeAppendf("half alpha = 1.0;" ); |
127 | varyingHandler->addPassThroughAttribute(gp.fInCoverage, "alpha" ); |
128 | fragBuilder->codeAppendf("%s = half4(alpha);" , args.fOutputCoverage); |
129 | } else if (gp.coverage() == 0xff) { |
130 | fragBuilder->codeAppendf("%s = half4(1);" , args.fOutputCoverage); |
131 | } else { |
132 | const char* fragCoverage; |
133 | fCoverageUniform = uniformHandler->addUniform(nullptr, |
134 | kFragment_GrShaderFlag, |
135 | kHalf_GrSLType, |
136 | "Coverage" , |
137 | &fragCoverage); |
138 | fragBuilder->codeAppendf("%s = half4(%s);" , args.fOutputCoverage, fragCoverage); |
139 | } |
140 | } |
141 | |
142 | static inline void GenKey(const GrGeometryProcessor& gp, |
143 | const GrShaderCaps&, |
144 | GrProcessorKeyBuilder* b) { |
145 | const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); |
146 | uint32_t key = def.fFlags; |
147 | key |= (def.coverage() == 0xff) ? 0x80 : 0; |
148 | key |= def.localCoordsWillBeRead() ? 0x100 : 0; |
149 | |
150 | bool usesLocalMatrix = def.localCoordsWillBeRead() && |
151 | !def.fInLocalCoords.isInitialized(); |
152 | key = AddMatrixKeys(key, def.viewMatrix(), |
153 | usesLocalMatrix ? def.localMatrix() : SkMatrix::I()); |
154 | b->add32(key); |
155 | } |
156 | |
157 | void setData(const GrGLSLProgramDataManager& pdman, |
158 | const GrPrimitiveProcessor& gp) override { |
159 | const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>(); |
160 | |
161 | this->setTransform(pdman, fViewMatrixUniform, dgp.viewMatrix(), &fViewMatrix); |
162 | this->setTransform(pdman, fLocalMatrixUniform, dgp.localMatrix(), &fLocalMatrix); |
163 | |
164 | if (!dgp.hasVertexColor() && dgp.color() != fColor) { |
165 | pdman.set4fv(fColorUniform, 1, dgp.color().vec()); |
166 | fColor = dgp.color(); |
167 | } |
168 | |
169 | if (dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) { |
170 | pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage())); |
171 | fCoverage = dgp.coverage(); |
172 | } |
173 | } |
174 | |
175 | private: |
176 | SkMatrix fViewMatrix; |
177 | SkMatrix fLocalMatrix; |
178 | SkPMColor4f fColor; |
179 | uint8_t fCoverage; |
180 | UniformHandle fViewMatrixUniform; |
181 | UniformHandle fLocalMatrixUniform; |
182 | UniformHandle fColorUniform; |
183 | UniformHandle fCoverageUniform; |
184 | |
185 | typedef GrGLSLGeometryProcessor INHERITED; |
186 | }; |
187 | |
188 | void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { |
189 | GLSLProcessor::GenKey(*this, caps, b); |
190 | } |
191 | |
192 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { |
193 | return new GLSLProcessor(); |
194 | } |
195 | |
196 | private: |
197 | friend class ::SkArenaAlloc; // for access to ctor |
198 | |
199 | DefaultGeoProc(uint32_t gpTypeFlags, |
200 | const SkPMColor4f& color, |
201 | const SkMatrix& viewMatrix, |
202 | const SkMatrix& localMatrix, |
203 | uint8_t coverage, |
204 | bool localCoordsWillBeRead) |
205 | : INHERITED(kDefaultGeoProc_ClassID) |
206 | , fColor(color) |
207 | , fViewMatrix(viewMatrix) |
208 | , fLocalMatrix(localMatrix) |
209 | , fCoverage(coverage) |
210 | , fFlags(gpTypeFlags) |
211 | , fLocalCoordsWillBeRead(localCoordsWillBeRead) { |
212 | fInPosition = {"inPosition" , kFloat2_GrVertexAttribType, kFloat2_GrSLType}; |
213 | if (fFlags & kColorAttribute_GPFlag) { |
214 | fInColor = MakeColorAttribute("inColor" , |
215 | SkToBool(fFlags & kColorAttributeIsWide_GPFlag)); |
216 | } |
217 | if (fFlags & kLocalCoordAttribute_GPFlag) { |
218 | fInLocalCoords = {"inLocalCoord" , kFloat2_GrVertexAttribType, |
219 | kFloat2_GrSLType}; |
220 | } |
221 | if (fFlags & kCoverageAttribute_GPFlag) { |
222 | fInCoverage = {"inCoverage" , kFloat_GrVertexAttribType, kHalf_GrSLType}; |
223 | } |
224 | this->setVertexAttributes(&fInPosition, 4); |
225 | } |
226 | |
227 | Attribute fInPosition; |
228 | Attribute fInColor; |
229 | Attribute fInLocalCoords; |
230 | Attribute fInCoverage; |
231 | SkPMColor4f fColor; |
232 | SkMatrix fViewMatrix; |
233 | SkMatrix fLocalMatrix; |
234 | uint8_t fCoverage; |
235 | uint32_t fFlags; |
236 | bool fLocalCoordsWillBeRead; |
237 | |
238 | GR_DECLARE_GEOMETRY_PROCESSOR_TEST |
239 | |
240 | typedef GrGeometryProcessor INHERITED; |
241 | }; |
242 | |
243 | GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc); |
244 | |
245 | #if GR_TEST_UTILS |
246 | GrGeometryProcessor* DefaultGeoProc::TestCreate(GrProcessorTestData* d) { |
247 | uint32_t flags = 0; |
248 | if (d->fRandom->nextBool()) { |
249 | flags |= kColorAttribute_GPFlag; |
250 | } |
251 | if (d->fRandom->nextBool()) { |
252 | flags |= kColorAttributeIsWide_GPFlag; |
253 | } |
254 | if (d->fRandom->nextBool()) { |
255 | flags |= kCoverageAttribute_GPFlag; |
256 | if (d->fRandom->nextBool()) { |
257 | flags |= kCoverageAttributeTweak_GPFlag; |
258 | } |
259 | } |
260 | if (d->fRandom->nextBool()) { |
261 | flags |= kLocalCoordAttribute_GPFlag; |
262 | } |
263 | |
264 | return DefaultGeoProc::Make(d->allocator(), |
265 | flags, |
266 | SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), |
267 | GrTest::TestMatrix(d->fRandom), |
268 | GrTest::TestMatrix(d->fRandom), |
269 | d->fRandom->nextBool(), |
270 | GrRandomCoverage(d->fRandom)); |
271 | } |
272 | #endif |
273 | |
274 | GrGeometryProcessor* GrDefaultGeoProcFactory::Make(SkArenaAlloc* arena, |
275 | const Color& color, |
276 | const Coverage& coverage, |
277 | const LocalCoords& localCoords, |
278 | const SkMatrix& viewMatrix) { |
279 | uint32_t flags = 0; |
280 | if (Color::kPremulGrColorAttribute_Type == color.fType) { |
281 | flags |= kColorAttribute_GPFlag; |
282 | } else if (Color::kPremulWideColorAttribute_Type == color.fType) { |
283 | flags |= kColorAttribute_GPFlag | kColorAttributeIsWide_GPFlag; |
284 | } |
285 | if (Coverage::kAttribute_Type == coverage.fType) { |
286 | flags |= kCoverageAttribute_GPFlag; |
287 | } else if (Coverage::kAttributeTweakAlpha_Type == coverage.fType) { |
288 | flags |= kCoverageAttribute_GPFlag | kCoverageAttributeTweak_GPFlag; |
289 | } |
290 | flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0; |
291 | |
292 | uint8_t inCoverage = coverage.fCoverage; |
293 | bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type; |
294 | |
295 | return DefaultGeoProc::Make(arena, |
296 | flags, |
297 | color.fColor, |
298 | viewMatrix, |
299 | localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), |
300 | localCoordsWillBeRead, |
301 | inCoverage); |
302 | } |
303 | |
304 | GrGeometryProcessor* GrDefaultGeoProcFactory::MakeForDeviceSpace(SkArenaAlloc* arena, |
305 | const Color& color, |
306 | const Coverage& coverage, |
307 | const LocalCoords& localCoords, |
308 | const SkMatrix& viewMatrix) { |
309 | SkMatrix invert = SkMatrix::I(); |
310 | if (LocalCoords::kUnused_Type != localCoords.fType) { |
311 | SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType); |
312 | if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) { |
313 | return nullptr; |
314 | } |
315 | |
316 | if (localCoords.hasLocalMatrix()) { |
317 | invert.postConcat(*localCoords.fMatrix); |
318 | } |
319 | } |
320 | |
321 | LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert); |
322 | return Make(arena, color, coverage, inverted, SkMatrix::I()); |
323 | } |
324 | |