blob: 111f27c99cdafd56641d1354dfff77db1d59d1cd [file] [log] [blame]
Chris Daltona32a3c32017-12-05 10:05:21 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/ccpr/GrCCClipProcessor.h"
Chris Daltona32a3c32017-12-05 10:05:21 -07009
Ben Wagner729a23f2019-05-17 16:29:34 -040010#include "src/gpu/ccpr/GrCCClipPath.h"
Brian Salomon5cd393b2020-06-12 11:31:37 -040011#include "src/gpu/effects/GrTextureEffect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
13#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
Chris Daltona32a3c32017-12-05 10:05:21 -070014
Greg Daniele810d832020-02-07 17:20:56 -050015static GrSurfaceProxyView make_view(const GrCaps& caps, GrSurfaceProxy* proxy,
16 bool isCoverageCount) {
17 GrColorType ct = isCoverageCount ? GrColorType::kAlpha_F16 : GrColorType::kAlpha_8;
18 GrSwizzle swizzle = caps.getReadSwizzle(proxy->backendFormat(), ct);
19 return { sk_ref_sp(proxy), GrCCAtlas::kTextureOrigin, swizzle };
20}
21
Brian Salomon5cd393b2020-06-12 11:31:37 -040022GrCCClipProcessor::GrCCClipProcessor(const GrCaps& caps,
23 const GrCCClipPath* clipPath,
Greg Daniele810d832020-02-07 17:20:56 -050024 IsCoverageCount isCoverageCount,
Chris Daltonc3318f02019-07-19 14:20:53 -060025 MustCheckBounds mustCheckBounds)
Chris Dalton383a2ef2018-01-08 17:21:41 -050026 : INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Chris Daltona32a3c32017-12-05 10:05:21 -070027 , fClipPath(clipPath)
Chris Daltonc3318f02019-07-19 14:20:53 -060028 , fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount)
Brian Salomon5cd393b2020-06-12 11:31:37 -040029 , fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) {
30 auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
31 auto te = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
32 te->setSampledWithExplicitCoords();
33 this->registerChildProcessor(std::move(te));
Chris Daltona32a3c32017-12-05 10:05:21 -070034}
35
Brian Salomon5cd393b2020-06-12 11:31:37 -040036GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
37 : INHERITED(kGrCCClipProcessor_ClassID, that.optimizationFlags())
38 , fClipPath(that.fClipPath)
39 , fIsCoverageCount(that.fIsCoverageCount)
40 , fMustCheckBounds(that.fMustCheckBounds) {
41 auto child = that.childProcessor(0).clone();
42 child->setSampledWithExplicitCoords();
43 this->registerChildProcessor(std::move(child));
Greg Daniele810d832020-02-07 17:20:56 -050044}
45
Chris Dalton383a2ef2018-01-08 17:21:41 -050046std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
Brian Salomon5cd393b2020-06-12 11:31:37 -040047 return std::unique_ptr<GrFragmentProcessor>(new GrCCClipProcessor(*this));
Chris Daltona32a3c32017-12-05 10:05:21 -070048}
49
Chris Dalton383a2ef2018-01-08 17:21:41 -050050void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
Chris Daltonc3318f02019-07-19 14:20:53 -060051 const SkPath& clipPath = fClipPath->deviceSpacePath();
52 uint32_t key = (fIsCoverageCount) ? (uint32_t)GrFillRuleForSkPath(clipPath) : 0;
53 key = (key << 1) | ((clipPath.isInverseFillType()) ? 1 : 0);
54 key = (key << 1) | ((fMustCheckBounds) ? 1 : 0);
55 b->add32(key);
Chris Daltona32a3c32017-12-05 10:05:21 -070056}
57
Chris Dalton383a2ef2018-01-08 17:21:41 -050058bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
59 const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>();
Brian Salomon5cd393b2020-06-12 11:31:37 -040060 return that.fClipPath->deviceSpacePath().getGenerationID() ==
61 fClipPath->deviceSpacePath().getGenerationID() &&
62 that.fClipPath->deviceSpacePath().getFillType() ==
Chris Daltonc3318f02019-07-19 14:20:53 -060063 fClipPath->deviceSpacePath().getFillType() &&
64 that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
Chris Daltona32a3c32017-12-05 10:05:21 -070065}
66
Chris Dalton383a2ef2018-01-08 17:21:41 -050067class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
Chris Daltona32a3c32017-12-05 10:05:21 -070068public:
69 void emitCode(EmitArgs& args) override {
Chris Dalton383a2ef2018-01-08 17:21:41 -050070 const GrCCClipProcessor& proc = args.fFp.cast<GrCCClipProcessor>();
Chris Daltona32a3c32017-12-05 10:05:21 -070071 GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
72 GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
73
74 f->codeAppend ("half coverage;");
Chris Daltonc3318f02019-07-19 14:20:53 -060075
Chris Daltona32a3c32017-12-05 10:05:21 -070076 if (proc.fMustCheckBounds) {
77 const char* pathIBounds;
Ethan Nicholas16464c32020-04-06 13:53:05 -040078 fPathIBoundsUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
79 kFloat4_GrSLType, "path_ibounds",
80 &pathIBounds);
Chris Daltona32a3c32017-12-05 10:05:21 -070081 f->codeAppendf("if (all(greaterThan(float4(sk_FragCoord.xy, %s.zw), "
82 "float4(%s.xy, sk_FragCoord.xy)))) {",
83 pathIBounds, pathIBounds);
84 }
85
Brian Salomon5cd393b2020-06-12 11:31:37 -040086 const char* atlasTranslate;
87 fAtlasTranslateUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
88 kFloat2_GrSLType, "atlas_translate",
89 &atlasTranslate);
90 SkString coord;
91 coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate);
92 SkString sample = this->invokeChild(0, args, coord.c_str());
93 f->codeAppendf("coverage = %s.a;", sample.c_str());
Chris Daltona32a3c32017-12-05 10:05:21 -070094
Chris Daltonc3318f02019-07-19 14:20:53 -060095 if (proc.fIsCoverageCount) {
96 auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
97 if (GrFillRule::kEvenOdd == fillRule) {
98 f->codeAppend ("half t = mod(abs(coverage), 2);");
99 f->codeAppend ("coverage = 1 - abs(t - 1);");
100 } else {
101 SkASSERT(GrFillRule::kNonzero == fillRule);
102 f->codeAppend ("coverage = min(abs(coverage), 1);");
103 }
Chris Daltona32a3c32017-12-05 10:05:21 -0700104 }
105
106 if (proc.fMustCheckBounds) {
107 f->codeAppend ("} else {");
108 f->codeAppend ( "coverage = 0;");
109 f->codeAppend ("}");
110 }
111
Chris Daltonc3318f02019-07-19 14:20:53 -0600112 if (proc.fClipPath->deviceSpacePath().isInverseFillType()) {
Chris Daltona32a3c32017-12-05 10:05:21 -0700113 f->codeAppend ("coverage = 1 - coverage;");
114 }
115
116 f->codeAppendf("%s = %s * coverage;", args.fOutputColor, args.fInputColor);
117 }
118
119 void onSetData(const GrGLSLProgramDataManager& pdman,
120 const GrFragmentProcessor& fp) override {
Chris Dalton383a2ef2018-01-08 17:21:41 -0500121 const GrCCClipProcessor& proc = fp.cast<GrCCClipProcessor>();
Chris Daltona32a3c32017-12-05 10:05:21 -0700122 if (proc.fMustCheckBounds) {
123 const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds());
124 pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(),
125 pathIBounds.right(), pathIBounds.bottom());
126 }
Brian Salomon5cd393b2020-06-12 11:31:37 -0400127 const SkIVector& trans = proc.fClipPath->atlasTranslate();
128 pdman.set2f(fAtlasTranslateUniform, trans.x(), trans.y());
Chris Daltona32a3c32017-12-05 10:05:21 -0700129 }
130
131private:
132 UniformHandle fPathIBoundsUniform;
Brian Salomon5cd393b2020-06-12 11:31:37 -0400133 UniformHandle fAtlasTranslateUniform;
Chris Daltona32a3c32017-12-05 10:05:21 -0700134};
135
Chris Dalton383a2ef2018-01-08 17:21:41 -0500136GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const {
Chris Daltona32a3c32017-12-05 10:05:21 -0700137 return new Impl();
138}