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 "SkTo.h"
12 #include "gl/GrGLGpu.h"
13 #include "gl/GrGLVaryingHandler.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "glsl/GrGLSLPrimitiveProcessor.h"
16 #include "glsl/GrGLSLUniformHandler.h"
17 #include "glsl/GrGLSLVarying.h"
18 
19 class GrGLPathProcessor : public GrGLSLPrimitiveProcessor {
20 public:
21     GrGLPathProcessor() : fColor(SK_PMColor4fILLEGAL) {}
22 
23     static void GenKey(const GrPathProcessor& pathProc,
24                        const GrShaderCaps&,
25                        GrProcessorKeyBuilder* b) {
26         b->add32(SkToInt(pathProc.viewMatrix().hasPerspective()));
27     }
28 
29     void emitCode(EmitArgs& args) override {
30         GrGLSLFPFragmentBuilder* 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.fFPCoordTransformHandler);
39 
40         // Setup uniform color
41         const char* stagedLocalVarName;
42         fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
43                                                          kHalf4_GrSLType,
44                                                          "Color",
45                                                          &stagedLocalVarName);
46         fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
47 
48         // setup constant solid coverage
49         fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
50     }
51 
52     void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
53                         FPCoordTransformHandler* transformHandler) {
54         int i = 0;
55         while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) {
56             GrSLType varyingType =
57                     coordTransform->getMatrix().hasPerspective() ? kHalf3_GrSLType
58                                                                  : kHalf2_GrSLType;
59 
60             SkString strVaryingName;
61             strVaryingName.printf("TransformedCoord_%d", i);
62             GrGLSLVarying v(varyingType);
63             GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*) varyingHandler;
64             fInstalledTransforms.push_back().fHandle =
65                     glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(),
66                                                                &v).toIndex();
67             fInstalledTransforms.back().fType = varyingType;
68 
69             transformHandler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
70             ++i;
71         }
72     }
73 
74     void setData(const GrGLSLProgramDataManager& pd,
75                  const GrPrimitiveProcessor& primProc,
76                  FPCoordTransformIter&& transformIter) override {
77         const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
78         if (pathProc.color() != fColor) {
79             pd.set4fv(fColorUniform, 1, pathProc.color().vec());
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 == kHalf2_GrSLType ||
93                      fInstalledTransforms[t].fType == kHalf3_GrSLType);
94             unsigned components = fInstalledTransforms[t].fType == kHalf2_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     SkPMColor4f fColor;
112 
113     typedef GrGLSLPrimitiveProcessor INHERITED;
114 };
115 
116 GrPathProcessor::GrPathProcessor(const SkPMColor4f& color,
117                                  const SkMatrix& viewMatrix,
118                                  const SkMatrix& localMatrix)
119         : INHERITED(kGrPathProcessor_ClassID)
120         , fColor(color)
121         , fViewMatrix(viewMatrix)
122         , fLocalMatrix(localMatrix) {}
123 
124 void GrPathProcessor::getGLSLProcessorKey(const GrShaderCaps& caps,
125                                           GrProcessorKeyBuilder* b) const {
126     GrGLPathProcessor::GenKey(*this, caps, b);
127 }
128 
129 GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrShaderCaps& caps) const {
130     SkASSERT(caps.pathRenderingSupport());
131     return new GrGLPathProcessor();
132 }
133