1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 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 "src/gpu/graphite/KeyHelpers.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkRuntimeEffect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkHalf.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBlendModeBlender.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBlenderBase.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorSpacePriv.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkDebugUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRuntimeBlender.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRuntimeEffectPriv.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkYUVMath.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkBlendModeColorFilter.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkColorFilterBase.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkColorSpaceXformColorFilter.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkComposeColorFilter.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkGaussianColorFilter.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkMatrixColorFilter.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkRuntimeColorFilter.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkTableColorFilter.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkWorkingFormatColorFilter.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Blend.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/DitherUtils.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/DrawContext.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Image_Base_Graphite.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Image_Graphite.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Image_YUVA_Graphite.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyContext.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyHelpers.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParams.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParamsKey.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PipelineData.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ReadSwizzle.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceProvider.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RuntimeEffectDictionary.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ShaderCodeDictionary.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Surface_Graphite.h"
55*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Texture.h"
56*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureProxy.h"
57*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureProxyView.h"
58*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureUtils.h"
59*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Uniform.h"
60*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/UniformManager.h"
61*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Base.h"
62*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkBlendShader.h"
63*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkColorFilterShader.h"
64*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkColorShader.h"
65*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkCoordClampShader.h"
66*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkEmptyShader.h"
67*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkImageShader.h"
68*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkLocalMatrixShader.h"
69*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkPerlinNoiseShaderImpl.h"
70*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkPerlinNoiseShaderType.h"
71*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkPictureShader.h"
72*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkRuntimeShader.h"
73*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkShaderBase.h"
74*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkTransformShader.h"
75*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkTriColorShader.h"
76*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkWorkingColorSpaceShader.h"
77*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/gradients/SkConicalGradient.h"
78*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/gradients/SkLinearGradient.h"
79*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/gradients/SkRadialGradient.h"
80*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/gradients/SkSweepGradient.h"
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker namespace {
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker // Automatically calls beginStruct() with the required alignment and endStruct() when it is deleted.
91*c8dee2aaSAndroid Build Coastguard Worker // Automatically registers uniform expectations in debug builds.
92*c8dee2aaSAndroid Build Coastguard Worker class ScopedUniformWriter {
93*c8dee2aaSAndroid Build Coastguard Worker public:
ScopedUniformWriter(PipelineDataGatherer * gatherer,const ShaderCodeDictionary * dict,BuiltInCodeSnippetID codeSnippetID)94*c8dee2aaSAndroid Build Coastguard Worker ScopedUniformWriter(PipelineDataGatherer* gatherer,
95*c8dee2aaSAndroid Build Coastguard Worker const ShaderCodeDictionary* dict,
96*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID codeSnippetID)
97*c8dee2aaSAndroid Build Coastguard Worker : ScopedUniformWriter(gatherer, dict->getEntry(codeSnippetID)) {}
98*c8dee2aaSAndroid Build Coastguard Worker
~ScopedUniformWriter()99*c8dee2aaSAndroid Build Coastguard Worker ~ScopedUniformWriter() {
100*c8dee2aaSAndroid Build Coastguard Worker if (fGatherer) {
101*c8dee2aaSAndroid Build Coastguard Worker fGatherer->endStruct();
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker }
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker private:
ScopedUniformWriter(PipelineDataGatherer * gatherer,const ShaderSnippet * snippet)106*c8dee2aaSAndroid Build Coastguard Worker ScopedUniformWriter(PipelineDataGatherer* gatherer, const ShaderSnippet* snippet)
107*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_DEBUG)
108*c8dee2aaSAndroid Build Coastguard Worker : fValidator(gatherer, snippet->fUniforms, SkToBool(snippet->fUniformStructName))
109*c8dee2aaSAndroid Build Coastguard Worker #endif
110*c8dee2aaSAndroid Build Coastguard Worker {
111*c8dee2aaSAndroid Build Coastguard Worker if (snippet->fUniformStructName) {
112*c8dee2aaSAndroid Build Coastguard Worker gatherer->beginStruct(snippet->fRequiredAlignment);
113*c8dee2aaSAndroid Build Coastguard Worker fGatherer = gatherer;
114*c8dee2aaSAndroid Build Coastguard Worker } else {
115*c8dee2aaSAndroid Build Coastguard Worker fGatherer = nullptr;
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker
119*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* fGatherer;
120*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(UniformExpectationsValidator fValidator;)
121*c8dee2aaSAndroid Build Coastguard Worker };
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker #define BEGIN_WRITE_UNIFORMS(gatherer, dict, codeSnippetID) \
124*c8dee2aaSAndroid Build Coastguard Worker ScopedUniformWriter scope{gatherer, dict, codeSnippetID};
125*c8dee2aaSAndroid Build Coastguard Worker
add_solid_uniform_data(const ShaderCodeDictionary * dict,const SkPMColor4f & premulColor,PipelineDataGatherer * gatherer)126*c8dee2aaSAndroid Build Coastguard Worker void add_solid_uniform_data(const ShaderCodeDictionary* dict,
127*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& premulColor,
128*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
129*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kSolidColorShader)
130*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(premulColor);
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
134*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkPMColor4f & premulColor)135*c8dee2aaSAndroid Build Coastguard Worker void SolidColorShaderBlock::AddBlock(const KeyContext& keyContext,
136*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
137*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
138*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& premulColor) {
139*c8dee2aaSAndroid Build Coastguard Worker add_solid_uniform_data(keyContext.dict(), premulColor, gatherer);
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kSolidColorShader);
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker namespace {
147*c8dee2aaSAndroid Build Coastguard Worker
add_rgb_paint_color_uniform_data(const ShaderCodeDictionary * dict,const SkPMColor4f & premulColor,PipelineDataGatherer * gatherer)148*c8dee2aaSAndroid Build Coastguard Worker void add_rgb_paint_color_uniform_data(const ShaderCodeDictionary* dict,
149*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& premulColor,
150*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
151*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kRGBPaintColor)
152*c8dee2aaSAndroid Build Coastguard Worker gatherer->writePaintColor(premulColor);
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker
add_alpha_only_paint_color_uniform_data(const ShaderCodeDictionary * dict,const SkPMColor4f & premulColor,PipelineDataGatherer * gatherer)155*c8dee2aaSAndroid Build Coastguard Worker void add_alpha_only_paint_color_uniform_data(const ShaderCodeDictionary* dict,
156*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& premulColor,
157*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
158*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kAlphaOnlyPaintColor)
159*c8dee2aaSAndroid Build Coastguard Worker gatherer->writePaintColor(premulColor);
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
163*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer)164*c8dee2aaSAndroid Build Coastguard Worker void RGBPaintColorBlock::AddBlock(const KeyContext& keyContext,
165*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
166*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
167*c8dee2aaSAndroid Build Coastguard Worker add_rgb_paint_color_uniform_data(keyContext.dict(), keyContext.paintColor(), gatherer);
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kRGBPaintColor);
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer)172*c8dee2aaSAndroid Build Coastguard Worker void AlphaOnlyPaintColorBlock::AddBlock(const KeyContext& keyContext,
173*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
174*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
175*c8dee2aaSAndroid Build Coastguard Worker add_alpha_only_paint_color_uniform_data(keyContext.dict(), keyContext.paintColor(), gatherer);
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kAlphaOnlyPaintColor);
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
181*c8dee2aaSAndroid Build Coastguard Worker
182*c8dee2aaSAndroid Build Coastguard Worker namespace {
183*c8dee2aaSAndroid Build Coastguard Worker
add_gradient_preamble(const GradientShaderBlocks::GradientData & gradData,PipelineDataGatherer * gatherer)184*c8dee2aaSAndroid Build Coastguard Worker void add_gradient_preamble(const GradientShaderBlocks::GradientData& gradData,
185*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
186*c8dee2aaSAndroid Build Coastguard Worker constexpr int kInternalStopLimit = GradientShaderBlocks::GradientData::kNumInternalStorageStops;
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker if (gradData.fNumStops <= kInternalStopLimit) {
189*c8dee2aaSAndroid Build Coastguard Worker if (gradData.fNumStops <= 4) {
190*c8dee2aaSAndroid Build Coastguard Worker // Round up to 4 stops.
191*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeArray(SkSpan{gradData.fColors, 4});
192*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(gradData.fOffsets[0]);
193*c8dee2aaSAndroid Build Coastguard Worker } else if (gradData.fNumStops <= 8) {
194*c8dee2aaSAndroid Build Coastguard Worker // Round up to 8 stops.
195*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeArray(SkSpan{gradData.fColors, 8});
196*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeArray(SkSpan{gradData.fOffsets, 2});
197*c8dee2aaSAndroid Build Coastguard Worker } else {
198*c8dee2aaSAndroid Build Coastguard Worker // Did kNumInternalStorageStops change?
199*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker
204*c8dee2aaSAndroid Build Coastguard Worker // All the gradients share a common postamble of:
205*c8dee2aaSAndroid Build Coastguard Worker // numStops - for texture-based gradients
206*c8dee2aaSAndroid Build Coastguard Worker // tilemode
207*c8dee2aaSAndroid Build Coastguard Worker // colorSpace
208*c8dee2aaSAndroid Build Coastguard Worker // doUnPremul
add_gradient_postamble(const GradientShaderBlocks::GradientData & gradData,int bufferOffset,PipelineDataGatherer * gatherer)209*c8dee2aaSAndroid Build Coastguard Worker void add_gradient_postamble(const GradientShaderBlocks::GradientData& gradData,
210*c8dee2aaSAndroid Build Coastguard Worker int bufferOffset,
211*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
212*c8dee2aaSAndroid Build Coastguard Worker using ColorSpace = SkGradientShader::Interpolation::ColorSpace;
213*c8dee2aaSAndroid Build Coastguard Worker
214*c8dee2aaSAndroid Build Coastguard Worker constexpr int kInternalStopLimit = GradientShaderBlocks::GradientData::kNumInternalStorageStops;
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kLab) == 2);
217*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kOKLab) == 3);
218*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kOKLabGamutMap) == 4);
219*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kLCH) == 5);
220*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kOKLCH) == 6);
221*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kOKLCHGamutMap) == 7);
222*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kHSL) == 9);
223*c8dee2aaSAndroid Build Coastguard Worker static_assert(static_cast<int>(ColorSpace::kHWB) == 10);
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker bool inputPremul = static_cast<bool>(gradData.fInterpolation.fInPremul);
226*c8dee2aaSAndroid Build Coastguard Worker
227*c8dee2aaSAndroid Build Coastguard Worker if (gradData.fNumStops > kInternalStopLimit) {
228*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(gradData.fNumStops);
229*c8dee2aaSAndroid Build Coastguard Worker if (gradData.fUseStorageBuffer) {
230*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(bufferOffset);
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(gradData.fTM));
235*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(gradData.fInterpolation.fColorSpace));
236*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(inputPremul));
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker
add_linear_gradient_uniform_data(const ShaderCodeDictionary * dict,BuiltInCodeSnippetID codeSnippetID,const GradientShaderBlocks::GradientData & gradData,int bufferOffset,PipelineDataGatherer * gatherer)239*c8dee2aaSAndroid Build Coastguard Worker void add_linear_gradient_uniform_data(const ShaderCodeDictionary* dict,
240*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID codeSnippetID,
241*c8dee2aaSAndroid Build Coastguard Worker const GradientShaderBlocks::GradientData& gradData,
242*c8dee2aaSAndroid Build Coastguard Worker int bufferOffset,
243*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
244*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, codeSnippetID)
245*c8dee2aaSAndroid Build Coastguard Worker
246*c8dee2aaSAndroid Build Coastguard Worker add_gradient_preamble(gradData, gatherer);
247*c8dee2aaSAndroid Build Coastguard Worker add_gradient_postamble(gradData, bufferOffset, gatherer);
248*c8dee2aaSAndroid Build Coastguard Worker };
249*c8dee2aaSAndroid Build Coastguard Worker
add_radial_gradient_uniform_data(const ShaderCodeDictionary * dict,BuiltInCodeSnippetID codeSnippetID,const GradientShaderBlocks::GradientData & gradData,int bufferOffset,PipelineDataGatherer * gatherer)250*c8dee2aaSAndroid Build Coastguard Worker void add_radial_gradient_uniform_data(const ShaderCodeDictionary* dict,
251*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID codeSnippetID,
252*c8dee2aaSAndroid Build Coastguard Worker const GradientShaderBlocks::GradientData& gradData,
253*c8dee2aaSAndroid Build Coastguard Worker int bufferOffset,
254*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
255*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, codeSnippetID)
256*c8dee2aaSAndroid Build Coastguard Worker
257*c8dee2aaSAndroid Build Coastguard Worker add_gradient_preamble(gradData, gatherer);
258*c8dee2aaSAndroid Build Coastguard Worker add_gradient_postamble(gradData, bufferOffset, gatherer);
259*c8dee2aaSAndroid Build Coastguard Worker };
260*c8dee2aaSAndroid Build Coastguard Worker
add_sweep_gradient_uniform_data(const ShaderCodeDictionary * dict,BuiltInCodeSnippetID codeSnippetID,const GradientShaderBlocks::GradientData & gradData,int bufferOffset,PipelineDataGatherer * gatherer)261*c8dee2aaSAndroid Build Coastguard Worker void add_sweep_gradient_uniform_data(const ShaderCodeDictionary* dict,
262*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID codeSnippetID,
263*c8dee2aaSAndroid Build Coastguard Worker const GradientShaderBlocks::GradientData& gradData,
264*c8dee2aaSAndroid Build Coastguard Worker int bufferOffset,
265*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
266*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, codeSnippetID)
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker add_gradient_preamble(gradData, gatherer);
269*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(gradData.fBias);
270*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(gradData.fScale);
271*c8dee2aaSAndroid Build Coastguard Worker add_gradient_postamble(gradData, bufferOffset, gatherer);
272*c8dee2aaSAndroid Build Coastguard Worker };
273*c8dee2aaSAndroid Build Coastguard Worker
add_conical_gradient_uniform_data(const ShaderCodeDictionary * dict,BuiltInCodeSnippetID codeSnippetID,const GradientShaderBlocks::GradientData & gradData,int bufferOffset,PipelineDataGatherer * gatherer)274*c8dee2aaSAndroid Build Coastguard Worker void add_conical_gradient_uniform_data(const ShaderCodeDictionary* dict,
275*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID codeSnippetID,
276*c8dee2aaSAndroid Build Coastguard Worker const GradientShaderBlocks::GradientData& gradData,
277*c8dee2aaSAndroid Build Coastguard Worker int bufferOffset,
278*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
279*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, codeSnippetID)
280*c8dee2aaSAndroid Build Coastguard Worker
281*c8dee2aaSAndroid Build Coastguard Worker float dRadius = gradData.fRadii[1] - gradData.fRadii[0];
282*c8dee2aaSAndroid Build Coastguard Worker bool isRadial = SkPoint::Distance(gradData.fPoints[1], gradData.fPoints[0])
283*c8dee2aaSAndroid Build Coastguard Worker < SK_ScalarNearlyZero;
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker // When a == 0, encode invA == 1 for radial case, and invA == 0 for linear edge case.
286*c8dee2aaSAndroid Build Coastguard Worker float a = 0;
287*c8dee2aaSAndroid Build Coastguard Worker float invA = 1;
288*c8dee2aaSAndroid Build Coastguard Worker if (!isRadial) {
289*c8dee2aaSAndroid Build Coastguard Worker a = 1 - dRadius * dRadius;
290*c8dee2aaSAndroid Build Coastguard Worker if (std::abs(a) > SK_ScalarNearlyZero) {
291*c8dee2aaSAndroid Build Coastguard Worker invA = 1.0 / (2.0 * a);
292*c8dee2aaSAndroid Build Coastguard Worker } else {
293*c8dee2aaSAndroid Build Coastguard Worker a = 0;
294*c8dee2aaSAndroid Build Coastguard Worker invA = 0;
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker } else {
297*c8dee2aaSAndroid Build Coastguard Worker // Since radius0 is being scaled by 1 / dRadius, and the original radius
298*c8dee2aaSAndroid Build Coastguard Worker // is always positive, this gives us the original sign of dRadius.
299*c8dee2aaSAndroid Build Coastguard Worker dRadius = gradData.fRadii[0] > 0 ? 1 : -1;
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker add_gradient_preamble(gradData, gatherer);
303*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(gradData.fRadii[0]);
304*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(dRadius);
305*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(a);
306*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(invA);
307*c8dee2aaSAndroid Build Coastguard Worker add_gradient_postamble(gradData, bufferOffset, gatherer);
308*c8dee2aaSAndroid Build Coastguard Worker };
309*c8dee2aaSAndroid Build Coastguard Worker
310*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
311*c8dee2aaSAndroid Build Coastguard Worker
312*c8dee2aaSAndroid Build Coastguard Worker // Writes the color and offset data directly in the gatherer gradient buffer and returns the
313*c8dee2aaSAndroid Build Coastguard Worker // offset the data begins at in the buffer.
write_color_and_offset_bufdata(int numStops,const SkPMColor4f * colors,const float * offsets,const SkGradientBaseShader * shader,PipelineDataGatherer * gatherer)314*c8dee2aaSAndroid Build Coastguard Worker static int write_color_and_offset_bufdata(int numStops,
315*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f* colors,
316*c8dee2aaSAndroid Build Coastguard Worker const float* offsets,
317*c8dee2aaSAndroid Build Coastguard Worker const SkGradientBaseShader* shader,
318*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
319*c8dee2aaSAndroid Build Coastguard Worker auto [dstData, bufferOffset] = gatherer->allocateGradientData(numStops, shader);
320*c8dee2aaSAndroid Build Coastguard Worker if (dstData) {
321*c8dee2aaSAndroid Build Coastguard Worker // Data doesn't already exist so we need to write it.
322*c8dee2aaSAndroid Build Coastguard Worker // Writes all offset data, then color data. This way when binary searching through the
323*c8dee2aaSAndroid Build Coastguard Worker // offsets, there is better cache locality.
324*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0, colorIdx = numStops; i < numStops; i++, colorIdx+=4) {
325*c8dee2aaSAndroid Build Coastguard Worker SkColor4f unpremulColor = colors[i].unpremul();
326*c8dee2aaSAndroid Build Coastguard Worker
327*c8dee2aaSAndroid Build Coastguard Worker float offset = offsets ? offsets[i] : SkIntToFloat(i) / (numStops - 1);
328*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(offset >= 0.0f && offset <= 1.0f);
329*c8dee2aaSAndroid Build Coastguard Worker
330*c8dee2aaSAndroid Build Coastguard Worker dstData[i] = offset;
331*c8dee2aaSAndroid Build Coastguard Worker dstData[colorIdx + 0] = unpremulColor.fR;
332*c8dee2aaSAndroid Build Coastguard Worker dstData[colorIdx + 1] = unpremulColor.fG;
333*c8dee2aaSAndroid Build Coastguard Worker dstData[colorIdx + 2] = unpremulColor.fB;
334*c8dee2aaSAndroid Build Coastguard Worker dstData[colorIdx + 3] = unpremulColor.fA;
335*c8dee2aaSAndroid Build Coastguard Worker }
336*c8dee2aaSAndroid Build Coastguard Worker }
337*c8dee2aaSAndroid Build Coastguard Worker
338*c8dee2aaSAndroid Build Coastguard Worker return bufferOffset;
339*c8dee2aaSAndroid Build Coastguard Worker }
340*c8dee2aaSAndroid Build Coastguard Worker
GradientData(SkShaderBase::GradientType type,int numStops,bool useStorageBuffer)341*c8dee2aaSAndroid Build Coastguard Worker GradientShaderBlocks::GradientData::GradientData(SkShaderBase::GradientType type,
342*c8dee2aaSAndroid Build Coastguard Worker int numStops,
343*c8dee2aaSAndroid Build Coastguard Worker bool useStorageBuffer)
344*c8dee2aaSAndroid Build Coastguard Worker : fType(type)
345*c8dee2aaSAndroid Build Coastguard Worker , fPoints{{0.0f, 0.0f}, {0.0f, 0.0f}}
346*c8dee2aaSAndroid Build Coastguard Worker , fRadii{0.0f, 0.0f}
347*c8dee2aaSAndroid Build Coastguard Worker , fBias(0.0f)
348*c8dee2aaSAndroid Build Coastguard Worker , fScale(0.0f)
349*c8dee2aaSAndroid Build Coastguard Worker , fTM(SkTileMode::kClamp)
350*c8dee2aaSAndroid Build Coastguard Worker , fNumStops(numStops)
351*c8dee2aaSAndroid Build Coastguard Worker , fUseStorageBuffer(useStorageBuffer)
352*c8dee2aaSAndroid Build Coastguard Worker , fSrcColors(nullptr)
353*c8dee2aaSAndroid Build Coastguard Worker , fSrcOffsets(nullptr) {
354*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(fColors, sizeof(fColors));
355*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(fOffsets, sizeof(fOffsets));
356*c8dee2aaSAndroid Build Coastguard Worker }
357*c8dee2aaSAndroid Build Coastguard Worker
GradientData(SkShaderBase::GradientType type,SkPoint point0,SkPoint point1,float radius0,float radius1,float bias,float scale,SkTileMode tm,int numStops,const SkPMColor4f * colors,const float * offsets,const SkGradientBaseShader * shader,sk_sp<TextureProxy> colorsAndOffsetsProxy,bool useStorageBuffer,const SkGradientShader::Interpolation & interp)358*c8dee2aaSAndroid Build Coastguard Worker GradientShaderBlocks::GradientData::GradientData(SkShaderBase::GradientType type,
359*c8dee2aaSAndroid Build Coastguard Worker SkPoint point0, SkPoint point1,
360*c8dee2aaSAndroid Build Coastguard Worker float radius0, float radius1,
361*c8dee2aaSAndroid Build Coastguard Worker float bias, float scale,
362*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm,
363*c8dee2aaSAndroid Build Coastguard Worker int numStops,
364*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f* colors,
365*c8dee2aaSAndroid Build Coastguard Worker const float* offsets,
366*c8dee2aaSAndroid Build Coastguard Worker const SkGradientBaseShader* shader,
367*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> colorsAndOffsetsProxy,
368*c8dee2aaSAndroid Build Coastguard Worker bool useStorageBuffer,
369*c8dee2aaSAndroid Build Coastguard Worker const SkGradientShader::Interpolation& interp)
370*c8dee2aaSAndroid Build Coastguard Worker : fType(type)
371*c8dee2aaSAndroid Build Coastguard Worker , fBias(bias)
372*c8dee2aaSAndroid Build Coastguard Worker , fScale(scale)
373*c8dee2aaSAndroid Build Coastguard Worker , fTM(tm)
374*c8dee2aaSAndroid Build Coastguard Worker , fNumStops(numStops)
375*c8dee2aaSAndroid Build Coastguard Worker , fUseStorageBuffer(useStorageBuffer)
376*c8dee2aaSAndroid Build Coastguard Worker , fSrcColors(colors)
377*c8dee2aaSAndroid Build Coastguard Worker , fSrcOffsets(offsets)
378*c8dee2aaSAndroid Build Coastguard Worker , fSrcShader(shader)
379*c8dee2aaSAndroid Build Coastguard Worker , fInterpolation(interp) {
380*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fNumStops >= 1);
381*c8dee2aaSAndroid Build Coastguard Worker
382*c8dee2aaSAndroid Build Coastguard Worker fPoints[0] = point0;
383*c8dee2aaSAndroid Build Coastguard Worker fPoints[1] = point1;
384*c8dee2aaSAndroid Build Coastguard Worker fRadii[0] = radius0;
385*c8dee2aaSAndroid Build Coastguard Worker fRadii[1] = radius1;
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker if (fNumStops <= kNumInternalStorageStops) {
388*c8dee2aaSAndroid Build Coastguard Worker memcpy(fColors, colors, fNumStops * sizeof(SkColor4f));
389*c8dee2aaSAndroid Build Coastguard Worker float* rawOffsets = fOffsets[0].ptr();
390*c8dee2aaSAndroid Build Coastguard Worker if (offsets) {
391*c8dee2aaSAndroid Build Coastguard Worker memcpy(rawOffsets, offsets, fNumStops * sizeof(float));
392*c8dee2aaSAndroid Build Coastguard Worker } else {
393*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fNumStops; ++i) {
394*c8dee2aaSAndroid Build Coastguard Worker rawOffsets[i] = SkIntToFloat(i) / (fNumStops-1);
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker }
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker // Extend the colors and offset, if necessary, to fill out the arrays.
399*c8dee2aaSAndroid Build Coastguard Worker // The unrolled binary search implementation assumes excess stops match the last real value.
400*c8dee2aaSAndroid Build Coastguard Worker for (int i = fNumStops; i < kNumInternalStorageStops; ++i) {
401*c8dee2aaSAndroid Build Coastguard Worker fColors[i] = fColors[fNumStops-1];
402*c8dee2aaSAndroid Build Coastguard Worker rawOffsets[i] = rawOffsets[fNumStops-1];
403*c8dee2aaSAndroid Build Coastguard Worker }
404*c8dee2aaSAndroid Build Coastguard Worker } else {
405*c8dee2aaSAndroid Build Coastguard Worker if (!fUseStorageBuffer) {
406*c8dee2aaSAndroid Build Coastguard Worker fColorsAndOffsetsProxy = std::move(colorsAndOffsetsProxy);
407*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fColorsAndOffsetsProxy);
408*c8dee2aaSAndroid Build Coastguard Worker }
409*c8dee2aaSAndroid Build Coastguard Worker }
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const GradientData & gradData)412*c8dee2aaSAndroid Build Coastguard Worker void GradientShaderBlocks::AddBlock(const KeyContext& keyContext,
413*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
414*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
415*c8dee2aaSAndroid Build Coastguard Worker const GradientData& gradData) {
416*c8dee2aaSAndroid Build Coastguard Worker auto dict = keyContext.dict();
417*c8dee2aaSAndroid Build Coastguard Worker
418*c8dee2aaSAndroid Build Coastguard Worker int bufferOffset = 0;
419*c8dee2aaSAndroid Build Coastguard Worker if (gradData.fNumStops > GradientData::kNumInternalStorageStops && keyContext.recorder()) {
420*c8dee2aaSAndroid Build Coastguard Worker if (gradData.fUseStorageBuffer) {
421*c8dee2aaSAndroid Build Coastguard Worker bufferOffset = write_color_and_offset_bufdata(gradData.fNumStops,
422*c8dee2aaSAndroid Build Coastguard Worker gradData.fSrcColors,
423*c8dee2aaSAndroid Build Coastguard Worker gradData.fSrcOffsets,
424*c8dee2aaSAndroid Build Coastguard Worker gradData.fSrcShader,
425*c8dee2aaSAndroid Build Coastguard Worker gatherer);
426*c8dee2aaSAndroid Build Coastguard Worker } else {
427*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(gradData.fColorsAndOffsetsProxy);
428*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(gradData.fColorsAndOffsetsProxy,
429*c8dee2aaSAndroid Build Coastguard Worker {SkFilterMode::kNearest, SkTileMode::kClamp});
430*c8dee2aaSAndroid Build Coastguard Worker }
431*c8dee2aaSAndroid Build Coastguard Worker }
432*c8dee2aaSAndroid Build Coastguard Worker
433*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID codeSnippetID = BuiltInCodeSnippetID::kSolidColorShader;
434*c8dee2aaSAndroid Build Coastguard Worker switch (gradData.fType) {
435*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::kLinear:
436*c8dee2aaSAndroid Build Coastguard Worker codeSnippetID =
437*c8dee2aaSAndroid Build Coastguard Worker gradData.fNumStops <= 4 ? BuiltInCodeSnippetID::kLinearGradientShader4
438*c8dee2aaSAndroid Build Coastguard Worker : gradData.fNumStops <= 8 ? BuiltInCodeSnippetID::kLinearGradientShader8
439*c8dee2aaSAndroid Build Coastguard Worker : gradData.fUseStorageBuffer
440*c8dee2aaSAndroid Build Coastguard Worker ? BuiltInCodeSnippetID::kLinearGradientShaderBuffer
441*c8dee2aaSAndroid Build Coastguard Worker : BuiltInCodeSnippetID::kLinearGradientShaderTexture;
442*c8dee2aaSAndroid Build Coastguard Worker add_linear_gradient_uniform_data(dict, codeSnippetID, gradData, bufferOffset, gatherer);
443*c8dee2aaSAndroid Build Coastguard Worker break;
444*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::kRadial:
445*c8dee2aaSAndroid Build Coastguard Worker codeSnippetID =
446*c8dee2aaSAndroid Build Coastguard Worker gradData.fNumStops <= 4 ? BuiltInCodeSnippetID::kRadialGradientShader4
447*c8dee2aaSAndroid Build Coastguard Worker : gradData.fNumStops <= 8 ? BuiltInCodeSnippetID::kRadialGradientShader8
448*c8dee2aaSAndroid Build Coastguard Worker : gradData.fUseStorageBuffer
449*c8dee2aaSAndroid Build Coastguard Worker ? BuiltInCodeSnippetID::kRadialGradientShaderBuffer
450*c8dee2aaSAndroid Build Coastguard Worker : BuiltInCodeSnippetID::kRadialGradientShaderTexture;
451*c8dee2aaSAndroid Build Coastguard Worker add_radial_gradient_uniform_data(dict, codeSnippetID, gradData, bufferOffset, gatherer);
452*c8dee2aaSAndroid Build Coastguard Worker break;
453*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::kSweep:
454*c8dee2aaSAndroid Build Coastguard Worker codeSnippetID =
455*c8dee2aaSAndroid Build Coastguard Worker gradData.fNumStops <= 4 ? BuiltInCodeSnippetID::kSweepGradientShader4
456*c8dee2aaSAndroid Build Coastguard Worker : gradData.fNumStops <= 8 ? BuiltInCodeSnippetID::kSweepGradientShader8
457*c8dee2aaSAndroid Build Coastguard Worker : gradData.fUseStorageBuffer
458*c8dee2aaSAndroid Build Coastguard Worker ? BuiltInCodeSnippetID::kSweepGradientShaderBuffer
459*c8dee2aaSAndroid Build Coastguard Worker : BuiltInCodeSnippetID::kSweepGradientShaderTexture;
460*c8dee2aaSAndroid Build Coastguard Worker add_sweep_gradient_uniform_data(dict, codeSnippetID, gradData, bufferOffset, gatherer);
461*c8dee2aaSAndroid Build Coastguard Worker break;
462*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::kConical:
463*c8dee2aaSAndroid Build Coastguard Worker codeSnippetID =
464*c8dee2aaSAndroid Build Coastguard Worker gradData.fNumStops <= 4 ? BuiltInCodeSnippetID::kConicalGradientShader4
465*c8dee2aaSAndroid Build Coastguard Worker : gradData.fNumStops <= 8 ? BuiltInCodeSnippetID::kConicalGradientShader8
466*c8dee2aaSAndroid Build Coastguard Worker : gradData.fUseStorageBuffer
467*c8dee2aaSAndroid Build Coastguard Worker ? BuiltInCodeSnippetID::kConicalGradientShaderBuffer
468*c8dee2aaSAndroid Build Coastguard Worker : BuiltInCodeSnippetID::kConicalGradientShaderTexture;
469*c8dee2aaSAndroid Build Coastguard Worker add_conical_gradient_uniform_data(dict, codeSnippetID, gradData, bufferOffset, gatherer);
470*c8dee2aaSAndroid Build Coastguard Worker break;
471*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::kNone:
472*c8dee2aaSAndroid Build Coastguard Worker default:
473*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGFAIL("Expected a gradient shader, but it wasn't one.");
474*c8dee2aaSAndroid Build Coastguard Worker break;
475*c8dee2aaSAndroid Build Coastguard Worker }
476*c8dee2aaSAndroid Build Coastguard Worker
477*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(codeSnippetID);
478*c8dee2aaSAndroid Build Coastguard Worker }
479*c8dee2aaSAndroid Build Coastguard Worker
480*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
481*c8dee2aaSAndroid Build Coastguard Worker
482*c8dee2aaSAndroid Build Coastguard Worker namespace {
483*c8dee2aaSAndroid Build Coastguard Worker
add_localmatrixshader_uniform_data(const ShaderCodeDictionary * dict,const SkM44 & localMatrix,PipelineDataGatherer * gatherer)484*c8dee2aaSAndroid Build Coastguard Worker void add_localmatrixshader_uniform_data(const ShaderCodeDictionary* dict,
485*c8dee2aaSAndroid Build Coastguard Worker const SkM44& localMatrix,
486*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
487*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kLocalMatrixShader)
488*c8dee2aaSAndroid Build Coastguard Worker
489*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(localMatrix);
490*c8dee2aaSAndroid Build Coastguard Worker }
491*c8dee2aaSAndroid Build Coastguard Worker
492*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
493*c8dee2aaSAndroid Build Coastguard Worker
BeginBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const LMShaderData & lmShaderData)494*c8dee2aaSAndroid Build Coastguard Worker void LocalMatrixShaderBlock::BeginBlock(const KeyContext& keyContext,
495*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
496*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
497*c8dee2aaSAndroid Build Coastguard Worker const LMShaderData& lmShaderData) {
498*c8dee2aaSAndroid Build Coastguard Worker
499*c8dee2aaSAndroid Build Coastguard Worker add_localmatrixshader_uniform_data(keyContext.dict(), lmShaderData.fLocalMatrix, gatherer);
500*c8dee2aaSAndroid Build Coastguard Worker
501*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(lmShaderData.fHasPerspective
502*c8dee2aaSAndroid Build Coastguard Worker ? BuiltInCodeSnippetID::kLocalMatrixShaderPersp
503*c8dee2aaSAndroid Build Coastguard Worker : BuiltInCodeSnippetID::kLocalMatrixShader);
504*c8dee2aaSAndroid Build Coastguard Worker }
505*c8dee2aaSAndroid Build Coastguard Worker
506*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
507*c8dee2aaSAndroid Build Coastguard Worker
508*c8dee2aaSAndroid Build Coastguard Worker namespace {
509*c8dee2aaSAndroid Build Coastguard Worker
510*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kColorSpaceXformFlagAlphaSwizzle = 0x20;
511*c8dee2aaSAndroid Build Coastguard Worker
add_color_space_uniforms(const SkColorSpaceXformSteps & steps,ReadSwizzle readSwizzle,PipelineDataGatherer * gatherer)512*c8dee2aaSAndroid Build Coastguard Worker void add_color_space_uniforms(const SkColorSpaceXformSteps& steps,
513*c8dee2aaSAndroid Build Coastguard Worker ReadSwizzle readSwizzle,
514*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
515*c8dee2aaSAndroid Build Coastguard Worker // We have 7 source coefficients and 7 destination coefficients. We pass them via a 4x4 matrix;
516*c8dee2aaSAndroid Build Coastguard Worker // the first two columns hold the source values, and the second two hold the destination.
517*c8dee2aaSAndroid Build Coastguard Worker // (The final value of each 8-element group is ignored.)
518*c8dee2aaSAndroid Build Coastguard Worker // In std140, this arrangement is much more efficient than a simple array of scalars.
519*c8dee2aaSAndroid Build Coastguard Worker SkM44 coeffs;
520*c8dee2aaSAndroid Build Coastguard Worker
521*c8dee2aaSAndroid Build Coastguard Worker int colorXformFlags = SkTo<int>(steps.flags.mask());
522*c8dee2aaSAndroid Build Coastguard Worker if (readSwizzle != ReadSwizzle::kRGBA) {
523*c8dee2aaSAndroid Build Coastguard Worker // Ensure that we do the gamut step
524*c8dee2aaSAndroid Build Coastguard Worker SkColorSpaceXformSteps gamutSteps;
525*c8dee2aaSAndroid Build Coastguard Worker gamutSteps.flags.gamut_transform = true;
526*c8dee2aaSAndroid Build Coastguard Worker colorXformFlags |= SkTo<int>(gamutSteps.flags.mask());
527*c8dee2aaSAndroid Build Coastguard Worker if (readSwizzle != ReadSwizzle::kBGRA) {
528*c8dee2aaSAndroid Build Coastguard Worker // TODO: Maybe add a fullMask() method to XformSteps?
529*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(colorXformFlags < kColorSpaceXformFlagAlphaSwizzle);
530*c8dee2aaSAndroid Build Coastguard Worker colorXformFlags |= kColorSpaceXformFlagAlphaSwizzle;
531*c8dee2aaSAndroid Build Coastguard Worker }
532*c8dee2aaSAndroid Build Coastguard Worker }
533*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(colorXformFlags);
534*c8dee2aaSAndroid Build Coastguard Worker
535*c8dee2aaSAndroid Build Coastguard Worker if (steps.flags.linearize) {
536*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(skcms_TransferFunction_getType(&steps.srcTF)));
537*c8dee2aaSAndroid Build Coastguard Worker coeffs.setCol(0, {steps.srcTF.g, steps.srcTF.a, steps.srcTF.b, steps.srcTF.c});
538*c8dee2aaSAndroid Build Coastguard Worker coeffs.setCol(1, {steps.srcTF.d, steps.srcTF.e, steps.srcTF.f, 0.0f});
539*c8dee2aaSAndroid Build Coastguard Worker } else {
540*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(skcms_TFType::skcms_TFType_Invalid));
541*c8dee2aaSAndroid Build Coastguard Worker }
542*c8dee2aaSAndroid Build Coastguard Worker
543*c8dee2aaSAndroid Build Coastguard Worker SkMatrix gamutTransform;
544*c8dee2aaSAndroid Build Coastguard Worker const float identity[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
545*c8dee2aaSAndroid Build Coastguard Worker // TODO: it seems odd to copy this into an SkMatrix just to write it to the gatherer
546*c8dee2aaSAndroid Build Coastguard Worker // src_to_dst_matrix is column-major, SkMatrix is row-major.
547*c8dee2aaSAndroid Build Coastguard Worker const float* m = steps.flags.gamut_transform ? steps.src_to_dst_matrix : identity;
548*c8dee2aaSAndroid Build Coastguard Worker if (readSwizzle == ReadSwizzle::kRRR1) {
549*c8dee2aaSAndroid Build Coastguard Worker gamutTransform.setAll(m[0] + m[3] + m[6], 0, 0,
550*c8dee2aaSAndroid Build Coastguard Worker m[1] + m[4] + m[7], 0, 0,
551*c8dee2aaSAndroid Build Coastguard Worker m[2] + m[5] + m[8], 0, 0);
552*c8dee2aaSAndroid Build Coastguard Worker } else if (readSwizzle == ReadSwizzle::kBGRA) {
553*c8dee2aaSAndroid Build Coastguard Worker gamutTransform.setAll(m[6], m[3], m[0],
554*c8dee2aaSAndroid Build Coastguard Worker m[7], m[4], m[1],
555*c8dee2aaSAndroid Build Coastguard Worker m[8], m[5], m[2]);
556*c8dee2aaSAndroid Build Coastguard Worker } else if (readSwizzle == ReadSwizzle::k000R) {
557*c8dee2aaSAndroid Build Coastguard Worker gamutTransform.setAll(0, 0, 0,
558*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 0,
559*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 0);
560*c8dee2aaSAndroid Build Coastguard Worker } else if (steps.flags.gamut_transform) {
561*c8dee2aaSAndroid Build Coastguard Worker gamutTransform.setAll(m[0], m[3], m[6],
562*c8dee2aaSAndroid Build Coastguard Worker m[1], m[4], m[7],
563*c8dee2aaSAndroid Build Coastguard Worker m[2], m[5], m[8]);
564*c8dee2aaSAndroid Build Coastguard Worker }
565*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(gamutTransform);
566*c8dee2aaSAndroid Build Coastguard Worker
567*c8dee2aaSAndroid Build Coastguard Worker if (steps.flags.encode) {
568*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(skcms_TransferFunction_getType(&steps.dstTFInv)));
569*c8dee2aaSAndroid Build Coastguard Worker coeffs.setCol(2, {steps.dstTFInv.g, steps.dstTFInv.a, steps.dstTFInv.b, steps.dstTFInv.c});
570*c8dee2aaSAndroid Build Coastguard Worker coeffs.setCol(3, {steps.dstTFInv.d, steps.dstTFInv.e, steps.dstTFInv.f, 0.0f});
571*c8dee2aaSAndroid Build Coastguard Worker } else {
572*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(skcms_TFType::skcms_TFType_Invalid));
573*c8dee2aaSAndroid Build Coastguard Worker }
574*c8dee2aaSAndroid Build Coastguard Worker
575*c8dee2aaSAndroid Build Coastguard Worker // Pack alpha swizzle in the unused coeff entries.
576*c8dee2aaSAndroid Build Coastguard Worker switch (readSwizzle) {
577*c8dee2aaSAndroid Build Coastguard Worker case ReadSwizzle::k000R:
578*c8dee2aaSAndroid Build Coastguard Worker coeffs.setRC(3, 1, 1.f);
579*c8dee2aaSAndroid Build Coastguard Worker coeffs.setRC(3, 3, 0.f);
580*c8dee2aaSAndroid Build Coastguard Worker break;
581*c8dee2aaSAndroid Build Coastguard Worker case ReadSwizzle::kRGB1:
582*c8dee2aaSAndroid Build Coastguard Worker case ReadSwizzle::kRRR1:
583*c8dee2aaSAndroid Build Coastguard Worker coeffs.setRC(3, 1, 0.f);
584*c8dee2aaSAndroid Build Coastguard Worker coeffs.setRC(3, 3, 1.f);
585*c8dee2aaSAndroid Build Coastguard Worker break;
586*c8dee2aaSAndroid Build Coastguard Worker default:
587*c8dee2aaSAndroid Build Coastguard Worker coeffs.setRC(3, 1, 0.f);
588*c8dee2aaSAndroid Build Coastguard Worker coeffs.setRC(3, 3, 0.f);
589*c8dee2aaSAndroid Build Coastguard Worker break;
590*c8dee2aaSAndroid Build Coastguard Worker }
591*c8dee2aaSAndroid Build Coastguard Worker
592*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(coeffs);
593*c8dee2aaSAndroid Build Coastguard Worker }
594*c8dee2aaSAndroid Build Coastguard Worker
add_image_uniform_data(const ShaderCodeDictionary * dict,const ImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)595*c8dee2aaSAndroid Build Coastguard Worker void add_image_uniform_data(const ShaderCodeDictionary* dict,
596*c8dee2aaSAndroid Build Coastguard Worker const ImageShaderBlock::ImageData& imgData,
597*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
598*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!imgData.fSampling.useCubic);
599*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kImageShader)
600*c8dee2aaSAndroid Build Coastguard Worker
601*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
602*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(imgData.fSubset);
603*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.first));
604*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.second));
605*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fSampling.filter));
606*c8dee2aaSAndroid Build Coastguard Worker }
607*c8dee2aaSAndroid Build Coastguard Worker
add_cubic_image_uniform_data(const ShaderCodeDictionary * dict,const ImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)608*c8dee2aaSAndroid Build Coastguard Worker void add_cubic_image_uniform_data(const ShaderCodeDictionary* dict,
609*c8dee2aaSAndroid Build Coastguard Worker const ImageShaderBlock::ImageData& imgData,
610*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
611*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(imgData.fSampling.useCubic);
612*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kCubicImageShader)
613*c8dee2aaSAndroid Build Coastguard Worker
614*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
615*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(imgData.fSubset);
616*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.first));
617*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.second));
618*c8dee2aaSAndroid Build Coastguard Worker const SkCubicResampler& cubic = imgData.fSampling.cubic;
619*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(SkImageShader::CubicResamplerMatrix(cubic.B, cubic.C));
620*c8dee2aaSAndroid Build Coastguard Worker }
621*c8dee2aaSAndroid Build Coastguard Worker
add_hw_image_uniform_data(const ShaderCodeDictionary * dict,const ImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)622*c8dee2aaSAndroid Build Coastguard Worker void add_hw_image_uniform_data(const ShaderCodeDictionary* dict,
623*c8dee2aaSAndroid Build Coastguard Worker const ImageShaderBlock::ImageData& imgData,
624*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
625*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!imgData.fSampling.useCubic);
626*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kHWImageShader)
627*c8dee2aaSAndroid Build Coastguard Worker
628*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
629*c8dee2aaSAndroid Build Coastguard Worker }
630*c8dee2aaSAndroid Build Coastguard Worker
can_do_tiling_in_hw(const Caps * caps,const ImageShaderBlock::ImageData & imgData)631*c8dee2aaSAndroid Build Coastguard Worker bool can_do_tiling_in_hw(const Caps* caps, const ImageShaderBlock::ImageData& imgData) {
632*c8dee2aaSAndroid Build Coastguard Worker if (!caps->clampToBorderSupport() && (imgData.fTileModes.first == SkTileMode::kDecal ||
633*c8dee2aaSAndroid Build Coastguard Worker imgData.fTileModes.second == SkTileMode::kDecal)) {
634*c8dee2aaSAndroid Build Coastguard Worker return false;
635*c8dee2aaSAndroid Build Coastguard Worker }
636*c8dee2aaSAndroid Build Coastguard Worker return imgData.fSubset.contains(SkRect::Make(imgData.fImgSize));
637*c8dee2aaSAndroid Build Coastguard Worker }
638*c8dee2aaSAndroid Build Coastguard Worker
add_sampler_data_to_key(PaintParamsKeyBuilder * builder,const SamplerDesc & samplerDesc)639*c8dee2aaSAndroid Build Coastguard Worker void add_sampler_data_to_key(PaintParamsKeyBuilder* builder, const SamplerDesc& samplerDesc) {
640*c8dee2aaSAndroid Build Coastguard Worker if (samplerDesc.isImmutable()) {
641*c8dee2aaSAndroid Build Coastguard Worker builder->addData({samplerDesc.asSpan()});
642*c8dee2aaSAndroid Build Coastguard Worker } else {
643*c8dee2aaSAndroid Build Coastguard Worker // Means we have a regular dynamic sampler. Append a default SamplerDesc to convey this,
644*c8dee2aaSAndroid Build Coastguard Worker // allowing the key to maintain and convey sampler binding order.
645*c8dee2aaSAndroid Build Coastguard Worker builder->addData({{}});
646*c8dee2aaSAndroid Build Coastguard Worker }
647*c8dee2aaSAndroid Build Coastguard Worker }
648*c8dee2aaSAndroid Build Coastguard Worker
649*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
650*c8dee2aaSAndroid Build Coastguard Worker
ImageData(const SkSamplingOptions & sampling,SkTileMode tileModeX,SkTileMode tileModeY,SkISize imgSize,SkRect subset)651*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::ImageData::ImageData(const SkSamplingOptions& sampling,
652*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tileModeX,
653*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tileModeY,
654*c8dee2aaSAndroid Build Coastguard Worker SkISize imgSize,
655*c8dee2aaSAndroid Build Coastguard Worker SkRect subset)
656*c8dee2aaSAndroid Build Coastguard Worker : fSampling(sampling)
657*c8dee2aaSAndroid Build Coastguard Worker , fTileModes{tileModeX, tileModeY}
658*c8dee2aaSAndroid Build Coastguard Worker , fImgSize(imgSize)
659*c8dee2aaSAndroid Build Coastguard Worker , fSubset(subset) {
660*c8dee2aaSAndroid Build Coastguard Worker }
661*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const ImageData & imgData)662*c8dee2aaSAndroid Build Coastguard Worker void ImageShaderBlock::AddBlock(const KeyContext& keyContext,
663*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
664*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
665*c8dee2aaSAndroid Build Coastguard Worker const ImageData& imgData) {
666*c8dee2aaSAndroid Build Coastguard Worker
667*c8dee2aaSAndroid Build Coastguard Worker if (keyContext.recorder() && !imgData.fTextureProxy) {
668*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
669*c8dee2aaSAndroid Build Coastguard Worker return;
670*c8dee2aaSAndroid Build Coastguard Worker }
671*c8dee2aaSAndroid Build Coastguard Worker
672*c8dee2aaSAndroid Build Coastguard Worker const Caps* caps = keyContext.caps();
673*c8dee2aaSAndroid Build Coastguard Worker const bool doTilingInHw = !imgData.fSampling.useCubic && can_do_tiling_in_hw(caps, imgData);
674*c8dee2aaSAndroid Build Coastguard Worker
675*c8dee2aaSAndroid Build Coastguard Worker if (doTilingInHw) {
676*c8dee2aaSAndroid Build Coastguard Worker add_hw_image_uniform_data(keyContext.dict(), imgData, gatherer);
677*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(BuiltInCodeSnippetID::kHWImageShader);
678*c8dee2aaSAndroid Build Coastguard Worker } else if (imgData.fSampling.useCubic) {
679*c8dee2aaSAndroid Build Coastguard Worker add_cubic_image_uniform_data(keyContext.dict(), imgData, gatherer);
680*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(BuiltInCodeSnippetID::kCubicImageShader);
681*c8dee2aaSAndroid Build Coastguard Worker } else {
682*c8dee2aaSAndroid Build Coastguard Worker add_image_uniform_data(keyContext.dict(), imgData, gatherer);
683*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(BuiltInCodeSnippetID::kImageShader);
684*c8dee2aaSAndroid Build Coastguard Worker }
685*c8dee2aaSAndroid Build Coastguard Worker
686*c8dee2aaSAndroid Build Coastguard Worker static constexpr std::pair<SkTileMode, SkTileMode> kDefaultTileModes =
687*c8dee2aaSAndroid Build Coastguard Worker {SkTileMode::kClamp, SkTileMode::kClamp};
688*c8dee2aaSAndroid Build Coastguard Worker
689*c8dee2aaSAndroid Build Coastguard Worker // Image shaders must append immutable sampler data (or '0' in the more common case where
690*c8dee2aaSAndroid Build Coastguard Worker // regular samplers are used).
691*c8dee2aaSAndroid Build Coastguard Worker ImmutableSamplerInfo info = caps->getImmutableSamplerInfo(imgData.fTextureProxy.get());
692*c8dee2aaSAndroid Build Coastguard Worker SamplerDesc samplerDesc {imgData.fSampling,
693*c8dee2aaSAndroid Build Coastguard Worker doTilingInHw ? imgData.fTileModes : kDefaultTileModes,
694*c8dee2aaSAndroid Build Coastguard Worker info};
695*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(imgData.fTextureProxy, samplerDesc);
696*c8dee2aaSAndroid Build Coastguard Worker add_sampler_data_to_key(builder, samplerDesc);
697*c8dee2aaSAndroid Build Coastguard Worker
698*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
699*c8dee2aaSAndroid Build Coastguard Worker }
700*c8dee2aaSAndroid Build Coastguard Worker
701*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
702*c8dee2aaSAndroid Build Coastguard Worker
703*c8dee2aaSAndroid Build Coastguard Worker // makes use of ImageShader functions, above
704*c8dee2aaSAndroid Build Coastguard Worker namespace {
705*c8dee2aaSAndroid Build Coastguard Worker
add_yuv_image_uniform_data(const ShaderCodeDictionary * dict,const YUVImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)706*c8dee2aaSAndroid Build Coastguard Worker void add_yuv_image_uniform_data(const ShaderCodeDictionary* dict,
707*c8dee2aaSAndroid Build Coastguard Worker const YUVImageShaderBlock::ImageData& imgData,
708*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
709*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kYUVImageShader)
710*c8dee2aaSAndroid Build Coastguard Worker
711*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
712*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSizeUV.width(), 1.f/imgData.fImgSizeUV.height()));
713*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(imgData.fSubset);
714*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(imgData.fLinearFilterUVInset);
715*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.first));
716*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.second));
717*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fSampling.filter));
718*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fSamplingUV.filter));
719*c8dee2aaSAndroid Build Coastguard Worker
720*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
721*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fChannelSelect[i]);
722*c8dee2aaSAndroid Build Coastguard Worker }
723*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBMatrix);
724*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBTranslate);
725*c8dee2aaSAndroid Build Coastguard Worker }
726*c8dee2aaSAndroid Build Coastguard Worker
add_cubic_yuv_image_uniform_data(const ShaderCodeDictionary * dict,const YUVImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)727*c8dee2aaSAndroid Build Coastguard Worker void add_cubic_yuv_image_uniform_data(const ShaderCodeDictionary* dict,
728*c8dee2aaSAndroid Build Coastguard Worker const YUVImageShaderBlock::ImageData& imgData,
729*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
730*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kCubicYUVImageShader)
731*c8dee2aaSAndroid Build Coastguard Worker
732*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
733*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSizeUV.width(), 1.f/imgData.fImgSizeUV.height()));
734*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(imgData.fSubset);
735*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.first));
736*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkTo<int>(imgData.fTileModes.second));
737*c8dee2aaSAndroid Build Coastguard Worker const SkCubicResampler& cubic = imgData.fSampling.cubic;
738*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(SkImageShader::CubicResamplerMatrix(cubic.B, cubic.C));
739*c8dee2aaSAndroid Build Coastguard Worker
740*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
741*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fChannelSelect[i]);
742*c8dee2aaSAndroid Build Coastguard Worker }
743*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBMatrix);
744*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBTranslate);
745*c8dee2aaSAndroid Build Coastguard Worker }
746*c8dee2aaSAndroid Build Coastguard Worker
add_hw_yuv_image_uniform_data(const ShaderCodeDictionary * dict,const YUVImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)747*c8dee2aaSAndroid Build Coastguard Worker void add_hw_yuv_image_uniform_data(const ShaderCodeDictionary* dict,
748*c8dee2aaSAndroid Build Coastguard Worker const YUVImageShaderBlock::ImageData& imgData,
749*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
750*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kHWYUVImageShader)
751*c8dee2aaSAndroid Build Coastguard Worker
752*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
753*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSizeUV.width(), 1.f/imgData.fImgSizeUV.height()));
754*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
755*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fChannelSelect[i]);
756*c8dee2aaSAndroid Build Coastguard Worker }
757*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBMatrix);
758*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBTranslate);
759*c8dee2aaSAndroid Build Coastguard Worker }
760*c8dee2aaSAndroid Build Coastguard Worker
add_hw_yuv_no_swizzle_image_uniform_data(const ShaderCodeDictionary * dict,const YUVImageShaderBlock::ImageData & imgData,PipelineDataGatherer * gatherer)761*c8dee2aaSAndroid Build Coastguard Worker void add_hw_yuv_no_swizzle_image_uniform_data(const ShaderCodeDictionary* dict,
762*c8dee2aaSAndroid Build Coastguard Worker const YUVImageShaderBlock::ImageData& imgData,
763*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
764*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kHWYUVNoSwizzleImageShader)
765*c8dee2aaSAndroid Build Coastguard Worker
766*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSize.width(), 1.f/imgData.fImgSize.height()));
767*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(SkSize::Make(1.f/imgData.fImgSizeUV.width(), 1.f/imgData.fImgSizeUV.height()));
768*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(imgData.fYUVtoRGBMatrix);
769*c8dee2aaSAndroid Build Coastguard Worker SkV4 yuvToRGBXlateAlphaParam = {
770*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBTranslate.fX,
771*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBTranslate.fY,
772*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBTranslate.fZ,
773*c8dee2aaSAndroid Build Coastguard Worker imgData.fAlphaParam
774*c8dee2aaSAndroid Build Coastguard Worker };
775*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(yuvToRGBXlateAlphaParam);
776*c8dee2aaSAndroid Build Coastguard Worker }
777*c8dee2aaSAndroid Build Coastguard Worker
778*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
779*c8dee2aaSAndroid Build Coastguard Worker
ImageData(const SkSamplingOptions & sampling,SkTileMode tileModeX,SkTileMode tileModeY,SkISize imgSize,SkRect subset)780*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::ImageData::ImageData(const SkSamplingOptions& sampling,
781*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tileModeX,
782*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tileModeY,
783*c8dee2aaSAndroid Build Coastguard Worker SkISize imgSize,
784*c8dee2aaSAndroid Build Coastguard Worker SkRect subset)
785*c8dee2aaSAndroid Build Coastguard Worker : fSampling(sampling)
786*c8dee2aaSAndroid Build Coastguard Worker , fSamplingUV(sampling)
787*c8dee2aaSAndroid Build Coastguard Worker , fTileModes{tileModeX, tileModeY}
788*c8dee2aaSAndroid Build Coastguard Worker , fImgSize(imgSize)
789*c8dee2aaSAndroid Build Coastguard Worker , fImgSizeUV(imgSize)
790*c8dee2aaSAndroid Build Coastguard Worker , fSubset(subset) {
791*c8dee2aaSAndroid Build Coastguard Worker }
792*c8dee2aaSAndroid Build Coastguard Worker
can_do_yuv_tiling_in_hw(const Caps * caps,const YUVImageShaderBlock::ImageData & imgData)793*c8dee2aaSAndroid Build Coastguard Worker static bool can_do_yuv_tiling_in_hw(const Caps* caps,
794*c8dee2aaSAndroid Build Coastguard Worker const YUVImageShaderBlock::ImageData& imgData) {
795*c8dee2aaSAndroid Build Coastguard Worker if (!caps->clampToBorderSupport() && (imgData.fTileModes.first == SkTileMode::kDecal ||
796*c8dee2aaSAndroid Build Coastguard Worker imgData.fTileModes.second == SkTileMode::kDecal)) {
797*c8dee2aaSAndroid Build Coastguard Worker return false;
798*c8dee2aaSAndroid Build Coastguard Worker }
799*c8dee2aaSAndroid Build Coastguard Worker // We depend on the subset code to handle cases where the UV dimensions times the
800*c8dee2aaSAndroid Build Coastguard Worker // subsample factors are not equal to the Y dimensions.
801*c8dee2aaSAndroid Build Coastguard Worker if (imgData.fImgSize != imgData.fImgSizeUV) {
802*c8dee2aaSAndroid Build Coastguard Worker return false;
803*c8dee2aaSAndroid Build Coastguard Worker }
804*c8dee2aaSAndroid Build Coastguard Worker // For nearest filtering when the Y texture size is larger than the UV texture size,
805*c8dee2aaSAndroid Build Coastguard Worker // we use linear filtering for the UV texture. In this case we also adjust pixel centers
806*c8dee2aaSAndroid Build Coastguard Worker // which may affect dependent texture reads.
807*c8dee2aaSAndroid Build Coastguard Worker if (imgData.fSampling.filter != imgData.fSamplingUV.filter) {
808*c8dee2aaSAndroid Build Coastguard Worker return false;
809*c8dee2aaSAndroid Build Coastguard Worker }
810*c8dee2aaSAndroid Build Coastguard Worker return imgData.fSubset.contains(SkRect::Make(imgData.fImgSize));
811*c8dee2aaSAndroid Build Coastguard Worker }
812*c8dee2aaSAndroid Build Coastguard Worker
no_yuv_swizzle(const YUVImageShaderBlock::ImageData & imgData)813*c8dee2aaSAndroid Build Coastguard Worker static bool no_yuv_swizzle(const YUVImageShaderBlock::ImageData& imgData) {
814*c8dee2aaSAndroid Build Coastguard Worker // Y_U_V or U_Y_V format, reading from R channel for each texture
815*c8dee2aaSAndroid Build Coastguard Worker if (imgData.fChannelSelect[0].x == 1 &&
816*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[1].x == 1 &&
817*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[2].x == 1 &&
818*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[3].x == 1) {
819*c8dee2aaSAndroid Build Coastguard Worker return true;
820*c8dee2aaSAndroid Build Coastguard Worker }
821*c8dee2aaSAndroid Build Coastguard Worker
822*c8dee2aaSAndroid Build Coastguard Worker return false;
823*c8dee2aaSAndroid Build Coastguard Worker }
824*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const ImageData & imgData)825*c8dee2aaSAndroid Build Coastguard Worker void YUVImageShaderBlock::AddBlock(const KeyContext& keyContext,
826*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
827*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
828*c8dee2aaSAndroid Build Coastguard Worker const ImageData& imgData) {
829*c8dee2aaSAndroid Build Coastguard Worker if (keyContext.recorder() &&
830*c8dee2aaSAndroid Build Coastguard Worker (!imgData.fTextureProxies[0] || !imgData.fTextureProxies[1] ||
831*c8dee2aaSAndroid Build Coastguard Worker !imgData.fTextureProxies[2] || !imgData.fTextureProxies[3])) {
832*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
833*c8dee2aaSAndroid Build Coastguard Worker return;
834*c8dee2aaSAndroid Build Coastguard Worker }
835*c8dee2aaSAndroid Build Coastguard Worker
836*c8dee2aaSAndroid Build Coastguard Worker const Caps* caps = keyContext.caps();
837*c8dee2aaSAndroid Build Coastguard Worker const bool doTilingInHw = !imgData.fSampling.useCubic && can_do_yuv_tiling_in_hw(caps, imgData);
838*c8dee2aaSAndroid Build Coastguard Worker const bool noYUVSwizzle = no_yuv_swizzle(imgData);
839*c8dee2aaSAndroid Build Coastguard Worker
840*c8dee2aaSAndroid Build Coastguard Worker auto uvTileModes = std::make_pair(imgData.fTileModes.first == SkTileMode::kDecal
841*c8dee2aaSAndroid Build Coastguard Worker ? SkTileMode::kClamp : imgData.fTileModes.first,
842*c8dee2aaSAndroid Build Coastguard Worker imgData.fTileModes.second == SkTileMode::kDecal
843*c8dee2aaSAndroid Build Coastguard Worker ? SkTileMode::kClamp : imgData.fTileModes.second);
844*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(imgData.fTextureProxies[0], {imgData.fSampling, imgData.fTileModes});
845*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(imgData.fTextureProxies[1], {imgData.fSamplingUV, uvTileModes});
846*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(imgData.fTextureProxies[2], {imgData.fSamplingUV, uvTileModes});
847*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(imgData.fTextureProxies[3], {imgData.fSampling, imgData.fTileModes});
848*c8dee2aaSAndroid Build Coastguard Worker
849*c8dee2aaSAndroid Build Coastguard Worker if (doTilingInHw && noYUVSwizzle) {
850*c8dee2aaSAndroid Build Coastguard Worker add_hw_yuv_no_swizzle_image_uniform_data(keyContext.dict(), imgData, gatherer);
851*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kHWYUVNoSwizzleImageShader);
852*c8dee2aaSAndroid Build Coastguard Worker } else if (doTilingInHw) {
853*c8dee2aaSAndroid Build Coastguard Worker add_hw_yuv_image_uniform_data(keyContext.dict(), imgData, gatherer);
854*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kHWYUVImageShader);
855*c8dee2aaSAndroid Build Coastguard Worker } else if (imgData.fSampling.useCubic) {
856*c8dee2aaSAndroid Build Coastguard Worker add_cubic_yuv_image_uniform_data(keyContext.dict(), imgData, gatherer);
857*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kCubicYUVImageShader);
858*c8dee2aaSAndroid Build Coastguard Worker } else {
859*c8dee2aaSAndroid Build Coastguard Worker add_yuv_image_uniform_data(keyContext.dict(), imgData, gatherer);
860*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kYUVImageShader);
861*c8dee2aaSAndroid Build Coastguard Worker }
862*c8dee2aaSAndroid Build Coastguard Worker }
863*c8dee2aaSAndroid Build Coastguard Worker
864*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
865*c8dee2aaSAndroid Build Coastguard Worker
866*c8dee2aaSAndroid Build Coastguard Worker namespace {
867*c8dee2aaSAndroid Build Coastguard Worker
add_coordclamp_uniform_data(const ShaderCodeDictionary * dict,const CoordClampShaderBlock::CoordClampData & clampData,PipelineDataGatherer * gatherer)868*c8dee2aaSAndroid Build Coastguard Worker void add_coordclamp_uniform_data(const ShaderCodeDictionary* dict,
869*c8dee2aaSAndroid Build Coastguard Worker const CoordClampShaderBlock::CoordClampData& clampData,
870*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
871*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kCoordClampShader)
872*c8dee2aaSAndroid Build Coastguard Worker
873*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(clampData.fSubset);
874*c8dee2aaSAndroid Build Coastguard Worker }
875*c8dee2aaSAndroid Build Coastguard Worker
876*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
877*c8dee2aaSAndroid Build Coastguard Worker
BeginBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const CoordClampData & clampData)878*c8dee2aaSAndroid Build Coastguard Worker void CoordClampShaderBlock::BeginBlock(const KeyContext& keyContext,
879*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
880*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
881*c8dee2aaSAndroid Build Coastguard Worker const CoordClampData& clampData) {
882*c8dee2aaSAndroid Build Coastguard Worker add_coordclamp_uniform_data(keyContext.dict(), clampData, gatherer);
883*c8dee2aaSAndroid Build Coastguard Worker
884*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(BuiltInCodeSnippetID::kCoordClampShader);
885*c8dee2aaSAndroid Build Coastguard Worker }
886*c8dee2aaSAndroid Build Coastguard Worker
887*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
888*c8dee2aaSAndroid Build Coastguard Worker
889*c8dee2aaSAndroid Build Coastguard Worker namespace {
890*c8dee2aaSAndroid Build Coastguard Worker
add_dither_uniform_data(const ShaderCodeDictionary * dict,const DitherShaderBlock::DitherData & ditherData,PipelineDataGatherer * gatherer)891*c8dee2aaSAndroid Build Coastguard Worker void add_dither_uniform_data(const ShaderCodeDictionary* dict,
892*c8dee2aaSAndroid Build Coastguard Worker const DitherShaderBlock::DitherData& ditherData,
893*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
894*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kDitherShader)
895*c8dee2aaSAndroid Build Coastguard Worker
896*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(ditherData.fRange);
897*c8dee2aaSAndroid Build Coastguard Worker }
898*c8dee2aaSAndroid Build Coastguard Worker
899*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
900*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const DitherData & data)901*c8dee2aaSAndroid Build Coastguard Worker void DitherShaderBlock::AddBlock(const KeyContext& keyContext,
902*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
903*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
904*c8dee2aaSAndroid Build Coastguard Worker const DitherData& data) {
905*c8dee2aaSAndroid Build Coastguard Worker add_dither_uniform_data(keyContext.dict(), data, gatherer);
906*c8dee2aaSAndroid Build Coastguard Worker
907*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data.fLUTProxy || !keyContext.recorder());
908*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(data.fLUTProxy, {SkFilterMode::kNearest, SkTileMode::kRepeat});
909*c8dee2aaSAndroid Build Coastguard Worker
910*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kDitherShader);
911*c8dee2aaSAndroid Build Coastguard Worker }
912*c8dee2aaSAndroid Build Coastguard Worker
913*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
914*c8dee2aaSAndroid Build Coastguard Worker
915*c8dee2aaSAndroid Build Coastguard Worker namespace {
916*c8dee2aaSAndroid Build Coastguard Worker
add_perlin_noise_uniform_data(const ShaderCodeDictionary * dict,const PerlinNoiseShaderBlock::PerlinNoiseData & noiseData,PipelineDataGatherer * gatherer)917*c8dee2aaSAndroid Build Coastguard Worker void add_perlin_noise_uniform_data(const ShaderCodeDictionary* dict,
918*c8dee2aaSAndroid Build Coastguard Worker const PerlinNoiseShaderBlock::PerlinNoiseData& noiseData,
919*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
920*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kPerlinNoiseShader)
921*c8dee2aaSAndroid Build Coastguard Worker
922*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(noiseData.fBaseFrequency);
923*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(noiseData.fStitchData);
924*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(noiseData.fType));
925*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(noiseData.fNumOctaves);
926*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(noiseData.stitching()));
927*c8dee2aaSAndroid Build Coastguard Worker
928*c8dee2aaSAndroid Build Coastguard Worker static const std::pair<SkTileMode, SkTileMode> kRepeatXTileModes =
929*c8dee2aaSAndroid Build Coastguard Worker { SkTileMode::kRepeat, SkTileMode::kClamp };
930*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(noiseData.fPermutationsProxy, {SkFilterMode::kNearest, kRepeatXTileModes});
931*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(noiseData.fNoiseProxy, {SkFilterMode::kNearest, kRepeatXTileModes});
932*c8dee2aaSAndroid Build Coastguard Worker }
933*c8dee2aaSAndroid Build Coastguard Worker
934*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
935*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const PerlinNoiseData & noiseData)936*c8dee2aaSAndroid Build Coastguard Worker void PerlinNoiseShaderBlock::AddBlock(const KeyContext& keyContext,
937*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
938*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
939*c8dee2aaSAndroid Build Coastguard Worker const PerlinNoiseData& noiseData) {
940*c8dee2aaSAndroid Build Coastguard Worker add_perlin_noise_uniform_data(keyContext.dict(), noiseData, gatherer);
941*c8dee2aaSAndroid Build Coastguard Worker
942*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPerlinNoiseShader);
943*c8dee2aaSAndroid Build Coastguard Worker }
944*c8dee2aaSAndroid Build Coastguard Worker
945*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
946*c8dee2aaSAndroid Build Coastguard Worker
BeginBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer)947*c8dee2aaSAndroid Build Coastguard Worker void BlendComposeBlock::BeginBlock(const KeyContext& keyContext,
948*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
949*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
950*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, keyContext.dict(), BuiltInCodeSnippetID::kBlendCompose)
951*c8dee2aaSAndroid Build Coastguard Worker
952*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(BuiltInCodeSnippetID::kBlendCompose);
953*c8dee2aaSAndroid Build Coastguard Worker }
954*c8dee2aaSAndroid Build Coastguard Worker
955*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
956*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkSpan<const float> coeffs)957*c8dee2aaSAndroid Build Coastguard Worker void PorterDuffBlenderBlock::AddBlock(const KeyContext& keyContext,
958*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
959*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
960*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const float> coeffs) {
961*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, keyContext.dict(), BuiltInCodeSnippetID::kPorterDuffBlender)
962*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(coeffs.size() == 4);
963*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(SkV4{coeffs[0], coeffs[1], coeffs[2], coeffs[3]});
964*c8dee2aaSAndroid Build Coastguard Worker
965*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPorterDuffBlender);
966*c8dee2aaSAndroid Build Coastguard Worker }
967*c8dee2aaSAndroid Build Coastguard Worker
968*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
969*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkSpan<const float> coeffs)970*c8dee2aaSAndroid Build Coastguard Worker void HSLCBlenderBlock::AddBlock(const KeyContext& keyContext,
971*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
972*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
973*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const float> coeffs) {
974*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, keyContext.dict(), BuiltInCodeSnippetID::kHSLCBlender)
975*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(coeffs.size() == 2);
976*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(SkV2{coeffs[0], coeffs[1]});
977*c8dee2aaSAndroid Build Coastguard Worker
978*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kHSLCBlender);
979*c8dee2aaSAndroid Build Coastguard Worker }
980*c8dee2aaSAndroid Build Coastguard Worker
981*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
982*c8dee2aaSAndroid Build Coastguard Worker
BeginBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer)983*c8dee2aaSAndroid Build Coastguard Worker void ComposeBlock::BeginBlock(const KeyContext& keyContext,
984*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
985*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
986*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(BuiltInCodeSnippetID::kCompose);
987*c8dee2aaSAndroid Build Coastguard Worker }
988*c8dee2aaSAndroid Build Coastguard Worker
989*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
990*c8dee2aaSAndroid Build Coastguard Worker
991*c8dee2aaSAndroid Build Coastguard Worker namespace {
992*c8dee2aaSAndroid Build Coastguard Worker
add_matrix_colorfilter_uniform_data(const ShaderCodeDictionary * dict,const MatrixColorFilterBlock::MatrixColorFilterData & data,PipelineDataGatherer * gatherer)993*c8dee2aaSAndroid Build Coastguard Worker void add_matrix_colorfilter_uniform_data(const ShaderCodeDictionary* dict,
994*c8dee2aaSAndroid Build Coastguard Worker const MatrixColorFilterBlock::MatrixColorFilterData& data,
995*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
996*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kMatrixColorFilter)
997*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(data.fMatrix);
998*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(data.fTranslate);
999*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(data.fInHSLA));
1000*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(static_cast<int>(data.fClamp));
1001*c8dee2aaSAndroid Build Coastguard Worker }
1002*c8dee2aaSAndroid Build Coastguard Worker
1003*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
1004*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const MatrixColorFilterData & matrixCFData)1005*c8dee2aaSAndroid Build Coastguard Worker void MatrixColorFilterBlock::AddBlock(const KeyContext& keyContext,
1006*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1007*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1008*c8dee2aaSAndroid Build Coastguard Worker const MatrixColorFilterData& matrixCFData) {
1009*c8dee2aaSAndroid Build Coastguard Worker
1010*c8dee2aaSAndroid Build Coastguard Worker add_matrix_colorfilter_uniform_data(keyContext.dict(), matrixCFData, gatherer);
1011*c8dee2aaSAndroid Build Coastguard Worker
1012*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kMatrixColorFilter);
1013*c8dee2aaSAndroid Build Coastguard Worker }
1014*c8dee2aaSAndroid Build Coastguard Worker
1015*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1016*c8dee2aaSAndroid Build Coastguard Worker
1017*c8dee2aaSAndroid Build Coastguard Worker namespace {
1018*c8dee2aaSAndroid Build Coastguard Worker
add_table_colorfilter_uniform_data(const ShaderCodeDictionary * dict,const TableColorFilterBlock::TableColorFilterData & data,PipelineDataGatherer * gatherer)1019*c8dee2aaSAndroid Build Coastguard Worker void add_table_colorfilter_uniform_data(const ShaderCodeDictionary* dict,
1020*c8dee2aaSAndroid Build Coastguard Worker const TableColorFilterBlock::TableColorFilterData& data,
1021*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
1022*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kTableColorFilter)
1023*c8dee2aaSAndroid Build Coastguard Worker
1024*c8dee2aaSAndroid Build Coastguard Worker gatherer->add(data.fTextureProxy, {SkFilterMode::kNearest, SkTileMode::kClamp});
1025*c8dee2aaSAndroid Build Coastguard Worker }
1026*c8dee2aaSAndroid Build Coastguard Worker
1027*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
1028*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const TableColorFilterData & data)1029*c8dee2aaSAndroid Build Coastguard Worker void TableColorFilterBlock::AddBlock(const KeyContext& keyContext,
1030*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1031*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1032*c8dee2aaSAndroid Build Coastguard Worker const TableColorFilterData& data) {
1033*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data.fTextureProxy || !keyContext.recorder());
1034*c8dee2aaSAndroid Build Coastguard Worker
1035*c8dee2aaSAndroid Build Coastguard Worker add_table_colorfilter_uniform_data(keyContext.dict(), data, gatherer);
1036*c8dee2aaSAndroid Build Coastguard Worker
1037*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kTableColorFilter);
1038*c8dee2aaSAndroid Build Coastguard Worker }
1039*c8dee2aaSAndroid Build Coastguard Worker
1040*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1041*c8dee2aaSAndroid Build Coastguard Worker namespace {
1042*c8dee2aaSAndroid Build Coastguard Worker
add_color_space_xform_uniform_data(const ShaderCodeDictionary * dict,const ColorSpaceTransformBlock::ColorSpaceTransformData & data,PipelineDataGatherer * gatherer)1043*c8dee2aaSAndroid Build Coastguard Worker void add_color_space_xform_uniform_data(
1044*c8dee2aaSAndroid Build Coastguard Worker const ShaderCodeDictionary* dict,
1045*c8dee2aaSAndroid Build Coastguard Worker const ColorSpaceTransformBlock::ColorSpaceTransformData& data,
1046*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
1047*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kColorSpaceXformColorFilter)
1048*c8dee2aaSAndroid Build Coastguard Worker add_color_space_uniforms(data.fSteps, data.fReadSwizzle, gatherer);
1049*c8dee2aaSAndroid Build Coastguard Worker }
1050*c8dee2aaSAndroid Build Coastguard Worker
1051*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
1052*c8dee2aaSAndroid Build Coastguard Worker
ColorSpaceTransformData(const SkColorSpace * src,SkAlphaType srcAT,const SkColorSpace * dst,SkAlphaType dstAT)1053*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData::ColorSpaceTransformData(const SkColorSpace* src,
1054*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType srcAT,
1055*c8dee2aaSAndroid Build Coastguard Worker const SkColorSpace* dst,
1056*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAT)
1057*c8dee2aaSAndroid Build Coastguard Worker : fSteps(src, srcAT, dst, dstAT) {}
1058*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const ColorSpaceTransformData & data)1059*c8dee2aaSAndroid Build Coastguard Worker void ColorSpaceTransformBlock::AddBlock(const KeyContext& keyContext,
1060*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1061*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1062*c8dee2aaSAndroid Build Coastguard Worker const ColorSpaceTransformData& data) {
1063*c8dee2aaSAndroid Build Coastguard Worker add_color_space_xform_uniform_data(keyContext.dict(), data, gatherer);
1064*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kColorSpaceXformColorFilter);
1065*c8dee2aaSAndroid Build Coastguard Worker }
1066*c8dee2aaSAndroid Build Coastguard Worker
1067*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1068*c8dee2aaSAndroid Build Coastguard Worker namespace {
1069*c8dee2aaSAndroid Build Coastguard Worker
add_circular_rrect_clip_data(const ShaderCodeDictionary * dict,const CircularRRectClipBlock::CircularRRectClipData & data,PipelineDataGatherer * gatherer)1070*c8dee2aaSAndroid Build Coastguard Worker void add_circular_rrect_clip_data(
1071*c8dee2aaSAndroid Build Coastguard Worker const ShaderCodeDictionary* dict,
1072*c8dee2aaSAndroid Build Coastguard Worker const CircularRRectClipBlock::CircularRRectClipData& data,
1073*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
1074*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kCircularRRectClip)
1075*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(data.fRect);
1076*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(data.fRadiusPlusHalf);
1077*c8dee2aaSAndroid Build Coastguard Worker gatherer->writeHalf(data.fEdgeSelect);
1078*c8dee2aaSAndroid Build Coastguard Worker }
1079*c8dee2aaSAndroid Build Coastguard Worker
1080*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
1081*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const CircularRRectClipData & data)1082*c8dee2aaSAndroid Build Coastguard Worker void CircularRRectClipBlock::AddBlock(const KeyContext& keyContext,
1083*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1084*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1085*c8dee2aaSAndroid Build Coastguard Worker const CircularRRectClipData& data) {
1086*c8dee2aaSAndroid Build Coastguard Worker add_circular_rrect_clip_data(keyContext.dict(), data, gatherer);
1087*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kCircularRRectClip);
1088*c8dee2aaSAndroid Build Coastguard Worker }
1089*c8dee2aaSAndroid Build Coastguard Worker
1090*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1091*c8dee2aaSAndroid Build Coastguard Worker namespace {
1092*c8dee2aaSAndroid Build Coastguard Worker
add_primitive_color_uniform_data(const ShaderCodeDictionary * dict,const SkColorSpaceXformSteps & steps,PipelineDataGatherer * gatherer)1093*c8dee2aaSAndroid Build Coastguard Worker void add_primitive_color_uniform_data(
1094*c8dee2aaSAndroid Build Coastguard Worker const ShaderCodeDictionary* dict,
1095*c8dee2aaSAndroid Build Coastguard Worker const SkColorSpaceXformSteps& steps,
1096*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
1097*c8dee2aaSAndroid Build Coastguard Worker
1098*c8dee2aaSAndroid Build Coastguard Worker BEGIN_WRITE_UNIFORMS(gatherer, dict, BuiltInCodeSnippetID::kPrimitiveColor)
1099*c8dee2aaSAndroid Build Coastguard Worker add_color_space_uniforms(steps, ReadSwizzle::kRGBA, gatherer);
1100*c8dee2aaSAndroid Build Coastguard Worker }
1101*c8dee2aaSAndroid Build Coastguard Worker
1102*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
1103*c8dee2aaSAndroid Build Coastguard Worker
AddBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer)1104*c8dee2aaSAndroid Build Coastguard Worker void PrimitiveColorBlock::AddBlock(const KeyContext& keyContext,
1105*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1106*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
1107*c8dee2aaSAndroid Build Coastguard Worker SkColorSpaceXformSteps steps = SkColorSpaceXformSteps(SkColorSpace::MakeSRGB().get(),
1108*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
1109*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace(),
1110*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().alphaType());
1111*c8dee2aaSAndroid Build Coastguard Worker add_primitive_color_uniform_data(keyContext.dict(), steps, gatherer);
1112*c8dee2aaSAndroid Build Coastguard Worker
1113*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPrimitiveColor);
1114*c8dee2aaSAndroid Build Coastguard Worker }
1115*c8dee2aaSAndroid Build Coastguard Worker
1116*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1117*c8dee2aaSAndroid Build Coastguard Worker
AddBlendModeColorFilter(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkBlendMode bm,const SkPMColor4f & srcColor)1118*c8dee2aaSAndroid Build Coastguard Worker void AddBlendModeColorFilter(const KeyContext& keyContext,
1119*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1120*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1121*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode bm,
1122*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& srcColor) {
1123*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, builder, gatherer,
1124*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&] () -> void {
1125*c8dee2aaSAndroid Build Coastguard Worker AddBlendMode(keyContext, builder, gatherer, bm);
1126*c8dee2aaSAndroid Build Coastguard Worker },
1127*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&]() -> void {
1128*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(keyContext, builder, gatherer, srcColor);
1129*c8dee2aaSAndroid Build Coastguard Worker },
1130*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
1131*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
1132*c8dee2aaSAndroid Build Coastguard Worker });
1133*c8dee2aaSAndroid Build Coastguard Worker }
1134*c8dee2aaSAndroid Build Coastguard Worker
ShaderData(sk_sp<const SkRuntimeEffect> effect)1135*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::ShaderData::ShaderData(sk_sp<const SkRuntimeEffect> effect)
1136*c8dee2aaSAndroid Build Coastguard Worker : fEffect(std::move(effect)) {}
1137*c8dee2aaSAndroid Build Coastguard Worker
ShaderData(sk_sp<const SkRuntimeEffect> effect,sk_sp<const SkData> uniforms)1138*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::ShaderData::ShaderData(sk_sp<const SkRuntimeEffect> effect,
1139*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const SkData> uniforms)
1140*c8dee2aaSAndroid Build Coastguard Worker : fEffect(std::move(effect))
1141*c8dee2aaSAndroid Build Coastguard Worker , fUniforms(std::move(uniforms)) {}
1142*c8dee2aaSAndroid Build Coastguard Worker
skdata_matches(const SkData * a,const SkData * b)1143*c8dee2aaSAndroid Build Coastguard Worker static bool skdata_matches(const SkData* a, const SkData* b) {
1144*c8dee2aaSAndroid Build Coastguard Worker // Returns true if both SkData objects hold the same contents, or if they are both null.
1145*c8dee2aaSAndroid Build Coastguard Worker // (SkData::equals supports passing null, and returns false.)
1146*c8dee2aaSAndroid Build Coastguard Worker return a ? a->equals(b) : (a == b);
1147*c8dee2aaSAndroid Build Coastguard Worker }
1148*c8dee2aaSAndroid Build Coastguard Worker
operator ==(const ShaderData & rhs) const1149*c8dee2aaSAndroid Build Coastguard Worker bool RuntimeEffectBlock::ShaderData::operator==(const ShaderData& rhs) const {
1150*c8dee2aaSAndroid Build Coastguard Worker return fEffect == rhs.fEffect && skdata_matches(fUniforms.get(), rhs.fUniforms.get());
1151*c8dee2aaSAndroid Build Coastguard Worker }
1152*c8dee2aaSAndroid Build Coastguard Worker
gather_runtime_effect_uniforms(const KeyContext & keyContext,const SkRuntimeEffect * effect,SkSpan<const Uniform> graphiteUniforms,const SkData * uniformData,PipelineDataGatherer * gatherer)1153*c8dee2aaSAndroid Build Coastguard Worker static void gather_runtime_effect_uniforms(const KeyContext& keyContext,
1154*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* effect,
1155*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Uniform> graphiteUniforms,
1156*c8dee2aaSAndroid Build Coastguard Worker const SkData* uniformData,
1157*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) {
1158*c8dee2aaSAndroid Build Coastguard Worker if (!uniformData) {
1159*c8dee2aaSAndroid Build Coastguard Worker return; // precompiling
1160*c8dee2aaSAndroid Build Coastguard Worker }
1161*c8dee2aaSAndroid Build Coastguard Worker
1162*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, graphiteUniforms);)
1163*c8dee2aaSAndroid Build Coastguard Worker
1164*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkRuntimeEffect::Uniform> rtsUniforms = effect->uniforms();
1165*c8dee2aaSAndroid Build Coastguard Worker
1166*c8dee2aaSAndroid Build Coastguard Worker if (!rtsUniforms.empty() && uniformData) {
1167*c8dee2aaSAndroid Build Coastguard Worker // Collect all the other uniforms from the provided SkData.
1168*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* uniformBase = uniformData->bytes();
1169*c8dee2aaSAndroid Build Coastguard Worker for (size_t index = 0; index < rtsUniforms.size(); ++index) {
1170*c8dee2aaSAndroid Build Coastguard Worker const Uniform& uniform = graphiteUniforms[index];
1171*c8dee2aaSAndroid Build Coastguard Worker // Get a pointer to the offset in our data for this uniform.
1172*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* uniformPtr = uniformBase + rtsUniforms[index].offset;
1173*c8dee2aaSAndroid Build Coastguard Worker // Pass the uniform data to the gatherer.
1174*c8dee2aaSAndroid Build Coastguard Worker gatherer->write(uniform, uniformPtr);
1175*c8dee2aaSAndroid Build Coastguard Worker }
1176*c8dee2aaSAndroid Build Coastguard Worker }
1177*c8dee2aaSAndroid Build Coastguard Worker }
1178*c8dee2aaSAndroid Build Coastguard Worker
BeginBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const ShaderData & shaderData)1179*c8dee2aaSAndroid Build Coastguard Worker void RuntimeEffectBlock::BeginBlock(const KeyContext& keyContext,
1180*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1181*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1182*c8dee2aaSAndroid Build Coastguard Worker const ShaderData& shaderData) {
1183*c8dee2aaSAndroid Build Coastguard Worker ShaderCodeDictionary* dict = keyContext.dict();
1184*c8dee2aaSAndroid Build Coastguard Worker int codeSnippetID = dict->findOrCreateRuntimeEffectSnippet(shaderData.fEffect.get());
1185*c8dee2aaSAndroid Build Coastguard Worker
1186*c8dee2aaSAndroid Build Coastguard Worker if (codeSnippetID >= SkKnownRuntimeEffects::kUnknownRuntimeEffectIDStart) {
1187*c8dee2aaSAndroid Build Coastguard Worker keyContext.rtEffectDict()->set(codeSnippetID, shaderData.fEffect);
1188*c8dee2aaSAndroid Build Coastguard Worker }
1189*c8dee2aaSAndroid Build Coastguard Worker
1190*c8dee2aaSAndroid Build Coastguard Worker const ShaderSnippet* entry = dict->getEntry(codeSnippetID);
1191*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(entry);
1192*c8dee2aaSAndroid Build Coastguard Worker
1193*c8dee2aaSAndroid Build Coastguard Worker gather_runtime_effect_uniforms(keyContext,
1194*c8dee2aaSAndroid Build Coastguard Worker shaderData.fEffect.get(),
1195*c8dee2aaSAndroid Build Coastguard Worker entry->fUniforms,
1196*c8dee2aaSAndroid Build Coastguard Worker shaderData.fUniforms.get(),
1197*c8dee2aaSAndroid Build Coastguard Worker gatherer);
1198*c8dee2aaSAndroid Build Coastguard Worker
1199*c8dee2aaSAndroid Build Coastguard Worker builder->beginBlock(codeSnippetID);
1200*c8dee2aaSAndroid Build Coastguard Worker }
1201*c8dee2aaSAndroid Build Coastguard Worker
1202*c8dee2aaSAndroid Build Coastguard Worker // ==================================================================
1203*c8dee2aaSAndroid Build Coastguard Worker
1204*c8dee2aaSAndroid Build Coastguard Worker namespace {
1205*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkBlendModeBlender * blender)1206*c8dee2aaSAndroid Build Coastguard Worker void add_to_key(const KeyContext& keyContext,
1207*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1208*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1209*c8dee2aaSAndroid Build Coastguard Worker const SkBlendModeBlender* blender) {
1210*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(blender);
1211*c8dee2aaSAndroid Build Coastguard Worker
1212*c8dee2aaSAndroid Build Coastguard Worker AddBlendMode(keyContext, builder, gatherer, blender->mode());
1213*c8dee2aaSAndroid Build Coastguard Worker }
1214*c8dee2aaSAndroid Build Coastguard Worker
1215*c8dee2aaSAndroid Build Coastguard Worker // Be sure to keep this function in sync w/ the code in PrecompileRTEffect::addToKey
add_children_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkSpan<const SkRuntimeEffect::ChildPtr> children,const SkRuntimeEffect * effect)1216*c8dee2aaSAndroid Build Coastguard Worker void add_children_to_key(const KeyContext& keyContext,
1217*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1218*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1219*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkRuntimeEffect::ChildPtr> children,
1220*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect* effect) {
1221*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkRuntimeEffect::Child> childInfo = effect->children();
1222*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(children.size() == childInfo.size());
1223*c8dee2aaSAndroid Build Coastguard Worker
1224*c8dee2aaSAndroid Build Coastguard Worker using ChildType = SkRuntimeEffect::ChildType;
1225*c8dee2aaSAndroid Build Coastguard Worker
1226*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
1227*c8dee2aaSAndroid Build Coastguard Worker for (size_t index = 0; index < children.size(); ++index) {
1228*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeEffect::ChildPtr& child = children[index];
1229*c8dee2aaSAndroid Build Coastguard Worker std::optional<ChildType> type = child.type();
1230*c8dee2aaSAndroid Build Coastguard Worker if (type == ChildType::kShader) {
1231*c8dee2aaSAndroid Build Coastguard Worker AddToKey(childContext, builder, gatherer, child.shader());
1232*c8dee2aaSAndroid Build Coastguard Worker } else if (type == ChildType::kColorFilter) {
1233*c8dee2aaSAndroid Build Coastguard Worker AddToKey(childContext, builder, gatherer, child.colorFilter());
1234*c8dee2aaSAndroid Build Coastguard Worker } else if (type == ChildType::kBlender) {
1235*c8dee2aaSAndroid Build Coastguard Worker AddToKey(childContext, builder, gatherer, child.blender());
1236*c8dee2aaSAndroid Build Coastguard Worker } else {
1237*c8dee2aaSAndroid Build Coastguard Worker // We don't have a child effect. Substitute in a no-op effect.
1238*c8dee2aaSAndroid Build Coastguard Worker switch (childInfo[index].type) {
1239*c8dee2aaSAndroid Build Coastguard Worker case ChildType::kShader:
1240*c8dee2aaSAndroid Build Coastguard Worker // A missing shader returns transparent black
1241*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(childContext, builder, gatherer,
1242*c8dee2aaSAndroid Build Coastguard Worker SK_PMColor4fTRANSPARENT);
1243*c8dee2aaSAndroid Build Coastguard Worker break;
1244*c8dee2aaSAndroid Build Coastguard Worker
1245*c8dee2aaSAndroid Build Coastguard Worker case ChildType::kColorFilter:
1246*c8dee2aaSAndroid Build Coastguard Worker // A "passthrough" color filter returns the input color as-is.
1247*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
1248*c8dee2aaSAndroid Build Coastguard Worker break;
1249*c8dee2aaSAndroid Build Coastguard Worker
1250*c8dee2aaSAndroid Build Coastguard Worker case ChildType::kBlender:
1251*c8dee2aaSAndroid Build Coastguard Worker // A "passthrough" blender performs `blend_src_over(src, dest)`.
1252*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(childContext, builder, gatherer, SkBlendMode::kSrcOver);
1253*c8dee2aaSAndroid Build Coastguard Worker break;
1254*c8dee2aaSAndroid Build Coastguard Worker }
1255*c8dee2aaSAndroid Build Coastguard Worker }
1256*c8dee2aaSAndroid Build Coastguard Worker }
1257*c8dee2aaSAndroid Build Coastguard Worker
1258*c8dee2aaSAndroid Build Coastguard Worker // Runtime effects that reference color transform intrinsics have two extra children that
1259*c8dee2aaSAndroid Build Coastguard Worker // are bound to the colorspace xform snippet with values to go to and from the linear srgb
1260*c8dee2aaSAndroid Build Coastguard Worker // to the current working/dst color space.
1261*c8dee2aaSAndroid Build Coastguard Worker if (SkRuntimeEffectPriv::UsesColorTransform(effect)) {
1262*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace* dstCS = keyContext.dstColorInfo().colorSpace();
1263*c8dee2aaSAndroid Build Coastguard Worker if (!dstCS) {
1264*c8dee2aaSAndroid Build Coastguard Worker dstCS = sk_srgb_linear_singleton(); // turn colorspace conversion into a noop
1265*c8dee2aaSAndroid Build Coastguard Worker }
1266*c8dee2aaSAndroid Build Coastguard Worker
1267*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/332565302): If the runtime shader only uses one of these transforms, we could
1268*c8dee2aaSAndroid Build Coastguard Worker // upload only one set of uniforms.
1269*c8dee2aaSAndroid Build Coastguard Worker
1270*c8dee2aaSAndroid Build Coastguard Worker // NOTE: This must be kept in sync with the logic used to generate the toLinearSrgb() and
1271*c8dee2aaSAndroid Build Coastguard Worker // fromLinearSrgb() expressions for each runtime effect. toLinearSrgb() is assumed to be
1272*c8dee2aaSAndroid Build Coastguard Worker // the second to last child, and fromLinearSrgb() is assumed to be the last.
1273*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData dstToLinear(dstCS,
1274*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType,
1275*c8dee2aaSAndroid Build Coastguard Worker sk_srgb_linear_singleton(),
1276*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType);
1277*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData linearToDst(sk_srgb_linear_singleton(),
1278*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType,
1279*c8dee2aaSAndroid Build Coastguard Worker dstCS,
1280*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType);
1281*c8dee2aaSAndroid Build Coastguard Worker
1282*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(childContext, builder, gatherer, dstToLinear);
1283*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(childContext, builder, gatherer, linearToDst);
1284*c8dee2aaSAndroid Build Coastguard Worker }
1285*c8dee2aaSAndroid Build Coastguard Worker }
1286*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkRuntimeBlender * blender)1287*c8dee2aaSAndroid Build Coastguard Worker void add_to_key(const KeyContext& keyContext,
1288*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1289*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1290*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeBlender* blender) {
1291*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(blender);
1292*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkRuntimeEffect> effect = blender->effect();
1293*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(effect);
1294*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const SkData> uniforms = SkRuntimeEffectPriv::TransformUniforms(
1295*c8dee2aaSAndroid Build Coastguard Worker effect->uniforms(),
1296*c8dee2aaSAndroid Build Coastguard Worker blender->uniforms(),
1297*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace());
1298*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(uniforms);
1299*c8dee2aaSAndroid Build Coastguard Worker
1300*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer,
1301*c8dee2aaSAndroid Build Coastguard Worker { effect, std::move(uniforms) });
1302*c8dee2aaSAndroid Build Coastguard Worker
1303*c8dee2aaSAndroid Build Coastguard Worker add_children_to_key(keyContext, builder, gatherer,
1304*c8dee2aaSAndroid Build Coastguard Worker blender->children(), effect.get());
1305*c8dee2aaSAndroid Build Coastguard Worker
1306*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1307*c8dee2aaSAndroid Build Coastguard Worker }
1308*c8dee2aaSAndroid Build Coastguard Worker
notify_in_use(Recorder * recorder,DrawContext * drawContext,SkSpan<const SkRuntimeEffect::ChildPtr> children)1309*c8dee2aaSAndroid Build Coastguard Worker void notify_in_use(Recorder* recorder,
1310*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
1311*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkRuntimeEffect::ChildPtr> children) {
1312*c8dee2aaSAndroid Build Coastguard Worker for (const auto& child : children) {
1313*c8dee2aaSAndroid Build Coastguard Worker if (child.type().has_value()) {
1314*c8dee2aaSAndroid Build Coastguard Worker switch (*child.type()) {
1315*c8dee2aaSAndroid Build Coastguard Worker case SkRuntimeEffect::ChildType::kShader:
1316*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, child.shader());
1317*c8dee2aaSAndroid Build Coastguard Worker break;
1318*c8dee2aaSAndroid Build Coastguard Worker case SkRuntimeEffect::ChildType::kColorFilter:
1319*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, child.colorFilter());
1320*c8dee2aaSAndroid Build Coastguard Worker break;
1321*c8dee2aaSAndroid Build Coastguard Worker case SkRuntimeEffect::ChildType::kBlender:
1322*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, child.blender());
1323*c8dee2aaSAndroid Build Coastguard Worker break;
1324*c8dee2aaSAndroid Build Coastguard Worker }
1325*c8dee2aaSAndroid Build Coastguard Worker } // else a null child is a no-op, so cannot sample an image
1326*c8dee2aaSAndroid Build Coastguard Worker }
1327*c8dee2aaSAndroid Build Coastguard Worker }
1328*c8dee2aaSAndroid Build Coastguard Worker
1329*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
1330*c8dee2aaSAndroid Build Coastguard Worker
AddToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkBlender * blender)1331*c8dee2aaSAndroid Build Coastguard Worker void AddToKey(const KeyContext& keyContext,
1332*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1333*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1334*c8dee2aaSAndroid Build Coastguard Worker const SkBlender* blender) {
1335*c8dee2aaSAndroid Build Coastguard Worker if (!blender) {
1336*c8dee2aaSAndroid Build Coastguard Worker // Calling code assumes a block will be appended. Add a fixed block to preserve shader
1337*c8dee2aaSAndroid Build Coastguard Worker // and PaintParamsKey structure in release builds but assert since this should either not
1338*c8dee2aaSAndroid Build Coastguard Worker // happen or should be changing high-level logic within PaintParams::toKey().
1339*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
1340*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, builder, gatherer, SkBlendMode::kSrcOver);
1341*c8dee2aaSAndroid Build Coastguard Worker return;
1342*c8dee2aaSAndroid Build Coastguard Worker }
1343*c8dee2aaSAndroid Build Coastguard Worker switch (as_BB(blender)->type()) {
1344*c8dee2aaSAndroid Build Coastguard Worker #define M(type) \
1345*c8dee2aaSAndroid Build Coastguard Worker case SkBlenderBase::BlenderType::k##type: \
1346*c8dee2aaSAndroid Build Coastguard Worker add_to_key(keyContext, \
1347*c8dee2aaSAndroid Build Coastguard Worker builder, \
1348*c8dee2aaSAndroid Build Coastguard Worker gatherer, \
1349*c8dee2aaSAndroid Build Coastguard Worker static_cast<const Sk##type##Blender*>(blender)); \
1350*c8dee2aaSAndroid Build Coastguard Worker return;
1351*c8dee2aaSAndroid Build Coastguard Worker SK_ALL_BLENDERS(M)
1352*c8dee2aaSAndroid Build Coastguard Worker #undef M
1353*c8dee2aaSAndroid Build Coastguard Worker }
1354*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
1355*c8dee2aaSAndroid Build Coastguard Worker }
1356*c8dee2aaSAndroid Build Coastguard Worker
NotifyImagesInUse(Recorder * recorder,DrawContext * drawContext,const SkBlender * blender)1357*c8dee2aaSAndroid Build Coastguard Worker void NotifyImagesInUse(Recorder* recorder, DrawContext* drawContext, const SkBlender* blender) {
1358*c8dee2aaSAndroid Build Coastguard Worker if (!blender) {
1359*c8dee2aaSAndroid Build Coastguard Worker return;
1360*c8dee2aaSAndroid Build Coastguard Worker }
1361*c8dee2aaSAndroid Build Coastguard Worker if (as_BB(blender)->type() == SkBlenderBase::BlenderType::kRuntime) {
1362*c8dee2aaSAndroid Build Coastguard Worker const auto* rbb = static_cast<const SkRuntimeBlender*>(blender);
1363*c8dee2aaSAndroid Build Coastguard Worker notify_in_use(recorder, drawContext, rbb->children());
1364*c8dee2aaSAndroid Build Coastguard Worker } // else blend mode doesn't reference images
1365*c8dee2aaSAndroid Build Coastguard Worker }
1366*c8dee2aaSAndroid Build Coastguard Worker
1367*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
1368*c8dee2aaSAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
map_color(const SkColor4f & c,SkColorSpace * src,SkColorSpace * dst)1369*c8dee2aaSAndroid Build Coastguard Worker static SkPMColor4f map_color(const SkColor4f& c, SkColorSpace* src, SkColorSpace* dst) {
1370*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f color = {c.fR, c.fG, c.fB, c.fA};
1371*c8dee2aaSAndroid Build Coastguard Worker SkColorSpaceXformSteps(src, kUnpremul_SkAlphaType, dst, kPremul_SkAlphaType).apply(color.vec());
1372*c8dee2aaSAndroid Build Coastguard Worker return color;
1373*c8dee2aaSAndroid Build Coastguard Worker }
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkBlendModeColorFilter * filter)1374*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1375*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1376*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1377*c8dee2aaSAndroid Build Coastguard Worker const SkBlendModeColorFilter* filter) {
1378*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1379*c8dee2aaSAndroid Build Coastguard Worker
1380*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f color = map_color(filter->color(), sk_srgb_singleton(),
1381*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace());
1382*c8dee2aaSAndroid Build Coastguard Worker
1383*c8dee2aaSAndroid Build Coastguard Worker AddBlendModeColorFilter(keyContext, builder, gatherer, filter->mode(), color);
1384*c8dee2aaSAndroid Build Coastguard Worker }
1385*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkColorSpaceXformColorFilter * filter)1386*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1387*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1388*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1389*c8dee2aaSAndroid Build Coastguard Worker const SkColorSpaceXformColorFilter* filter) {
1390*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1391*c8dee2aaSAndroid Build Coastguard Worker
1392*c8dee2aaSAndroid Build Coastguard Worker constexpr SkAlphaType kAlphaType = kPremul_SkAlphaType;
1393*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData csData(filter->src().get(), kAlphaType,
1394*c8dee2aaSAndroid Build Coastguard Worker filter->dst().get(), kAlphaType);
1395*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, csData);
1396*c8dee2aaSAndroid Build Coastguard Worker }
1397*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer,const SkComposeColorFilter * filter)1398*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1399*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* keyBuilder,
1400*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1401*c8dee2aaSAndroid Build Coastguard Worker const SkComposeColorFilter* filter) {
1402*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1403*c8dee2aaSAndroid Build Coastguard Worker
1404*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, keyBuilder, gatherer,
1405*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1406*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, keyBuilder, gatherer, filter->inner().get());
1407*c8dee2aaSAndroid Build Coastguard Worker },
1408*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1409*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, keyBuilder, gatherer, filter->outer().get());
1410*c8dee2aaSAndroid Build Coastguard Worker });
1411*c8dee2aaSAndroid Build Coastguard Worker }
1412*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkGaussianColorFilter *)1413*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1414*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1415*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1416*c8dee2aaSAndroid Build Coastguard Worker const SkGaussianColorFilter*) {
1417*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kGaussianColorFilter);
1418*c8dee2aaSAndroid Build Coastguard Worker }
1419*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkMatrixColorFilter * filter)1420*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1421*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1422*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1423*c8dee2aaSAndroid Build Coastguard Worker const SkMatrixColorFilter* filter) {
1424*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1425*c8dee2aaSAndroid Build Coastguard Worker
1426*c8dee2aaSAndroid Build Coastguard Worker bool inHSLA = filter->domain() == SkMatrixColorFilter::Domain::kHSLA;
1427*c8dee2aaSAndroid Build Coastguard Worker bool clamp = filter->clamp() == SkMatrixColorFilter::Clamp::kYes;
1428*c8dee2aaSAndroid Build Coastguard Worker MatrixColorFilterBlock::MatrixColorFilterData matrixCFData(filter->matrix(), inHSLA, clamp);
1429*c8dee2aaSAndroid Build Coastguard Worker
1430*c8dee2aaSAndroid Build Coastguard Worker MatrixColorFilterBlock::AddBlock(keyContext, builder, gatherer, matrixCFData);
1431*c8dee2aaSAndroid Build Coastguard Worker }
1432*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkRuntimeColorFilter * filter)1433*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1434*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1435*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1436*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeColorFilter* filter) {
1437*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1438*c8dee2aaSAndroid Build Coastguard Worker
1439*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkRuntimeEffect> effect = filter->effect();
1440*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const SkData> uniforms = SkRuntimeEffectPriv::TransformUniforms(
1441*c8dee2aaSAndroid Build Coastguard Worker effect->uniforms(), filter->uniforms(), keyContext.dstColorInfo().colorSpace());
1442*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(uniforms);
1443*c8dee2aaSAndroid Build Coastguard Worker
1444*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer, {effect, std::move(uniforms)});
1445*c8dee2aaSAndroid Build Coastguard Worker
1446*c8dee2aaSAndroid Build Coastguard Worker add_children_to_key(keyContext, builder, gatherer,
1447*c8dee2aaSAndroid Build Coastguard Worker filter->children(), effect.get());
1448*c8dee2aaSAndroid Build Coastguard Worker
1449*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1450*c8dee2aaSAndroid Build Coastguard Worker }
1451*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkTableColorFilter * filter)1452*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1453*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1454*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1455*c8dee2aaSAndroid Build Coastguard Worker const SkTableColorFilter* filter) {
1456*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1457*c8dee2aaSAndroid Build Coastguard Worker
1458*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> proxy = RecorderPriv::CreateCachedProxy(keyContext.recorder(),
1459*c8dee2aaSAndroid Build Coastguard Worker filter->bitmap(),
1460*c8dee2aaSAndroid Build Coastguard Worker "TableColorFilterTexture");
1461*c8dee2aaSAndroid Build Coastguard Worker if (!proxy) {
1462*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create TableColorFilter's table");
1463*c8dee2aaSAndroid Build Coastguard Worker
1464*c8dee2aaSAndroid Build Coastguard Worker // Return the input color as-is.
1465*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
1466*c8dee2aaSAndroid Build Coastguard Worker return;
1467*c8dee2aaSAndroid Build Coastguard Worker }
1468*c8dee2aaSAndroid Build Coastguard Worker
1469*c8dee2aaSAndroid Build Coastguard Worker TableColorFilterBlock::TableColorFilterData data(std::move(proxy));
1470*c8dee2aaSAndroid Build Coastguard Worker
1471*c8dee2aaSAndroid Build Coastguard Worker TableColorFilterBlock::AddBlock(keyContext, builder, gatherer, data);
1472*c8dee2aaSAndroid Build Coastguard Worker }
1473*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkWorkingFormatColorFilter * filter)1474*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1475*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1476*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1477*c8dee2aaSAndroid Build Coastguard Worker const SkWorkingFormatColorFilter* filter) {
1478*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(filter);
1479*c8dee2aaSAndroid Build Coastguard Worker
1480*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& dstInfo = keyContext.dstColorInfo();
1481*c8dee2aaSAndroid Build Coastguard Worker const SkAlphaType dstAT = dstInfo.alphaType();
1482*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> dstCS = dstInfo.refColorSpace();
1483*c8dee2aaSAndroid Build Coastguard Worker if (!dstCS) {
1484*c8dee2aaSAndroid Build Coastguard Worker dstCS = SkColorSpace::MakeSRGB();
1485*c8dee2aaSAndroid Build Coastguard Worker }
1486*c8dee2aaSAndroid Build Coastguard Worker
1487*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType workingAT;
1488*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> workingCS = filter->workingFormat(dstCS, &workingAT);
1489*c8dee2aaSAndroid Build Coastguard Worker SkColorInfo workingInfo(dstInfo.colorType(), workingAT, workingCS);
1490*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithColorInfo workingContext(keyContext, workingInfo);
1491*c8dee2aaSAndroid Build Coastguard Worker
1492*c8dee2aaSAndroid Build Coastguard Worker // Use two nested compose blocks to chain (dst->working), child, and (working->dst) together
1493*c8dee2aaSAndroid Build Coastguard Worker // while appearing as one block to the parent node.
1494*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
1495*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1496*c8dee2aaSAndroid Build Coastguard Worker // Inner compose
1497*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
1498*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1499*c8dee2aaSAndroid Build Coastguard Worker // Innermost (inner of inner compose)
1500*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData data1(
1501*c8dee2aaSAndroid Build Coastguard Worker dstCS.get(), dstAT, workingCS.get(), workingAT);
1502*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer,
1503*c8dee2aaSAndroid Build Coastguard Worker data1);
1504*c8dee2aaSAndroid Build Coastguard Worker },
1505*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1506*c8dee2aaSAndroid Build Coastguard Worker // Middle (outer of inner compose)
1507*c8dee2aaSAndroid Build Coastguard Worker AddToKey(workingContext, builder, gatherer, filter->child().get());
1508*c8dee2aaSAndroid Build Coastguard Worker });
1509*c8dee2aaSAndroid Build Coastguard Worker },
1510*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1511*c8dee2aaSAndroid Build Coastguard Worker // Outermost (outer of outer compose)
1512*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData data2(
1513*c8dee2aaSAndroid Build Coastguard Worker workingCS.get(), workingAT, dstCS.get(), dstAT);
1514*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, data2);
1515*c8dee2aaSAndroid Build Coastguard Worker });
1516*c8dee2aaSAndroid Build Coastguard Worker }
1517*c8dee2aaSAndroid Build Coastguard Worker
AddToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkColorFilter * filter)1518*c8dee2aaSAndroid Build Coastguard Worker void AddToKey(const KeyContext& keyContext,
1519*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1520*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1521*c8dee2aaSAndroid Build Coastguard Worker const SkColorFilter* filter) {
1522*c8dee2aaSAndroid Build Coastguard Worker if (!filter) {
1523*c8dee2aaSAndroid Build Coastguard Worker // Calling code assumes a block will be appended. Add a fixed block to preserve shader
1524*c8dee2aaSAndroid Build Coastguard Worker // and PaintParamsKey structure in release builds but assert since this should either not
1525*c8dee2aaSAndroid Build Coastguard Worker // happen or should be changing high-level logic within PaintParams::toKey().
1526*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
1527*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
1528*c8dee2aaSAndroid Build Coastguard Worker return;
1529*c8dee2aaSAndroid Build Coastguard Worker }
1530*c8dee2aaSAndroid Build Coastguard Worker switch (as_CFB(filter)->type()) {
1531*c8dee2aaSAndroid Build Coastguard Worker case SkColorFilterBase::Type::kNoop:
1532*c8dee2aaSAndroid Build Coastguard Worker // Return the input color as-is.
1533*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
1534*c8dee2aaSAndroid Build Coastguard Worker return;
1535*c8dee2aaSAndroid Build Coastguard Worker #define M(type) \
1536*c8dee2aaSAndroid Build Coastguard Worker case SkColorFilterBase::Type::k##type: \
1537*c8dee2aaSAndroid Build Coastguard Worker add_to_key(keyContext, \
1538*c8dee2aaSAndroid Build Coastguard Worker builder, \
1539*c8dee2aaSAndroid Build Coastguard Worker gatherer, \
1540*c8dee2aaSAndroid Build Coastguard Worker static_cast<const Sk##type##ColorFilter*>(filter)); \
1541*c8dee2aaSAndroid Build Coastguard Worker return;
1542*c8dee2aaSAndroid Build Coastguard Worker SK_ALL_COLOR_FILTERS(M)
1543*c8dee2aaSAndroid Build Coastguard Worker #undef M
1544*c8dee2aaSAndroid Build Coastguard Worker }
1545*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
1546*c8dee2aaSAndroid Build Coastguard Worker }
1547*c8dee2aaSAndroid Build Coastguard Worker
NotifyImagesInUse(Recorder * recorder,DrawContext * drawContext,const SkColorFilter * filter)1548*c8dee2aaSAndroid Build Coastguard Worker void NotifyImagesInUse(Recorder* recorder, DrawContext* drawContext, const SkColorFilter* filter) {
1549*c8dee2aaSAndroid Build Coastguard Worker if (!filter) {
1550*c8dee2aaSAndroid Build Coastguard Worker return;
1551*c8dee2aaSAndroid Build Coastguard Worker }
1552*c8dee2aaSAndroid Build Coastguard Worker if (as_CFB(filter)->type() == SkColorFilterBase::Type::kCompose) {
1553*c8dee2aaSAndroid Build Coastguard Worker // Recurse to two children
1554*c8dee2aaSAndroid Build Coastguard Worker const auto* cf = static_cast<const SkComposeColorFilter*>(filter);
1555*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, cf->inner().get());
1556*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, cf->outer().get());
1557*c8dee2aaSAndroid Build Coastguard Worker } else if (as_CFB(filter)->type() == SkColorFilterBase::Type::kWorkingFormat) {
1558*c8dee2aaSAndroid Build Coastguard Worker // Recurse to one child
1559*c8dee2aaSAndroid Build Coastguard Worker const auto* wfcf = static_cast<const SkWorkingFormatColorFilter*>(filter);
1560*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, wfcf->child().get());
1561*c8dee2aaSAndroid Build Coastguard Worker } else if (as_CFB(filter)->type() == SkColorFilterBase::Type::kRuntime) {
1562*c8dee2aaSAndroid Build Coastguard Worker // Recurse to all children
1563*c8dee2aaSAndroid Build Coastguard Worker const auto* rcf = static_cast<const SkRuntimeColorFilter*>(filter);
1564*c8dee2aaSAndroid Build Coastguard Worker notify_in_use(recorder, drawContext, rcf->children());
1565*c8dee2aaSAndroid Build Coastguard Worker } // else other color filters do not rely on SkImages
1566*c8dee2aaSAndroid Build Coastguard Worker }
1567*c8dee2aaSAndroid Build Coastguard Worker
1568*c8dee2aaSAndroid Build Coastguard Worker // ==================================================================
1569*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkBlendShader * shader)1570*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1571*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1572*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1573*c8dee2aaSAndroid Build Coastguard Worker const SkBlendShader* shader) {
1574*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
1575*c8dee2aaSAndroid Build Coastguard Worker
1576*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, builder, gatherer,
1577*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&] () -> void {
1578*c8dee2aaSAndroid Build Coastguard Worker AddBlendMode(keyContext, builder, gatherer, shader->mode());
1579*c8dee2aaSAndroid Build Coastguard Worker },
1580*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&]() -> void {
1581*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, shader->src().get());
1582*c8dee2aaSAndroid Build Coastguard Worker },
1583*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
1584*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, shader->dst().get());
1585*c8dee2aaSAndroid Build Coastguard Worker });
1586*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkBlendShader * shader)1587*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
1588*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
1589*c8dee2aaSAndroid Build Coastguard Worker const SkBlendShader* shader) {
1590*c8dee2aaSAndroid Build Coastguard Worker // SkBlendShader uses a fixed blend mode, so there's no blender to recurse through
1591*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->src().get());
1592*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->dst().get());
1593*c8dee2aaSAndroid Build Coastguard Worker }
1594*c8dee2aaSAndroid Build Coastguard Worker
matrix_invert_or_identity(const SkMatrix & matrix)1595*c8dee2aaSAndroid Build Coastguard Worker static SkMatrix matrix_invert_or_identity(const SkMatrix& matrix) {
1596*c8dee2aaSAndroid Build Coastguard Worker SkMatrix inverseMatrix;
1597*c8dee2aaSAndroid Build Coastguard Worker if (!matrix.invert(&inverseMatrix)) {
1598*c8dee2aaSAndroid Build Coastguard Worker inverseMatrix.setIdentity();
1599*c8dee2aaSAndroid Build Coastguard Worker }
1600*c8dee2aaSAndroid Build Coastguard Worker
1601*c8dee2aaSAndroid Build Coastguard Worker return inverseMatrix;
1602*c8dee2aaSAndroid Build Coastguard Worker }
1603*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkCTMShader * shader)1604*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1605*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1606*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1607*c8dee2aaSAndroid Build Coastguard Worker const SkCTMShader* shader) {
1608*c8dee2aaSAndroid Build Coastguard Worker // CTM shaders are always given device coordinates, so we don't have to modify the CTM itself
1609*c8dee2aaSAndroid Build Coastguard Worker // with keyContext's local transform.
1610*c8dee2aaSAndroid Build Coastguard Worker
1611*c8dee2aaSAndroid Build Coastguard Worker SkMatrix lmInverse = matrix_invert_or_identity(shader->ctm());
1612*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::LMShaderData lmShaderData(lmInverse);
1613*c8dee2aaSAndroid Build Coastguard Worker
1614*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithLocalMatrix newContext(keyContext, shader->ctm());
1615*c8dee2aaSAndroid Build Coastguard Worker
1616*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::BeginBlock(newContext, builder, gatherer, lmShaderData);
1617*c8dee2aaSAndroid Build Coastguard Worker
1618*c8dee2aaSAndroid Build Coastguard Worker AddToKey(newContext, builder, gatherer, shader->proxyShader().get());
1619*c8dee2aaSAndroid Build Coastguard Worker
1620*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1621*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkCTMShader * shader)1622*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder, DrawContext* drawContext, const SkCTMShader* shader) {
1623*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->proxyShader().get());
1624*c8dee2aaSAndroid Build Coastguard Worker }
1625*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkColorShader * shader)1626*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1627*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1628*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1629*c8dee2aaSAndroid Build Coastguard Worker const SkColorShader* shader) {
1630*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
1631*c8dee2aaSAndroid Build Coastguard Worker
1632*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(keyContext, builder, gatherer,
1633*c8dee2aaSAndroid Build Coastguard Worker SkColor4f::FromColor(shader->color()).premul());
1634*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkColorShader *)1635*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkColorShader*) {
1636*c8dee2aaSAndroid Build Coastguard Worker // No-op
1637*c8dee2aaSAndroid Build Coastguard Worker }
1638*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkColor4Shader * shader)1639*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1640*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1641*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1642*c8dee2aaSAndroid Build Coastguard Worker const SkColor4Shader* shader) {
1643*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
1644*c8dee2aaSAndroid Build Coastguard Worker
1645*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f color = map_color(shader->color(), shader->colorSpace().get(),
1646*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace());
1647*c8dee2aaSAndroid Build Coastguard Worker
1648*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(keyContext, builder, gatherer, color);
1649*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkColor4Shader *)1650*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkColor4Shader*) {
1651*c8dee2aaSAndroid Build Coastguard Worker // No-op
1652*c8dee2aaSAndroid Build Coastguard Worker }
1653*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkColorFilterShader * shader)1654*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1655*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1656*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1657*c8dee2aaSAndroid Build Coastguard Worker const SkColorFilterShader* shader) {
1658*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
1659*c8dee2aaSAndroid Build Coastguard Worker
1660*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
1661*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1662*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, shader->shader().get());
1663*c8dee2aaSAndroid Build Coastguard Worker },
1664*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1665*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, shader->filter().get());
1666*c8dee2aaSAndroid Build Coastguard Worker });
1667*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkColorFilterShader * shader)1668*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
1669*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
1670*c8dee2aaSAndroid Build Coastguard Worker const SkColorFilterShader* shader) {
1671*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->shader().get());
1672*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->filter().get());
1673*c8dee2aaSAndroid Build Coastguard Worker }
1674*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkCoordClampShader * shader)1675*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1676*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1677*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1678*c8dee2aaSAndroid Build Coastguard Worker const SkCoordClampShader* shader) {
1679*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
1680*c8dee2aaSAndroid Build Coastguard Worker
1681*c8dee2aaSAndroid Build Coastguard Worker CoordClampShaderBlock::CoordClampData data(shader->subset());
1682*c8dee2aaSAndroid Build Coastguard Worker
1683*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithCoordClamp childContext(keyContext);
1684*c8dee2aaSAndroid Build Coastguard Worker CoordClampShaderBlock::BeginBlock(keyContext, builder, gatherer, data);
1685*c8dee2aaSAndroid Build Coastguard Worker AddToKey(childContext, builder, gatherer, shader->shader().get());
1686*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
1687*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkCoordClampShader * shader)1688*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
1689*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
1690*c8dee2aaSAndroid Build Coastguard Worker const SkCoordClampShader* shader) {
1691*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->shader().get());
1692*c8dee2aaSAndroid Build Coastguard Worker }
1693*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkEmptyShader *)1694*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1695*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1696*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1697*c8dee2aaSAndroid Build Coastguard Worker const SkEmptyShader*) {
1698*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
1699*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkEmptyShader *)1700*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkEmptyShader*) {
1701*c8dee2aaSAndroid Build Coastguard Worker // No-op
1702*c8dee2aaSAndroid Build Coastguard Worker }
1703*c8dee2aaSAndroid Build Coastguard Worker
is_premul_alpha_only(const ColorSpaceTransformBlock::ColorSpaceTransformData & data)1704*c8dee2aaSAndroid Build Coastguard Worker static bool is_premul_alpha_only(const ColorSpaceTransformBlock::ColorSpaceTransformData& data) {
1705*c8dee2aaSAndroid Build Coastguard Worker // A mask value of 16 means premul only.
1706*c8dee2aaSAndroid Build Coastguard Worker if (SkTo<int>(data.fSteps.flags.mask()) != 16) {
1707*c8dee2aaSAndroid Build Coastguard Worker return false;
1708*c8dee2aaSAndroid Build Coastguard Worker }
1709*c8dee2aaSAndroid Build Coastguard Worker
1710*c8dee2aaSAndroid Build Coastguard Worker // If read swizzle is RGBA or BGRA we don't need to do alpha swizzle
1711*c8dee2aaSAndroid Build Coastguard Worker return (data.fReadSwizzle == ReadSwizzle::kRGBA || data.fReadSwizzle == ReadSwizzle::kBGRA);
1712*c8dee2aaSAndroid Build Coastguard Worker }
1713*c8dee2aaSAndroid Build Coastguard Worker
add_yuv_image_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkImageShader * origShader,sk_sp<const SkImage> imageToDraw,SkSamplingOptions sampling)1714*c8dee2aaSAndroid Build Coastguard Worker static void add_yuv_image_to_key(const KeyContext& keyContext,
1715*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1716*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1717*c8dee2aaSAndroid Build Coastguard Worker const SkImageShader* origShader,
1718*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const SkImage> imageToDraw,
1719*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions sampling) {
1720*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!imageToDraw->isAlphaOnly());
1721*c8dee2aaSAndroid Build Coastguard Worker
1722*c8dee2aaSAndroid Build Coastguard Worker const Image_YUVA* yuvaImage = static_cast<const Image_YUVA*>(imageToDraw.get());
1723*c8dee2aaSAndroid Build Coastguard Worker const SkYUVAInfo& yuvaInfo = yuvaImage->yuvaInfo();
1724*c8dee2aaSAndroid Build Coastguard Worker // We would want to add a translation to the local matrix to handle other sitings.
1725*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(yuvaInfo.sitingX() == SkYUVAInfo::Siting::kCentered);
1726*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(yuvaInfo.sitingY() == SkYUVAInfo::Siting::kCentered);
1727*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::ImageData imgData(sampling,
1728*c8dee2aaSAndroid Build Coastguard Worker origShader->tileModeX(),
1729*c8dee2aaSAndroid Build Coastguard Worker origShader->tileModeY(),
1730*c8dee2aaSAndroid Build Coastguard Worker imageToDraw->dimensions(),
1731*c8dee2aaSAndroid Build Coastguard Worker origShader->subset());
1732*c8dee2aaSAndroid Build Coastguard Worker for (int locIndex = 0; locIndex < SkYUVAInfo::kYUVAChannelCount; ++locIndex) {
1733*c8dee2aaSAndroid Build Coastguard Worker const TextureProxyView& view = yuvaImage->proxyView(locIndex);
1734*c8dee2aaSAndroid Build Coastguard Worker if (view) {
1735*c8dee2aaSAndroid Build Coastguard Worker imgData.fTextureProxies[locIndex] = view.refProxy();
1736*c8dee2aaSAndroid Build Coastguard Worker // The view's swizzle has the data channel for the YUVA location in all slots, so read
1737*c8dee2aaSAndroid Build Coastguard Worker // the 0th slot to determine fChannelSelect
1738*c8dee2aaSAndroid Build Coastguard Worker switch(view.swizzle()[0]) {
1739*c8dee2aaSAndroid Build Coastguard Worker case 'r': imgData.fChannelSelect[locIndex] = {1.f, 0.f, 0.f, 0.f}; break;
1740*c8dee2aaSAndroid Build Coastguard Worker case 'g': imgData.fChannelSelect[locIndex] = {0.f, 1.f, 0.f, 0.f}; break;
1741*c8dee2aaSAndroid Build Coastguard Worker case 'b': imgData.fChannelSelect[locIndex] = {0.f, 0.f, 1.f, 0.f}; break;
1742*c8dee2aaSAndroid Build Coastguard Worker case 'a': imgData.fChannelSelect[locIndex] = {0.f, 0.f, 0.f, 1.f}; break;
1743*c8dee2aaSAndroid Build Coastguard Worker default:
1744*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[locIndex] = {0.f, 0.f, 0.f, 0.f};
1745*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGFAILF("Unexpected swizzle for YUVA data: %c", view.swizzle()[0]);
1746*c8dee2aaSAndroid Build Coastguard Worker break;
1747*c8dee2aaSAndroid Build Coastguard Worker }
1748*c8dee2aaSAndroid Build Coastguard Worker } else {
1749*c8dee2aaSAndroid Build Coastguard Worker // Only the A proxy view should be null, in which case we bind the Y proxy view to
1750*c8dee2aaSAndroid Build Coastguard Worker // pass validation and send all 1s for the channel selection to signal opaque alpha.
1751*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(locIndex == 3);
1752*c8dee2aaSAndroid Build Coastguard Worker imgData.fTextureProxies[locIndex] = yuvaImage->proxyView(SkYUVAInfo::kY).refProxy();
1753*c8dee2aaSAndroid Build Coastguard Worker imgData.fChannelSelect[locIndex] = {1.f, 1.f, 1.f, 1.f};
1754*c8dee2aaSAndroid Build Coastguard Worker // For the hardcoded sampling no-swizzle case, we use this to set constant alpha
1755*c8dee2aaSAndroid Build Coastguard Worker imgData.fAlphaParam = 1;
1756*c8dee2aaSAndroid Build Coastguard Worker }
1757*c8dee2aaSAndroid Build Coastguard Worker }
1758*c8dee2aaSAndroid Build Coastguard Worker
1759*c8dee2aaSAndroid Build Coastguard Worker auto [ssx, ssy] = yuvaImage->uvSubsampleFactors();
1760*c8dee2aaSAndroid Build Coastguard Worker if (ssx > 1 || ssy > 1) {
1761*c8dee2aaSAndroid Build Coastguard Worker // We need to adjust the image size we use for sampling to reflect the actual image size of
1762*c8dee2aaSAndroid Build Coastguard Worker // the UV planes. However, since our coordinates are in Y's texel space we need to scale
1763*c8dee2aaSAndroid Build Coastguard Worker // accordingly.
1764*c8dee2aaSAndroid Build Coastguard Worker const TextureProxyView& view = yuvaImage->proxyView(SkYUVAInfo::kU);
1765*c8dee2aaSAndroid Build Coastguard Worker imgData.fImgSizeUV = {view.dimensions().width()*ssx, view.dimensions().height()*ssy};
1766*c8dee2aaSAndroid Build Coastguard Worker // This promotion of nearest to linear filtering for UV planes exists to mimic
1767*c8dee2aaSAndroid Build Coastguard Worker // libjpeg[-turbo]'s do_fancy_upsampling option. We will filter the subsampled plane,
1768*c8dee2aaSAndroid Build Coastguard Worker // however we want to filter at a fixed point for each logical image pixel to simulate
1769*c8dee2aaSAndroid Build Coastguard Worker // nearest neighbor. In the shader we detect that the UV filtermode doesn't match the Y
1770*c8dee2aaSAndroid Build Coastguard Worker // filtermode, and snap to Y pixel centers.
1771*c8dee2aaSAndroid Build Coastguard Worker if (imgData.fSampling.filter == SkFilterMode::kNearest) {
1772*c8dee2aaSAndroid Build Coastguard Worker imgData.fSamplingUV = SkSamplingOptions(SkFilterMode::kLinear,
1773*c8dee2aaSAndroid Build Coastguard Worker imgData.fSampling.mipmap);
1774*c8dee2aaSAndroid Build Coastguard Worker // Consider a logical image pixel at the edge of the subset. When computing the logical
1775*c8dee2aaSAndroid Build Coastguard Worker // pixel color value we should use a blend of two values from the subsampled plane.
1776*c8dee2aaSAndroid Build Coastguard Worker // Depending on where the subset edge falls in actual subsampled plane, one of those
1777*c8dee2aaSAndroid Build Coastguard Worker // values may come from outside the subset. Hence, we will use the default inset
1778*c8dee2aaSAndroid Build Coastguard Worker // in Y texel space of 1/2. This applies the wrap mode to the subset but allows
1779*c8dee2aaSAndroid Build Coastguard Worker // linear filtering to read pixels that are just outside the subset.
1780*c8dee2aaSAndroid Build Coastguard Worker imgData.fLinearFilterUVInset.fX = 0.5f;
1781*c8dee2aaSAndroid Build Coastguard Worker imgData.fLinearFilterUVInset.fY = 0.5f;
1782*c8dee2aaSAndroid Build Coastguard Worker } else if (imgData.fSampling.filter == SkFilterMode::kLinear) {
1783*c8dee2aaSAndroid Build Coastguard Worker // We need to inset so that we aren't sampling outside the subset, but no farther.
1784*c8dee2aaSAndroid Build Coastguard Worker // Start by mapping the subset to UV texel space
1785*c8dee2aaSAndroid Build Coastguard Worker float scaleX = 1.f/ssx;
1786*c8dee2aaSAndroid Build Coastguard Worker float scaleY = 1.f/ssy;
1787*c8dee2aaSAndroid Build Coastguard Worker SkRect subsetUV = {imgData.fSubset.fLeft *scaleX,
1788*c8dee2aaSAndroid Build Coastguard Worker imgData.fSubset.fTop *scaleY,
1789*c8dee2aaSAndroid Build Coastguard Worker imgData.fSubset.fRight *scaleX,
1790*c8dee2aaSAndroid Build Coastguard Worker imgData.fSubset.fBottom*scaleY};
1791*c8dee2aaSAndroid Build Coastguard Worker // Round to UV texel borders
1792*c8dee2aaSAndroid Build Coastguard Worker SkIRect iSubsetUV = subsetUV.roundOut();
1793*c8dee2aaSAndroid Build Coastguard Worker // Inset in UV and map back to Y texel space. This gives us the largest possible
1794*c8dee2aaSAndroid Build Coastguard Worker // inset rectangle that will not sample outside of the subset texels in UV space.
1795*c8dee2aaSAndroid Build Coastguard Worker SkRect insetRectUV = {(iSubsetUV.fLeft +0.5f)*ssx,
1796*c8dee2aaSAndroid Build Coastguard Worker (iSubsetUV.fTop +0.5f)*ssy,
1797*c8dee2aaSAndroid Build Coastguard Worker (iSubsetUV.fRight -0.5f)*ssx,
1798*c8dee2aaSAndroid Build Coastguard Worker (iSubsetUV.fBottom-0.5f)*ssy};
1799*c8dee2aaSAndroid Build Coastguard Worker // Compute intersection with original inset
1800*c8dee2aaSAndroid Build Coastguard Worker SkRect insetRect = imgData.fSubset.makeOutset(-0.5f, -0.5f);
1801*c8dee2aaSAndroid Build Coastguard Worker (void) insetRect.intersect(insetRectUV);
1802*c8dee2aaSAndroid Build Coastguard Worker // Compute max inset values to ensure we always remain within the subset.
1803*c8dee2aaSAndroid Build Coastguard Worker imgData.fLinearFilterUVInset = {std::max(insetRect.fLeft - imgData.fSubset.fLeft,
1804*c8dee2aaSAndroid Build Coastguard Worker imgData.fSubset.fRight - insetRect.fRight),
1805*c8dee2aaSAndroid Build Coastguard Worker std::max(insetRect.fTop - imgData.fSubset.fTop,
1806*c8dee2aaSAndroid Build Coastguard Worker imgData.fSubset.fBottom - insetRect.fBottom)};
1807*c8dee2aaSAndroid Build Coastguard Worker }
1808*c8dee2aaSAndroid Build Coastguard Worker }
1809*c8dee2aaSAndroid Build Coastguard Worker
1810*c8dee2aaSAndroid Build Coastguard Worker float yuvM[20];
1811*c8dee2aaSAndroid Build Coastguard Worker SkColorMatrix_YUV2RGB(yuvaInfo.yuvColorSpace(), yuvM);
1812*c8dee2aaSAndroid Build Coastguard Worker // We drop the fourth column entirely since the transformation
1813*c8dee2aaSAndroid Build Coastguard Worker // should not depend on alpha. The fifth column is sent as a separate
1814*c8dee2aaSAndroid Build Coastguard Worker // vector. The fourth row is also dropped entirely because alpha should
1815*c8dee2aaSAndroid Build Coastguard Worker // never be modified.
1816*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(yuvM[3] == 0 && yuvM[8] == 0 && yuvM[13] == 0 && yuvM[18] == 1);
1817*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(yuvM[15] == 0 && yuvM[16] == 0 && yuvM[17] == 0 && yuvM[19] == 0);
1818*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBMatrix.setAll(
1819*c8dee2aaSAndroid Build Coastguard Worker yuvM[ 0], yuvM[ 1], yuvM[ 2],
1820*c8dee2aaSAndroid Build Coastguard Worker yuvM[ 5], yuvM[ 6], yuvM[ 7],
1821*c8dee2aaSAndroid Build Coastguard Worker yuvM[10], yuvM[11], yuvM[12]
1822*c8dee2aaSAndroid Build Coastguard Worker );
1823*c8dee2aaSAndroid Build Coastguard Worker imgData.fYUVtoRGBTranslate = {yuvM[4], yuvM[9], yuvM[14]};
1824*c8dee2aaSAndroid Build Coastguard Worker
1825*c8dee2aaSAndroid Build Coastguard Worker SkColorSpaceXformSteps steps;
1826*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(steps.flags.mask() == 0); // By default, the colorspace should have no effect
1827*c8dee2aaSAndroid Build Coastguard Worker
1828*c8dee2aaSAndroid Build Coastguard Worker // The actual output from the YUV image shader for non-opaque images is unpremul so
1829*c8dee2aaSAndroid Build Coastguard Worker // we need to correct for the fact that the Image_YUVA_Graphite's alpha type is premul.
1830*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType srcAT = imageToDraw->alphaType() == kPremul_SkAlphaType
1831*c8dee2aaSAndroid Build Coastguard Worker ? kUnpremul_SkAlphaType
1832*c8dee2aaSAndroid Build Coastguard Worker : imageToDraw->alphaType();
1833*c8dee2aaSAndroid Build Coastguard Worker if (origShader->isRaw()) {
1834*c8dee2aaSAndroid Build Coastguard Worker // Because we've avoided the premul alpha step in the YUV shader, we need to make sure
1835*c8dee2aaSAndroid Build Coastguard Worker // it happens when drawing unpremul (i.e., non-opaque) images.
1836*c8dee2aaSAndroid Build Coastguard Worker steps = SkColorSpaceXformSteps(imageToDraw->colorSpace(),
1837*c8dee2aaSAndroid Build Coastguard Worker srcAT,
1838*c8dee2aaSAndroid Build Coastguard Worker imageToDraw->colorSpace(),
1839*c8dee2aaSAndroid Build Coastguard Worker imageToDraw->alphaType());
1840*c8dee2aaSAndroid Build Coastguard Worker } else {
1841*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAT = keyContext.dstColorInfo().alphaType();
1842*c8dee2aaSAndroid Build Coastguard Worker // Setting the dst alphaType up this way is necessary because otherwise the constructor
1843*c8dee2aaSAndroid Build Coastguard Worker // for SkColorSpaceXformSteps will set dstAT = srcAT when dstAT == kOpaque, and the
1844*c8dee2aaSAndroid Build Coastguard Worker // premul step needed for non-opaque images won't occur.
1845*c8dee2aaSAndroid Build Coastguard Worker if (dstAT == kOpaque_SkAlphaType && srcAT == kUnpremul_SkAlphaType) {
1846*c8dee2aaSAndroid Build Coastguard Worker dstAT = kPremul_SkAlphaType;
1847*c8dee2aaSAndroid Build Coastguard Worker }
1848*c8dee2aaSAndroid Build Coastguard Worker steps = SkColorSpaceXformSteps(imageToDraw->colorSpace(),
1849*c8dee2aaSAndroid Build Coastguard Worker srcAT,
1850*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace(),
1851*c8dee2aaSAndroid Build Coastguard Worker dstAT);
1852*c8dee2aaSAndroid Build Coastguard Worker }
1853*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData data(steps);
1854*c8dee2aaSAndroid Build Coastguard Worker
1855*c8dee2aaSAndroid Build Coastguard Worker // We only do this for YUV images because this is the only case where we expect
1856*c8dee2aaSAndroid Build Coastguard Worker // a premul-only colorspace transformation to be common. Otherwise it's not
1857*c8dee2aaSAndroid Build Coastguard Worker // worth the combinatorial explosion in the precompile system.
1858*c8dee2aaSAndroid Build Coastguard Worker if (is_premul_alpha_only(data)) {
1859*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
1860*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1861*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
1862*c8dee2aaSAndroid Build Coastguard Worker },
1863*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1864*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPremulAlphaColorFilter);
1865*c8dee2aaSAndroid Build Coastguard Worker });
1866*c8dee2aaSAndroid Build Coastguard Worker } else {
1867*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
1868*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1869*c8dee2aaSAndroid Build Coastguard Worker YUVImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
1870*c8dee2aaSAndroid Build Coastguard Worker },
1871*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1872*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, data);
1873*c8dee2aaSAndroid Build Coastguard Worker });
1874*c8dee2aaSAndroid Build Coastguard Worker }
1875*c8dee2aaSAndroid Build Coastguard Worker }
1876*c8dee2aaSAndroid Build Coastguard Worker
swizzle_class_to_read_enum(const skgpu::Swizzle & swizzle)1877*c8dee2aaSAndroid Build Coastguard Worker static skgpu::graphite::ReadSwizzle swizzle_class_to_read_enum(const skgpu::Swizzle& swizzle) {
1878*c8dee2aaSAndroid Build Coastguard Worker if (swizzle == skgpu::Swizzle::RGBA()) {
1879*c8dee2aaSAndroid Build Coastguard Worker return skgpu::graphite::ReadSwizzle::kRGBA;
1880*c8dee2aaSAndroid Build Coastguard Worker } else if (swizzle == skgpu::Swizzle::RGB1()) {
1881*c8dee2aaSAndroid Build Coastguard Worker return skgpu::graphite::ReadSwizzle::kRGB1;
1882*c8dee2aaSAndroid Build Coastguard Worker } else if (swizzle == skgpu::Swizzle("rrr1")) {
1883*c8dee2aaSAndroid Build Coastguard Worker return skgpu::graphite::ReadSwizzle::kRRR1;
1884*c8dee2aaSAndroid Build Coastguard Worker } else if (swizzle == skgpu::Swizzle::BGRA()) {
1885*c8dee2aaSAndroid Build Coastguard Worker return skgpu::graphite::ReadSwizzle::kBGRA;
1886*c8dee2aaSAndroid Build Coastguard Worker } else if (swizzle == skgpu::Swizzle("000r")) {
1887*c8dee2aaSAndroid Build Coastguard Worker return skgpu::graphite::ReadSwizzle::k000R;
1888*c8dee2aaSAndroid Build Coastguard Worker } else {
1889*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("%s is an unsupported read swizzle. Defaulting to RGBA.\n",
1890*c8dee2aaSAndroid Build Coastguard Worker swizzle.asString().data());
1891*c8dee2aaSAndroid Build Coastguard Worker return skgpu::graphite::ReadSwizzle::kRGBA;
1892*c8dee2aaSAndroid Build Coastguard Worker }
1893*c8dee2aaSAndroid Build Coastguard Worker }
1894*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkImageShader * shader)1895*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
1896*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
1897*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
1898*c8dee2aaSAndroid Build Coastguard Worker const SkImageShader* shader) {
1899*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
1900*c8dee2aaSAndroid Build Coastguard Worker
1901*c8dee2aaSAndroid Build Coastguard Worker auto [ imageToDraw, newSampling ] = GetGraphiteBacked(keyContext.recorder(),
1902*c8dee2aaSAndroid Build Coastguard Worker shader->image().get(),
1903*c8dee2aaSAndroid Build Coastguard Worker shader->sampling());
1904*c8dee2aaSAndroid Build Coastguard Worker if (!imageToDraw) {
1905*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't convert ImageShader's image to a Graphite-backed image");
1906*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
1907*c8dee2aaSAndroid Build Coastguard Worker return;
1908*c8dee2aaSAndroid Build Coastguard Worker }
1909*c8dee2aaSAndroid Build Coastguard Worker if (!as_IB(shader->image())->isGraphiteBacked()) {
1910*c8dee2aaSAndroid Build Coastguard Worker // GetGraphiteBacked() created a new image (or fetched a cached image) from the client
1911*c8dee2aaSAndroid Build Coastguard Worker // image provider. This image was not available when NotifyInUse() visited the shader tree,
1912*c8dee2aaSAndroid Build Coastguard Worker // so call notify again. These images shouldn't really be producing new tasks since it's
1913*c8dee2aaSAndroid Build Coastguard Worker // unlikely that a client will be fulfilling with a dynamic image that wraps a long-lived
1914*c8dee2aaSAndroid Build Coastguard Worker // SkSurface. However, the images can be linked to a surface that rendered the initial
1915*c8dee2aaSAndroid Build Coastguard Worker // content and not calling notifyInUse() prevents unlinking the image from the Device.
1916*c8dee2aaSAndroid Build Coastguard Worker // If the client image provider then holds on to many of these images, the leaked Device and
1917*c8dee2aaSAndroid Build Coastguard Worker // DrawContext memory can be surprisingly high. b/338453542.
1918*c8dee2aaSAndroid Build Coastguard Worker // TODO (b/330864257): Once paint keys are extracted at draw time, AddToKey() will be
1919*c8dee2aaSAndroid Build Coastguard Worker // fully responsible for notifyInUse() calls and then we can simply always call this on
1920*c8dee2aaSAndroid Build Coastguard Worker // `imageToDraw`. The DrawContext that samples the image will also be available to AddToKey
1921*c8dee2aaSAndroid Build Coastguard Worker // so we won't have to pass in nullptr.
1922*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(as_IB(imageToDraw)->isGraphiteBacked());
1923*c8dee2aaSAndroid Build Coastguard Worker static_cast<Image_Base*>(imageToDraw.get())->notifyInUse(keyContext.recorder(),
1924*c8dee2aaSAndroid Build Coastguard Worker /*drawContext=*/nullptr);
1925*c8dee2aaSAndroid Build Coastguard Worker }
1926*c8dee2aaSAndroid Build Coastguard Worker if (as_IB(imageToDraw)->isYUVA()) {
1927*c8dee2aaSAndroid Build Coastguard Worker return add_yuv_image_to_key(keyContext,
1928*c8dee2aaSAndroid Build Coastguard Worker builder,
1929*c8dee2aaSAndroid Build Coastguard Worker gatherer,
1930*c8dee2aaSAndroid Build Coastguard Worker shader,
1931*c8dee2aaSAndroid Build Coastguard Worker std::move(imageToDraw),
1932*c8dee2aaSAndroid Build Coastguard Worker newSampling);
1933*c8dee2aaSAndroid Build Coastguard Worker }
1934*c8dee2aaSAndroid Build Coastguard Worker
1935*c8dee2aaSAndroid Build Coastguard Worker auto view = AsView(imageToDraw.get());
1936*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(newSampling.mipmap == SkMipmapMode::kNone || view.mipmapped() == Mipmapped::kYes);
1937*c8dee2aaSAndroid Build Coastguard Worker
1938*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::ImageData imgData(shader->sampling(),
1939*c8dee2aaSAndroid Build Coastguard Worker shader->tileModeX(),
1940*c8dee2aaSAndroid Build Coastguard Worker shader->tileModeY(),
1941*c8dee2aaSAndroid Build Coastguard Worker view.proxy()->dimensions(),
1942*c8dee2aaSAndroid Build Coastguard Worker shader->subset());
1943*c8dee2aaSAndroid Build Coastguard Worker
1944*c8dee2aaSAndroid Build Coastguard Worker // Here we detect pixel aligned blit-like image draws. Some devices have low precision filtering
1945*c8dee2aaSAndroid Build Coastguard Worker // and will produce degraded (blurry) images unexpectedly for sequential exact pixel blits when
1946*c8dee2aaSAndroid Build Coastguard Worker // not using nearest filtering. This is common for canvas scrolling implementations. Forcing
1947*c8dee2aaSAndroid Build Coastguard Worker // nearest filtering when possible can also be a minor perf/power optimization depending on the
1948*c8dee2aaSAndroid Build Coastguard Worker // hardware.
1949*c8dee2aaSAndroid Build Coastguard Worker bool samplingHasNoEffect = false;
1950*c8dee2aaSAndroid Build Coastguard Worker // Cubic sampling is will not filter the same as nearest even when pixel aligned.
1951*c8dee2aaSAndroid Build Coastguard Worker if (keyContext.optimizeSampling() == KeyContext::OptimizeSampling::kYes &&
1952*c8dee2aaSAndroid Build Coastguard Worker !newSampling.useCubic) {
1953*c8dee2aaSAndroid Build Coastguard Worker SkMatrix totalM = keyContext.local2Dev().asM33();
1954*c8dee2aaSAndroid Build Coastguard Worker if (keyContext.localMatrix()) {
1955*c8dee2aaSAndroid Build Coastguard Worker totalM.preConcat(*keyContext.localMatrix());
1956*c8dee2aaSAndroid Build Coastguard Worker }
1957*c8dee2aaSAndroid Build Coastguard Worker totalM.normalizePerspective();
1958*c8dee2aaSAndroid Build Coastguard Worker // The matrix should be translation with only pixel aligned 2d translation.
1959*c8dee2aaSAndroid Build Coastguard Worker samplingHasNoEffect = totalM.isTranslate() && SkScalarIsInt(totalM.getTranslateX()) &&
1960*c8dee2aaSAndroid Build Coastguard Worker SkScalarIsInt(totalM.getTranslateY());
1961*c8dee2aaSAndroid Build Coastguard Worker }
1962*c8dee2aaSAndroid Build Coastguard Worker
1963*c8dee2aaSAndroid Build Coastguard Worker imgData.fSampling = samplingHasNoEffect ? SkFilterMode::kNearest : newSampling;
1964*c8dee2aaSAndroid Build Coastguard Worker imgData.fTextureProxy = view.refProxy();
1965*c8dee2aaSAndroid Build Coastguard Worker skgpu::Swizzle readSwizzle = view.swizzle();
1966*c8dee2aaSAndroid Build Coastguard Worker // If the color type is alpha-only, propagate the alpha value to the other channels.
1967*c8dee2aaSAndroid Build Coastguard Worker if (imageToDraw->isAlphaOnly()) {
1968*c8dee2aaSAndroid Build Coastguard Worker readSwizzle = skgpu::Swizzle::Concat(readSwizzle, skgpu::Swizzle("000a"));
1969*c8dee2aaSAndroid Build Coastguard Worker }
1970*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData colorXformData(
1971*c8dee2aaSAndroid Build Coastguard Worker swizzle_class_to_read_enum(readSwizzle));
1972*c8dee2aaSAndroid Build Coastguard Worker
1973*c8dee2aaSAndroid Build Coastguard Worker if (!shader->isRaw()) {
1974*c8dee2aaSAndroid Build Coastguard Worker colorXformData.fSteps = SkColorSpaceXformSteps(imageToDraw->colorSpace(),
1975*c8dee2aaSAndroid Build Coastguard Worker imageToDraw->alphaType(),
1976*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace(),
1977*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().alphaType());
1978*c8dee2aaSAndroid Build Coastguard Worker
1979*c8dee2aaSAndroid Build Coastguard Worker if (imageToDraw->isAlphaOnly() && keyContext.scope() != KeyContext::Scope::kRuntimeEffect) {
1980*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, builder, gatherer,
1981*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&] () -> void {
1982*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, builder, gatherer, SkBlendMode::kDstIn);
1983*c8dee2aaSAndroid Build Coastguard Worker },
1984*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&] () -> void {
1985*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
1986*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
1987*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::AddBlock(keyContext, builder, gatherer,
1988*c8dee2aaSAndroid Build Coastguard Worker imgData);
1989*c8dee2aaSAndroid Build Coastguard Worker },
1990*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
1991*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer,
1992*c8dee2aaSAndroid Build Coastguard Worker colorXformData);
1993*c8dee2aaSAndroid Build Coastguard Worker });
1994*c8dee2aaSAndroid Build Coastguard Worker },
1995*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
1996*c8dee2aaSAndroid Build Coastguard Worker RGBPaintColorBlock::AddBlock(keyContext, builder, gatherer);
1997*c8dee2aaSAndroid Build Coastguard Worker });
1998*c8dee2aaSAndroid Build Coastguard Worker return;
1999*c8dee2aaSAndroid Build Coastguard Worker }
2000*c8dee2aaSAndroid Build Coastguard Worker }
2001*c8dee2aaSAndroid Build Coastguard Worker
2002*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
2003*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
2004*c8dee2aaSAndroid Build Coastguard Worker ImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
2005*c8dee2aaSAndroid Build Coastguard Worker },
2006*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
2007*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, colorXformData);
2008*c8dee2aaSAndroid Build Coastguard Worker });
2009*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkImageShader * shader)2010*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
2011*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
2012*c8dee2aaSAndroid Build Coastguard Worker const SkImageShader* shader) {
2013*c8dee2aaSAndroid Build Coastguard Worker auto image = as_IB(shader->image());
2014*c8dee2aaSAndroid Build Coastguard Worker if (!image->isGraphiteBacked()) {
2015*c8dee2aaSAndroid Build Coastguard Worker // If it's not graphite-backed, there's no pending graphite work.
2016*c8dee2aaSAndroid Build Coastguard Worker return;
2017*c8dee2aaSAndroid Build Coastguard Worker }
2018*c8dee2aaSAndroid Build Coastguard Worker
2019*c8dee2aaSAndroid Build Coastguard Worker static_cast<Image_Base*>(image)->notifyInUse(recorder, drawContext);
2020*c8dee2aaSAndroid Build Coastguard Worker }
2021*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkLocalMatrixShader * shader)2022*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2023*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2024*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2025*c8dee2aaSAndroid Build Coastguard Worker const SkLocalMatrixShader* shader) {
2026*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
2027*c8dee2aaSAndroid Build Coastguard Worker auto wrappedShader = shader->wrappedShader().get();
2028*c8dee2aaSAndroid Build Coastguard Worker
2029*c8dee2aaSAndroid Build Coastguard Worker // Fold the texture's origin flip into the local matrix so that the image shader doesn't need
2030*c8dee2aaSAndroid Build Coastguard Worker // additional state.
2031*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix;
2032*c8dee2aaSAndroid Build Coastguard Worker
2033*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase* wrappedShaderBase = as_SB(wrappedShader);
2034*c8dee2aaSAndroid Build Coastguard Worker if (wrappedShaderBase->type() == SkShaderBase::ShaderType::kImage) {
2035*c8dee2aaSAndroid Build Coastguard Worker auto imgShader = static_cast<const SkImageShader*>(wrappedShader);
2036*c8dee2aaSAndroid Build Coastguard Worker // If the image is not graphite backed then we can assume the origin will be TopLeft as we
2037*c8dee2aaSAndroid Build Coastguard Worker // require that in the ImageProvider utility. Also Graphite YUV images are assumed to be
2038*c8dee2aaSAndroid Build Coastguard Worker // TopLeft origin.
2039*c8dee2aaSAndroid Build Coastguard Worker auto imgBase = as_IB(imgShader->image());
2040*c8dee2aaSAndroid Build Coastguard Worker if (imgBase->isGraphiteBacked()) {
2041*c8dee2aaSAndroid Build Coastguard Worker // The YUV formats can encode their own origin including reflection and rotation,
2042*c8dee2aaSAndroid Build Coastguard Worker // so we need to concat that to the local matrix transform.
2043*c8dee2aaSAndroid Build Coastguard Worker if (imgBase->isYUVA()) {
2044*c8dee2aaSAndroid Build Coastguard Worker auto imgYUVA = static_cast<const Image_YUVA*>(imgBase);
2045*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(imgYUVA);
2046*c8dee2aaSAndroid Build Coastguard Worker matrix = matrix_invert_or_identity(imgYUVA->yuvaInfo().originMatrix());
2047*c8dee2aaSAndroid Build Coastguard Worker } else {
2048*c8dee2aaSAndroid Build Coastguard Worker auto imgGraphite = static_cast<Image*>(imgBase);
2049*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(imgGraphite);
2050*c8dee2aaSAndroid Build Coastguard Worker const auto& view = imgGraphite->textureProxyView();
2051*c8dee2aaSAndroid Build Coastguard Worker if (view.origin() == Origin::kBottomLeft) {
2052*c8dee2aaSAndroid Build Coastguard Worker matrix.setScaleY(-1);
2053*c8dee2aaSAndroid Build Coastguard Worker matrix.setTranslateY(view.height());
2054*c8dee2aaSAndroid Build Coastguard Worker }
2055*c8dee2aaSAndroid Build Coastguard Worker }
2056*c8dee2aaSAndroid Build Coastguard Worker
2057*c8dee2aaSAndroid Build Coastguard Worker }
2058*c8dee2aaSAndroid Build Coastguard Worker } else if (wrappedShaderBase->type() == SkShaderBase::ShaderType::kGradientBase) {
2059*c8dee2aaSAndroid Build Coastguard Worker auto gradShader = static_cast<const SkGradientBaseShader*>(wrappedShader);
2060*c8dee2aaSAndroid Build Coastguard Worker matrix = gradShader->getGradientMatrix();
2061*c8dee2aaSAndroid Build Coastguard Worker
2062*c8dee2aaSAndroid Build Coastguard Worker // Override the conical gradient matrix since graphite uses a different algorithm
2063*c8dee2aaSAndroid Build Coastguard Worker // than the ganesh and raster backends.
2064*c8dee2aaSAndroid Build Coastguard Worker if (gradShader->asGradient() == SkShaderBase::GradientType::kConical) {
2065*c8dee2aaSAndroid Build Coastguard Worker auto conicalShader = static_cast<const SkConicalGradient*>(gradShader);
2066*c8dee2aaSAndroid Build Coastguard Worker
2067*c8dee2aaSAndroid Build Coastguard Worker SkMatrix conicalMatrix;
2068*c8dee2aaSAndroid Build Coastguard Worker if (conicalShader->getType() == SkConicalGradient::Type::kRadial) {
2069*c8dee2aaSAndroid Build Coastguard Worker SkPoint center = conicalShader->getStartCenter();
2070*c8dee2aaSAndroid Build Coastguard Worker conicalMatrix.postTranslate(-center.fX, -center.fY);
2071*c8dee2aaSAndroid Build Coastguard Worker
2072*c8dee2aaSAndroid Build Coastguard Worker float scale = sk_ieee_float_divide(1, conicalShader->getDiffRadius());
2073*c8dee2aaSAndroid Build Coastguard Worker conicalMatrix.postScale(scale, scale);
2074*c8dee2aaSAndroid Build Coastguard Worker } else {
2075*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(SkConicalGradient::MapToUnitX(conicalShader->getStartCenter(),
2076*c8dee2aaSAndroid Build Coastguard Worker conicalShader->getEndCenter(),
2077*c8dee2aaSAndroid Build Coastguard Worker &conicalMatrix));
2078*c8dee2aaSAndroid Build Coastguard Worker }
2079*c8dee2aaSAndroid Build Coastguard Worker matrix = conicalMatrix;
2080*c8dee2aaSAndroid Build Coastguard Worker }
2081*c8dee2aaSAndroid Build Coastguard Worker }
2082*c8dee2aaSAndroid Build Coastguard Worker
2083*c8dee2aaSAndroid Build Coastguard Worker SkMatrix lmInverse = matrix_invert_or_identity(shader->localMatrix());
2084*c8dee2aaSAndroid Build Coastguard Worker lmInverse.postConcat(matrix);
2085*c8dee2aaSAndroid Build Coastguard Worker
2086*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::LMShaderData lmShaderData(lmInverse);
2087*c8dee2aaSAndroid Build Coastguard Worker
2088*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithLocalMatrix newContext(keyContext, shader->localMatrix());
2089*c8dee2aaSAndroid Build Coastguard Worker
2090*c8dee2aaSAndroid Build Coastguard Worker LocalMatrixShaderBlock::BeginBlock(newContext, builder, gatherer, lmShaderData);
2091*c8dee2aaSAndroid Build Coastguard Worker
2092*c8dee2aaSAndroid Build Coastguard Worker AddToKey(newContext, builder, gatherer, wrappedShader);
2093*c8dee2aaSAndroid Build Coastguard Worker
2094*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
2095*c8dee2aaSAndroid Build Coastguard Worker }
2096*c8dee2aaSAndroid Build Coastguard Worker
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkLocalMatrixShader * shader)2097*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
2098*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
2099*c8dee2aaSAndroid Build Coastguard Worker const SkLocalMatrixShader* shader) {
2100*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->wrappedShader().get());
2101*c8dee2aaSAndroid Build Coastguard Worker }
2102*c8dee2aaSAndroid Build Coastguard Worker
2103*c8dee2aaSAndroid Build Coastguard Worker // If either of these change then the corresponding change must also be made in the SkSL
2104*c8dee2aaSAndroid Build Coastguard Worker // perlin_noise_shader function.
2105*c8dee2aaSAndroid Build Coastguard Worker static_assert((int)SkPerlinNoiseShaderType::kFractalNoise ==
2106*c8dee2aaSAndroid Build Coastguard Worker (int)PerlinNoiseShaderBlock::Type::kFractalNoise);
2107*c8dee2aaSAndroid Build Coastguard Worker static_assert((int)SkPerlinNoiseShaderType::kTurbulence ==
2108*c8dee2aaSAndroid Build Coastguard Worker (int)PerlinNoiseShaderBlock::Type::kTurbulence);
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkPerlinNoiseShader * shader)2109*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2110*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2111*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2112*c8dee2aaSAndroid Build Coastguard Worker const SkPerlinNoiseShader* shader) {
2113*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
2114*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader->numOctaves());
2115*c8dee2aaSAndroid Build Coastguard Worker
2116*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPerlinNoiseShader::PaintingData> paintingData = shader->getPaintingData();
2117*c8dee2aaSAndroid Build Coastguard Worker paintingData->generateBitmaps();
2118*c8dee2aaSAndroid Build Coastguard Worker
2119*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> perm =
2120*c8dee2aaSAndroid Build Coastguard Worker RecorderPriv::CreateCachedProxy(keyContext.recorder(),
2121*c8dee2aaSAndroid Build Coastguard Worker paintingData->getPermutationsBitmap(),
2122*c8dee2aaSAndroid Build Coastguard Worker "PerlinNoisePermTable");
2123*c8dee2aaSAndroid Build Coastguard Worker
2124*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> noise =
2125*c8dee2aaSAndroid Build Coastguard Worker RecorderPriv::CreateCachedProxy(keyContext.recorder(), paintingData->getNoiseBitmap(),
2126*c8dee2aaSAndroid Build Coastguard Worker "PerlinNoiseNoiseTable");
2127*c8dee2aaSAndroid Build Coastguard Worker
2128*c8dee2aaSAndroid Build Coastguard Worker if (!perm || !noise) {
2129*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create tables for PerlinNoiseShader");
2130*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2131*c8dee2aaSAndroid Build Coastguard Worker return;
2132*c8dee2aaSAndroid Build Coastguard Worker }
2133*c8dee2aaSAndroid Build Coastguard Worker
2134*c8dee2aaSAndroid Build Coastguard Worker PerlinNoiseShaderBlock::PerlinNoiseData perlinData(
2135*c8dee2aaSAndroid Build Coastguard Worker static_cast<PerlinNoiseShaderBlock::Type>(shader->noiseType()),
2136*c8dee2aaSAndroid Build Coastguard Worker paintingData->fBaseFrequency,
2137*c8dee2aaSAndroid Build Coastguard Worker shader->numOctaves(),
2138*c8dee2aaSAndroid Build Coastguard Worker {paintingData->fStitchDataInit.fWidth, paintingData->fStitchDataInit.fHeight});
2139*c8dee2aaSAndroid Build Coastguard Worker
2140*c8dee2aaSAndroid Build Coastguard Worker perlinData.fPermutationsProxy = std::move(perm);
2141*c8dee2aaSAndroid Build Coastguard Worker perlinData.fNoiseProxy = std::move(noise);
2142*c8dee2aaSAndroid Build Coastguard Worker
2143*c8dee2aaSAndroid Build Coastguard Worker PerlinNoiseShaderBlock::AddBlock(keyContext, builder, gatherer, perlinData);
2144*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkPerlinNoiseShader *)2145*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkPerlinNoiseShader*) {
2146*c8dee2aaSAndroid Build Coastguard Worker // No-op, perlin noise has no children.
2147*c8dee2aaSAndroid Build Coastguard Worker }
2148*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkPictureShader * shader)2149*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2150*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2151*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2152*c8dee2aaSAndroid Build Coastguard Worker const SkPictureShader* shader) {
2153*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
2154*c8dee2aaSAndroid Build Coastguard Worker
2155*c8dee2aaSAndroid Build Coastguard Worker Recorder* recorder = keyContext.recorder();
2156*c8dee2aaSAndroid Build Coastguard Worker const Caps* caps = recorder->priv().caps();
2157*c8dee2aaSAndroid Build Coastguard Worker
2158*c8dee2aaSAndroid Build Coastguard Worker // TODO: We'll need additional plumbing to get the correct props from our callers. In
2159*c8dee2aaSAndroid Build Coastguard Worker // particular we'll need to expand the keyContext to have the surfaceProps.
2160*c8dee2aaSAndroid Build Coastguard Worker SkSurfaceProps props{};
2161*c8dee2aaSAndroid Build Coastguard Worker
2162*c8dee2aaSAndroid Build Coastguard Worker SkMatrix totalM = keyContext.local2Dev().asM33();
2163*c8dee2aaSAndroid Build Coastguard Worker if (keyContext.localMatrix()) {
2164*c8dee2aaSAndroid Build Coastguard Worker totalM.preConcat(*keyContext.localMatrix());
2165*c8dee2aaSAndroid Build Coastguard Worker }
2166*c8dee2aaSAndroid Build Coastguard Worker auto info = SkPictureShader::CachedImageInfo::Make(shader->tile(),
2167*c8dee2aaSAndroid Build Coastguard Worker totalM,
2168*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorType(),
2169*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace(),
2170*c8dee2aaSAndroid Build Coastguard Worker caps->maxTextureSize(),
2171*c8dee2aaSAndroid Build Coastguard Worker props);
2172*c8dee2aaSAndroid Build Coastguard Worker if (!info.success) {
2173*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't access PictureShaders' Image info");
2174*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2175*c8dee2aaSAndroid Build Coastguard Worker return;
2176*c8dee2aaSAndroid Build Coastguard Worker }
2177*c8dee2aaSAndroid Build Coastguard Worker
2178*c8dee2aaSAndroid Build Coastguard Worker // NOTE: While this is intended to be a "scratch" surface, we don't use MakeScratch() because
2179*c8dee2aaSAndroid Build Coastguard Worker // the SkPicture could contain arbitrary operations that rely on the Recorder's atlases, which
2180*c8dee2aaSAndroid Build Coastguard Worker // means the Surface's device has to participate in flushing when the atlas fills up.
2181*c8dee2aaSAndroid Build Coastguard Worker // TODO: Can this be an approx-fit image that's generated?
2182*c8dee2aaSAndroid Build Coastguard Worker // TODO: right now we're explicitly not caching here. We could expand the ImageProvider
2183*c8dee2aaSAndroid Build Coastguard Worker // API to include already Graphite-backed images, add a Recorder-local cache or add
2184*c8dee2aaSAndroid Build Coastguard Worker // rendered-picture images to the global cache.
2185*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Surface> surface = Surface::Make(recorder,
2186*c8dee2aaSAndroid Build Coastguard Worker info.imageInfo,
2187*c8dee2aaSAndroid Build Coastguard Worker "PictureShaderTexture",
2188*c8dee2aaSAndroid Build Coastguard Worker Budgeted::kYes,
2189*c8dee2aaSAndroid Build Coastguard Worker Mipmapped::kNo,
2190*c8dee2aaSAndroid Build Coastguard Worker SkBackingFit::kExact,
2191*c8dee2aaSAndroid Build Coastguard Worker &info.props);
2192*c8dee2aaSAndroid Build Coastguard Worker if (!surface) {
2193*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Could not create surface to render PictureShader");
2194*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2195*c8dee2aaSAndroid Build Coastguard Worker return;
2196*c8dee2aaSAndroid Build Coastguard Worker }
2197*c8dee2aaSAndroid Build Coastguard Worker
2198*c8dee2aaSAndroid Build Coastguard Worker // NOTE: Don't call CachedImageInfo::makeImage() since that uses the legacy makeImageSnapshot()
2199*c8dee2aaSAndroid Build Coastguard Worker // API, which results in an extra texture copy on a Graphite Surface.
2200*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->concat(info.matrixForDraw);
2201*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPicture(shader->picture().get());
2202*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> img = SkSurfaces::AsImage(std::move(surface));
2203*c8dee2aaSAndroid Build Coastguard Worker // TODO: 'img' did not exist when notify_in_use() was called, but ideally the DrawTask to render
2204*c8dee2aaSAndroid Build Coastguard Worker // into 'surface' would be a child of the current device. While we push all tasks to the root
2205*c8dee2aaSAndroid Build Coastguard Worker // list this works out okay, but will need to be addressed before we move off that system.
2206*c8dee2aaSAndroid Build Coastguard Worker if (!img) {
2207*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create SkImage for PictureShader");
2208*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2209*c8dee2aaSAndroid Build Coastguard Worker return;
2210*c8dee2aaSAndroid Build Coastguard Worker }
2211*c8dee2aaSAndroid Build Coastguard Worker
2212*c8dee2aaSAndroid Build Coastguard Worker const auto shaderLM = SkMatrix::Scale(1.f/info.tileScale.width(), 1.f/info.tileScale.height());
2213*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> imgShader = img->makeShader(shader->tileModeX(), shader->tileModeY(),
2214*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(shader->filter()), &shaderLM);
2215*c8dee2aaSAndroid Build Coastguard Worker if (!imgShader) {
2216*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create SkImageShader for PictureShader");
2217*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2218*c8dee2aaSAndroid Build Coastguard Worker return;
2219*c8dee2aaSAndroid Build Coastguard Worker }
2220*c8dee2aaSAndroid Build Coastguard Worker
2221*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, imgShader.get());
2222*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkPictureShader *)2223*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkPictureShader*) {
2224*c8dee2aaSAndroid Build Coastguard Worker // While the SkPicture the shader points to, may have Graphite-backed shaders that need to be
2225*c8dee2aaSAndroid Build Coastguard Worker // notified, that will happen when the picture is rendered into an image in add_to_key
2226*c8dee2aaSAndroid Build Coastguard Worker }
2227*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkRuntimeShader * shader)2228*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2229*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2230*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2231*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeShader* shader) {
2232*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
2233*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkRuntimeEffect> effect = shader->effect();
2234*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const SkData> uniforms = SkRuntimeEffectPriv::TransformUniforms(
2235*c8dee2aaSAndroid Build Coastguard Worker effect->uniforms(),
2236*c8dee2aaSAndroid Build Coastguard Worker shader->uniformData(keyContext.dstColorInfo().colorSpace()),
2237*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo().colorSpace());
2238*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(uniforms);
2239*c8dee2aaSAndroid Build Coastguard Worker
2240*c8dee2aaSAndroid Build Coastguard Worker RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer,
2241*c8dee2aaSAndroid Build Coastguard Worker {effect, std::move(uniforms)});
2242*c8dee2aaSAndroid Build Coastguard Worker
2243*c8dee2aaSAndroid Build Coastguard Worker add_children_to_key(keyContext, builder, gatherer,
2244*c8dee2aaSAndroid Build Coastguard Worker shader->children(), effect.get());
2245*c8dee2aaSAndroid Build Coastguard Worker
2246*c8dee2aaSAndroid Build Coastguard Worker builder->endBlock();
2247*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkRuntimeShader * shader)2248*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
2249*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
2250*c8dee2aaSAndroid Build Coastguard Worker const SkRuntimeShader* shader) {
2251*c8dee2aaSAndroid Build Coastguard Worker notify_in_use(recorder, drawContext, shader->children());
2252*c8dee2aaSAndroid Build Coastguard Worker }
2253*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkTransformShader * shader)2254*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2255*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2256*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2257*c8dee2aaSAndroid Build Coastguard Worker const SkTransformShader* shader) {
2258*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Raster-only SkShader (SkTransformShader) encountered");
2259*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2260*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkTransformShader *)2261*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkTransformShader*) {
2262*c8dee2aaSAndroid Build Coastguard Worker // no-op
2263*c8dee2aaSAndroid Build Coastguard Worker }
2264*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkTriColorShader * shader)2265*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2266*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2267*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2268*c8dee2aaSAndroid Build Coastguard Worker const SkTriColorShader* shader) {
2269*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Raster-only SkShader (SkTriColorShader) encountered");
2270*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2271*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkTriColorShader *)2272*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkTriColorShader*) {
2273*c8dee2aaSAndroid Build Coastguard Worker // no-op
2274*c8dee2aaSAndroid Build Coastguard Worker }
2275*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkWorkingColorSpaceShader * shader)2276*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2277*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2278*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2279*c8dee2aaSAndroid Build Coastguard Worker const SkWorkingColorSpaceShader* shader) {
2280*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
2281*c8dee2aaSAndroid Build Coastguard Worker
2282*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& dstInfo = keyContext.dstColorInfo();
2283*c8dee2aaSAndroid Build Coastguard Worker const SkAlphaType dstAT = dstInfo.alphaType();
2284*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> dstCS = dstInfo.refColorSpace();
2285*c8dee2aaSAndroid Build Coastguard Worker if (!dstCS) {
2286*c8dee2aaSAndroid Build Coastguard Worker dstCS = SkColorSpace::MakeSRGB();
2287*c8dee2aaSAndroid Build Coastguard Worker }
2288*c8dee2aaSAndroid Build Coastguard Worker
2289*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> workingCS = shader->workingSpace();
2290*c8dee2aaSAndroid Build Coastguard Worker SkColorInfo workingInfo(dstInfo.colorType(), dstAT, workingCS);
2291*c8dee2aaSAndroid Build Coastguard Worker KeyContextWithColorInfo workingContext(keyContext, workingInfo);
2292*c8dee2aaSAndroid Build Coastguard Worker
2293*c8dee2aaSAndroid Build Coastguard Worker // Compose the inner shader (in the working space) with a (working->dst) transform:
2294*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
2295*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
2296*c8dee2aaSAndroid Build Coastguard Worker AddToKey(workingContext, builder, gatherer, shader->shader().get());
2297*c8dee2aaSAndroid Build Coastguard Worker },
2298*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
2299*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData data(
2300*c8dee2aaSAndroid Build Coastguard Worker workingCS.get(), dstAT, dstCS.get(), dstAT);
2301*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, data);
2302*c8dee2aaSAndroid Build Coastguard Worker });
2303*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder * recorder,DrawContext * drawContext,const SkWorkingColorSpaceShader * shader)2304*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder* recorder,
2305*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
2306*c8dee2aaSAndroid Build Coastguard Worker const SkWorkingColorSpaceShader* shader) {
2307*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, shader->shader().get());
2308*c8dee2aaSAndroid Build Coastguard Worker }
2309*c8dee2aaSAndroid Build Coastguard Worker
create_color_and_offset_bitmap(int numStops,const SkPMColor4f * colors,const float * offsets)2310*c8dee2aaSAndroid Build Coastguard Worker static SkBitmap create_color_and_offset_bitmap(int numStops,
2311*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f* colors,
2312*c8dee2aaSAndroid Build Coastguard Worker const float* offsets) {
2313*c8dee2aaSAndroid Build Coastguard Worker SkBitmap colorsAndOffsetsBitmap;
2314*c8dee2aaSAndroid Build Coastguard Worker
2315*c8dee2aaSAndroid Build Coastguard Worker colorsAndOffsetsBitmap.allocPixels(
2316*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo::Make(numStops, 2, kRGBA_F16_SkColorType, kPremul_SkAlphaType));
2317*c8dee2aaSAndroid Build Coastguard Worker
2318*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < numStops; i++) {
2319*c8dee2aaSAndroid Build Coastguard Worker // TODO: there should be a way to directly set a premul pixel in a bitmap with
2320*c8dee2aaSAndroid Build Coastguard Worker // a premul color.
2321*c8dee2aaSAndroid Build Coastguard Worker SkColor4f unpremulColor = colors[i].unpremul();
2322*c8dee2aaSAndroid Build Coastguard Worker colorsAndOffsetsBitmap.erase(unpremulColor, SkIRect::MakeXYWH(i, 0, 1, 1));
2323*c8dee2aaSAndroid Build Coastguard Worker
2324*c8dee2aaSAndroid Build Coastguard Worker float offset = offsets ? offsets[i] : SkIntToFloat(i) / (numStops - 1);
2325*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(offset >= 0.0f && offset <= 1.0f);
2326*c8dee2aaSAndroid Build Coastguard Worker
2327*c8dee2aaSAndroid Build Coastguard Worker int exponent;
2328*c8dee2aaSAndroid Build Coastguard Worker float mantissa = frexp(offset, &exponent);
2329*c8dee2aaSAndroid Build Coastguard Worker
2330*c8dee2aaSAndroid Build Coastguard Worker SkHalf halfE = SkFloatToHalf(exponent);
2331*c8dee2aaSAndroid Build Coastguard Worker if ((int)SkHalfToFloat(halfE) != exponent) {
2332*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Encoding gradient to f16 failed");
2333*c8dee2aaSAndroid Build Coastguard Worker return {};
2334*c8dee2aaSAndroid Build Coastguard Worker }
2335*c8dee2aaSAndroid Build Coastguard Worker
2336*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_DEBUG)
2337*c8dee2aaSAndroid Build Coastguard Worker SkHalf halfM = SkFloatToHalf(mantissa);
2338*c8dee2aaSAndroid Build Coastguard Worker
2339*c8dee2aaSAndroid Build Coastguard Worker float restored = ldexp(SkHalfToFloat(halfM), (int)SkHalfToFloat(halfE));
2340*c8dee2aaSAndroid Build Coastguard Worker float error = abs(restored - offset);
2341*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(error < 0.001f);
2342*c8dee2aaSAndroid Build Coastguard Worker #endif
2343*c8dee2aaSAndroid Build Coastguard Worker
2344*c8dee2aaSAndroid Build Coastguard Worker // TODO: we're only using 2 of the f16s here. The encoding could be altered to better
2345*c8dee2aaSAndroid Build Coastguard Worker // preserve precision. This encoding yields < 0.001f error for 2^20 evenly spaced stops.
2346*c8dee2aaSAndroid Build Coastguard Worker colorsAndOffsetsBitmap.erase(SkColor4f{mantissa, (float)exponent, 0, 1},
2347*c8dee2aaSAndroid Build Coastguard Worker SkIRect::MakeXYWH(i, 1, 1, 1));
2348*c8dee2aaSAndroid Build Coastguard Worker }
2349*c8dee2aaSAndroid Build Coastguard Worker
2350*c8dee2aaSAndroid Build Coastguard Worker return colorsAndOffsetsBitmap;
2351*c8dee2aaSAndroid Build Coastguard Worker }
2352*c8dee2aaSAndroid Build Coastguard Worker
2353*c8dee2aaSAndroid Build Coastguard Worker // Please see GrGradientShader.cpp::make_interpolated_to_dst for substantial comments
2354*c8dee2aaSAndroid Build Coastguard Worker // as to why this code is structured this way.
make_interpolated_to_dst(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const GradientShaderBlocks::GradientData & gradData,const SkGradientShader::Interpolation & interp,SkColorSpace * intermediateCS)2355*c8dee2aaSAndroid Build Coastguard Worker static void make_interpolated_to_dst(const KeyContext& keyContext,
2356*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2357*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2358*c8dee2aaSAndroid Build Coastguard Worker const GradientShaderBlocks::GradientData& gradData,
2359*c8dee2aaSAndroid Build Coastguard Worker const SkGradientShader::Interpolation& interp,
2360*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace* intermediateCS) {
2361*c8dee2aaSAndroid Build Coastguard Worker using ColorSpace = SkGradientShader::Interpolation::ColorSpace;
2362*c8dee2aaSAndroid Build Coastguard Worker
2363*c8dee2aaSAndroid Build Coastguard Worker bool inputPremul = static_cast<bool>(interp.fInPremul);
2364*c8dee2aaSAndroid Build Coastguard Worker
2365*c8dee2aaSAndroid Build Coastguard Worker switch (interp.fColorSpace) {
2366*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kLab:
2367*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kOKLab:
2368*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kOKLabGamutMap:
2369*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kLCH:
2370*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kOKLCH:
2371*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kOKLCHGamutMap:
2372*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kHSL:
2373*c8dee2aaSAndroid Build Coastguard Worker case ColorSpace::kHWB:
2374*c8dee2aaSAndroid Build Coastguard Worker inputPremul = false;
2375*c8dee2aaSAndroid Build Coastguard Worker break;
2376*c8dee2aaSAndroid Build Coastguard Worker default:
2377*c8dee2aaSAndroid Build Coastguard Worker break;
2378*c8dee2aaSAndroid Build Coastguard Worker }
2379*c8dee2aaSAndroid Build Coastguard Worker
2380*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& dstColorInfo = keyContext.dstColorInfo();
2381*c8dee2aaSAndroid Build Coastguard Worker
2382*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace* dstColorSpace =
2383*c8dee2aaSAndroid Build Coastguard Worker dstColorInfo.colorSpace() ? dstColorInfo.colorSpace() : sk_srgb_singleton();
2384*c8dee2aaSAndroid Build Coastguard Worker
2385*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType intermediateAlphaType = inputPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
2386*c8dee2aaSAndroid Build Coastguard Worker
2387*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::ColorSpaceTransformData data(
2388*c8dee2aaSAndroid Build Coastguard Worker intermediateCS, intermediateAlphaType, dstColorSpace, dstColorInfo.alphaType());
2389*c8dee2aaSAndroid Build Coastguard Worker
2390*c8dee2aaSAndroid Build Coastguard Worker // The gradient block and colorSpace conversion block need to be combined
2391*c8dee2aaSAndroid Build Coastguard Worker // (via the Compose block) so that the localMatrix block can treat them as
2392*c8dee2aaSAndroid Build Coastguard Worker // one child.
2393*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
2394*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
2395*c8dee2aaSAndroid Build Coastguard Worker GradientShaderBlocks::AddBlock(keyContext, builder, gatherer, gradData);
2396*c8dee2aaSAndroid Build Coastguard Worker },
2397*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
2398*c8dee2aaSAndroid Build Coastguard Worker ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, data);
2399*c8dee2aaSAndroid Build Coastguard Worker });
2400*c8dee2aaSAndroid Build Coastguard Worker }
2401*c8dee2aaSAndroid Build Coastguard Worker
add_gradient_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkGradientBaseShader * shader,SkPoint point0,SkPoint point1,float radius0,float radius1,float bias,float scale)2402*c8dee2aaSAndroid Build Coastguard Worker static void add_gradient_to_key(const KeyContext& keyContext,
2403*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2404*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2405*c8dee2aaSAndroid Build Coastguard Worker const SkGradientBaseShader* shader,
2406*c8dee2aaSAndroid Build Coastguard Worker SkPoint point0,
2407*c8dee2aaSAndroid Build Coastguard Worker SkPoint point1,
2408*c8dee2aaSAndroid Build Coastguard Worker float radius0,
2409*c8dee2aaSAndroid Build Coastguard Worker float radius1,
2410*c8dee2aaSAndroid Build Coastguard Worker float bias,
2411*c8dee2aaSAndroid Build Coastguard Worker float scale) {
2412*c8dee2aaSAndroid Build Coastguard Worker SkColor4fXformer xformedColors(shader, keyContext.dstColorInfo().colorSpace());
2413*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f* colors = xformedColors.fColors.begin();
2414*c8dee2aaSAndroid Build Coastguard Worker const float* positions = xformedColors.fPositions;
2415*c8dee2aaSAndroid Build Coastguard Worker const int colorCount = xformedColors.fColors.size();
2416*c8dee2aaSAndroid Build Coastguard Worker
2417*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> proxy;
2418*c8dee2aaSAndroid Build Coastguard Worker
2419*c8dee2aaSAndroid Build Coastguard Worker bool useStorageBuffer = keyContext.caps()->gradientBufferSupport();
2420*c8dee2aaSAndroid Build Coastguard Worker if (colorCount > GradientShaderBlocks::GradientData::kNumInternalStorageStops
2421*c8dee2aaSAndroid Build Coastguard Worker && !useStorageBuffer) {
2422*c8dee2aaSAndroid Build Coastguard Worker if (shader->cachedBitmap().empty()) {
2423*c8dee2aaSAndroid Build Coastguard Worker SkBitmap colorsAndOffsetsBitmap =
2424*c8dee2aaSAndroid Build Coastguard Worker create_color_and_offset_bitmap(colorCount, colors, positions);
2425*c8dee2aaSAndroid Build Coastguard Worker if (colorsAndOffsetsBitmap.empty()) {
2426*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create GradientShader's color and offset bitmap");
2427*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2428*c8dee2aaSAndroid Build Coastguard Worker return;
2429*c8dee2aaSAndroid Build Coastguard Worker }
2430*c8dee2aaSAndroid Build Coastguard Worker shader->setCachedBitmap(colorsAndOffsetsBitmap);
2431*c8dee2aaSAndroid Build Coastguard Worker }
2432*c8dee2aaSAndroid Build Coastguard Worker
2433*c8dee2aaSAndroid Build Coastguard Worker proxy = RecorderPriv::CreateCachedProxy(keyContext.recorder(), shader->cachedBitmap(),
2434*c8dee2aaSAndroid Build Coastguard Worker "GradientTexture");
2435*c8dee2aaSAndroid Build Coastguard Worker if (!proxy) {
2436*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create GradientShader's color and offset bitmap proxy");
2437*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kError);
2438*c8dee2aaSAndroid Build Coastguard Worker return;
2439*c8dee2aaSAndroid Build Coastguard Worker }
2440*c8dee2aaSAndroid Build Coastguard Worker }
2441*c8dee2aaSAndroid Build Coastguard Worker
2442*c8dee2aaSAndroid Build Coastguard Worker GradientShaderBlocks::GradientData data(shader->asGradient(),
2443*c8dee2aaSAndroid Build Coastguard Worker point0,
2444*c8dee2aaSAndroid Build Coastguard Worker point1,
2445*c8dee2aaSAndroid Build Coastguard Worker radius0,
2446*c8dee2aaSAndroid Build Coastguard Worker radius1,
2447*c8dee2aaSAndroid Build Coastguard Worker bias,
2448*c8dee2aaSAndroid Build Coastguard Worker scale,
2449*c8dee2aaSAndroid Build Coastguard Worker shader->getTileMode(),
2450*c8dee2aaSAndroid Build Coastguard Worker colorCount,
2451*c8dee2aaSAndroid Build Coastguard Worker colors,
2452*c8dee2aaSAndroid Build Coastguard Worker positions,
2453*c8dee2aaSAndroid Build Coastguard Worker shader,
2454*c8dee2aaSAndroid Build Coastguard Worker std::move(proxy),
2455*c8dee2aaSAndroid Build Coastguard Worker useStorageBuffer,
2456*c8dee2aaSAndroid Build Coastguard Worker shader->getInterpolation());
2457*c8dee2aaSAndroid Build Coastguard Worker
2458*c8dee2aaSAndroid Build Coastguard Worker make_interpolated_to_dst(keyContext,
2459*c8dee2aaSAndroid Build Coastguard Worker builder,
2460*c8dee2aaSAndroid Build Coastguard Worker gatherer,
2461*c8dee2aaSAndroid Build Coastguard Worker data,
2462*c8dee2aaSAndroid Build Coastguard Worker shader->getInterpolation(),
2463*c8dee2aaSAndroid Build Coastguard Worker xformedColors.fIntermediateColorSpace.get());
2464*c8dee2aaSAndroid Build Coastguard Worker }
2465*c8dee2aaSAndroid Build Coastguard Worker
add_gradient_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkConicalGradient * shader)2466*c8dee2aaSAndroid Build Coastguard Worker static void add_gradient_to_key(const KeyContext& keyContext,
2467*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2468*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2469*c8dee2aaSAndroid Build Coastguard Worker const SkConicalGradient* shader) {
2470*c8dee2aaSAndroid Build Coastguard Worker SkScalar r0 = shader->getStartRadius();
2471*c8dee2aaSAndroid Build Coastguard Worker SkScalar r1 = shader->getEndRadius();
2472*c8dee2aaSAndroid Build Coastguard Worker
2473*c8dee2aaSAndroid Build Coastguard Worker if (shader->getType() != SkConicalGradient::Type::kRadial) {
2474*c8dee2aaSAndroid Build Coastguard Worker // Since we map the centers to be (0,0) and (1,0) in the gradient matrix,
2475*c8dee2aaSAndroid Build Coastguard Worker // there is a scale of 1/distance-between-centers that has to be applied to the radii.
2476*c8dee2aaSAndroid Build Coastguard Worker r0 /= shader->getCenterX1();
2477*c8dee2aaSAndroid Build Coastguard Worker r1 /= shader->getCenterX1();
2478*c8dee2aaSAndroid Build Coastguard Worker } else {
2479*c8dee2aaSAndroid Build Coastguard Worker r0 /= shader->getDiffRadius();
2480*c8dee2aaSAndroid Build Coastguard Worker r1 /= shader->getDiffRadius();
2481*c8dee2aaSAndroid Build Coastguard Worker }
2482*c8dee2aaSAndroid Build Coastguard Worker
2483*c8dee2aaSAndroid Build Coastguard Worker add_gradient_to_key(keyContext,
2484*c8dee2aaSAndroid Build Coastguard Worker builder,
2485*c8dee2aaSAndroid Build Coastguard Worker gatherer,
2486*c8dee2aaSAndroid Build Coastguard Worker shader,
2487*c8dee2aaSAndroid Build Coastguard Worker shader->getStartCenter(),
2488*c8dee2aaSAndroid Build Coastguard Worker shader->getEndCenter(),
2489*c8dee2aaSAndroid Build Coastguard Worker r0,
2490*c8dee2aaSAndroid Build Coastguard Worker r1,
2491*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2492*c8dee2aaSAndroid Build Coastguard Worker 0.0f);
2493*c8dee2aaSAndroid Build Coastguard Worker }
2494*c8dee2aaSAndroid Build Coastguard Worker
add_gradient_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkLinearGradient * shader)2495*c8dee2aaSAndroid Build Coastguard Worker static void add_gradient_to_key(const KeyContext& keyContext,
2496*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2497*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2498*c8dee2aaSAndroid Build Coastguard Worker const SkLinearGradient* shader) {
2499*c8dee2aaSAndroid Build Coastguard Worker add_gradient_to_key(keyContext,
2500*c8dee2aaSAndroid Build Coastguard Worker builder,
2501*c8dee2aaSAndroid Build Coastguard Worker gatherer,
2502*c8dee2aaSAndroid Build Coastguard Worker shader,
2503*c8dee2aaSAndroid Build Coastguard Worker shader->start(),
2504*c8dee2aaSAndroid Build Coastguard Worker shader->end(),
2505*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2506*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2507*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2508*c8dee2aaSAndroid Build Coastguard Worker 0.0f);
2509*c8dee2aaSAndroid Build Coastguard Worker }
2510*c8dee2aaSAndroid Build Coastguard Worker
add_gradient_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkRadialGradient * shader)2511*c8dee2aaSAndroid Build Coastguard Worker static void add_gradient_to_key(const KeyContext& keyContext,
2512*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2513*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2514*c8dee2aaSAndroid Build Coastguard Worker const SkRadialGradient* shader) {
2515*c8dee2aaSAndroid Build Coastguard Worker add_gradient_to_key(keyContext,
2516*c8dee2aaSAndroid Build Coastguard Worker builder,
2517*c8dee2aaSAndroid Build Coastguard Worker gatherer,
2518*c8dee2aaSAndroid Build Coastguard Worker shader,
2519*c8dee2aaSAndroid Build Coastguard Worker shader->center(),
2520*c8dee2aaSAndroid Build Coastguard Worker { 0.0f, 0.0f },
2521*c8dee2aaSAndroid Build Coastguard Worker shader->radius(),
2522*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2523*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2524*c8dee2aaSAndroid Build Coastguard Worker 0.0f);
2525*c8dee2aaSAndroid Build Coastguard Worker }
2526*c8dee2aaSAndroid Build Coastguard Worker
add_gradient_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkSweepGradient * shader)2527*c8dee2aaSAndroid Build Coastguard Worker static void add_gradient_to_key(const KeyContext& keyContext,
2528*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2529*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2530*c8dee2aaSAndroid Build Coastguard Worker const SkSweepGradient* shader) {
2531*c8dee2aaSAndroid Build Coastguard Worker add_gradient_to_key(keyContext,
2532*c8dee2aaSAndroid Build Coastguard Worker builder,
2533*c8dee2aaSAndroid Build Coastguard Worker gatherer,
2534*c8dee2aaSAndroid Build Coastguard Worker shader,
2535*c8dee2aaSAndroid Build Coastguard Worker shader->center(),
2536*c8dee2aaSAndroid Build Coastguard Worker { 0.0f, 0.0f },
2537*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2538*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
2539*c8dee2aaSAndroid Build Coastguard Worker shader->tBias(),
2540*c8dee2aaSAndroid Build Coastguard Worker shader->tScale());
2541*c8dee2aaSAndroid Build Coastguard Worker }
2542*c8dee2aaSAndroid Build Coastguard Worker
add_to_key(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkGradientBaseShader * shader)2543*c8dee2aaSAndroid Build Coastguard Worker static void add_to_key(const KeyContext& keyContext,
2544*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2545*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2546*c8dee2aaSAndroid Build Coastguard Worker const SkGradientBaseShader* shader) {
2547*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shader);
2548*c8dee2aaSAndroid Build Coastguard Worker switch (shader->asGradient()) {
2549*c8dee2aaSAndroid Build Coastguard Worker #define M(type) \
2550*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::k##type: \
2551*c8dee2aaSAndroid Build Coastguard Worker add_gradient_to_key(keyContext, \
2552*c8dee2aaSAndroid Build Coastguard Worker builder, \
2553*c8dee2aaSAndroid Build Coastguard Worker gatherer, \
2554*c8dee2aaSAndroid Build Coastguard Worker static_cast<const Sk##type##Gradient*>(shader)); \
2555*c8dee2aaSAndroid Build Coastguard Worker return;
2556*c8dee2aaSAndroid Build Coastguard Worker SK_ALL_GRADIENTS(M)
2557*c8dee2aaSAndroid Build Coastguard Worker #undef M
2558*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::GradientType::kNone:
2559*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGFAIL("Gradient shader says its type is none");
2560*c8dee2aaSAndroid Build Coastguard Worker return;
2561*c8dee2aaSAndroid Build Coastguard Worker }
2562*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
2563*c8dee2aaSAndroid Build Coastguard Worker }
notify_in_use(Recorder *,DrawContext *,const SkGradientBaseShader *)2564*c8dee2aaSAndroid Build Coastguard Worker static void notify_in_use(Recorder*, DrawContext*, const SkGradientBaseShader*) {
2565*c8dee2aaSAndroid Build Coastguard Worker // Gradients do not have children, so no images to notify
2566*c8dee2aaSAndroid Build Coastguard Worker }
2567*c8dee2aaSAndroid Build Coastguard Worker
AddToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,const SkShader * shader)2568*c8dee2aaSAndroid Build Coastguard Worker void AddToKey(const KeyContext& keyContext,
2569*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
2570*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
2571*c8dee2aaSAndroid Build Coastguard Worker const SkShader* shader) {
2572*c8dee2aaSAndroid Build Coastguard Worker if (!shader) {
2573*c8dee2aaSAndroid Build Coastguard Worker // Calling code assumes a block will be appended. Add a fixed block to preserve shader
2574*c8dee2aaSAndroid Build Coastguard Worker // and PaintParamsKey structure in release builds but assert since this should either not
2575*c8dee2aaSAndroid Build Coastguard Worker // happen or should be changing high-level logic within PaintParams::toKey().
2576*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
2577*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(keyContext, builder, gatherer, SK_PMColor4fTRANSPARENT);
2578*c8dee2aaSAndroid Build Coastguard Worker return;
2579*c8dee2aaSAndroid Build Coastguard Worker }
2580*c8dee2aaSAndroid Build Coastguard Worker switch (as_SB(shader)->type()) {
2581*c8dee2aaSAndroid Build Coastguard Worker #define M(type) \
2582*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::ShaderType::k##type: \
2583*c8dee2aaSAndroid Build Coastguard Worker add_to_key(keyContext, \
2584*c8dee2aaSAndroid Build Coastguard Worker builder, \
2585*c8dee2aaSAndroid Build Coastguard Worker gatherer, \
2586*c8dee2aaSAndroid Build Coastguard Worker static_cast<const Sk##type##Shader*>(shader)); \
2587*c8dee2aaSAndroid Build Coastguard Worker return;
2588*c8dee2aaSAndroid Build Coastguard Worker SK_ALL_SHADERS(M)
2589*c8dee2aaSAndroid Build Coastguard Worker #undef M
2590*c8dee2aaSAndroid Build Coastguard Worker }
2591*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
2592*c8dee2aaSAndroid Build Coastguard Worker }
2593*c8dee2aaSAndroid Build Coastguard Worker
NotifyImagesInUse(Recorder * recorder,DrawContext * drawContext,const SkShader * shader)2594*c8dee2aaSAndroid Build Coastguard Worker void NotifyImagesInUse(Recorder* recorder,
2595*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext,
2596*c8dee2aaSAndroid Build Coastguard Worker const SkShader* shader) {
2597*c8dee2aaSAndroid Build Coastguard Worker if (!shader) {
2598*c8dee2aaSAndroid Build Coastguard Worker return;
2599*c8dee2aaSAndroid Build Coastguard Worker }
2600*c8dee2aaSAndroid Build Coastguard Worker switch (as_SB(shader)->type()) {
2601*c8dee2aaSAndroid Build Coastguard Worker #define M(type) \
2602*c8dee2aaSAndroid Build Coastguard Worker case SkShaderBase::ShaderType::k##type: \
2603*c8dee2aaSAndroid Build Coastguard Worker notify_in_use(recorder, \
2604*c8dee2aaSAndroid Build Coastguard Worker drawContext, \
2605*c8dee2aaSAndroid Build Coastguard Worker static_cast<const Sk##type##Shader*>(shader)); \
2606*c8dee2aaSAndroid Build Coastguard Worker return;
2607*c8dee2aaSAndroid Build Coastguard Worker SK_ALL_SHADERS(M)
2608*c8dee2aaSAndroid Build Coastguard Worker #undef M
2609*c8dee2aaSAndroid Build Coastguard Worker }
2610*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
2611*c8dee2aaSAndroid Build Coastguard Worker }
2612*c8dee2aaSAndroid Build Coastguard Worker
2613*c8dee2aaSAndroid Build Coastguard Worker
2614*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
2615