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