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 "GrGLPathProcessor.h"
9
10#include "GrPathProcessor.h"
11#include "GrGLGpu.h"
12#include "GrGLPathRendering.h"
13
14GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
15    : fColor(GrColor_ILLEGAL) {}
16
17void GrGLPathProcessor::emitCode(EmitArgs& args) {
18    GrGLGPBuilder* pb = args.fPB;
19    GrGLFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
20    const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
21
22    // emit transforms
23    this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
24
25    // Setup uniform color
26    if (kUniform_GrGPInput == local.fInputColorType) {
27        const char* stagedLocalVarName;
28        fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
29                                       kVec4f_GrSLType,
30                                       kDefault_GrSLPrecision,
31                                       "Color",
32                                       &stagedLocalVarName);
33        fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
34    }
35
36    // setup constant solid coverage
37    if (kAllOnes_GrGPInput == local.fInputCoverageType) {
38        fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
39    }
40}
41
42void GrGLPathProcessor::GenKey(const GrPathProcessor&,
43                               const GrBatchTracker& bt,
44                               const GrGLSLCaps&,
45                               GrProcessorKeyBuilder* b) {
46    const PathBatchTracker& local = bt.cast<PathBatchTracker>();
47    b->add32(local.fInputColorType | local.fInputCoverageType << 16);
48}
49
50void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
51                                const GrPrimitiveProcessor& primProc,
52                                const GrBatchTracker& bt) {
53    const PathBatchTracker& local = bt.cast<PathBatchTracker>();
54    if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
55        GrGLfloat c[4];
56        GrColorToRGBAFloat(local.fColor, c);
57        pdman.set4fv(fColorUniform, 1, c);
58        fColor = local.fColor;
59    }
60}
61
62void GrGLPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
63                                       TransformsOut* tout) {
64    tout->push_back_n(tin.count());
65    fInstalledTransforms.push_back_n(tin.count());
66    for (int i = 0; i < tin.count(); i++) {
67        const ProcCoords& coordTransforms = tin[i];
68        fInstalledTransforms[i].push_back_n(coordTransforms.count());
69        for (int t = 0; t < coordTransforms.count(); t++) {
70            GrSLType varyingType =
71                    coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
72                                                                       kVec2f_GrSLType;
73
74
75            SkString strVaryingName("MatrixCoord");
76            strVaryingName.appendf("_%i_%i", i, t);
77            GrGLVertToFrag v(varyingType);
78            pb->addVarying(strVaryingName.c_str(), &v);
79            SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
80            varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
81            varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
82            varyingInfo.fType = varyingType;
83            fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
84            fInstalledTransforms[i][t].fType = varyingType;
85
86            SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
87                                   (SkString(v.fsIn()), varyingType));
88        }
89    }
90}
91
92void GrGLPathProcessor::resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
93    int count = fSeparableVaryingInfos.count();
94    for (int i = 0; i < count; ++i) {
95        GrGLint location;
96        GR_GL_CALL_RET(gpu->glInterface(),
97                       location,
98                       GetProgramResourceLocation(programId,
99                                                  GR_GL_FRAGMENT_INPUT,
100                                                  fSeparableVaryingInfos[i].fVariable.c_str()));
101        fSeparableVaryingInfos[i].fLocation = location;
102    }
103}
104
105void GrGLPathProcessor::setTransformData(
106        const GrPrimitiveProcessor& primProc,
107        int index,
108        const SkTArray<const GrCoordTransform*, true>& coordTransforms,
109        GrGLPathRendering* glpr,
110        GrGLuint programID) {
111    const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
112    SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
113    int numTransforms = transforms.count();
114    for (int t = 0; t < numTransforms; ++t) {
115        SkASSERT(transforms[t].fHandle.isValid());
116        const SkMatrix& transform = GetTransformMatrix(pathProc.localMatrix(),
117                                                       *coordTransforms[t]);
118        if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
119            continue;
120        }
121        transforms[t].fCurrentValue = transform;
122        const SeparableVaryingInfo& fragmentInput =
123                fSeparableVaryingInfos[transforms[t].fHandle.handle()];
124        SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
125                 transforms[t].fType == kVec3f_GrSLType);
126        unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
127        glpr->setProgramPathFragmentInputTransform(programID,
128                                                   fragmentInput.fLocation,
129                                                   GR_GL_OBJECT_LINEAR,
130                                                   components,
131                                                   transform);
132    }
133}
134