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