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