|  | /* | 
|  | * Copyright 2013 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "src/gpu/GrPathProcessor.h" | 
|  |  | 
|  | #include "include/private/SkTo.h" | 
|  | #include "src/core/SkMatrixPriv.h" | 
|  | #include "src/gpu/GrShaderCaps.h" | 
|  | #include "src/gpu/gl/GrGLGpu.h" | 
|  | #ifdef SK_GL | 
|  | #include "src/gpu/gl/GrGLVaryingHandler.h" | 
|  | #endif | 
|  | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" | 
|  | #include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h" | 
|  | #include "src/gpu/glsl/GrGLSLUniformHandler.h" | 
|  | #include "src/gpu/glsl/GrGLSLVarying.h" | 
|  |  | 
|  | class GrGLPathProcessor : public GrGLSLPrimitiveProcessor { | 
|  | public: | 
|  | GrGLPathProcessor() : fColor(SK_PMColor4fILLEGAL) {} | 
|  |  | 
|  | static void GenKey(const GrPathProcessor& pathProc, | 
|  | const GrShaderCaps&, | 
|  | GrProcessorKeyBuilder* b) { | 
|  | b->add32(SkToInt(pathProc.viewMatrix().hasPerspective())); | 
|  | } | 
|  |  | 
|  | void emitCode(EmitArgs& args) override { | 
|  | GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | 
|  | const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>(); | 
|  |  | 
|  | if (!pathProc.viewMatrix().hasPerspective()) { | 
|  | args.fVaryingHandler->setNoPerspective(); | 
|  | } | 
|  |  | 
|  | // emit transforms | 
|  | this->emitTransforms(args.fVaryingHandler, args.fUniformHandler, | 
|  | args.fFPCoordTransformHandler); | 
|  |  | 
|  | // Setup uniform color | 
|  | const char* stagedLocalVarName; | 
|  | fColorUniform = args.fUniformHandler->addUniform(nullptr, | 
|  | kFragment_GrShaderFlag, | 
|  | kHalf4_GrSLType, | 
|  | "Color", | 
|  | &stagedLocalVarName); | 
|  | fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName); | 
|  |  | 
|  | // setup constant solid coverage | 
|  | fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage); | 
|  | } | 
|  |  | 
|  | void emitTransforms(GrGLSLVaryingHandler* varyingHandler, | 
|  | GrGLSLUniformHandler* uniformHandler, | 
|  | FPCoordTransformHandler* transformHandler) { | 
|  | for (int i = 0; *transformHandler; ++*transformHandler, ++i) { | 
|  | SkString strVaryingName; | 
|  | strVaryingName.printf("TransformedCoord_%d", i); | 
|  | GrGLSLVarying v(kFloat2_GrSLType); | 
|  | #ifdef SK_GL | 
|  | GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*)varyingHandler; | 
|  | fVaryingTransform.push_back().fHandle = | 
|  | glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(), &v) | 
|  | .toIndex(); | 
|  | #endif | 
|  | GrShaderVar fragmentVar = {SkString(v.fsIn()), kFloat2_GrSLType}; | 
|  | transformHandler->specifyCoordsForCurrCoordTransform(fragmentVar); | 
|  | } | 
|  | } | 
|  |  | 
|  | void setData(const GrGLSLProgramDataManager& pd, | 
|  | const GrPrimitiveProcessor& primProc) override { | 
|  | const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>(); | 
|  | if (pathProc.color() != fColor) { | 
|  | pd.set4fv(fColorUniform, 1, pathProc.color().vec()); | 
|  | fColor = pathProc.color(); | 
|  | } | 
|  |  | 
|  | for (int v = 0; v < fVaryingTransform.count(); ++v) { | 
|  | if (fVaryingTransform[v].fHandle.isValid()) { | 
|  | SkMatrix m = pathProc.localMatrix(); | 
|  | if (!SkMatrixPriv::CheapEqual(fVaryingTransform[v].fCurrentValue, m)) { | 
|  | fVaryingTransform[v].fCurrentValue = m; | 
|  | pd.setPathFragmentInputTransform(fVaryingTransform[v].fHandle, 2, m); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | using VaryingHandle = GrGLSLProgramDataManager::VaryingHandle; | 
|  |  | 
|  | // Varying transforms are used for non-explicitly sampled FPs. We provide a matrix | 
|  | // to GL as fixed function state and it uses it to compute a varying that we pick up | 
|  | // in the FS as the transformed local coords. | 
|  | struct TransformVarying { | 
|  | VaryingHandle fHandle; | 
|  | SkMatrix      fCurrentValue = SkMatrix::InvalidMatrix(); | 
|  | }; | 
|  |  | 
|  | SkTArray<TransformVarying, true> fVaryingTransform; | 
|  |  | 
|  | UniformHandle fColorUniform; | 
|  | SkPMColor4f fColor; | 
|  |  | 
|  | using INHERITED = GrGLSLPrimitiveProcessor; | 
|  | }; | 
|  |  | 
|  | GrPathProcessor::GrPathProcessor(const SkPMColor4f& color, | 
|  | const SkMatrix& viewMatrix, | 
|  | const SkMatrix& localMatrix) | 
|  | : INHERITED(kGrPathProcessor_ClassID) | 
|  | , fColor(color) | 
|  | , fViewMatrix(viewMatrix) | 
|  | , fLocalMatrix(localMatrix) {} | 
|  |  | 
|  | void GrPathProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, | 
|  | GrProcessorKeyBuilder* b) const { | 
|  | GrGLPathProcessor::GenKey(*this, caps, b); | 
|  | } | 
|  |  | 
|  | GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrShaderCaps& caps) const { | 
|  | SkASSERT(caps.pathRenderingSupport()); | 
|  | return new GrGLPathProcessor(); | 
|  | } |