blob: 718985ac5fb99d84e655bf51b50d8ebb11c6a9e3 [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
John Stiles956ec8a2020-06-19 15:32:16 -040022GrCCClipProcessor::GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
23 const GrCaps& caps,
Brian Salomon5cd393b2020-06-12 11:31:37 -040024 const GrCCClipPath* clipPath,
Greg Daniele810d832020-02-07 17:20:56 -050025 IsCoverageCount isCoverageCount,
Chris Daltonc3318f02019-07-19 14:20:53 -060026 MustCheckBounds mustCheckBounds)
Chris Dalton383a2ef2018-01-08 17:21:41 -050027 : INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Chris Daltona32a3c32017-12-05 10:05:21 -070028 , fClipPath(clipPath)
Chris Daltonc3318f02019-07-19 14:20:53 -060029 , fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount)
Brian Salomon5cd393b2020-06-12 11:31:37 -040030 , fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) {
31 auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
John Stiles956ec8a2020-06-19 15:32:16 -040032 auto texEffect = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
Michael Ludwig9aba6252020-06-22 14:46:36 -040033 this->registerExplicitlySampledChild(std::move(texEffect));
John Stiles956ec8a2020-06-19 15:32:16 -040034
35 if (inputFP != nullptr) {
Michael Ludwig9aba6252020-06-22 14:46:36 -040036 this->registerChild(std::move(inputFP));
John Stiles956ec8a2020-06-19 15:32:16 -040037 }
Chris Daltona32a3c32017-12-05 10:05:21 -070038}
39
Brian Salomon5cd393b2020-06-12 11:31:37 -040040GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
41 : INHERITED(kGrCCClipProcessor_ClassID, that.optimizationFlags())
42 , fClipPath(that.fClipPath)
43 , fIsCoverageCount(that.fIsCoverageCount)
44 , fMustCheckBounds(that.fMustCheckBounds) {
John Stiles956ec8a2020-06-19 15:32:16 -040045 this->cloneAndRegisterAllChildProcessors(that);
Greg Daniele810d832020-02-07 17:20:56 -050046}
47
Chris Dalton383a2ef2018-01-08 17:21:41 -050048std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
Brian Salomon5cd393b2020-06-12 11:31:37 -040049 return std::unique_ptr<GrFragmentProcessor>(new GrCCClipProcessor(*this));
Chris Daltona32a3c32017-12-05 10:05:21 -070050}
51
Chris Dalton383a2ef2018-01-08 17:21:41 -050052void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
Chris Daltonc3318f02019-07-19 14:20:53 -060053 const SkPath& clipPath = fClipPath->deviceSpacePath();
54 uint32_t key = (fIsCoverageCount) ? (uint32_t)GrFillRuleForSkPath(clipPath) : 0;
55 key = (key << 1) | ((clipPath.isInverseFillType()) ? 1 : 0);
56 key = (key << 1) | ((fMustCheckBounds) ? 1 : 0);
57 b->add32(key);
Chris Daltona32a3c32017-12-05 10:05:21 -070058}
59
Chris Dalton383a2ef2018-01-08 17:21:41 -050060bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
61 const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>();
Brian Salomon5cd393b2020-06-12 11:31:37 -040062 return that.fClipPath->deviceSpacePath().getGenerationID() ==
63 fClipPath->deviceSpacePath().getGenerationID() &&
64 that.fClipPath->deviceSpacePath().getFillType() ==
Chris Daltonc3318f02019-07-19 14:20:53 -060065 fClipPath->deviceSpacePath().getFillType() &&
66 that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
Chris Daltona32a3c32017-12-05 10:05:21 -070067}
68
John Stiles956ec8a2020-06-19 15:32:16 -040069bool GrCCClipProcessor::hasInputFP() const {
70 // We always have a `texEffect`, and this accounts for one child.
71 // The second child will be the input FP, if we have one.
72 return this->numChildProcessors() > 1;
73}
74
Chris Dalton383a2ef2018-01-08 17:21:41 -050075class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
Chris Daltona32a3c32017-12-05 10:05:21 -070076public:
77 void emitCode(EmitArgs& args) override {
Chris Dalton383a2ef2018-01-08 17:21:41 -050078 const GrCCClipProcessor& proc = args.fFp.cast<GrCCClipProcessor>();
Chris Daltona32a3c32017-12-05 10:05:21 -070079 GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
80 GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
81
John Stiles956ec8a2020-06-19 15:32:16 -040082 f->codeAppend("half coverage;");
Chris Daltonc3318f02019-07-19 14:20:53 -060083
Chris Daltona32a3c32017-12-05 10:05:21 -070084 if (proc.fMustCheckBounds) {
85 const char* pathIBounds;
Ethan Nicholas16464c32020-04-06 13:53:05 -040086 fPathIBoundsUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
87 kFloat4_GrSLType, "path_ibounds",
88 &pathIBounds);
Chris Daltona32a3c32017-12-05 10:05:21 -070089 f->codeAppendf("if (all(greaterThan(float4(sk_FragCoord.xy, %s.zw), "
90 "float4(%s.xy, sk_FragCoord.xy)))) {",
91 pathIBounds, pathIBounds);
92 }
93
Brian Salomon5cd393b2020-06-12 11:31:37 -040094 const char* atlasTranslate;
95 fAtlasTranslateUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
96 kFloat2_GrSLType, "atlas_translate",
97 &atlasTranslate);
98 SkString coord;
99 coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate);
John Stiles956ec8a2020-06-19 15:32:16 -0400100 constexpr int kTexEffectFPIndex = 0;
101 SkString sample = this->invokeChild(kTexEffectFPIndex, args, coord.c_str());
Brian Salomon5cd393b2020-06-12 11:31:37 -0400102 f->codeAppendf("coverage = %s.a;", sample.c_str());
Chris Daltona32a3c32017-12-05 10:05:21 -0700103
Chris Daltonc3318f02019-07-19 14:20:53 -0600104 if (proc.fIsCoverageCount) {
105 auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
106 if (GrFillRule::kEvenOdd == fillRule) {
John Stiles956ec8a2020-06-19 15:32:16 -0400107 f->codeAppend("half t = mod(abs(coverage), 2);");
108 f->codeAppend("coverage = 1 - abs(t - 1);");
Chris Daltonc3318f02019-07-19 14:20:53 -0600109 } else {
110 SkASSERT(GrFillRule::kNonzero == fillRule);
John Stiles956ec8a2020-06-19 15:32:16 -0400111 f->codeAppend("coverage = min(abs(coverage), 1);");
Chris Daltonc3318f02019-07-19 14:20:53 -0600112 }
Chris Daltona32a3c32017-12-05 10:05:21 -0700113 }
114
115 if (proc.fMustCheckBounds) {
John Stiles956ec8a2020-06-19 15:32:16 -0400116 f->codeAppend("} else {");
117 f->codeAppend( "coverage = 0;");
118 f->codeAppend("}");
Chris Daltona32a3c32017-12-05 10:05:21 -0700119 }
120
Chris Daltonc3318f02019-07-19 14:20:53 -0600121 if (proc.fClipPath->deviceSpacePath().isInverseFillType()) {
John Stiles956ec8a2020-06-19 15:32:16 -0400122 f->codeAppend("coverage = 1 - coverage;");
Chris Daltona32a3c32017-12-05 10:05:21 -0700123 }
124
John Stiles956ec8a2020-06-19 15:32:16 -0400125 constexpr int kInputFPIndex = 1;
126 SkString inputColor = proc.hasInputFP()
127 ? this->invokeChild(kInputFPIndex, args.fInputColor, args)
128 : SkString(args.fInputColor);
129
130 f->codeAppendf("%s = %s * coverage;", args.fOutputColor, inputColor.c_str());
Chris Daltona32a3c32017-12-05 10:05:21 -0700131 }
132
133 void onSetData(const GrGLSLProgramDataManager& pdman,
134 const GrFragmentProcessor& fp) override {
Chris Dalton383a2ef2018-01-08 17:21:41 -0500135 const GrCCClipProcessor& proc = fp.cast<GrCCClipProcessor>();
Chris Daltona32a3c32017-12-05 10:05:21 -0700136 if (proc.fMustCheckBounds) {
137 const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds());
138 pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(),
139 pathIBounds.right(), pathIBounds.bottom());
140 }
Brian Salomon5cd393b2020-06-12 11:31:37 -0400141 const SkIVector& trans = proc.fClipPath->atlasTranslate();
142 pdman.set2f(fAtlasTranslateUniform, trans.x(), trans.y());
Chris Daltona32a3c32017-12-05 10:05:21 -0700143 }
144
145private:
146 UniformHandle fPathIBoundsUniform;
Brian Salomon5cd393b2020-06-12 11:31:37 -0400147 UniformHandle fAtlasTranslateUniform;
Chris Daltona32a3c32017-12-05 10:05:21 -0700148};
149
Chris Dalton383a2ef2018-01-08 17:21:41 -0500150GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const {
Chris Daltona32a3c32017-12-05 10:05:21 -0700151 return new Impl();
152}