1 /* 2 * Copyright 2017 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 "GrCCClipProcessor.h" 9 10 #include "GrCCClipPath.h" 11 #include "GrTexture.h" 12 #include "GrTextureProxy.h" 13 #include "SkMakeUnique.h" 14 #include "glsl/GrGLSLFragmentProcessor.h" 15 #include "glsl/GrGLSLFragmentShaderBuilder.h" 16 17 GrCCClipProcessor::GrCCClipProcessor(const GrCCClipPath* clipPath, MustCheckBounds mustCheckBounds, 18 SkPath::FillType overrideFillType) 19 : INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) 20 , fClipPath(clipPath) 21 , fMustCheckBounds((bool)mustCheckBounds) 22 , fOverrideFillType(overrideFillType) 23 , fAtlasAccess(sk_ref_sp(fClipPath->atlasLazyProxy()), GrSamplerState::Filter::kNearest, 24 GrSamplerState::WrapMode::kClamp) { 25 SkASSERT(fAtlasAccess.proxy()); 26 this->setTextureSamplerCnt(1); 27 } 28 29 std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const { 30 return skstd::make_unique<GrCCClipProcessor>(fClipPath, MustCheckBounds(fMustCheckBounds), 31 fOverrideFillType); 32 } 33 34 void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { 35 b->add32((fOverrideFillType << 1) | (int)fMustCheckBounds); 36 } 37 38 bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const { 39 const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>(); 40 // Each ClipPath path has a unique atlas proxy, so hasSameSamplersAndAccesses should have 41 // already weeded out FPs with different ClipPaths. 42 SkASSERT(that.fClipPath->deviceSpacePath().getGenerationID() == 43 fClipPath->deviceSpacePath().getGenerationID()); 44 return that.fOverrideFillType == fOverrideFillType; 45 } 46 47 class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor { 48 public: 49 void emitCode(EmitArgs& args) override { 50 const GrCCClipProcessor& proc = args.fFp.cast<GrCCClipProcessor>(); 51 GrGLSLUniformHandler* uniHandler = args.fUniformHandler; 52 GrGLSLFPFragmentBuilder* f = args.fFragBuilder; 53 54 f->codeAppend ("half coverage;"); 55 if (proc.fMustCheckBounds) { 56 const char* pathIBounds; 57 fPathIBoundsUniform = uniHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, 58 "path_ibounds", &pathIBounds); 59 f->codeAppendf("if (all(greaterThan(float4(sk_FragCoord.xy, %s.zw), " 60 "float4(%s.xy, sk_FragCoord.xy)))) {", 61 pathIBounds, pathIBounds); 62 } 63 64 const char* atlasTransform; 65 fAtlasTransformUniform = uniHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, 66 "atlas_transform", &atlasTransform); 67 f->codeAppendf("float2 texcoord = sk_FragCoord.xy * %s.xy + %s.zw;", 68 atlasTransform, atlasTransform); 69 70 f->codeAppend ("half coverage_count = "); 71 f->appendTextureLookup(args.fTexSamplers[0], "texcoord", kHalf2_GrSLType); 72 f->codeAppend (".a;"); 73 74 if (SkPath::kEvenOdd_FillType == proc.fOverrideFillType || 75 SkPath::kInverseEvenOdd_FillType == proc.fOverrideFillType) { 76 f->codeAppend ("half t = mod(abs(coverage_count), 2);"); 77 f->codeAppend ("coverage = 1 - abs(t - 1);"); 78 } else { 79 f->codeAppend ("coverage = min(abs(coverage_count), 1);"); 80 } 81 82 if (proc.fMustCheckBounds) { 83 f->codeAppend ("} else {"); 84 f->codeAppend ( "coverage = 0;"); 85 f->codeAppend ("}"); 86 } 87 88 if (SkPath::IsInverseFillType(proc.fOverrideFillType)) { 89 f->codeAppend ("coverage = 1 - coverage;"); 90 } 91 92 f->codeAppendf("%s = %s * coverage;", args.fOutputColor, args.fInputColor); 93 } 94 95 void onSetData(const GrGLSLProgramDataManager& pdman, 96 const GrFragmentProcessor& fp) override { 97 const GrCCClipProcessor& proc = fp.cast<GrCCClipProcessor>(); 98 if (proc.fMustCheckBounds) { 99 const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds()); 100 pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(), 101 pathIBounds.right(), pathIBounds.bottom()); 102 } 103 const SkVector& scale = proc.fClipPath->atlasScale(); 104 const SkVector& trans = proc.fClipPath->atlasTranslate(); 105 pdman.set4f(fAtlasTransformUniform, scale.x(), scale.y(), trans.x(), trans.y()); 106 } 107 108 private: 109 UniformHandle fPathIBoundsUniform; 110 UniformHandle fAtlasTransformUniform; 111 }; 112 113 GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const { 114 return new Impl(); 115 } 116