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