1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileShader.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkRuntimeEffect.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileBlender.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorSpacePriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkKnownRuntimeEffects.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Blend.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/BuiltInCodeSnippetID.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyContext.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyHelpers.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParams.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParamsKey.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PrecompileInternal.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ReadSwizzle.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileBaseComplete.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileBasePriv.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileBlenderPriv.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileShaderPriv.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileShadersPriv.h"
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker PrecompileShader::~PrecompileShader() = default;
33*c8dee2aaSAndroid Build Coastguard Worker
makeWithColorFilter(sk_sp<PrecompileColorFilter> cf) const34*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShader::makeWithColorFilter(
35*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileColorFilter> cf) const {
36*c8dee2aaSAndroid Build Coastguard Worker if (!cf) {
37*c8dee2aaSAndroid Build Coastguard Worker return sk_ref_sp(this);
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::ColorFilter({ sk_ref_sp(this) }, { std::move(cf) });
41*c8dee2aaSAndroid Build Coastguard Worker }
42*c8dee2aaSAndroid Build Coastguard Worker
makeWithWorkingColorSpace(sk_sp<SkColorSpace> cs) const43*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShader::makeWithWorkingColorSpace(sk_sp<SkColorSpace> cs) const {
44*c8dee2aaSAndroid Build Coastguard Worker if (!cs) {
45*c8dee2aaSAndroid Build Coastguard Worker return sk_ref_sp(this);
46*c8dee2aaSAndroid Build Coastguard Worker }
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::WorkingColorSpace({ sk_ref_sp(this) }, { std::move(cs) });
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
52*c8dee2aaSAndroid Build Coastguard Worker class PrecompileEmptyShader final : public PrecompileShader {
53*c8dee2aaSAndroid Build Coastguard Worker private:
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const54*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
55*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
56*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
57*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination == 0); // The empty shader only ever has one combination
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker };
64*c8dee2aaSAndroid Build Coastguard Worker
Empty()65*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Empty() {
66*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileEmptyShader>();
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
70*c8dee2aaSAndroid Build Coastguard Worker class PrecompileColorShader final : public PrecompileShader {
71*c8dee2aaSAndroid Build Coastguard Worker private:
isConstant(int desiredCombination) const72*c8dee2aaSAndroid Build Coastguard Worker bool isConstant(int desiredCombination) const override {
73*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination == 0); // The color shader only ever has one combination
74*c8dee2aaSAndroid Build Coastguard Worker return true;
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const77*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
78*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
79*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
80*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination == 0); // The color shader only ever has one combination
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker // The white PMColor is just a placeholder for the actual paint params color
85*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(keyContext, builder, gatherer, SK_PMColor4fWHITE);
86*c8dee2aaSAndroid Build Coastguard Worker }
87*c8dee2aaSAndroid Build Coastguard Worker };
88*c8dee2aaSAndroid Build Coastguard Worker
Color()89*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Color() {
90*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileColorShader>();
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker
93*c8dee2aaSAndroid Build Coastguard Worker // The colorSpace is safe to ignore - it is just applied to the color and doesn't modify the
94*c8dee2aaSAndroid Build Coastguard Worker // generated program.
Color(sk_sp<SkColorSpace>)95*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Color(sk_sp<SkColorSpace>) {
96*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileColorShader>();
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker
99*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
100*c8dee2aaSAndroid Build Coastguard Worker class PrecompileBlendShader final : public PrecompileShader {
101*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileBlendShader(PrecompileBlenderList && blenders,SkSpan<const sk_sp<PrecompileShader>> dsts,SkSpan<const sk_sp<PrecompileShader>> srcs)102*c8dee2aaSAndroid Build Coastguard Worker PrecompileBlendShader(PrecompileBlenderList&& blenders,
103*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> dsts,
104*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> srcs)
105*c8dee2aaSAndroid Build Coastguard Worker : fBlenderOptions(std::move(blenders))
106*c8dee2aaSAndroid Build Coastguard Worker , fDstOptions(dsts.begin(), dsts.end())
107*c8dee2aaSAndroid Build Coastguard Worker , fSrcOptions(srcs.begin(), srcs.end()) {
108*c8dee2aaSAndroid Build Coastguard Worker fNumDstCombos = 0;
109*c8dee2aaSAndroid Build Coastguard Worker for (const auto& d : fDstOptions) {
110*c8dee2aaSAndroid Build Coastguard Worker fNumDstCombos += d->priv().numCombinations();
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker
113*c8dee2aaSAndroid Build Coastguard Worker fNumSrcCombos = 0;
114*c8dee2aaSAndroid Build Coastguard Worker for (const auto& s : fSrcOptions) {
115*c8dee2aaSAndroid Build Coastguard Worker fNumSrcCombos += s->priv().numCombinations();
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker
119*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const120*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override {
121*c8dee2aaSAndroid Build Coastguard Worker return fBlenderOptions.numCombinations() * fNumDstCombos * fNumSrcCombos;
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const124*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
125*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
126*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
127*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
128*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numCombinations());
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker const int desiredDstCombination = desiredCombination % fNumDstCombos;
131*c8dee2aaSAndroid Build Coastguard Worker int remainingCombinations = desiredCombination / fNumDstCombos;
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker const int desiredSrcCombination = remainingCombinations % fNumSrcCombos;
134*c8dee2aaSAndroid Build Coastguard Worker remainingCombinations /= fNumSrcCombos;
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker int desiredBlendCombination = remainingCombinations;
137*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredBlendCombination < fBlenderOptions.numCombinations());
138*c8dee2aaSAndroid Build Coastguard Worker
139*c8dee2aaSAndroid Build Coastguard Worker auto [blender, blenderCombination] = fBlenderOptions.selectOption(desiredBlendCombination);
140*c8dee2aaSAndroid Build Coastguard Worker if (blender->priv().asBlendMode()) {
141*c8dee2aaSAndroid Build Coastguard Worker // Coefficient and HSLC blends, and other fixed SkBlendMode blenders use the
142*c8dee2aaSAndroid Build Coastguard Worker // BlendCompose block to organize the children.
143*c8dee2aaSAndroid Build Coastguard Worker BlendComposeBlock::BeginBlock(keyContext, builder, gatherer);
144*c8dee2aaSAndroid Build Coastguard Worker } else {
145*c8dee2aaSAndroid Build Coastguard Worker // Runtime blenders are wrapped in the kBlend runtime shader, although functionally
146*c8dee2aaSAndroid Build Coastguard Worker // it is identical to the BlendCompose snippet.
147*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* blendEffect =
148*c8dee2aaSAndroid Build Coastguard Worker GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kBlend);
149*c8dee2aaSAndroid Build Coastguard Worker
150*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer,
151*c8dee2aaSAndroid Build Coastguard Worker { sk_ref_sp(blendEffect) });
152*c8dee2aaSAndroid Build Coastguard Worker }
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fSrcOptions,
155*c8dee2aaSAndroid Build Coastguard Worker desiredSrcCombination);
156*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fDstOptions,
157*c8dee2aaSAndroid Build Coastguard Worker desiredDstCombination);
158*c8dee2aaSAndroid Build Coastguard Worker
159*c8dee2aaSAndroid Build Coastguard Worker if (blender->priv().asBlendMode()) {
160*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(blenderCombination == 0);
161*c8dee2aaSAndroid Build Coastguard Worker AddBlendMode(keyContext, builder, gatherer, *blender->priv().asBlendMode());
162*c8dee2aaSAndroid Build Coastguard Worker } else {
163*c8dee2aaSAndroid Build Coastguard Worker blender->priv().addToKey(keyContext, builder, gatherer, blenderCombination);
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock(); // BlendComposeBlock or RuntimeEffectBlock
167*c8dee2aaSAndroid Build Coastguard Worker }
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker PrecompileBlenderList fBlenderOptions;
170*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fDstOptions;
171*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fSrcOptions;
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker int fNumDstCombos;
174*c8dee2aaSAndroid Build Coastguard Worker int fNumSrcCombos;
175*c8dee2aaSAndroid Build Coastguard Worker };
176*c8dee2aaSAndroid Build Coastguard Worker
Blend(SkSpan<const sk_sp<PrecompileBlender>> blenders,SkSpan<const sk_sp<PrecompileShader>> dsts,SkSpan<const sk_sp<PrecompileShader>> srcs)177*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Blend(
178*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileBlender>> blenders,
179*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> dsts,
180*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> srcs) {
181*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileBlendShader>(PrecompileBlenderList(blenders), dsts, srcs);
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker
Blend(SkSpan<const SkBlendMode> blendModes,SkSpan<const sk_sp<PrecompileShader>> dsts,SkSpan<const sk_sp<PrecompileShader>> srcs)184*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Blend(
185*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkBlendMode> blendModes,
186*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> dsts,
187*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> srcs) {
188*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileBlendShader>(PrecompileBlenderList(blendModes), dsts, srcs);
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
192*c8dee2aaSAndroid Build Coastguard Worker class PrecompileCoordClampShader final : public PrecompileShader {
193*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileCoordClampShader(SkSpan<const sk_sp<PrecompileShader>> shaders)194*c8dee2aaSAndroid Build Coastguard Worker PrecompileCoordClampShader(SkSpan<const sk_sp<PrecompileShader>> shaders)
195*c8dee2aaSAndroid Build Coastguard Worker : fShaders(shaders.begin(), shaders.end()) {
196*c8dee2aaSAndroid Build Coastguard Worker fNumShaderCombos = 0;
197*c8dee2aaSAndroid Build Coastguard Worker for (const auto& s : fShaders) {
198*c8dee2aaSAndroid Build Coastguard Worker fNumShaderCombos += s->priv().numCombinations();
199*c8dee2aaSAndroid Build Coastguard Worker }
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const203*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override {
204*c8dee2aaSAndroid Build Coastguard Worker return fNumShaderCombos;
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const207*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
208*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
209*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
210*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
211*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < fNumShaderCombos);
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker constexpr SkRect kIgnored { 0, 0, 256, 256 }; // ignored bc we're precompiling
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker // TODO: update CoordClampShaderBlock so this is optional
216*c8dee2aaSAndroid Build Coastguard Worker CoordClampShaderBlock::CoordClampData data(kIgnored);
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker CoordClampShaderBlock::BeginBlock(keyContext, builder, gatherer, data);
219*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fShaders, desiredCombination);
220*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fShaders;
224*c8dee2aaSAndroid Build Coastguard Worker int fNumShaderCombos;
225*c8dee2aaSAndroid Build Coastguard Worker };
226*c8dee2aaSAndroid Build Coastguard Worker
CoordClamp(SkSpan<const sk_sp<PrecompileShader>> input)227*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::CoordClamp(SkSpan<const sk_sp<PrecompileShader>> input) {
228*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileCoordClampShader>(input);
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker
231*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
232*c8dee2aaSAndroid Build Coastguard Worker class PrecompileImageShader final : public PrecompileShader {
233*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileImageShader(SkEnumBitMask<PrecompileImageShaderFlags> flags)234*c8dee2aaSAndroid Build Coastguard Worker PrecompileImageShader(SkEnumBitMask<PrecompileImageShaderFlags> flags) : fFlags(flags) {}
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker private:
237*c8dee2aaSAndroid Build Coastguard Worker // The ImageShader has 3 potential sampling/tiling variants: hardware-tiled, shader-tiled and
238*c8dee2aaSAndroid Build Coastguard Worker // cubic sampling (which always uses shader-tiling)
239*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumSamplingTilingCombos = 3;
240*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kCubicSampled = 2;
241*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kHWTiled = 1;
242*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kShaderTiled = 0;
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker // There are also 2 potential alpha combinations: alpha-only and not-alpha-only
245*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumAlphaCombinations = 2;
246*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kAlphaOnly = 1;
247*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNonAlphaOnly = 0;
248*c8dee2aaSAndroid Build Coastguard Worker
numIntrinsicCombinations() const249*c8dee2aaSAndroid Build Coastguard Worker int numIntrinsicCombinations() const override {
250*c8dee2aaSAndroid Build Coastguard Worker int numSamplingTilingCombos =
251*c8dee2aaSAndroid Build Coastguard Worker (fFlags & PrecompileImageShaderFlags::kExcludeCubic) ? 2 : kNumSamplingTilingCombos;
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker if (fFlags & PrecompileImageShaderFlags::kExcludeAlpha) {
254*c8dee2aaSAndroid Build Coastguard Worker // RawImageShaders don't blend alpha-only images w/ the paint color
255*c8dee2aaSAndroid Build Coastguard Worker return numSamplingTilingCombos;
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker return numSamplingTilingCombos * kNumAlphaCombinations;
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const260*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
261*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
262*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
263*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
264*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numIntrinsicCombinations());
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard Worker int desiredAlphaCombo, desiredSamplingTilingCombo;
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker if (fFlags & PrecompileImageShaderFlags::kExcludeAlpha) {
269*c8dee2aaSAndroid Build Coastguard Worker desiredAlphaCombo = kNonAlphaOnly;
270*c8dee2aaSAndroid Build Coastguard Worker desiredSamplingTilingCombo = desiredCombination;
271*c8dee2aaSAndroid Build Coastguard Worker } else {
272*c8dee2aaSAndroid Build Coastguard Worker desiredAlphaCombo = desiredCombination % kNumAlphaCombinations;
273*c8dee2aaSAndroid Build Coastguard Worker desiredSamplingTilingCombo = desiredCombination / kNumAlphaCombinations;
274*c8dee2aaSAndroid Build Coastguard Worker }
275*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(int numSamplingTilingCombos =
276*c8dee2aaSAndroid Build Coastguard Worker (fFlags & PrecompileImageShaderFlags::kExcludeCubic) ? 2 : kNumSamplingTilingCombos;)
277*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredSamplingTilingCombo < numSamplingTilingCombos);
278*c8dee2aaSAndroid Build Coastguard Worker
279*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkSamplingOptions kDefaultCubicSampling(SkCubicResampler::Mitchell());
280*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkSamplingOptions kDefaultSampling;
281*c8dee2aaSAndroid Build Coastguard Worker constexpr ReadSwizzle kIgnoredSwizzle = ReadSwizzle::kRGBA;
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker // ImageShaderBlock will use hardware tiling when the subset covers the entire image, so we
284*c8dee2aaSAndroid Build Coastguard Worker // create subset + image size combinations where subset == imgSize (for a shader that uses
285*c8dee2aaSAndroid Build Coastguard Worker // hardware tiling) and subset < imgSize (for a shader that does shader-based tiling).
286*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkRect kSubset = SkRect::MakeWH(1.0f, 1.0f);
287*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkISize kHWTileableSize = SkISize::Make(1, 1);
288*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkISize kShaderTileableSize = SkISize::Make(2, 2);
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::ImageData imgData(
291*c8dee2aaSAndroid Build Coastguard Worker desiredSamplingTilingCombo == kCubicSampled ? kDefaultCubicSampling
292*c8dee2aaSAndroid Build Coastguard Worker : kDefaultSampling,
293*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp, SkTileMode::kClamp,
294*c8dee2aaSAndroid Build Coastguard Worker desiredSamplingTilingCombo == kHWTiled ? kHWTileableSize : kShaderTileableSize,
295*c8dee2aaSAndroid Build Coastguard Worker kSubset);
296*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData colorXformData(kIgnoredSwizzle);
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker if (desiredAlphaCombo == kAlphaOnly) {
299*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!(fFlags & PrecompileImageShaderFlags::kExcludeAlpha));
300*c8dee2aaSAndroid Build Coastguard Worker
301*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, builder, gatherer,
302*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&] () -> void {
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, builder, gatherer, SkBlendMode::kDstIn);
305*c8dee2aaSAndroid Build Coastguard Worker },
306*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&] () -> void {
307*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
308*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
309*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::AddBlock(keyContext, builder, gatherer,
310*c8dee2aaSAndroid Build Coastguard Worker imgData);
311*c8dee2aaSAndroid Build Coastguard Worker },
312*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
313*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer,
314*c8dee2aaSAndroid Build Coastguard Worker colorXformData);
315*c8dee2aaSAndroid Build Coastguard Worker });
316*c8dee2aaSAndroid Build Coastguard Worker },
317*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
318*c8dee2aaSAndroid Build Coastguard Worker RGBPaintColorBlock::AddBlock(keyContext, builder, gatherer);
319*c8dee2aaSAndroid Build Coastguard Worker });
320*c8dee2aaSAndroid Build Coastguard Worker } else {
321*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
322*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
323*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
324*c8dee2aaSAndroid Build Coastguard Worker },
325*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
326*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer,
327*c8dee2aaSAndroid Build Coastguard Worker colorXformData);
328*c8dee2aaSAndroid Build Coastguard Worker });
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker }
331*c8dee2aaSAndroid Build Coastguard Worker
332*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<PrecompileImageShaderFlags> fFlags;
333*c8dee2aaSAndroid Build Coastguard Worker };
334*c8dee2aaSAndroid Build Coastguard Worker
Image()335*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Image() {
336*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix(
337*c8dee2aaSAndroid Build Coastguard Worker { sk_make_sp<PrecompileImageShader>(PrecompileImageShaderFlags::kNone) });
338*c8dee2aaSAndroid Build Coastguard Worker }
339*c8dee2aaSAndroid Build Coastguard Worker
RawImage()340*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::RawImage() {
341*c8dee2aaSAndroid Build Coastguard Worker // Raw images do not perform color space conversion, but in Graphite, this is represented as
342*c8dee2aaSAndroid Build Coastguard Worker // an identity color space xform, not as a distinct shader
343*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix(
344*c8dee2aaSAndroid Build Coastguard Worker { sk_make_sp<PrecompileImageShader>(PrecompileImageShaderFlags::kExcludeAlpha) });
345*c8dee2aaSAndroid Build Coastguard Worker }
346*c8dee2aaSAndroid Build Coastguard Worker
Image(SkEnumBitMask<PrecompileImageShaderFlags> flags)347*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::Image(
348*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<PrecompileImageShaderFlags> flags) {
349*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ sk_make_sp<PrecompileImageShader>(flags) });
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker
RawImage(SkEnumBitMask<PrecompileImageShaderFlags> flags)352*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::RawImage(
353*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<PrecompileImageShaderFlags> flags) {
354*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix(
355*c8dee2aaSAndroid Build Coastguard Worker { sk_make_sp<PrecompileImageShader>(flags |
356*c8dee2aaSAndroid Build Coastguard Worker PrecompileImageShaderFlags::kExcludeAlpha) });
357*c8dee2aaSAndroid Build Coastguard Worker }
358*c8dee2aaSAndroid Build Coastguard Worker
359*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
360*c8dee2aaSAndroid Build Coastguard Worker class PrecompileYUVImageShader : public PrecompileShader {
361*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileYUVImageShader()362*c8dee2aaSAndroid Build Coastguard Worker PrecompileYUVImageShader() {}
363*c8dee2aaSAndroid Build Coastguard Worker
364*c8dee2aaSAndroid Build Coastguard Worker private:
365*c8dee2aaSAndroid Build Coastguard Worker // There are 8 intrinsic YUV shaders:
366*c8dee2aaSAndroid Build Coastguard Worker // 4 tiling modes
367*c8dee2aaSAndroid Build Coastguard Worker // HW tiling w/o swizzle
368*c8dee2aaSAndroid Build Coastguard Worker // HW tiling w/ swizzle
369*c8dee2aaSAndroid Build Coastguard Worker // cubic shader tiling
370*c8dee2aaSAndroid Build Coastguard Worker // non-cubic shader tiling
371*c8dee2aaSAndroid Build Coastguard Worker // crossed with two postambles:
372*c8dee2aaSAndroid Build Coastguard Worker // just premul
373*c8dee2aaSAndroid Build Coastguard Worker // full-blown colorSpace transform
374*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumTilingModes = 4;
375*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kHWTiledNoSwizzle = 3;
376*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kHWTiledWithSwizzle = 2;
377*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kCubicShaderTiled = 1;
378*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kShaderTiled = 0;
379*c8dee2aaSAndroid Build Coastguard Worker
380*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumPostambles = 2;
381*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kWithColorSpaceXform = 1;
382*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kJustPremul = 0;
383*c8dee2aaSAndroid Build Coastguard Worker
384*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumIntrinsicCombinations = kNumTilingModes * kNumPostambles;
385*c8dee2aaSAndroid Build Coastguard Worker
numIntrinsicCombinations() const386*c8dee2aaSAndroid Build Coastguard Worker int numIntrinsicCombinations() const override { return kNumIntrinsicCombinations; }
387*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const388*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
389*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
390*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
391*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
392*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < kNumIntrinsicCombinations);
393*c8dee2aaSAndroid Build Coastguard Worker
394*c8dee2aaSAndroid Build Coastguard Worker int desiredPostamble = desiredCombination % kNumPostambles;
395*c8dee2aaSAndroid Build Coastguard Worker int desiredTiling = desiredCombination / kNumPostambles;
396*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredTiling < kNumTilingModes);
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkSamplingOptions kDefaultCubicSampling(SkCubicResampler::Mitchell());
399*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkSamplingOptions kDefaultSampling;
400*c8dee2aaSAndroid Build Coastguard Worker
401*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::ImageData imgData(desiredTiling == kCubicShaderTiled
402*c8dee2aaSAndroid Build Coastguard Worker ? kDefaultCubicSampling
403*c8dee2aaSAndroid Build Coastguard Worker : kDefaultSampling,
404*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp, SkTileMode::kClamp,
405*c8dee2aaSAndroid Build Coastguard Worker /* imgSize= */ { 1, 1 },
406*c8dee2aaSAndroid Build Coastguard Worker /* subset= */ desiredTiling == kShaderTiled
407*c8dee2aaSAndroid Build Coastguard Worker ? SkRect::MakeEmpty()
408*c8dee2aaSAndroid Build Coastguard Worker : SkRect::MakeWH(1, 1));
409*c8dee2aaSAndroid Build Coastguard Worker
410*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkV4 kRedChannel{ 1.f, 0.f, 0.f, 0.f };
411*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[0] = kRedChannel;
412*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[1] = kRedChannel;
413*c8dee2aaSAndroid Build Coastguard Worker if (desiredTiling == kHWTiledNoSwizzle) {
414*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[2] = kRedChannel;
415*c8dee2aaSAndroid Build Coastguard Worker } else {
416*c8dee2aaSAndroid Build Coastguard Worker // Having a non-red channel selector forces a swizzle
417*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[2] = { 0.f, 1.f, 0.f, 0.f};
418*c8dee2aaSAndroid Build Coastguard Worker }
419*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[3] = kRedChannel;
420*c8dee2aaSAndroid Build Coastguard Worker
421*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBMatrix.setAll(1, 0, 0, 0, 1, 0, 0, 0, 0);
422*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBTranslate = { 0, 0, 0 };
423*c8dee2aaSAndroid Build Coastguard Worker
424*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData colorXformData(
425*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::ReadSwizzle::kRGBA);
426*c8dee2aaSAndroid Build Coastguard Worker
427*c8dee2aaSAndroid Build Coastguard Worker if (desiredPostamble == kJustPremul) {
428*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
429*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
430*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
431*c8dee2aaSAndroid Build Coastguard Worker },
432*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
433*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPremulAlphaColorFilter);
434*c8dee2aaSAndroid Build Coastguard Worker });
435*c8dee2aaSAndroid Build Coastguard Worker } else {
436*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
437*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
438*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
439*c8dee2aaSAndroid Build Coastguard Worker },
440*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
441*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer,
442*c8dee2aaSAndroid Build Coastguard Worker colorXformData);
443*c8dee2aaSAndroid Build Coastguard Worker });
444*c8dee2aaSAndroid Build Coastguard Worker }
445*c8dee2aaSAndroid Build Coastguard Worker
446*c8dee2aaSAndroid Build Coastguard Worker }
447*c8dee2aaSAndroid Build Coastguard Worker };
448*c8dee2aaSAndroid Build Coastguard Worker
YUVImage()449*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::YUVImage() {
450*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ sk_make_sp<PrecompileYUVImageShader>() });
451*c8dee2aaSAndroid Build Coastguard Worker }
452*c8dee2aaSAndroid Build Coastguard Worker
453*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
454*c8dee2aaSAndroid Build Coastguard Worker class PrecompilePerlinNoiseShader final : public PrecompileShader {
455*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompilePerlinNoiseShader()456*c8dee2aaSAndroid Build Coastguard Worker PrecompilePerlinNoiseShader() {}
457*c8dee2aaSAndroid Build Coastguard Worker
458*c8dee2aaSAndroid Build Coastguard Worker private:
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const459*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
460*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
461*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
462*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination == 0); // The Perlin noise shader only ever has one combination
465*c8dee2aaSAndroid Build Coastguard Worker
466*c8dee2aaSAndroid Build Coastguard Worker // TODO: update PerlinNoiseShaderBlock so the NoiseData is optional
467*c8dee2aaSAndroid Build Coastguard Worker static const PerlinNoiseShaderBlock::PerlinNoiseData kIgnoredNoiseData(
468*c8dee2aaSAndroid Build Coastguard Worker PerlinNoiseShaderBlock::Type::kFractalNoise, { 0.0f, 0.0f }, 2, {1, 1});
469*c8dee2aaSAndroid Build Coastguard Worker
470*c8dee2aaSAndroid Build Coastguard Worker PerlinNoiseShaderBlock::AddBlock(keyContext, builder, gatherer, kIgnoredNoiseData);
471*c8dee2aaSAndroid Build Coastguard Worker }
472*c8dee2aaSAndroid Build Coastguard Worker
473*c8dee2aaSAndroid Build Coastguard Worker };
474*c8dee2aaSAndroid Build Coastguard Worker
MakeFractalNoise()475*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::MakeFractalNoise() {
476*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompilePerlinNoiseShader>();
477*c8dee2aaSAndroid Build Coastguard Worker }
478*c8dee2aaSAndroid Build Coastguard Worker
MakeTurbulence()479*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::MakeTurbulence() {
480*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompilePerlinNoiseShader>();
481*c8dee2aaSAndroid Build Coastguard Worker }
482*c8dee2aaSAndroid Build Coastguard Worker
483*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
484*c8dee2aaSAndroid Build Coastguard Worker class PrecompileGradientShader final : public PrecompileShader {
485*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileGradientShader(SkShaderBase::GradientType type)486*c8dee2aaSAndroid Build Coastguard Worker PrecompileGradientShader(SkShaderBase::GradientType type) : fType(type) {}
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker private:
489*c8dee2aaSAndroid Build Coastguard Worker /*
490*c8dee2aaSAndroid Build Coastguard Worker * The gradients currently have three specializations based on the number of stops.
491*c8dee2aaSAndroid Build Coastguard Worker */
492*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumStopVariants = 3;
493*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kStopVariants[kNumStopVariants] =
494*c8dee2aaSAndroid Build Coastguard Worker { 4, 8, GradientShaderBlocks::GradientData::kNumInternalStorageStops+1 };
495*c8dee2aaSAndroid Build Coastguard Worker
numIntrinsicCombinations() const496*c8dee2aaSAndroid Build Coastguard Worker int numIntrinsicCombinations() const override {
497*c8dee2aaSAndroid Build Coastguard Worker return kNumStopVariants;
498*c8dee2aaSAndroid Build Coastguard Worker }
499*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const500*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
501*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
502*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
503*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
504*c8dee2aaSAndroid Build Coastguard Worker const int intrinsicCombination = desiredCombination / this->numChildCombinations();
505*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(int childCombination = desiredCombination % this->numChildCombinations();)
506*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(intrinsicCombination < kNumStopVariants);
507*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(childCombination == 0);
508*c8dee2aaSAndroid Build Coastguard Worker
509*c8dee2aaSAndroid Build Coastguard Worker bool useStorageBuffer = keyContext.caps()->gradientBufferSupport();
510*c8dee2aaSAndroid Build Coastguard Worker
511*c8dee2aaSAndroid Build Coastguard Worker GradientShaderBlocks::GradientData gradData(fType,
512*c8dee2aaSAndroid Build Coastguard Worker kStopVariants[intrinsicCombination],
513*c8dee2aaSAndroid Build Coastguard Worker useStorageBuffer);
514*c8dee2aaSAndroid Build Coastguard Worker
515*c8dee2aaSAndroid Build Coastguard Worker constexpr SkAlphaType kAlphaType = kPremul_SkAlphaType;
516*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData csData(sk_srgb_singleton(), kAlphaType,
517*c8dee2aaSAndroid Build Coastguard Worker sk_srgb_singleton(), kAlphaType);
518*c8dee2aaSAndroid Build Coastguard Worker
519*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
520*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
521*c8dee2aaSAndroid Build Coastguard Worker GradientShaderBlocks::AddBlock(keyContext, builder, gatherer, gradData);
522*c8dee2aaSAndroid Build Coastguard Worker },
523*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
524*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, csData);
525*c8dee2aaSAndroid Build Coastguard Worker });
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker
528*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientType fType;
529*c8dee2aaSAndroid Build Coastguard Worker };
530*c8dee2aaSAndroid Build Coastguard Worker
LinearGradient()531*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::LinearGradient() {
532*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> s =
533*c8dee2aaSAndroid Build Coastguard Worker sk_make_sp<PrecompileGradientShader>(SkShaderBase::GradientType::kLinear);
534*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ std::move(s) });
535*c8dee2aaSAndroid Build Coastguard Worker }
536*c8dee2aaSAndroid Build Coastguard Worker
RadialGradient()537*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::RadialGradient() {
538*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> s =
539*c8dee2aaSAndroid Build Coastguard Worker sk_make_sp<PrecompileGradientShader>(SkShaderBase::GradientType::kRadial);
540*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ std::move(s) });
541*c8dee2aaSAndroid Build Coastguard Worker }
542*c8dee2aaSAndroid Build Coastguard Worker
SweepGradient()543*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::SweepGradient() {
544*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> s =
545*c8dee2aaSAndroid Build Coastguard Worker sk_make_sp<PrecompileGradientShader>(SkShaderBase::GradientType::kSweep);
546*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ std::move(s) });
547*c8dee2aaSAndroid Build Coastguard Worker }
548*c8dee2aaSAndroid Build Coastguard Worker
TwoPointConicalGradient()549*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::TwoPointConicalGradient() {
550*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> s =
551*c8dee2aaSAndroid Build Coastguard Worker sk_make_sp<PrecompileGradientShader>(SkShaderBase::GradientType::kConical);
552*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ std::move(s) });
553*c8dee2aaSAndroid Build Coastguard Worker }
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
556*c8dee2aaSAndroid Build Coastguard Worker // The PictureShader ultimately turns into an SkImageShader optionally wrapped in a
557*c8dee2aaSAndroid Build Coastguard Worker // LocalMatrixShader.
558*c8dee2aaSAndroid Build Coastguard Worker // Note that this means each precompile PictureShader will add 12 combinations:
559*c8dee2aaSAndroid Build Coastguard Worker // 2 (pictureshader LM) x 6 (imageShader variations)
Picture()560*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::Picture() {
561*c8dee2aaSAndroid Build Coastguard Worker // Note: We don't need to consider the PrecompileYUVImageShader since the image
562*c8dee2aaSAndroid Build Coastguard Worker // being drawn was created internally by Skia (as non-YUV).
563*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShadersPriv::LocalMatrixBothVariants({ PrecompileShaders::Image() });
564*c8dee2aaSAndroid Build Coastguard Worker }
565*c8dee2aaSAndroid Build Coastguard Worker
Picture(bool withLM)566*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::Picture(bool withLM) {
567*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> s = PrecompileShaders::Image();
568*c8dee2aaSAndroid Build Coastguard Worker if (withLM) {
569*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ std::move(s) });
570*c8dee2aaSAndroid Build Coastguard Worker }
571*c8dee2aaSAndroid Build Coastguard Worker return s;
572*c8dee2aaSAndroid Build Coastguard Worker }
573*c8dee2aaSAndroid Build Coastguard Worker
574*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
575*c8dee2aaSAndroid Build Coastguard Worker // In the main Skia API the SkLocalMatrixShader is optimized away when the LM is the identity
576*c8dee2aaSAndroid Build Coastguard Worker // or omitted. The PrecompileLocalMatrixShader captures this by adding two intrinsic options.
577*c8dee2aaSAndroid Build Coastguard Worker // One with the LMShader wrapping the child and one without the LMShader.
578*c8dee2aaSAndroid Build Coastguard Worker class PrecompileLocalMatrixShader final : public PrecompileShader {
579*c8dee2aaSAndroid Build Coastguard Worker public:
580*c8dee2aaSAndroid Build Coastguard Worker enum class Flags {
581*c8dee2aaSAndroid Build Coastguard Worker kNone = 0b00,
582*c8dee2aaSAndroid Build Coastguard Worker kIsPerspective = 0b01,
583*c8dee2aaSAndroid Build Coastguard Worker kIncludeWithOutVariant = 0b10,
584*c8dee2aaSAndroid Build Coastguard Worker };
585*c8dee2aaSAndroid Build Coastguard Worker
PrecompileLocalMatrixShader(SkSpan<const sk_sp<PrecompileShader>> wrapped,SkEnumBitMask<Flags> flags=Flags::kNone)586*c8dee2aaSAndroid Build Coastguard Worker PrecompileLocalMatrixShader(SkSpan<const sk_sp<PrecompileShader>> wrapped,
587*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<Flags> flags = Flags::kNone)
588*c8dee2aaSAndroid Build Coastguard Worker : fWrapped(wrapped.begin(), wrapped.end())
589*c8dee2aaSAndroid Build Coastguard Worker , fFlags(flags) {
590*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos = 0;
591*c8dee2aaSAndroid Build Coastguard Worker for (const auto& s : fWrapped) {
592*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos += s->priv().numCombinations();
593*c8dee2aaSAndroid Build Coastguard Worker }
594*c8dee2aaSAndroid Build Coastguard Worker }
595*c8dee2aaSAndroid Build Coastguard Worker
isConstant(int desiredCombination) const596*c8dee2aaSAndroid Build Coastguard Worker bool isConstant(int desiredCombination) const override {
597*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numCombinations());
598*c8dee2aaSAndroid Build Coastguard Worker
599*c8dee2aaSAndroid Build Coastguard Worker /*
600*c8dee2aaSAndroid Build Coastguard Worker * Regardless of whether the LocalMatrixShader elides itself or not, we always want
601*c8dee2aaSAndroid Build Coastguard Worker * the Constant-ness of the wrapped shader.
602*c8dee2aaSAndroid Build Coastguard Worker */
603*c8dee2aaSAndroid Build Coastguard Worker int desiredWrappedCombination = desiredCombination / kNumIntrinsicCombinations;
604*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredWrappedCombination < fNumWrappedCombos);
605*c8dee2aaSAndroid Build Coastguard Worker
606*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<PrecompileShader>, int> wrapped =
607*c8dee2aaSAndroid Build Coastguard Worker PrecompileBase::SelectOption(SkSpan(fWrapped), desiredWrappedCombination);
608*c8dee2aaSAndroid Build Coastguard Worker if (wrapped.first) {
609*c8dee2aaSAndroid Build Coastguard Worker return wrapped.first->priv().isConstant(wrapped.second);
610*c8dee2aaSAndroid Build Coastguard Worker }
611*c8dee2aaSAndroid Build Coastguard Worker
612*c8dee2aaSAndroid Build Coastguard Worker return false;
613*c8dee2aaSAndroid Build Coastguard Worker }
614*c8dee2aaSAndroid Build Coastguard Worker
getWrapped() const615*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> getWrapped() const {
616*c8dee2aaSAndroid Build Coastguard Worker return fWrapped;
617*c8dee2aaSAndroid Build Coastguard Worker }
618*c8dee2aaSAndroid Build Coastguard Worker
getFlags() const619*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<Flags> getFlags() const { return fFlags; }
620*c8dee2aaSAndroid Build Coastguard Worker
621*c8dee2aaSAndroid Build Coastguard Worker private:
622*c8dee2aaSAndroid Build Coastguard Worker // The LocalMatrixShader has two potential variants: with and without the LocalMatrixShader
623*c8dee2aaSAndroid Build Coastguard Worker // In the "with" variant, the kIsPerspective flag will determine if the shader performs
624*c8dee2aaSAndroid Build Coastguard Worker // the perspective division or not.
625*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumIntrinsicCombinations = 2;
626*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kWithLocalMatrix = 1;
627*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kWithoutLocalMatrix = 0;
628*c8dee2aaSAndroid Build Coastguard Worker
isALocalMatrixShader() const629*c8dee2aaSAndroid Build Coastguard Worker bool isALocalMatrixShader() const override { return true; }
630*c8dee2aaSAndroid Build Coastguard Worker
numIntrinsicCombinations() const631*c8dee2aaSAndroid Build Coastguard Worker int numIntrinsicCombinations() const override {
632*c8dee2aaSAndroid Build Coastguard Worker if (!(fFlags & Flags::kIncludeWithOutVariant)) {
633*c8dee2aaSAndroid Build Coastguard Worker return 1; // just kWithLocalMatrix
634*c8dee2aaSAndroid Build Coastguard Worker }
635*c8dee2aaSAndroid Build Coastguard Worker return kNumIntrinsicCombinations;
636*c8dee2aaSAndroid Build Coastguard Worker }
637*c8dee2aaSAndroid Build Coastguard Worker
numChildCombinations() const638*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumWrappedCombos; }
639*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const640*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
641*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
642*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
643*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
644*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numCombinations());
645*c8dee2aaSAndroid Build Coastguard Worker
646*c8dee2aaSAndroid Build Coastguard Worker int desiredLMCombination, desiredWrappedCombination;
647*c8dee2aaSAndroid Build Coastguard Worker
648*c8dee2aaSAndroid Build Coastguard Worker if (!(fFlags & Flags::kIncludeWithOutVariant)) {
649*c8dee2aaSAndroid Build Coastguard Worker desiredLMCombination = kWithLocalMatrix;
650*c8dee2aaSAndroid Build Coastguard Worker desiredWrappedCombination = desiredCombination;
651*c8dee2aaSAndroid Build Coastguard Worker } else {
652*c8dee2aaSAndroid Build Coastguard Worker desiredLMCombination = desiredCombination % kNumIntrinsicCombinations;
653*c8dee2aaSAndroid Build Coastguard Worker desiredWrappedCombination = desiredCombination / kNumIntrinsicCombinations;
654*c8dee2aaSAndroid Build Coastguard Worker }
655*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredWrappedCombination < fNumWrappedCombos);
656*c8dee2aaSAndroid Build Coastguard Worker
657*c8dee2aaSAndroid Build Coastguard Worker if (desiredLMCombination == kWithLocalMatrix) {
658*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix = SkMatrix::I();
659*c8dee2aaSAndroid Build Coastguard Worker if (fFlags & Flags::kIsPerspective) {
660*c8dee2aaSAndroid Build Coastguard Worker matrix.setPerspX(0.1f);
661*c8dee2aaSAndroid Build Coastguard Worker }
662*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::LMShaderData lmShaderData(matrix);
663*c8dee2aaSAndroid Build Coastguard Worker
664*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::BeginBlock(keyContext, builder, gatherer, matrix);
665*c8dee2aaSAndroid Build Coastguard Worker }
666*c8dee2aaSAndroid Build Coastguard Worker
667*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fWrapped,
668*c8dee2aaSAndroid Build Coastguard Worker desiredWrappedCombination);
669*c8dee2aaSAndroid Build Coastguard Worker
670*c8dee2aaSAndroid Build Coastguard Worker if (desiredLMCombination == kWithLocalMatrix) {
671*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
672*c8dee2aaSAndroid Build Coastguard Worker }
673*c8dee2aaSAndroid Build Coastguard Worker }
674*c8dee2aaSAndroid Build Coastguard Worker
675*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fWrapped;
676*c8dee2aaSAndroid Build Coastguard Worker int fNumWrappedCombos;
677*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<Flags> fFlags;
678*c8dee2aaSAndroid Build Coastguard Worker };
679*c8dee2aaSAndroid Build Coastguard Worker
LocalMatrix(SkSpan<const sk_sp<PrecompileShader>> wrapped,bool isPerspective)680*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::LocalMatrix(
681*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> wrapped,
682*c8dee2aaSAndroid Build Coastguard Worker bool isPerspective) {
683*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileLocalMatrixShader>(
684*c8dee2aaSAndroid Build Coastguard Worker std::move(wrapped),
685*c8dee2aaSAndroid Build Coastguard Worker isPerspective ? PrecompileLocalMatrixShader::Flags::kIsPerspective
686*c8dee2aaSAndroid Build Coastguard Worker : PrecompileLocalMatrixShader::Flags::kNone);
687*c8dee2aaSAndroid Build Coastguard Worker }
688*c8dee2aaSAndroid Build Coastguard Worker
LocalMatrixBothVariants(SkSpan<const sk_sp<PrecompileShader>> wrapped)689*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::LocalMatrixBothVariants(
690*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> wrapped) {
691*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileLocalMatrixShader>(
692*c8dee2aaSAndroid Build Coastguard Worker std::move(wrapped),
693*c8dee2aaSAndroid Build Coastguard Worker PrecompileLocalMatrixShader::Flags::kIncludeWithOutVariant);
694*c8dee2aaSAndroid Build Coastguard Worker }
695*c8dee2aaSAndroid Build Coastguard Worker
makeWithLocalMatrix(bool isPerspective) const696*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShader::makeWithLocalMatrix(bool isPerspective) const {
697*c8dee2aaSAndroid Build Coastguard Worker if (this->priv().isALocalMatrixShader()) {
698*c8dee2aaSAndroid Build Coastguard Worker // SkShader::makeWithLocalMatrix collapses chains of localMatrix shaders so we need to
699*c8dee2aaSAndroid Build Coastguard Worker // follow suit here, folding in any new perspective flag if needed.
700*c8dee2aaSAndroid Build Coastguard Worker auto thisAsLMShader = static_cast<const PrecompileLocalMatrixShader*>(this);
701*c8dee2aaSAndroid Build Coastguard Worker if (isPerspective && !(thisAsLMShader->getFlags() &
702*c8dee2aaSAndroid Build Coastguard Worker PrecompileLocalMatrixShader::Flags::kIsPerspective)) {
703*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileLocalMatrixShader>(
704*c8dee2aaSAndroid Build Coastguard Worker thisAsLMShader->getWrapped(),
705*c8dee2aaSAndroid Build Coastguard Worker thisAsLMShader->getFlags() | PrecompileLocalMatrixShader::Flags::kIsPerspective);
706*c8dee2aaSAndroid Build Coastguard Worker }
707*c8dee2aaSAndroid Build Coastguard Worker
708*c8dee2aaSAndroid Build Coastguard Worker return sk_ref_sp(this);
709*c8dee2aaSAndroid Build Coastguard Worker }
710*c8dee2aaSAndroid Build Coastguard Worker
711*c8dee2aaSAndroid Build Coastguard Worker return PrecompileShaders::LocalMatrix({ sk_ref_sp(this) }, isPerspective);
712*c8dee2aaSAndroid Build Coastguard Worker }
713*c8dee2aaSAndroid Build Coastguard Worker
714*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
715*c8dee2aaSAndroid Build Coastguard Worker class PrecompileColorFilterShader final : public PrecompileShader {
716*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileColorFilterShader(SkSpan<const sk_sp<PrecompileShader>> shaders,SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters)717*c8dee2aaSAndroid Build Coastguard Worker PrecompileColorFilterShader(SkSpan<const sk_sp<PrecompileShader>> shaders,
718*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters)
719*c8dee2aaSAndroid Build Coastguard Worker : fShaders(shaders.begin(), shaders.end())
720*c8dee2aaSAndroid Build Coastguard Worker , fColorFilters(colorFilters.begin(), colorFilters.end()) {
721*c8dee2aaSAndroid Build Coastguard Worker fNumShaderCombos = 0;
722*c8dee2aaSAndroid Build Coastguard Worker for (const auto& s : fShaders) {
723*c8dee2aaSAndroid Build Coastguard Worker fNumShaderCombos += s->priv().numCombinations();
724*c8dee2aaSAndroid Build Coastguard Worker }
725*c8dee2aaSAndroid Build Coastguard Worker fNumColorFilterCombos = 0;
726*c8dee2aaSAndroid Build Coastguard Worker for (const auto& cf : fColorFilters) {
727*c8dee2aaSAndroid Build Coastguard Worker fNumColorFilterCombos += cf->priv().numCombinations();
728*c8dee2aaSAndroid Build Coastguard Worker }
729*c8dee2aaSAndroid Build Coastguard Worker }
730*c8dee2aaSAndroid Build Coastguard Worker
731*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const732*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumShaderCombos * fNumColorFilterCombos; }
733*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const734*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
735*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
736*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
737*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
738*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numCombinations());
739*c8dee2aaSAndroid Build Coastguard Worker
740*c8dee2aaSAndroid Build Coastguard Worker int desiredShaderCombination = desiredCombination % fNumShaderCombos;
741*c8dee2aaSAndroid Build Coastguard Worker int desiredColorFilterCombination = desiredCombination / fNumShaderCombos;
742*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredColorFilterCombination < fNumColorFilterCombos);
743*c8dee2aaSAndroid Build Coastguard Worker
744*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
745*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
746*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fShaders,
747*c8dee2aaSAndroid Build Coastguard Worker desiredShaderCombination);
748*c8dee2aaSAndroid Build Coastguard Worker },
749*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
750*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileColorFilter>(keyContext, builder, gatherer, fColorFilters,
751*c8dee2aaSAndroid Build Coastguard Worker desiredColorFilterCombination);
752*c8dee2aaSAndroid Build Coastguard Worker });
753*c8dee2aaSAndroid Build Coastguard Worker }
754*c8dee2aaSAndroid Build Coastguard Worker
755*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fShaders;
756*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileColorFilter>> fColorFilters;
757*c8dee2aaSAndroid Build Coastguard Worker int fNumShaderCombos;
758*c8dee2aaSAndroid Build Coastguard Worker int fNumColorFilterCombos;
759*c8dee2aaSAndroid Build Coastguard Worker };
760*c8dee2aaSAndroid Build Coastguard Worker
ColorFilter(SkSpan<const sk_sp<PrecompileShader>> shaders,SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters)761*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::ColorFilter(
762*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> shaders,
763*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters) {
764*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileColorFilterShader>(std::move(shaders), std::move(colorFilters));
765*c8dee2aaSAndroid Build Coastguard Worker }
766*c8dee2aaSAndroid Build Coastguard Worker
767*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
768*c8dee2aaSAndroid Build Coastguard Worker class PrecompileWorkingColorSpaceShader final : public PrecompileShader {
769*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileWorkingColorSpaceShader(SkSpan<const sk_sp<PrecompileShader>> shaders,SkSpan<const sk_sp<SkColorSpace>> colorSpaces)770*c8dee2aaSAndroid Build Coastguard Worker PrecompileWorkingColorSpaceShader(SkSpan<const sk_sp<PrecompileShader>> shaders,
771*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<SkColorSpace>> colorSpaces)
772*c8dee2aaSAndroid Build Coastguard Worker : fShaders(shaders.begin(), shaders.end())
773*c8dee2aaSAndroid Build Coastguard Worker , fColorSpaces(colorSpaces.begin(), colorSpaces.end()) {
774*c8dee2aaSAndroid Build Coastguard Worker fNumShaderCombos = 0;
775*c8dee2aaSAndroid Build Coastguard Worker for (const auto& s : fShaders) {
776*c8dee2aaSAndroid Build Coastguard Worker fNumShaderCombos += s->priv().numCombinations();
777*c8dee2aaSAndroid Build Coastguard Worker }
778*c8dee2aaSAndroid Build Coastguard Worker }
779*c8dee2aaSAndroid Build Coastguard Worker
780*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const781*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumShaderCombos * fColorSpaces.size(); }
782*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const783*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
784*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
785*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
786*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
787*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numCombinations());
788*c8dee2aaSAndroid Build Coastguard Worker
789*c8dee2aaSAndroid Build Coastguard Worker int desiredShaderCombination = desiredCombination % fNumShaderCombos;
790*c8dee2aaSAndroid Build Coastguard Worker int desiredColorSpaceCombination = desiredCombination / fNumShaderCombos;
791*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredColorSpaceCombination < (int) fColorSpaces.size());
792*c8dee2aaSAndroid Build Coastguard Worker
793*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& dstInfo = keyContext.dstColorInfo();
794*c8dee2aaSAndroid Build Coastguard Worker const SkAlphaType dstAT = dstInfo.alphaType();
795*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> dstCS = dstInfo.refColorSpace();
796*c8dee2aaSAndroid Build Coastguard Worker if (!dstCS) {
797*c8dee2aaSAndroid Build Coastguard Worker dstCS = SkColorSpace::MakeSRGB();
798*c8dee2aaSAndroid Build Coastguard Worker }
799*c8dee2aaSAndroid Build Coastguard Worker
800*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> workingCS = fColorSpaces[desiredColorSpaceCombination];
801*c8dee2aaSAndroid Build Coastguard Worker SkColorInfo workingInfo(dstInfo.colorType(), dstAT, workingCS);
802*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithColorInfo workingContext(keyContext, workingInfo);
803*c8dee2aaSAndroid Build Coastguard Worker
804*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
805*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
806*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fShaders,
807*c8dee2aaSAndroid Build Coastguard Worker desiredShaderCombination);
808*c8dee2aaSAndroid Build Coastguard Worker },
809*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
810*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData data(
811*c8dee2aaSAndroid Build Coastguard Worker workingCS.get(), dstAT, dstCS.get(), dstAT);
812*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, data);
813*c8dee2aaSAndroid Build Coastguard Worker });
814*c8dee2aaSAndroid Build Coastguard Worker }
815*c8dee2aaSAndroid Build Coastguard Worker
816*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fShaders;
817*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<SkColorSpace>> fColorSpaces;
818*c8dee2aaSAndroid Build Coastguard Worker int fNumShaderCombos;
819*c8dee2aaSAndroid Build Coastguard Worker };
820*c8dee2aaSAndroid Build Coastguard Worker
WorkingColorSpace(SkSpan<const sk_sp<PrecompileShader>> shaders,SkSpan<const sk_sp<SkColorSpace>> colorSpaces)821*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShaders::WorkingColorSpace(
822*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<PrecompileShader>> shaders,
823*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const sk_sp<SkColorSpace>> colorSpaces) {
824*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileWorkingColorSpaceShader>(std::move(shaders),
825*c8dee2aaSAndroid Build Coastguard Worker std::move(colorSpaces));
826*c8dee2aaSAndroid Build Coastguard Worker }
827*c8dee2aaSAndroid Build Coastguard Worker
828*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
829*c8dee2aaSAndroid Build Coastguard Worker // In Graphite this acts as a non-elidable LocalMatrixShader
830*c8dee2aaSAndroid Build Coastguard Worker class PrecompileCTMShader final : public PrecompileShader {
831*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileCTMShader(SkSpan<const sk_sp<PrecompileShader>> wrapped)832*c8dee2aaSAndroid Build Coastguard Worker PrecompileCTMShader(SkSpan<const sk_sp<PrecompileShader>> wrapped)
833*c8dee2aaSAndroid Build Coastguard Worker : fWrapped(wrapped.begin(), wrapped.end()) {
834*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos = 0;
835*c8dee2aaSAndroid Build Coastguard Worker for (const auto& s : fWrapped) {
836*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos += s->priv().numCombinations();
837*c8dee2aaSAndroid Build Coastguard Worker }
838*c8dee2aaSAndroid Build Coastguard Worker }
839*c8dee2aaSAndroid Build Coastguard Worker
isConstant(int desiredCombination) const840*c8dee2aaSAndroid Build Coastguard Worker bool isConstant(int desiredCombination) const override {
841*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < fNumWrappedCombos);
842*c8dee2aaSAndroid Build Coastguard Worker
843*c8dee2aaSAndroid Build Coastguard Worker std::pair<sk_sp<PrecompileShader>, int> wrapped =
844*c8dee2aaSAndroid Build Coastguard Worker PrecompileBase::SelectOption(SkSpan(fWrapped), desiredCombination);
845*c8dee2aaSAndroid Build Coastguard Worker if (wrapped.first) {
846*c8dee2aaSAndroid Build Coastguard Worker return wrapped.first->priv().isConstant(wrapped.second);
847*c8dee2aaSAndroid Build Coastguard Worker }
848*c8dee2aaSAndroid Build Coastguard Worker
849*c8dee2aaSAndroid Build Coastguard Worker return false;
850*c8dee2aaSAndroid Build Coastguard Worker }
851*c8dee2aaSAndroid Build Coastguard Worker
852*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const853*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumWrappedCombos; }
854*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const855*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
856*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
857*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
858*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
859*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < fNumWrappedCombos);
860*c8dee2aaSAndroid Build Coastguard Worker
861*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::LMShaderData kIgnoredLMShaderData(SkMatrix::I());
862*c8dee2aaSAndroid Build Coastguard Worker
863*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::BeginBlock(keyContext, builder, gatherer, kIgnoredLMShaderData);
864*c8dee2aaSAndroid Build Coastguard Worker
865*c8dee2aaSAndroid Build Coastguard Worker AddToKey<PrecompileShader>(keyContext, builder, gatherer, fWrapped, desiredCombination);
866*c8dee2aaSAndroid Build Coastguard Worker
867*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
868*c8dee2aaSAndroid Build Coastguard Worker }
869*c8dee2aaSAndroid Build Coastguard Worker
870*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<PrecompileShader>> fWrapped;
871*c8dee2aaSAndroid Build Coastguard Worker int fNumWrappedCombos;
872*c8dee2aaSAndroid Build Coastguard Worker };
873*c8dee2aaSAndroid Build Coastguard Worker
CTM(SkSpan<const sk_sp<PrecompileShader>> wrapped)874*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::CTM(SkSpan<const sk_sp<PrecompileShader>> wrapped) {
875*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileCTMShader>(std::move(wrapped));
876*c8dee2aaSAndroid Build Coastguard Worker }
877*c8dee2aaSAndroid Build Coastguard Worker
878*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
879*c8dee2aaSAndroid Build Coastguard Worker class PrecompileBlurShader final : public PrecompileShader {
880*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileBlurShader(sk_sp<PrecompileShader> wrapped)881*c8dee2aaSAndroid Build Coastguard Worker PrecompileBlurShader(sk_sp<PrecompileShader> wrapped)
882*c8dee2aaSAndroid Build Coastguard Worker : fWrapped(std::move(wrapped)) {
883*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos = fWrapped->priv().numCombinations();
884*c8dee2aaSAndroid Build Coastguard Worker }
885*c8dee2aaSAndroid Build Coastguard Worker
886*c8dee2aaSAndroid Build Coastguard Worker private:
887*c8dee2aaSAndroid Build Coastguard Worker // 6 known 1D blur effects + 6 known 2D blur effects
888*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumIntrinsicCombinations = 12;
889*c8dee2aaSAndroid Build Coastguard Worker
numIntrinsicCombinations() const890*c8dee2aaSAndroid Build Coastguard Worker int numIntrinsicCombinations() const override { return kNumIntrinsicCombinations; }
891*c8dee2aaSAndroid Build Coastguard Worker
numChildCombinations() const892*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumWrappedCombos; }
893*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const894*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
895*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
896*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
897*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
898*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numCombinations());
899*c8dee2aaSAndroid Build Coastguard Worker
900*c8dee2aaSAndroid Build Coastguard Worker using namespace SkKnownRuntimeEffects;
901*c8dee2aaSAndroid Build Coastguard Worker
902*c8dee2aaSAndroid Build Coastguard Worker int desiredBlurCombination = desiredCombination % kNumIntrinsicCombinations;
903*c8dee2aaSAndroid Build Coastguard Worker int desiredWrappedCombination = desiredCombination / kNumIntrinsicCombinations;
904*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredWrappedCombination < fNumWrappedCombos);
905*c8dee2aaSAndroid Build Coastguard Worker
906*c8dee2aaSAndroid Build Coastguard Worker static const StableKey kIDs[kNumIntrinsicCombinations] = {
907*c8dee2aaSAndroid Build Coastguard Worker StableKey::k1DBlur4, StableKey::k1DBlur8, StableKey::k1DBlur12,
908*c8dee2aaSAndroid Build Coastguard Worker StableKey::k1DBlur16, StableKey::k1DBlur20, StableKey::k1DBlur28,
909*c8dee2aaSAndroid Build Coastguard Worker
910*c8dee2aaSAndroid Build Coastguard Worker StableKey::k2DBlur4, StableKey::k2DBlur8, StableKey::k2DBlur12,
911*c8dee2aaSAndroid Build Coastguard Worker StableKey::k2DBlur16, StableKey::k2DBlur20, StableKey::k2DBlur28,
912*c8dee2aaSAndroid Build Coastguard Worker };
913*c8dee2aaSAndroid Build Coastguard Worker
914*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* fEffect = GetKnownRuntimeEffect(kIDs[desiredBlurCombination]);
915*c8dee2aaSAndroid Build Coastguard Worker
916*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
917*c8dee2aaSAndroid Build Coastguard Worker
918*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer, { sk_ref_sp(fEffect) });
919*c8dee2aaSAndroid Build Coastguard Worker fWrapped->priv().addToKey(childContext, builder, gatherer, desiredWrappedCombination);
920*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
921*c8dee2aaSAndroid Build Coastguard Worker }
922*c8dee2aaSAndroid Build Coastguard Worker
923*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fWrapped;
924*c8dee2aaSAndroid Build Coastguard Worker int fNumWrappedCombos;
925*c8dee2aaSAndroid Build Coastguard Worker };
926*c8dee2aaSAndroid Build Coastguard Worker
Blur(sk_sp<PrecompileShader> wrapped)927*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::Blur(sk_sp<PrecompileShader> wrapped) {
928*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileBlurShader>(std::move(wrapped));
929*c8dee2aaSAndroid Build Coastguard Worker }
930*c8dee2aaSAndroid Build Coastguard Worker
931*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
932*c8dee2aaSAndroid Build Coastguard Worker class PrecompileMatrixConvolutionShader final : public PrecompileShader {
933*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileMatrixConvolutionShader(sk_sp<PrecompileShader> wrapped)934*c8dee2aaSAndroid Build Coastguard Worker PrecompileMatrixConvolutionShader(sk_sp<PrecompileShader> wrapped)
935*c8dee2aaSAndroid Build Coastguard Worker : fWrapped(std::move(wrapped)) {
936*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos = fWrapped->priv().numCombinations();
937*c8dee2aaSAndroid Build Coastguard Worker
938*c8dee2aaSAndroid Build Coastguard Worker // When the matrix convolution ImageFilter uses a texture we know it will only ever
939*c8dee2aaSAndroid Build Coastguard Worker // be SkFilterMode::kNearest and SkTileMode::kClamp.
940*c8dee2aaSAndroid Build Coastguard Worker // TODO: add a PrecompileImageShaderFlags to further limit the raw image shader
941*c8dee2aaSAndroid Build Coastguard Worker // combinations. Right now we're getting two combinations for the raw shader
942*c8dee2aaSAndroid Build Coastguard Worker // (sk_image_shader and sk_hw_image_shader).
943*c8dee2aaSAndroid Build Coastguard Worker fRawImageShader =
944*c8dee2aaSAndroid Build Coastguard Worker PrecompileShadersPriv::RawImage(PrecompileImageShaderFlags::kExcludeCubic);
945*c8dee2aaSAndroid Build Coastguard Worker fNumRawImageShaderCombos = fRawImageShader->priv().numCombinations();
946*c8dee2aaSAndroid Build Coastguard Worker }
947*c8dee2aaSAndroid Build Coastguard Worker
948*c8dee2aaSAndroid Build Coastguard Worker private:
numIntrinsicCombinations() const949*c8dee2aaSAndroid Build Coastguard Worker int numIntrinsicCombinations() const override {
950*c8dee2aaSAndroid Build Coastguard Worker // The uniform version only has one option but the two texture-based versions will
951*c8dee2aaSAndroid Build Coastguard Worker // have as many combinations as the raw image shader.
952*c8dee2aaSAndroid Build Coastguard Worker return 1 + 2 * fNumRawImageShaderCombos;
953*c8dee2aaSAndroid Build Coastguard Worker }
954*c8dee2aaSAndroid Build Coastguard Worker
numChildCombinations() const955*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumWrappedCombos; }
956*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const957*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
958*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
959*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
960*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
961*c8dee2aaSAndroid Build Coastguard Worker
962*c8dee2aaSAndroid Build Coastguard Worker int desiredTextureCombination = 0;
963*c8dee2aaSAndroid Build Coastguard Worker
964*c8dee2aaSAndroid Build Coastguard Worker const int desiredWrappedCombination = desiredCombination % fNumWrappedCombos;
965*c8dee2aaSAndroid Build Coastguard Worker int remainingCombinations = desiredCombination / fNumWrappedCombos;
966*c8dee2aaSAndroid Build Coastguard Worker
967*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey stableKey = SkKnownRuntimeEffects::StableKey::kInvalid;
968*c8dee2aaSAndroid Build Coastguard Worker if (remainingCombinations == 0) {
969*c8dee2aaSAndroid Build Coastguard Worker stableKey = SkKnownRuntimeEffects::StableKey::kMatrixConvUniforms;
970*c8dee2aaSAndroid Build Coastguard Worker } else {
971*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkKnownRuntimeEffects::StableKey kTextureBasedStableKeys[] = {
972*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey::kMatrixConvTexSm,
973*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey::kMatrixConvTexLg,
974*c8dee2aaSAndroid Build Coastguard Worker };
975*c8dee2aaSAndroid Build Coastguard Worker
976*c8dee2aaSAndroid Build Coastguard Worker --remainingCombinations;
977*c8dee2aaSAndroid Build Coastguard Worker stableKey = kTextureBasedStableKeys[remainingCombinations % 2];
978*c8dee2aaSAndroid Build Coastguard Worker desiredTextureCombination = remainingCombinations / 2;
979*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredTextureCombination < fNumRawImageShaderCombos);
980*c8dee2aaSAndroid Build Coastguard Worker }
981*c8dee2aaSAndroid Build Coastguard Worker
982*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* fEffect = GetKnownRuntimeEffect(stableKey);
983*c8dee2aaSAndroid Build Coastguard Worker
984*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
985*c8dee2aaSAndroid Build Coastguard Worker
986*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer, { sk_ref_sp(fEffect) });
987*c8dee2aaSAndroid Build Coastguard Worker fWrapped->priv().addToKey(childContext, builder, gatherer, desiredWrappedCombination);
988*c8dee2aaSAndroid Build Coastguard Worker if (stableKey != SkKnownRuntimeEffects::StableKey::kMatrixConvUniforms) {
989*c8dee2aaSAndroid Build Coastguard Worker fRawImageShader->priv().addToKey(childContext, builder, gatherer,
990*c8dee2aaSAndroid Build Coastguard Worker desiredTextureCombination);
991*c8dee2aaSAndroid Build Coastguard Worker }
992*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
993*c8dee2aaSAndroid Build Coastguard Worker }
994*c8dee2aaSAndroid Build Coastguard Worker
995*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fWrapped;
996*c8dee2aaSAndroid Build Coastguard Worker int fNumWrappedCombos;
997*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fRawImageShader;
998*c8dee2aaSAndroid Build Coastguard Worker int fNumRawImageShaderCombos;
999*c8dee2aaSAndroid Build Coastguard Worker };
1000*c8dee2aaSAndroid Build Coastguard Worker
MatrixConvolution(sk_sp<skgpu::graphite::PrecompileShader> wrapped)1001*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::MatrixConvolution(
1002*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skgpu::graphite::PrecompileShader> wrapped) {
1003*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileMatrixConvolutionShader>(std::move(wrapped));
1004*c8dee2aaSAndroid Build Coastguard Worker }
1005*c8dee2aaSAndroid Build Coastguard Worker
1006*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1007*c8dee2aaSAndroid Build Coastguard Worker class PrecompileMorphologyShader final : public PrecompileShader {
1008*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileMorphologyShader(sk_sp<PrecompileShader> wrapped,SkKnownRuntimeEffects::StableKey stableKey)1009*c8dee2aaSAndroid Build Coastguard Worker PrecompileMorphologyShader(sk_sp<PrecompileShader> wrapped,
1010*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey stableKey)
1011*c8dee2aaSAndroid Build Coastguard Worker : fWrapped(std::move(wrapped))
1012*c8dee2aaSAndroid Build Coastguard Worker , fStableKey(stableKey) {
1013*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos = fWrapped->priv().numCombinations();
1014*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(stableKey == SkKnownRuntimeEffects::StableKey::kLinearMorphology ||
1015*c8dee2aaSAndroid Build Coastguard Worker stableKey == SkKnownRuntimeEffects::StableKey::kSparseMorphology);
1016*c8dee2aaSAndroid Build Coastguard Worker }
1017*c8dee2aaSAndroid Build Coastguard Worker
1018*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const1019*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumWrappedCombos; }
1020*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const1021*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
1022*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1023*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1024*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
1025*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < fNumWrappedCombos);
1026*c8dee2aaSAndroid Build Coastguard Worker
1027*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* effect = GetKnownRuntimeEffect(fStableKey);
1028*c8dee2aaSAndroid Build Coastguard Worker
1029*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
1030*c8dee2aaSAndroid Build Coastguard Worker
1031*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer, { sk_ref_sp(effect) });
1032*c8dee2aaSAndroid Build Coastguard Worker fWrapped->priv().addToKey(childContext, builder, gatherer, desiredCombination);
1033*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1034*c8dee2aaSAndroid Build Coastguard Worker }
1035*c8dee2aaSAndroid Build Coastguard Worker
1036*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fWrapped;
1037*c8dee2aaSAndroid Build Coastguard Worker int fNumWrappedCombos;
1038*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey fStableKey;
1039*c8dee2aaSAndroid Build Coastguard Worker };
1040*c8dee2aaSAndroid Build Coastguard Worker
LinearMorphology(sk_sp<PrecompileShader> wrapped)1041*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::LinearMorphology(sk_sp<PrecompileShader> wrapped) {
1042*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileMorphologyShader>(
1043*c8dee2aaSAndroid Build Coastguard Worker std::move(wrapped),
1044*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey::kLinearMorphology);
1045*c8dee2aaSAndroid Build Coastguard Worker }
1046*c8dee2aaSAndroid Build Coastguard Worker
SparseMorphology(sk_sp<PrecompileShader> wrapped)1047*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::SparseMorphology(sk_sp<PrecompileShader> wrapped) {
1048*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileMorphologyShader>(
1049*c8dee2aaSAndroid Build Coastguard Worker std::move(wrapped),
1050*c8dee2aaSAndroid Build Coastguard Worker SkKnownRuntimeEffects::StableKey::kSparseMorphology);
1051*c8dee2aaSAndroid Build Coastguard Worker }
1052*c8dee2aaSAndroid Build Coastguard Worker
1053*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1054*c8dee2aaSAndroid Build Coastguard Worker class PrecompileDisplacementShader final : public PrecompileShader {
1055*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileDisplacementShader(sk_sp<PrecompileShader> displacement,sk_sp<PrecompileShader> color)1056*c8dee2aaSAndroid Build Coastguard Worker PrecompileDisplacementShader(sk_sp<PrecompileShader> displacement,
1057*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> color)
1058*c8dee2aaSAndroid Build Coastguard Worker : fDisplacement(std::move(displacement))
1059*c8dee2aaSAndroid Build Coastguard Worker , fColor(std::move(color)) {
1060*c8dee2aaSAndroid Build Coastguard Worker fNumDisplacementCombos = fDisplacement->priv().numCombinations();
1061*c8dee2aaSAndroid Build Coastguard Worker fNumColorCombos = fColor->priv().numCombinations();
1062*c8dee2aaSAndroid Build Coastguard Worker }
1063*c8dee2aaSAndroid Build Coastguard Worker
1064*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const1065*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumDisplacementCombos * fNumColorCombos; }
1066*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const1067*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
1068*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1069*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1070*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
1071*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < this->numChildCombinations());
1072*c8dee2aaSAndroid Build Coastguard Worker
1073*c8dee2aaSAndroid Build Coastguard Worker const int desiredDisplacementCombination = desiredCombination % fNumDisplacementCombos;
1074*c8dee2aaSAndroid Build Coastguard Worker const int desiredColorCombination = desiredCombination / fNumDisplacementCombos;
1075*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredColorCombination < fNumColorCombos);
1076*c8dee2aaSAndroid Build Coastguard Worker
1077*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* fEffect =
1078*c8dee2aaSAndroid Build Coastguard Worker GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kDisplacement);
1079*c8dee2aaSAndroid Build Coastguard Worker
1080*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
1081*c8dee2aaSAndroid Build Coastguard Worker
1082*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer, { sk_ref_sp(fEffect) });
1083*c8dee2aaSAndroid Build Coastguard Worker fDisplacement->priv().addToKey(childContext, builder, gatherer,
1084*c8dee2aaSAndroid Build Coastguard Worker desiredDisplacementCombination);
1085*c8dee2aaSAndroid Build Coastguard Worker fColor->priv().addToKey(childContext, builder, gatherer,
1086*c8dee2aaSAndroid Build Coastguard Worker desiredColorCombination);
1087*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1088*c8dee2aaSAndroid Build Coastguard Worker }
1089*c8dee2aaSAndroid Build Coastguard Worker
1090*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fDisplacement;
1091*c8dee2aaSAndroid Build Coastguard Worker int fNumDisplacementCombos;
1092*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fColor;
1093*c8dee2aaSAndroid Build Coastguard Worker int fNumColorCombos;
1094*c8dee2aaSAndroid Build Coastguard Worker };
1095*c8dee2aaSAndroid Build Coastguard Worker
1096*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
Displacement(sk_sp<PrecompileShader> displacement,sk_sp<PrecompileShader> color)1097*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::Displacement(sk_sp<PrecompileShader> displacement,
1098*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> color) {
1099*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileDisplacementShader>(std::move(displacement), std::move(color));
1100*c8dee2aaSAndroid Build Coastguard Worker }
1101*c8dee2aaSAndroid Build Coastguard Worker
1102*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1103*c8dee2aaSAndroid Build Coastguard Worker class PrecompileLightingShader final : public PrecompileShader {
1104*c8dee2aaSAndroid Build Coastguard Worker public:
PrecompileLightingShader(sk_sp<PrecompileShader> wrapped)1105*c8dee2aaSAndroid Build Coastguard Worker PrecompileLightingShader(sk_sp<PrecompileShader> wrapped)
1106*c8dee2aaSAndroid Build Coastguard Worker : fWrapped(std::move(wrapped)) {
1107*c8dee2aaSAndroid Build Coastguard Worker fNumWrappedCombos = fWrapped->priv().numCombinations();
1108*c8dee2aaSAndroid Build Coastguard Worker }
1109*c8dee2aaSAndroid Build Coastguard Worker
1110*c8dee2aaSAndroid Build Coastguard Worker private:
numChildCombinations() const1111*c8dee2aaSAndroid Build Coastguard Worker int numChildCombinations() const override { return fNumWrappedCombos; }
1112*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,int desiredCombination) const1113*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const KeyContext& keyContext,
1114*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1115*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1116*c8dee2aaSAndroid Build Coastguard Worker int desiredCombination) const override {
1117*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredCombination < fNumWrappedCombos);
1118*c8dee2aaSAndroid Build Coastguard Worker
1119*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* normalEffect =
1120*c8dee2aaSAndroid Build Coastguard Worker GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kNormal);
1121*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* lightingEffect =
1122*c8dee2aaSAndroid Build Coastguard Worker GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kLighting);
1123*c8dee2aaSAndroid Build Coastguard Worker
1124*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
1125*c8dee2aaSAndroid Build Coastguard Worker
1126*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer,
1127*c8dee2aaSAndroid Build Coastguard Worker { sk_ref_sp(lightingEffect) });
1128*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(childContext, builder, gatherer,
1129*c8dee2aaSAndroid Build Coastguard Worker { sk_ref_sp(normalEffect) });
1130*c8dee2aaSAndroid Build Coastguard Worker fWrapped->priv().addToKey(childContext, builder, gatherer, desiredCombination);
1131*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1132*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1133*c8dee2aaSAndroid Build Coastguard Worker }
1134*c8dee2aaSAndroid Build Coastguard Worker
1135*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> fWrapped;
1136*c8dee2aaSAndroid Build Coastguard Worker int fNumWrappedCombos;
1137*c8dee2aaSAndroid Build Coastguard Worker };
1138*c8dee2aaSAndroid Build Coastguard Worker
Lighting(sk_sp<PrecompileShader> wrapped)1139*c8dee2aaSAndroid Build Coastguard Worker sk_sp<PrecompileShader> PrecompileShadersPriv::Lighting(sk_sp<PrecompileShader> wrapped) {
1140*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<PrecompileLightingShader>(std::move(wrapped));
1141*c8dee2aaSAndroid Build Coastguard Worker }
1142*c8dee2aaSAndroid Build Coastguard Worker
1143*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1144*c8dee2aaSAndroid Build Coastguard Worker
1145*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
1146