Home | History | Annotate | Download | only in gpu
      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