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
16class GrGLPathProcessor : public GrGLSLPrimitiveProcessor {
17public:
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        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                                                         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
99private:
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
115GrPathProcessor::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
123void GrPathProcessor::getGLSLProcessorKey(const GrShaderCaps& caps,
124                                          GrProcessorKeyBuilder* b) const {
125    GrGLPathProcessor::GenKey(*this, caps, b);
126}
127
128GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrShaderCaps& caps) const {
129    SkASSERT(caps.pathRenderingSupport());
130    return new GrGLPathProcessor();
131}
132