blob: 7edcf92f3fb190052be57c708d422c2f3bb18798 [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
8#include "GrCCPRClipProcessor.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
16GrCCPRClipProcessor::GrCCPRClipProcessor(const ClipPath* clipPath, MustCheckBounds mustCheckBounds,
17 SkPath::FillType overrideFillType)
18 : INHERITED(kCCPRClipProcessor_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
27std::unique_ptr<GrFragmentProcessor> GrCCPRClipProcessor::clone() const {
28 return skstd::make_unique<GrCCPRClipProcessor>(fClipPath, MustCheckBounds(fMustCheckBounds),
29 fOverrideFillType);
30}
31
32void GrCCPRClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
33 GrProcessorKeyBuilder* b) const {
34 b->add32((fOverrideFillType << 1) | (int)fMustCheckBounds);
35}
36
37bool GrCCPRClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
38 const GrCCPRClipProcessor& that = fp.cast<GrCCPRClipProcessor>();
39 // 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
46class GrCCPRClipProcessor::Impl : public GrGLSLFragmentProcessor {
47public:
48 void emitCode(EmitArgs& args) override {
49 const GrCCPRClipProcessor& proc = args.fFp.cast<GrCCPRClipProcessor>();
50 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 {
96 const GrCCPRClipProcessor& proc = fp.cast<GrCCPRClipProcessor>();
97 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
112GrGLSLFragmentProcessor* GrCCPRClipProcessor::onCreateGLSLInstance() const {
113 return new Impl();
114}