OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGeometryProcessor.h" | 8 #include "GrGeometryProcessor.h" |
9 | 9 |
10 #include "GrCoordTransform.h" | |
11 #include "GrInvariantOutput.h" | 10 #include "GrInvariantOutput.h" |
12 #include "gl/GrGLGeometryProcessor.h" | |
13 | |
14 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
15 | |
16 /** | |
17 * The key for an individual coord transform is made up of a matrix type, a prec
ision, and a bit | |
18 * that indicates the source of the input coords. | |
19 */ | |
20 enum { | |
21 kMatrixTypeKeyBits = 1, | |
22 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1, | |
23 | |
24 kPrecisionBits = 2, | |
25 kPrecisionShift = kMatrixTypeKeyBits, | |
26 | |
27 kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)), | |
28 kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag, | |
29 | |
30 kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2, | |
31 }; | |
32 | |
33 GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits)); | |
34 | |
35 /** | |
36 * We specialize the vertex code for each of these matrix types. | |
37 */ | |
38 enum MatrixType { | |
39 kNoPersp_MatrixType = 0, | |
40 kGeneral_MatrixType = 1, | |
41 }; | |
42 | |
43 uint32_t | |
44 GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, tr
ue>& coords) const { | |
45 uint32_t totalKey = 0; | |
46 for (int t = 0; t < coords.count(); ++t) { | |
47 uint32_t key = 0; | |
48 const GrCoordTransform* coordTransform = coords[t]; | |
49 if (coordTransform->getMatrix().hasPerspective()) { | |
50 key |= kGeneral_MatrixType; | |
51 } else { | |
52 key |= kNoPersp_MatrixType; | |
53 } | |
54 | |
55 if (kLocal_GrCoordSet == coordTransform->sourceCoords() && | |
56 !this->hasExplicitLocalCoords()) { | |
57 key |= kPositionCoords_Flag; | |
58 } else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) { | |
59 key |= kDeviceCoords_Flag; | |
60 } | |
61 | |
62 GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits)); | |
63 key |= (coordTransform->precision() << kPrecisionShift); | |
64 | |
65 key <<= kTransformKeyBits * t; | |
66 | |
67 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to
overlap | |
68 totalKey |= key; | |
69 } | |
70 return totalKey; | |
71 } | |
72 | |
73 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
74 | 11 |
75 void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) co
nst { | 12 void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) co
nst { |
76 if (fHasVertexColor) { | 13 if (fHasVertexColor) { |
77 if (fOpaqueVertexColors) { | 14 if (fOpaqueVertexColors) { |
78 out->setUnknownOpaqueFourComponents(); | 15 out->setUnknownOpaqueFourComponents(); |
79 } else { | 16 } else { |
80 out->setUnknownFourComponents(); | 17 out->setUnknownFourComponents(); |
81 } | 18 } |
82 } else { | 19 } else { |
83 out->setKnownFourComponents(fColor); | 20 out->setKnownFourComponents(fColor); |
84 } | 21 } |
85 this->onGetInvariantOutputColor(out); | 22 this->onGetInvariantOutputColor(out); |
86 } | 23 } |
87 | 24 |
88 void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
const { | 25 void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
const { |
89 this->onGetInvariantOutputCoverage(out); | 26 this->onGetInvariantOutputCoverage(out); |
90 } | 27 } |
91 | 28 |
92 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
93 | 29 |
94 #include "gl/builders/GrGLProgramBuilder.h" | |
95 | |
96 SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix, | |
97 const GrCoordTransform& coor
dTransform) { | |
98 SkMatrix combined; | |
99 // We only apply the localmatrix to localcoords | |
100 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { | |
101 combined.setConcat(coordTransform.getMatrix(), localMatrix); | |
102 } else { | |
103 combined = coordTransform.getMatrix(); | |
104 } | |
105 if (coordTransform.reverseY()) { | |
106 // combined.postScale(1,-1); | |
107 // combined.postTranslate(0,1); | |
108 combined.set(SkMatrix::kMSkewY, | |
109 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); | |
110 combined.set(SkMatrix::kMScaleY, | |
111 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); | |
112 combined.set(SkMatrix::kMTransY, | |
113 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); | |
114 } | |
115 return combined; | |
116 } | |
117 | |
118 void | |
119 GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb, | |
120 GrGPInput inputType, | |
121 const char* outputName, | |
122 const GrGeometryProcessor::Attribu
te* colorAttr, | |
123 UniformHandle* colorUniform) { | |
124 GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder(); | |
125 if (kUniform_GrGPInput == inputType) { | |
126 SkASSERT(colorUniform); | |
127 const char* stagedLocalVarName; | |
128 *colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
129 kVec4f_GrSLType, | |
130 kDefault_GrSLPrecision, | |
131 "Color", | |
132 &stagedLocalVarName); | |
133 fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName); | |
134 } else if (kAttribute_GrGPInput == inputType) { | |
135 SkASSERT(colorAttr); | |
136 pb->addPassThroughAttribute(colorAttr, outputName); | |
137 } else if (kAllOnes_GrGPInput == inputType) { | |
138 fs->codeAppendf("%s = vec4(1);", outputName); | |
139 } | |
140 } | |
141 | |
142 void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) { | |
143 fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility, | |
144 kMat33f_GrSLType, kDefault_GrSLPrecision
, | |
145 "uViewM", | |
146 &fViewMatrixName); | |
147 } | |
148 | |
149 void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager&
pdman, | |
150 const SkMatrix& viewMatrix) { | |
151 if (!fViewMatrix.cheapEqualTo(viewMatrix)) { | |
152 SkASSERT(fViewMatrixUniform.isValid()); | |
153 fViewMatrix = viewMatrix; | |
154 | |
155 GrGLfloat viewMatrix[3 * 3]; | |
156 GrGLGetMatrix<3>(viewMatrix, fViewMatrix); | |
157 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); | |
158 } | |
159 } | |
160 | |
161 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
162 | |
163 | |
164 void GrGLGeometryProcessor::emitCode(EmitArgs& args) { | |
165 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
166 GrGPArgs gpArgs; | |
167 this->onEmitCode(args, &gpArgs); | |
168 vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar); | |
169 } | |
170 | |
171 void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb, | |
172 const GrShaderVar& posVar, | |
173 const char* localCoords, | |
174 const SkMatrix& localMatrix, | |
175 const TransformsIn& tin, | |
176 TransformsOut* tout) { | |
177 GrGLVertexBuilder* vb = pb->getVertexShaderBuilder(); | |
178 tout->push_back_n(tin.count()); | |
179 fInstalledTransforms.push_back_n(tin.count()); | |
180 for (int i = 0; i < tin.count(); i++) { | |
181 const ProcCoords& coordTransforms = tin[i]; | |
182 fInstalledTransforms[i].push_back_n(coordTransforms.count()); | |
183 for (int t = 0; t < coordTransforms.count(); t++) { | |
184 SkString strUniName("StageMatrix"); | |
185 strUniName.appendf("_%i_%i", i, t); | |
186 GrSLType varyingType; | |
187 | |
188 GrCoordSet coordType = coordTransforms[t]->sourceCoords(); | |
189 uint32_t type = coordTransforms[t]->getMatrix().getType(); | |
190 if (kLocal_GrCoordSet == coordType) { | |
191 type |= localMatrix.getType(); | |
192 } | |
193 varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_
GrSLType : | |
194 kVec2f_
GrSLType; | |
195 GrSLPrecision precision = coordTransforms[t]->precision(); | |
196 | |
197 const char* uniName; | |
198 fInstalledTransforms[i][t].fHandle = | |
199 pb->addUniform(GrGLProgramBuilder::kVertex_Visibility, | |
200 kMat33f_GrSLType, precision, | |
201 strUniName.c_str(), | |
202 &uniName).toShaderBuilderIndex(); | |
203 | |
204 SkString strVaryingName("MatrixCoord"); | |
205 strVaryingName.appendf("_%i_%i", i, t); | |
206 | |
207 GrGLVertToFrag v(varyingType); | |
208 pb->addVarying(strVaryingName.c_str(), &v, precision); | |
209 | |
210 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyin
gType); | |
211 SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords
, | |
212 (SkString(v.fsIn()), varyingType)); | |
213 | |
214 // varying = matrix * coords (logically) | |
215 if (kDevice_GrCoordSet == coordType) { | |
216 if (kVec2f_GrSLType == varyingType) { | |
217 if (kVec2f_GrSLType == posVar.getType()) { | |
218 vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", | |
219 v.vsOut(), uniName, posVar.c_str()); | |
220 } else { | |
221 // The brackets here are just to scope the temp variable | |
222 vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVa
r.c_str()); | |
223 vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z)
; }", v.vsOut()); | |
224 } | |
225 } else { | |
226 if (kVec2f_GrSLType == posVar.getType()) { | |
227 vb->codeAppendf("%s = %s * vec3(%s, 1);", | |
228 v.vsOut(), uniName, posVar.c_str()); | |
229 } else { | |
230 vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, pos
Var.c_str()); | |
231 } | |
232 } | |
233 } else { | |
234 if (kVec2f_GrSLType == varyingType) { | |
235 vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), un
iName, localCoords); | |
236 } else { | |
237 vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName
, localCoords); | |
238 } | |
239 } | |
240 } | |
241 } | |
242 } | |
243 | |
244 | |
245 void | |
246 GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc, | |
247 const GrGLProgramDataManager& pdman, | |
248 int index, | |
249 const SkTArray<const GrCoordTransform*,
true>& transforms) { | |
250 SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index]; | |
251 int numTransforms = transforms.count(); | |
252 for (int t = 0; t < numTransforms; ++t) { | |
253 SkASSERT(procTransforms[t].fHandle.isValid()); | |
254 const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *
transforms[t]); | |
255 if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) { | |
256 pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle()
, transform); | |
257 procTransforms[t].fCurrentValue = transform; | |
258 } | |
259 } | |
260 } | |
261 | |
262 void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder, | |
263 GrGPArgs* gpArgs, | |
264 const char* posName, | |
265 const SkMatrix& mat, | |
266 const char* matName) { | |
267 if (mat.isIdentity()) { | |
268 gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); | |
269 | |
270 vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), po
sName); | |
271 } else if (!mat.hasPerspective()) { | |
272 gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); | |
273 | |
274 vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));", | |
275 gpArgs->fPositionVar.c_str(), matName, posName); | |
276 } else { | |
277 gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3"); | |
278 | |
279 vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);", | |
280 gpArgs->fPositionVar.c_str(), matName, posName); | |
281 } | |
282 } | |
283 | |
284 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
285 | |
286 #include "gl/GrGLGpu.h" | |
287 #include "gl/GrGLPathRendering.h" | |
288 | |
289 struct PathBatchTracker { | |
290 GrGPInput fInputColorType; | |
291 GrGPInput fInputCoverageType; | |
292 GrColor fColor; | |
293 bool fUsesLocalCoords; | |
294 }; | |
295 | |
296 GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracke
r&) | |
297 : fColor(GrColor_ILLEGAL) {} | |
298 | |
299 void GrGLPathProcessor::emitCode(EmitArgs& args) { | |
300 GrGLGPBuilder* pb = args.fPB; | |
301 GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder(); | |
302 const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>(); | |
303 | |
304 // emit transforms | |
305 this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut); | |
306 | |
307 // Setup uniform color | |
308 if (kUniform_GrGPInput == local.fInputColorType) { | |
309 const char* stagedLocalVarName; | |
310 fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
311 kVec4f_GrSLType, | |
312 kDefault_GrSLPrecision, | |
313 "Color", | |
314 &stagedLocalVarName); | |
315 fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName); | |
316 } | |
317 | |
318 // setup constant solid coverage | |
319 if (kAllOnes_GrGPInput == local.fInputCoverageType) { | |
320 fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage); | |
321 } | |
322 } | |
323 | |
324 void GrGLPathProcessor::GenKey(const GrPathProcessor&, | |
325 const GrBatchTracker& bt, | |
326 const GrGLCaps&, | |
327 GrProcessorKeyBuilder* b) { | |
328 const PathBatchTracker& local = bt.cast<PathBatchTracker>(); | |
329 b->add32(local.fInputColorType | local.fInputCoverageType << 16); | |
330 } | |
331 | |
332 void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman, | |
333 const GrPrimitiveProcessor& primProc, | |
334 const GrBatchTracker& bt) { | |
335 const PathBatchTracker& local = bt.cast<PathBatchTracker>(); | |
336 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { | |
337 GrGLfloat c[4]; | |
338 GrColorToRGBAFloat(local.fColor, c); | |
339 pdman.set4fv(fColorUniform, 1, c); | |
340 fColor = local.fColor; | |
341 } | |
342 } | |
343 | |
344 class GrGLLegacyPathProcessor : public GrGLPathProcessor { | |
345 public: | |
346 GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracke
r& bt, | |
347 int maxTexCoords) | |
348 : INHERITED(pathProc, bt) | |
349 , fTexCoordSetCnt(0) { | |
350 SkDEBUGCODE(fMaxTexCoords = maxTexCoords;) | |
351 } | |
352 | |
353 int addTexCoordSets(int count) { | |
354 int firstFreeCoordSet = fTexCoordSetCnt; | |
355 fTexCoordSetCnt += count; | |
356 SkASSERT(fMaxTexCoords >= fTexCoordSetCnt); | |
357 return firstFreeCoordSet; | |
358 } | |
359 | |
360 void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut*
tout) SK_OVERRIDE { | |
361 tout->push_back_n(tin.count()); | |
362 fInstalledTransforms.push_back_n(tin.count()); | |
363 for (int i = 0; i < tin.count(); i++) { | |
364 const ProcCoords& coordTransforms = tin[i]; | |
365 int texCoordIndex = this->addTexCoordSets(coordTransforms.count()); | |
366 | |
367 // Use the first uniform location as the texcoord index. | |
368 fInstalledTransforms[i].push_back_n(1); | |
369 fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex); | |
370 | |
371 SkString name; | |
372 for (int t = 0; t < coordTransforms.count(); ++t) { | |
373 GrSLType type = coordTransforms[t]->getMatrix().hasPerspective()
? kVec3f_GrSLType : | |
374
kVec2f_GrSLType; | |
375 | |
376 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCo
ordIndex++); | |
377 SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCo
ords, (name, type)); | |
378 } | |
379 } | |
380 } | |
381 | |
382 void setTransformData(const GrPrimitiveProcessor& primProc, | |
383 int index, | |
384 const SkTArray<const GrCoordTransform*, true>& transfo
rms, | |
385 GrGLPathRendering* glpr, | |
386 GrGLuint) SK_OVERRIDE { | |
387 // We've hidden the texcoord index in the first entry of the transforms
array for each | |
388 // effect | |
389 int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle(); | |
390 for (int t = 0; t < transforms.count(); ++t) { | |
391 const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(
), *transforms[t]); | |
392 GrGLPathRendering::PathTexGenComponents components = | |
393 GrGLPathRendering::kST_PathTexGenComponents; | |
394 if (transform.hasPerspective()) { | |
395 components = GrGLPathRendering::kSTR_PathTexGenComponents; | |
396 } | |
397 glpr->enablePathTexGen(texCoordIndex++, components, transform); | |
398 } | |
399 } | |
400 | |
401 void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE { | |
402 glpr->flushPathTexGenSettings(fTexCoordSetCnt); | |
403 } | |
404 | |
405 private: | |
406 SkDEBUGCODE(int fMaxTexCoords;) | |
407 int fTexCoordSetCnt; | |
408 | |
409 typedef GrGLPathProcessor INHERITED; | |
410 }; | |
411 | |
412 class GrGLNormalPathProcessor : public GrGLPathProcessor { | |
413 public: | |
414 GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracke
r& bt) | |
415 : INHERITED(pathProc, bt) {} | |
416 | |
417 void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin, | |
418 TransformsOut* tout) SK_OVERRIDE { | |
419 tout->push_back_n(tin.count()); | |
420 fInstalledTransforms.push_back_n(tin.count()); | |
421 for (int i = 0; i < tin.count(); i++) { | |
422 const ProcCoords& coordTransforms = tin[i]; | |
423 fInstalledTransforms[i].push_back_n(coordTransforms.count()); | |
424 for (int t = 0; t < coordTransforms.count(); t++) { | |
425 GrSLType varyingType = | |
426 coordTransforms[t]->getMatrix().hasPerspective() ? kVec3
f_GrSLType : | |
427 kVec2
f_GrSLType; | |
428 | |
429 | |
430 SkString strVaryingName("MatrixCoord"); | |
431 strVaryingName.appendf("_%i_%i", i, t); | |
432 GrGLVertToFrag v(varyingType); | |
433 pb->addVarying(strVaryingName.c_str(), &v); | |
434 SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_
back(); | |
435 varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.
back(); | |
436 varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1; | |
437 varyingInfo.fType = varyingType; | |
438 fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo
.fLocation); | |
439 fInstalledTransforms[i][t].fType = varyingType; | |
440 | |
441 SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCo
ords, | |
442 (SkString(v.fsIn()), varyingType)); | |
443 } | |
444 } | |
445 } | |
446 | |
447 void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) { | |
448 int count = fSeparableVaryingInfos.count(); | |
449 for (int i = 0; i < count; ++i) { | |
450 GrGLint location; | |
451 GR_GL_CALL_RET(gpu->glInterface(), | |
452 location, | |
453 GetProgramResourceLocation(programId, | |
454 GR_GL_FRAGMENT_INPUT, | |
455 fSeparableVaryingInfos[i].
fVariable.c_str())); | |
456 fSeparableVaryingInfos[i].fLocation = location; | |
457 } | |
458 } | |
459 | |
460 void setTransformData(const GrPrimitiveProcessor& primProc, | |
461 int index, | |
462 const SkTArray<const GrCoordTransform*, true>& coordTr
ansforms, | |
463 GrGLPathRendering* glpr, | |
464 GrGLuint programID) SK_OVERRIDE { | |
465 SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index]; | |
466 int numTransforms = transforms.count(); | |
467 for (int t = 0; t < numTransforms; ++t) { | |
468 SkASSERT(transforms[t].fHandle.isValid()); | |
469 const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(
), | |
470 *coordTransforms[t]); | |
471 if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { | |
472 continue; | |
473 } | |
474 transforms[t].fCurrentValue = transform; | |
475 const SeparableVaryingInfo& fragmentInput = | |
476 fSeparableVaryingInfos[transforms[t].fHandle.handle()]; | |
477 SkASSERT(transforms[t].fType == kVec2f_GrSLType || | |
478 transforms[t].fType == kVec3f_GrSLType); | |
479 unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3
; | |
480 glpr->setProgramPathFragmentInputTransform(programID, | |
481 fragmentInput.fLocation, | |
482 GR_GL_OBJECT_LINEAR, | |
483 components, | |
484 transform); | |
485 } | |
486 } | |
487 | |
488 private: | |
489 struct SeparableVaryingInfo { | |
490 GrSLType fType; | |
491 GrGLShaderVar fVariable; | |
492 GrGLint fLocation; | |
493 }; | |
494 | |
495 | |
496 typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray; | |
497 | |
498 SeparableVaryingInfoArray fSeparableVaryingInfos; | |
499 | |
500 typedef GrGLPathProcessor INHERITED; | |
501 }; | |
502 | |
503 GrPathProcessor::GrPathProcessor(GrColor color, | |
504 const SkMatrix& viewMatrix, | |
505 const SkMatrix& localMatrix) | |
506 : INHERITED(viewMatrix, localMatrix, true) | |
507 , fColor(color) { | |
508 this->initClassID<GrPathProcessor>(); | |
509 } | |
510 | |
511 void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const
{ | |
512 out->setKnownFourComponents(fColor); | |
513 } | |
514 | |
515 void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) con
st { | |
516 out->setKnownSingleComponent(0xff); | |
517 } | |
518 | |
519 void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo&
init) const { | |
520 PathBatchTracker* local = bt->cast<PathBatchTracker>(); | |
521 if (init.fColorIgnored) { | |
522 local->fInputColorType = kIgnored_GrGPInput; | |
523 local->fColor = GrColor_ILLEGAL; | |
524 } else { | |
525 local->fInputColorType = kUniform_GrGPInput; | |
526 local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() : | |
527 init.fOverrideC
olor; | |
528 } | |
529 | |
530 local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAl
lOnes_GrGPInput; | |
531 local->fUsesLocalCoords = init.fUsesLocalCoords; | |
532 } | |
533 | |
534 bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m, | |
535 const GrPrimitiveProcessor& that, | |
536 const GrBatchTracker& t) const { | |
537 if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)
) { | |
538 return false; | |
539 } | |
540 | |
541 if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) { | |
542 return false; | |
543 } | |
544 | |
545 const PathBatchTracker& mine = m.cast<PathBatchTracker>(); | |
546 const PathBatchTracker& theirs = t.cast<PathBatchTracker>(); | |
547 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, | |
548 that, theirs.fUsesLocalCoords) && | |
549 CanCombineOutput(mine.fInputColorType, mine.fColor, | |
550 theirs.fInputColorType, theirs.fColor) && | |
551 CanCombineOutput(mine.fInputCoverageType, 0xff, | |
552 theirs.fInputCoverageType, 0xff); | |
553 } | |
554 | |
555 void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt, | |
556 const GrGLCaps& caps, | |
557 GrProcessorKeyBuilder* b) const { | |
558 GrGLPathProcessor::GenKey(*this, bt, caps, b); | |
559 } | |
560 | |
561 GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker&
bt, | |
562 const GrGLCaps& caps)
const { | |
563 SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport); | |
564 if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) { | |
565 return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt, | |
566 caps.maxFixedFunctionTexture
Coords())); | |
567 } else { | |
568 return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt)); | |
569 } | |
570 } | |
571 | |
OLD | NEW |