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