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