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 #include "GrPathProcessor.h"
9
10 #include "gl/GrGLGpu.h"
11 #include "glsl/GrGLSLCaps.h"
12 #include "glsl/GrGLSLFragmentShaderBuilder.h"
13 #include "glsl/GrGLSLProcessorTypes.h"
14 #include "glsl/GrGLSLUniformHandler.h"
15 #include "glsl/GrGLSLVarying.h"
16
17 class GrGLPathProcessor : public GrGLSLPrimitiveProcessor {
18 public:
GrGLPathProcessor()19 GrGLPathProcessor() : fColor(GrColor_ILLEGAL) {}
20
GenKey(const GrPathProcessor & pathProc,const GrGLSLCaps &,GrProcessorKeyBuilder * b)21 static void GenKey(const GrPathProcessor& pathProc,
22 const GrGLSLCaps&,
23 GrProcessorKeyBuilder* b) {
24 b->add32(SkToInt(pathProc.overrides().readsColor()) |
25 (SkToInt(pathProc.overrides().readsCoverage()) << 1) |
26 (SkToInt(pathProc.viewMatrix().hasPerspective()) << 2));
27 }
28
emitCode(EmitArgs & args)29 void emitCode(EmitArgs& args) override {
30 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
31 const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>();
32
33 if (!pathProc.viewMatrix().hasPerspective()) {
34 args.fVaryingHandler->setNoPerspective();
35 }
36
37 // emit transforms
38 this->emitTransforms(args.fVaryingHandler, args.fTransformsIn, args.fTransformsOut);
39
40 // Setup uniform color
41 if (pathProc.overrides().readsColor()) {
42 const char* stagedLocalVarName;
43 fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
44 kVec4f_GrSLType,
45 kDefault_GrSLPrecision,
46 "Color",
47 &stagedLocalVarName);
48 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
49 }
50
51 // setup constant solid coverage
52 if (pathProc.overrides().readsCoverage()) {
53 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
54 }
55 }
56
emitTransforms(GrGLSLVaryingHandler * varyingHandler,const TransformsIn & tin,TransformsOut * tout)57 void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
58 const TransformsIn& tin,
59 TransformsOut* tout) {
60 tout->push_back_n(tin.count());
61 fInstalledTransforms.push_back_n(tin.count());
62 for (int i = 0; i < tin.count(); i++) {
63 const ProcCoords& coordTransforms = tin[i];
64 fInstalledTransforms[i].push_back_n(coordTransforms.count());
65 for (int t = 0; t < coordTransforms.count(); t++) {
66 GrSLType varyingType =
67 coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
68 kVec2f_GrSLType;
69
70 SkString strVaryingName("MatrixCoord");
71 strVaryingName.appendf("_%i_%i", i, t);
72 GrGLSLVertToFrag v(varyingType);
73 GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*) varyingHandler;
74 fInstalledTransforms[i][t].fHandle =
75 glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(),
76 &v).toIndex();
77 fInstalledTransforms[i][t].fType = varyingType;
78
79 (*tout)[i].emplace_back(SkString(v.fsIn()), varyingType);
80 }
81 }
82 }
83
setData(const GrGLSLProgramDataManager & pd,const GrPrimitiveProcessor & primProc)84 void setData(const GrGLSLProgramDataManager& pd,
85 const GrPrimitiveProcessor& primProc) override {
86 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
87 if (pathProc.overrides().readsColor() && pathProc.color() != fColor) {
88 float c[4];
89 GrColorToRGBAFloat(pathProc.color(), c);
90 pd.set4fv(fColorUniform, 1, c);
91 fColor = pathProc.color();
92 }
93 }
94
setTransformData(const GrPrimitiveProcessor & primProc,const GrGLSLProgramDataManager & pdman,int index,const SkTArray<const GrCoordTransform *,true> & coordTransforms)95 void setTransformData(const GrPrimitiveProcessor& primProc,
96 const GrGLSLProgramDataManager& pdman,
97 int index,
98 const SkTArray<const GrCoordTransform*, true>& coordTransforms) override {
99 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
100 SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
101 int numTransforms = transforms.count();
102 for (int t = 0; t < numTransforms; ++t) {
103 SkASSERT(transforms[t].fHandle.isValid());
104 const SkMatrix& transform = GetTransformMatrix(pathProc.localMatrix(),
105 *coordTransforms[t]);
106 if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
107 continue;
108 }
109 transforms[t].fCurrentValue = transform;
110
111 SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
112 transforms[t].fType == kVec3f_GrSLType);
113 unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
114 pdman.setPathFragmentInputTransform(transforms[t].fHandle, components, transform);
115 }
116 }
117
118 private:
119 UniformHandle fColorUniform;
120 GrColor fColor;
121
122 typedef GrGLSLPrimitiveProcessor INHERITED;
123 };
124
GrPathProcessor(GrColor color,const GrXPOverridesForBatch & overrides,const SkMatrix & viewMatrix,const SkMatrix & localMatrix)125 GrPathProcessor::GrPathProcessor(GrColor color,
126 const GrXPOverridesForBatch& overrides,
127 const SkMatrix& viewMatrix,
128 const SkMatrix& localMatrix)
129 : fColor(color)
130 , fViewMatrix(viewMatrix)
131 , fLocalMatrix(localMatrix)
132 , fOverrides(overrides) {
133 this->initClassID<GrPathProcessor>();
134 }
135
getGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const136 void GrPathProcessor::getGLSLProcessorKey(const GrGLSLCaps& caps,
137 GrProcessorKeyBuilder* b) const {
138 GrGLPathProcessor::GenKey(*this, caps, b);
139 }
140
createGLSLInstance(const GrGLSLCaps & caps) const141 GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrGLSLCaps& caps) const {
142 SkASSERT(caps.pathRenderingSupport());
143 return new GrGLPathProcessor();
144 }
145