xref: /aosp_15_r20/external/skia/src/gpu/graphite/precompile/PaintOptions.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/PaintOptions.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileBlender.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileImageFilter.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileMaskFilter.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileShader.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextUtils.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyContext.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParamsKey.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PrecompileInternal.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Renderer.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ShaderCodeDictionary.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PaintOption.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PaintOptionsPriv.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 PaintOptions::PaintOptions() = default;
33*c8dee2aaSAndroid Build Coastguard Worker PaintOptions::PaintOptions(const PaintOptions&) = default;
34*c8dee2aaSAndroid Build Coastguard Worker PaintOptions::~PaintOptions() = default;
35*c8dee2aaSAndroid Build Coastguard Worker PaintOptions& PaintOptions::operator=(const PaintOptions&) = default;
36*c8dee2aaSAndroid Build Coastguard Worker 
setShaders(SkSpan<const sk_sp<PrecompileShader>> shaders)37*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setShaders(SkSpan<const sk_sp<PrecompileShader>> shaders) {
38*c8dee2aaSAndroid Build Coastguard Worker     fShaderOptions.clear();
39*c8dee2aaSAndroid Build Coastguard Worker     fShaderOptions.push_back_n(shaders.size(), shaders.data());
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker 
setImageFilters(SkSpan<const sk_sp<PrecompileImageFilter>> imageFilters)42*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setImageFilters(SkSpan<const sk_sp<PrecompileImageFilter>> imageFilters) {
43*c8dee2aaSAndroid Build Coastguard Worker     fImageFilterOptions.clear();
44*c8dee2aaSAndroid Build Coastguard Worker     fImageFilterOptions.push_back_n(imageFilters.size(), imageFilters.data());
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker 
setMaskFilters(SkSpan<const sk_sp<PrecompileMaskFilter>> maskFilters)47*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setMaskFilters(SkSpan<const sk_sp<PrecompileMaskFilter>> maskFilters) {
48*c8dee2aaSAndroid Build Coastguard Worker     fMaskFilterOptions.clear();
49*c8dee2aaSAndroid Build Coastguard Worker     fMaskFilterOptions.push_back_n(maskFilters.size(), maskFilters.data());
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker 
setColorFilters(SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters)52*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setColorFilters(SkSpan<const sk_sp<PrecompileColorFilter>> colorFilters) {
53*c8dee2aaSAndroid Build Coastguard Worker     fColorFilterOptions.clear();
54*c8dee2aaSAndroid Build Coastguard Worker     fColorFilterOptions.push_back_n(colorFilters.size(), colorFilters.data());
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker 
addColorFilter(sk_sp<PrecompileColorFilter> cf)57*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::addColorFilter(sk_sp<PrecompileColorFilter> cf) {
58*c8dee2aaSAndroid Build Coastguard Worker     fColorFilterOptions.push_back(std::move(cf));
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker 
setBlendModes(SkSpan<const SkBlendMode> blendModes)61*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setBlendModes(SkSpan<const SkBlendMode> blendModes) {
62*c8dee2aaSAndroid Build Coastguard Worker     fBlendModeOptions.clear();
63*c8dee2aaSAndroid Build Coastguard Worker     fBlendModeOptions.push_back_n(blendModes.size(), blendModes.data());
64*c8dee2aaSAndroid Build Coastguard Worker }
65*c8dee2aaSAndroid Build Coastguard Worker 
setBlenders(SkSpan<const sk_sp<PrecompileBlender>> blenders)66*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setBlenders(SkSpan<const sk_sp<PrecompileBlender>> blenders) {
67*c8dee2aaSAndroid Build Coastguard Worker     for (const sk_sp<PrecompileBlender>& b: blenders) {
68*c8dee2aaSAndroid Build Coastguard Worker         if (b->priv().asBlendMode().has_value()) {
69*c8dee2aaSAndroid Build Coastguard Worker             fBlendModeOptions.push_back(b->priv().asBlendMode().value());
70*c8dee2aaSAndroid Build Coastguard Worker         } else {
71*c8dee2aaSAndroid Build Coastguard Worker             fBlenderOptions.push_back(b);
72*c8dee2aaSAndroid Build Coastguard Worker         }
73*c8dee2aaSAndroid Build Coastguard Worker     }
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker 
setClipShaders(SkSpan<const sk_sp<PrecompileShader>> clipShaders)76*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::setClipShaders(SkSpan<const sk_sp<PrecompileShader>> clipShaders) {
77*c8dee2aaSAndroid Build Coastguard Worker     // In the normal API this modification happens in SkDevice::clipShader()
78*c8dee2aaSAndroid Build Coastguard Worker     fClipShaderOptions.reserve(2 * clipShaders.size());
79*c8dee2aaSAndroid Build Coastguard Worker     for (const sk_sp<PrecompileShader>& cs : clipShaders) {
80*c8dee2aaSAndroid Build Coastguard Worker         // All clipShaders get wrapped in a CTMShader ...
81*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<PrecompileShader> withCTM = cs ? PrecompileShadersPriv::CTM({ cs }) : nullptr;
82*c8dee2aaSAndroid Build Coastguard Worker         // and, if it is a SkClipOp::kDifference clip, an additional ColorFilterShader
83*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<PrecompileShader> inverted =
84*c8dee2aaSAndroid Build Coastguard Worker                 withCTM ? withCTM->makeWithColorFilter(PrecompileColorFilters::Blend())
85*c8dee2aaSAndroid Build Coastguard Worker                         : nullptr;
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker         fClipShaderOptions.emplace_back(std::move(withCTM));
88*c8dee2aaSAndroid Build Coastguard Worker         fClipShaderOptions.emplace_back(std::move(inverted));
89*c8dee2aaSAndroid Build Coastguard Worker     }
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker 
numShaderCombinations() const92*c8dee2aaSAndroid Build Coastguard Worker int PaintOptions::numShaderCombinations() const {
93*c8dee2aaSAndroid Build Coastguard Worker     int numShaderCombinations = 0;
94*c8dee2aaSAndroid Build Coastguard Worker     for (const sk_sp<PrecompileShader>& s : fShaderOptions) {
95*c8dee2aaSAndroid Build Coastguard Worker         numShaderCombinations += s->numCombinations();
96*c8dee2aaSAndroid Build Coastguard Worker     }
97*c8dee2aaSAndroid Build Coastguard Worker 
98*c8dee2aaSAndroid Build Coastguard Worker     // If no shader option is specified we will add a solid color shader option
99*c8dee2aaSAndroid Build Coastguard Worker     return numShaderCombinations ? numShaderCombinations : 1;
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker 
numColorFilterCombinations() const102*c8dee2aaSAndroid Build Coastguard Worker int PaintOptions::numColorFilterCombinations() const {
103*c8dee2aaSAndroid Build Coastguard Worker     int numColorFilterCombinations = 0;
104*c8dee2aaSAndroid Build Coastguard Worker     for (const sk_sp<PrecompileColorFilter>& cf : fColorFilterOptions) {
105*c8dee2aaSAndroid Build Coastguard Worker         if (!cf) {
106*c8dee2aaSAndroid Build Coastguard Worker             ++numColorFilterCombinations;
107*c8dee2aaSAndroid Build Coastguard Worker         } else {
108*c8dee2aaSAndroid Build Coastguard Worker             numColorFilterCombinations += cf->numCombinations();
109*c8dee2aaSAndroid Build Coastguard Worker         }
110*c8dee2aaSAndroid Build Coastguard Worker     }
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker     // If no color filter options are specified we will use the unmodified result color
113*c8dee2aaSAndroid Build Coastguard Worker     return numColorFilterCombinations ? numColorFilterCombinations : 1;
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker 
numBlendCombinations() const116*c8dee2aaSAndroid Build Coastguard Worker int PaintOptions::numBlendCombinations() const {
117*c8dee2aaSAndroid Build Coastguard Worker     int numBlendCombos = fBlendModeOptions.size();
118*c8dee2aaSAndroid Build Coastguard Worker     for (const sk_sp<PrecompileBlender>& b: fBlenderOptions) {
119*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!b->priv().asBlendMode().has_value());
120*c8dee2aaSAndroid Build Coastguard Worker         numBlendCombos += b->priv().numChildCombinations();
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker     if (!numBlendCombos) {
124*c8dee2aaSAndroid Build Coastguard Worker         // If the user didn't specify a blender we will fall back to kSrcOver blending
125*c8dee2aaSAndroid Build Coastguard Worker         numBlendCombos = 1;
126*c8dee2aaSAndroid Build Coastguard Worker     }
127*c8dee2aaSAndroid Build Coastguard Worker 
128*c8dee2aaSAndroid Build Coastguard Worker     return numBlendCombos;
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker 
numClipShaderCombinations() const131*c8dee2aaSAndroid Build Coastguard Worker int PaintOptions::numClipShaderCombinations() const {
132*c8dee2aaSAndroid Build Coastguard Worker     int numClipShaderCombos = 0;
133*c8dee2aaSAndroid Build Coastguard Worker     for (const sk_sp<PrecompileShader>& cs: fClipShaderOptions) {
134*c8dee2aaSAndroid Build Coastguard Worker         if (cs) {
135*c8dee2aaSAndroid Build Coastguard Worker             numClipShaderCombos += cs->priv().numChildCombinations();
136*c8dee2aaSAndroid Build Coastguard Worker         } else {
137*c8dee2aaSAndroid Build Coastguard Worker             ++numClipShaderCombos;
138*c8dee2aaSAndroid Build Coastguard Worker         }
139*c8dee2aaSAndroid Build Coastguard Worker     }
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     // If no clipShader options are specified we will just have the unclipped options
142*c8dee2aaSAndroid Build Coastguard Worker     return numClipShaderCombos ? numClipShaderCombos : 1;
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker 
numCombinations() const145*c8dee2aaSAndroid Build Coastguard Worker int PaintOptions::numCombinations() const {
146*c8dee2aaSAndroid Build Coastguard Worker     return this->numShaderCombinations() *
147*c8dee2aaSAndroid Build Coastguard Worker            this->numColorFilterCombinations() *
148*c8dee2aaSAndroid Build Coastguard Worker            this->numBlendCombinations() *
149*c8dee2aaSAndroid Build Coastguard Worker            this->numClipShaderCombinations();
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker namespace {
153*c8dee2aaSAndroid Build Coastguard Worker 
get_dst_read_req(const Caps * caps,Coverage coverage,PrecompileBlender * blender)154*c8dee2aaSAndroid Build Coastguard Worker DstReadRequirement get_dst_read_req(const Caps* caps,
155*c8dee2aaSAndroid Build Coastguard Worker                                     Coverage coverage,
156*c8dee2aaSAndroid Build Coastguard Worker                                     PrecompileBlender* blender) {
157*c8dee2aaSAndroid Build Coastguard Worker     if (blender) {
158*c8dee2aaSAndroid Build Coastguard Worker         return GetDstReadRequirement(caps, blender->priv().asBlendMode(), coverage);
159*c8dee2aaSAndroid Build Coastguard Worker     }
160*c8dee2aaSAndroid Build Coastguard Worker     return GetDstReadRequirement(caps, SkBlendMode::kSrcOver, coverage);
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
164*c8dee2aaSAndroid Build Coastguard Worker 
createKey(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer,int desiredCombination,bool addPrimitiveBlender,Coverage coverage) const165*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::createKey(const KeyContext& keyContext,
166*c8dee2aaSAndroid Build Coastguard Worker                              PaintParamsKeyBuilder* keyBuilder,
167*c8dee2aaSAndroid Build Coastguard Worker                              PipelineDataGatherer* gatherer,
168*c8dee2aaSAndroid Build Coastguard Worker                              int desiredCombination,
169*c8dee2aaSAndroid Build Coastguard Worker                              bool addPrimitiveBlender,
170*c8dee2aaSAndroid Build Coastguard Worker                              Coverage coverage) const {
171*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(keyBuilder->checkReset();)
172*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(desiredCombination < this->numCombinations());
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     const int numClipShaderCombos = this->numClipShaderCombinations();
175*c8dee2aaSAndroid Build Coastguard Worker     const int numBlendModeCombos = this->numBlendCombinations();
176*c8dee2aaSAndroid Build Coastguard Worker     const int numColorFilterCombinations = this->numColorFilterCombinations();
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker     const int desiredClipShaderCombination = desiredCombination % numClipShaderCombos;
179*c8dee2aaSAndroid Build Coastguard Worker     int remainingCombinations = desiredCombination / numClipShaderCombos;
180*c8dee2aaSAndroid Build Coastguard Worker 
181*c8dee2aaSAndroid Build Coastguard Worker     const int desiredBlendCombination = remainingCombinations % numBlendModeCombos;
182*c8dee2aaSAndroid Build Coastguard Worker     remainingCombinations /= numBlendModeCombos;
183*c8dee2aaSAndroid Build Coastguard Worker 
184*c8dee2aaSAndroid Build Coastguard Worker     const int desiredColorFilterCombination = remainingCombinations % numColorFilterCombinations;
185*c8dee2aaSAndroid Build Coastguard Worker     remainingCombinations /= numColorFilterCombinations;
186*c8dee2aaSAndroid Build Coastguard Worker 
187*c8dee2aaSAndroid Build Coastguard Worker     const int desiredShaderCombination = remainingCombinations;
188*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(desiredShaderCombination < this->numShaderCombinations());
189*c8dee2aaSAndroid Build Coastguard Worker 
190*c8dee2aaSAndroid Build Coastguard Worker     // TODO: this probably needs to be passed in just like addPrimitiveBlender
191*c8dee2aaSAndroid Build Coastguard Worker     const bool kOpaquePaintColor = true;
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker     auto clipShader = PrecompileBase::SelectOption(SkSpan(fClipShaderOptions),
194*c8dee2aaSAndroid Build Coastguard Worker                                                    desiredClipShaderCombination);
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker     std::pair<sk_sp<PrecompileBlender>, int> finalBlender;
197*c8dee2aaSAndroid Build Coastguard Worker     if (desiredBlendCombination < fBlendModeOptions.size()) {
198*c8dee2aaSAndroid Build Coastguard Worker         finalBlender = { PrecompileBlenders::Mode(fBlendModeOptions[desiredBlendCombination]), 0 };
199*c8dee2aaSAndroid Build Coastguard Worker     } else {
200*c8dee2aaSAndroid Build Coastguard Worker         finalBlender = PrecompileBase::SelectOption(
201*c8dee2aaSAndroid Build Coastguard Worker                             SkSpan(fBlenderOptions),
202*c8dee2aaSAndroid Build Coastguard Worker                             desiredBlendCombination - fBlendModeOptions.size());
203*c8dee2aaSAndroid Build Coastguard Worker     }
204*c8dee2aaSAndroid Build Coastguard Worker     if (!finalBlender.first) {
205*c8dee2aaSAndroid Build Coastguard Worker         finalBlender = { PrecompileBlenders::Mode(SkBlendMode::kSrcOver), 0 };
206*c8dee2aaSAndroid Build Coastguard Worker     }
207*c8dee2aaSAndroid Build Coastguard Worker     DstReadRequirement dstReadReq = get_dst_read_req(keyContext.caps(), coverage,
208*c8dee2aaSAndroid Build Coastguard Worker                                                      finalBlender.first.get());
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker     PaintOption option(kOpaquePaintColor,
211*c8dee2aaSAndroid Build Coastguard Worker                        finalBlender,
212*c8dee2aaSAndroid Build Coastguard Worker                        PrecompileBase::SelectOption(SkSpan(fShaderOptions),
213*c8dee2aaSAndroid Build Coastguard Worker                                                     desiredShaderCombination),
214*c8dee2aaSAndroid Build Coastguard Worker                        PrecompileBase::SelectOption(SkSpan(fColorFilterOptions),
215*c8dee2aaSAndroid Build Coastguard Worker                                                     desiredColorFilterCombination),
216*c8dee2aaSAndroid Build Coastguard Worker                        addPrimitiveBlender,
217*c8dee2aaSAndroid Build Coastguard Worker                        clipShader,
218*c8dee2aaSAndroid Build Coastguard Worker                        dstReadReq,
219*c8dee2aaSAndroid Build Coastguard Worker                        fDither);
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     option.toKey(keyContext, keyBuilder, gatherer);
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker namespace {
225*c8dee2aaSAndroid Build Coastguard Worker 
create_image_drawing_pipelines(const KeyContext & keyContext,PipelineDataGatherer * gatherer,const PaintOptions & orig,const RenderPassDesc & renderPassDesc,const PaintOptionsPriv::ProcessCombination & processCombination)226*c8dee2aaSAndroid Build Coastguard Worker void create_image_drawing_pipelines(const KeyContext& keyContext,
227*c8dee2aaSAndroid Build Coastguard Worker                                     PipelineDataGatherer* gatherer,
228*c8dee2aaSAndroid Build Coastguard Worker                                     const PaintOptions& orig,
229*c8dee2aaSAndroid Build Coastguard Worker                                     const RenderPassDesc& renderPassDesc,
230*c8dee2aaSAndroid Build Coastguard Worker                                     const PaintOptionsPriv::ProcessCombination& processCombination) {
231*c8dee2aaSAndroid Build Coastguard Worker     PaintOptions imagePaintOptions;
232*c8dee2aaSAndroid Build Coastguard Worker 
233*c8dee2aaSAndroid Build Coastguard Worker     // For imagefilters we know we don't have alpha-only textures and don't need cubic filtering.
234*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<PrecompileShader> imageShader = PrecompileShadersPriv::Image(
235*c8dee2aaSAndroid Build Coastguard Worker             PrecompileImageShaderFlags::kExcludeAlpha | PrecompileImageShaderFlags::kExcludeCubic);
236*c8dee2aaSAndroid Build Coastguard Worker 
237*c8dee2aaSAndroid Build Coastguard Worker     imagePaintOptions.setShaders({ imageShader });
238*c8dee2aaSAndroid Build Coastguard Worker     imagePaintOptions.setBlendModes(orig.getBlendModes());
239*c8dee2aaSAndroid Build Coastguard Worker     imagePaintOptions.setBlenders(orig.getBlenders());
240*c8dee2aaSAndroid Build Coastguard Worker     imagePaintOptions.setColorFilters(orig.getColorFilters());
241*c8dee2aaSAndroid Build Coastguard Worker     imagePaintOptions.priv().addColorFilter(nullptr);
242*c8dee2aaSAndroid Build Coastguard Worker 
243*c8dee2aaSAndroid Build Coastguard Worker     imagePaintOptions.priv().buildCombinations(keyContext,
244*c8dee2aaSAndroid Build Coastguard Worker                                                gatherer,
245*c8dee2aaSAndroid Build Coastguard Worker                                                DrawTypeFlags::kSimpleShape,
246*c8dee2aaSAndroid Build Coastguard Worker                                                /* withPrimitiveBlender= */ false,
247*c8dee2aaSAndroid Build Coastguard Worker                                                Coverage::kSingleChannel,
248*c8dee2aaSAndroid Build Coastguard Worker                                                renderPassDesc,
249*c8dee2aaSAndroid Build Coastguard Worker                                                processCombination);
250*c8dee2aaSAndroid Build Coastguard Worker }
251*c8dee2aaSAndroid Build Coastguard Worker 
252*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
253*c8dee2aaSAndroid Build Coastguard Worker 
buildCombinations(const KeyContext & keyContext,PipelineDataGatherer * gatherer,DrawTypeFlags drawTypes,bool withPrimitiveBlender,Coverage coverage,const RenderPassDesc & renderPassDesc,const ProcessCombination & processCombination) const254*c8dee2aaSAndroid Build Coastguard Worker void PaintOptions::buildCombinations(
255*c8dee2aaSAndroid Build Coastguard Worker         const KeyContext& keyContext,
256*c8dee2aaSAndroid Build Coastguard Worker         PipelineDataGatherer* gatherer,
257*c8dee2aaSAndroid Build Coastguard Worker         DrawTypeFlags drawTypes,
258*c8dee2aaSAndroid Build Coastguard Worker         bool withPrimitiveBlender,
259*c8dee2aaSAndroid Build Coastguard Worker         Coverage coverage,
260*c8dee2aaSAndroid Build Coastguard Worker         const RenderPassDesc& renderPassDesc,
261*c8dee2aaSAndroid Build Coastguard Worker         const ProcessCombination& processCombination) const {
262*c8dee2aaSAndroid Build Coastguard Worker 
263*c8dee2aaSAndroid Build Coastguard Worker     PaintParamsKeyBuilder builder(keyContext.dict());
264*c8dee2aaSAndroid Build Coastguard Worker 
265*c8dee2aaSAndroid Build Coastguard Worker     if (!fImageFilterOptions.empty() || !fMaskFilterOptions.empty()) {
266*c8dee2aaSAndroid Build Coastguard Worker         // TODO: split this out into a create_restore_draw_pipelines method
267*c8dee2aaSAndroid Build Coastguard Worker         PaintOptions tmp = *this;
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker         // When image filtering, the original blend mode is taken over by the restore paint
270*c8dee2aaSAndroid Build Coastguard Worker         tmp.setImageFilters({});
271*c8dee2aaSAndroid Build Coastguard Worker         tmp.setMaskFilters({});
272*c8dee2aaSAndroid Build Coastguard Worker         tmp.addBlendMode(SkBlendMode::kSrcOver);
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker         if (!fImageFilterOptions.empty()) {
275*c8dee2aaSAndroid Build Coastguard Worker             std::vector<sk_sp<PrecompileColorFilter>> newCFs(tmp.fColorFilterOptions.begin(),
276*c8dee2aaSAndroid Build Coastguard Worker                                                              tmp.fColorFilterOptions.end());
277*c8dee2aaSAndroid Build Coastguard Worker             if (newCFs.empty()) {
278*c8dee2aaSAndroid Build Coastguard Worker                 // TODO: I (robertphillips) believe this is unnecessary and is just a result of the
279*c8dee2aaSAndroid Build Coastguard Worker                 // base SkPaint generated in the PaintParamsKeyTest not correctly taking CFIFs into
280*c8dee2aaSAndroid Build Coastguard Worker                 // account.
281*c8dee2aaSAndroid Build Coastguard Worker                 newCFs.push_back(nullptr);
282*c8dee2aaSAndroid Build Coastguard Worker             }
283*c8dee2aaSAndroid Build Coastguard Worker 
284*c8dee2aaSAndroid Build Coastguard Worker             // As in SkCanvasPriv::ImageToColorFilter, we fuse CFIFs into the base draw's CFs.
285*c8dee2aaSAndroid Build Coastguard Worker             // TODO: in SkCanvasPriv::ImageToColorFilter this fusing of CFIFs and CFs is skipped
286*c8dee2aaSAndroid Build Coastguard Worker             // when there is a maskfilter. For now we over-generate.
287*c8dee2aaSAndroid Build Coastguard Worker             for (const sk_sp<PrecompileImageFilter>& o : fImageFilterOptions) {
288*c8dee2aaSAndroid Build Coastguard Worker                 sk_sp<PrecompileColorFilter> imageFiltersCF = o ? o->asAColorFilter() : nullptr;
289*c8dee2aaSAndroid Build Coastguard Worker                 if (imageFiltersCF) {
290*c8dee2aaSAndroid Build Coastguard Worker                     if (!tmp.fColorFilterOptions.empty()) {
291*c8dee2aaSAndroid Build Coastguard Worker                         for (const sk_sp<PrecompileColorFilter>& cf : tmp.fColorFilterOptions) {
292*c8dee2aaSAndroid Build Coastguard Worker                             // TODO: if a CFIF was fully handled here it should be removed from the
293*c8dee2aaSAndroid Build Coastguard Worker                             // later loop over fImageFilterOptions. For now we over-generate.
294*c8dee2aaSAndroid Build Coastguard Worker                             sk_sp<PrecompileColorFilter> newCF = imageFiltersCF->makeComposed(cf);
295*c8dee2aaSAndroid Build Coastguard Worker                             newCFs.push_back(std::move(newCF));
296*c8dee2aaSAndroid Build Coastguard Worker                         }
297*c8dee2aaSAndroid Build Coastguard Worker                     } else {
298*c8dee2aaSAndroid Build Coastguard Worker                         newCFs.push_back(imageFiltersCF);
299*c8dee2aaSAndroid Build Coastguard Worker                     }
300*c8dee2aaSAndroid Build Coastguard Worker                 }
301*c8dee2aaSAndroid Build Coastguard Worker             }
302*c8dee2aaSAndroid Build Coastguard Worker 
303*c8dee2aaSAndroid Build Coastguard Worker             tmp.setColorFilters(newCFs);
304*c8dee2aaSAndroid Build Coastguard Worker         }
305*c8dee2aaSAndroid Build Coastguard Worker 
306*c8dee2aaSAndroid Build Coastguard Worker         tmp.buildCombinations(keyContext, gatherer, drawTypes, withPrimitiveBlender, coverage,
307*c8dee2aaSAndroid Build Coastguard Worker                               renderPassDesc, processCombination);
308*c8dee2aaSAndroid Build Coastguard Worker 
309*c8dee2aaSAndroid Build Coastguard Worker         create_image_drawing_pipelines(keyContext, gatherer, *this,
310*c8dee2aaSAndroid Build Coastguard Worker                                        renderPassDesc, processCombination);
311*c8dee2aaSAndroid Build Coastguard Worker 
312*c8dee2aaSAndroid Build Coastguard Worker         for (const sk_sp<PrecompileImageFilter>& o : fImageFilterOptions) {
313*c8dee2aaSAndroid Build Coastguard Worker             o->createPipelines(keyContext, gatherer, renderPassDesc, processCombination);
314*c8dee2aaSAndroid Build Coastguard Worker         }
315*c8dee2aaSAndroid Build Coastguard Worker         for (const sk_sp<PrecompileMaskFilter>& o : fMaskFilterOptions) {
316*c8dee2aaSAndroid Build Coastguard Worker             o->createPipelines(keyContext, gatherer, *this, renderPassDesc, processCombination);
317*c8dee2aaSAndroid Build Coastguard Worker         }
318*c8dee2aaSAndroid Build Coastguard Worker     } else {
319*c8dee2aaSAndroid Build Coastguard Worker         int numCombinations = this->numCombinations();
320*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < numCombinations; ++i) {
321*c8dee2aaSAndroid Build Coastguard Worker             // Since the precompilation path's uniforms aren't used and don't change the key,
322*c8dee2aaSAndroid Build Coastguard Worker             // the exact layout doesn't matter
323*c8dee2aaSAndroid Build Coastguard Worker             gatherer->resetWithNewLayout(Layout::kMetal);
324*c8dee2aaSAndroid Build Coastguard Worker 
325*c8dee2aaSAndroid Build Coastguard Worker             this->createKey(keyContext, &builder, gatherer, i, withPrimitiveBlender, coverage);
326*c8dee2aaSAndroid Build Coastguard Worker 
327*c8dee2aaSAndroid Build Coastguard Worker             // The 'findOrCreate' calls lockAsKey on builder and then destroys the returned
328*c8dee2aaSAndroid Build Coastguard Worker             // PaintParamsKey. This serves to reset the builder.
329*c8dee2aaSAndroid Build Coastguard Worker             UniquePaintParamsID paintID = keyContext.dict()->findOrCreate(&builder);
330*c8dee2aaSAndroid Build Coastguard Worker 
331*c8dee2aaSAndroid Build Coastguard Worker             processCombination(paintID, drawTypes, withPrimitiveBlender, coverage, renderPassDesc);
332*c8dee2aaSAndroid Build Coastguard Worker         }
333*c8dee2aaSAndroid Build Coastguard Worker     }
334*c8dee2aaSAndroid Build Coastguard Worker }
335*c8dee2aaSAndroid Build Coastguard Worker 
addColorFilter(sk_sp<PrecompileColorFilter> cf)336*c8dee2aaSAndroid Build Coastguard Worker void PaintOptionsPriv::addColorFilter(sk_sp<PrecompileColorFilter> cf) {
337*c8dee2aaSAndroid Build Coastguard Worker     fPaintOptions->addColorFilter(std::move(cf));
338*c8dee2aaSAndroid Build Coastguard Worker }
339*c8dee2aaSAndroid Build Coastguard Worker 
340*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
341