blob: 6e5270674338007d628ad9ebc360be67bed9a2a2 [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);
33 texEffect->setSampledWithExplicitCoords();
34 this->registerChildProcessor(std::move(texEffect));
35
36 if (inputFP != nullptr) {
37 this->registerChildProcessor(std::move(inputFP));
38 }
Chris Daltona32a3c32017-12-05 10:05:21 -070039}
40
Brian Salomon5cd393b2020-06-12 11:31:37 -040041GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
42 : INHERITED(kGrCCClipProcessor_ClassID, that.optimizationFlags())
43 , fClipPath(that.fClipPath)
44 , fIsCoverageCount(that.fIsCoverageCount)
45 , fMustCheckBounds(that.fMustCheckBounds) {
John Stiles956ec8a2020-06-19 15:32:16 -040046 this->cloneAndRegisterAllChildProcessors(that);
Greg Daniele810d832020-02-07 17:20:56 -050047}
48
Chris Dalton383a2ef2018-01-08 17:21:41 -050049std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
Brian Salomon5cd393b2020-06-12 11:31:37 -040050 return std::unique_ptr<GrFragmentProcessor>(new GrCCClipProcessor(*this));
Chris Daltona32a3c32017-12-05 10:05:21 -070051}
52
Chris Dalton383a2ef2018-01-08 17:21:41 -050053void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
Chris Daltonc3318f02019-07-19 14:20:53 -060054 const SkPath& clipPath = fClipPath->deviceSpacePath();
55 uint32_t key = (fIsCoverageCount) ? (uint32_t)GrFillRuleForSkPath(clipPath) : 0;
56 key = (key << 1) | ((clipPath.isInverseFillType()) ? 1 : 0);
57 key = (key << 1) | ((fMustCheckBounds) ? 1 : 0);
58 b->add32(key);
Chris Daltona32a3c32017-12-05 10:05:21 -070059}
60
Chris Dalton383a2ef2018-01-08 17:21:41 -050061bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
62 const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>();
Brian Salomon5cd393b2020-06-12 11:31:37 -040063 return that.fClipPath->deviceSpacePath().getGenerationID() ==
64 fClipPath->deviceSpacePath().getGenerationID() &&
65 that.fClipPath->deviceSpacePath().getFillType() ==
Chris Daltonc3318f02019-07-19 14:20:53 -060066 fClipPath->deviceSpacePath().getFillType() &&
67 that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
Chris Daltona32a3c32017-12-05 10:05:21 -070068}
69
John Stiles956ec8a2020-06-19 15:32:16 -040070bool GrCCClipProcessor::hasInputFP() const {
71 // We always have a `texEffect`, and this accounts for one child.
72 // The second child will be the input FP, if we have one.
73 return this->numChildProcessors() > 1;
74}
75
Chris Dalton383a2ef2018-01-08 17:21:41 -050076class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
Chris Daltona32a3c32017-12-05 10:05:21 -070077public:
78 void emitCode(EmitArgs& args) override {
Chris Dalton383a2ef2018-01-08 17:21:41 -050079 const GrCCClipProcessor& proc = args.fFp.cast<GrCCClipProcessor>();
Chris Daltona32a3c32017-12-05 10:05:21 -070080 GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
81 GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
82
John Stiles956ec8a2020-06-19 15:32:16 -040083 f->codeAppend("half coverage;");
Chris Daltonc3318f02019-07-19 14:20:53 -060084
Chris Daltona32a3c32017-12-05 10:05:21 -070085 if (proc.fMustCheckBounds) {
86 const char* pathIBounds;
Ethan Nicholas16464c32020-04-06 13:53:05 -040087 fPathIBoundsUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
88 kFloat4_GrSLType, "path_ibounds",
89 &pathIBounds);
Chris Daltona32a3c32017-12-05 10:05:21 -070090 f->codeAppendf("if (all(greaterThan(float4(sk_FragCoord.xy, %s.zw), "
91 "float4(%s.xy, sk_FragCoord.xy)))) {",
92 pathIBounds, pathIBounds);
93 }
94
Brian Salomon5cd393b2020-06-12 11:31:37 -040095 const char* atlasTranslate;
96 fAtlasTranslateUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
97 kFloat2_GrSLType, "atlas_translate",
98 &atlasTranslate);
99 SkString coord;
100 coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate);
John Stiles956ec8a2020-06-19 15:32:16 -0400101 constexpr int kTexEffectFPIndex = 0;
102 SkString sample = this->invokeChild(kTexEffectFPIndex, args, coord.c_str());
Brian Salomon5cd393b2020-06-12 11:31:37 -0400103 f->codeAppendf("coverage = %s.a;", sample.c_str());
Chris Daltona32a3c32017-12-05 10:05:21 -0700104
Chris Daltonc3318f02019-07-19 14:20:53 -0600105 if (proc.fIsCoverageCount) {
106 auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
107 if (GrFillRule::kEvenOdd == fillRule) {
John Stiles956ec8a2020-06-19 15:32:16 -0400108 f->codeAppend("half t = mod(abs(coverage), 2);");
109 f->codeAppend("coverage = 1 - abs(t - 1);");
Chris Daltonc3318f02019-07-19 14:20:53 -0600110 } else {
111 SkASSERT(GrFillRule::kNonzero == fillRule);
John Stiles956ec8a2020-06-19 15:32:16 -0400112 f->codeAppend("coverage = min(abs(coverage), 1);");
Chris Daltonc3318f02019-07-19 14:20:53 -0600113 }
Chris Daltona32a3c32017-12-05 10:05:21 -0700114 }
115
116 if (proc.fMustCheckBounds) {
John Stiles956ec8a2020-06-19 15:32:16 -0400117 f->codeAppend("} else {");
118 f->codeAppend( "coverage = 0;");
119 f->codeAppend("}");
Chris Daltona32a3c32017-12-05 10:05:21 -0700120 }
121
Chris Daltonc3318f02019-07-19 14:20:53 -0600122 if (proc.fClipPath->deviceSpacePath().isInverseFillType()) {
John Stiles956ec8a2020-06-19 15:32:16 -0400123 f->codeAppend("coverage = 1 - coverage;");
Chris Daltona32a3c32017-12-05 10:05:21 -0700124 }
125
John Stiles956ec8a2020-06-19 15:32:16 -0400126 constexpr int kInputFPIndex = 1;
127 SkString inputColor = proc.hasInputFP()
128 ? this->invokeChild(kInputFPIndex, args.fInputColor, args)
129 : SkString(args.fInputColor);
130
131 f->codeAppendf("%s = %s * coverage;", args.fOutputColor, inputColor.c_str());
Chris Daltona32a3c32017-12-05 10:05:21 -0700132 }
133
134 void onSetData(const GrGLSLProgramDataManager& pdman,
135 const GrFragmentProcessor& fp) override {
Chris Dalton383a2ef2018-01-08 17:21:41 -0500136 const GrCCClipProcessor& proc = fp.cast<GrCCClipProcessor>();
Chris Daltona32a3c32017-12-05 10:05:21 -0700137 if (proc.fMustCheckBounds) {
138 const SkRect pathIBounds = SkRect::Make(proc.fClipPath->pathDevIBounds());
139 pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(),
140 pathIBounds.right(), pathIBounds.bottom());
141 }
Brian Salomon5cd393b2020-06-12 11:31:37 -0400142 const SkIVector& trans = proc.fClipPath->atlasTranslate();
143 pdman.set2f(fAtlasTranslateUniform, trans.x(), trans.y());
Chris Daltona32a3c32017-12-05 10:05:21 -0700144 }
145
146private:
147 UniformHandle fPathIBoundsUniform;
Brian Salomon5cd393b2020-06-12 11:31:37 -0400148 UniformHandle fAtlasTranslateUniform;
Chris Daltona32a3c32017-12-05 10:05:21 -0700149};
150
Chris Dalton383a2ef2018-01-08 17:21:41 -0500151GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const {
Chris Daltona32a3c32017-12-05 10:05:21 -0700152 return new Impl();
153}