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/PaintParams.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBlendModeBlender.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBlenderBase.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorSpacePriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/effects/colorfilters/SkColorFilterBase.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Blend.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/DitherUtils.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyContext.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyHelpers.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParamsKey.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PipelineData.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Uniform.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkShaderBase.h"
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker namespace {
30*c8dee2aaSAndroid Build Coastguard Worker
31*c8dee2aaSAndroid Build Coastguard Worker // This should be kept in sync w/ SkPaintPriv::ShouldDither and PaintOption::shouldDither
should_dither(const PaintParams & p,SkColorType dstCT)32*c8dee2aaSAndroid Build Coastguard Worker bool should_dither(const PaintParams& p, SkColorType dstCT) {
33*c8dee2aaSAndroid Build Coastguard Worker // The paint dither flag can veto.
34*c8dee2aaSAndroid Build Coastguard Worker if (!p.dither()) {
35*c8dee2aaSAndroid Build Coastguard Worker return false;
36*c8dee2aaSAndroid Build Coastguard Worker }
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker if (dstCT == kUnknown_SkColorType) {
39*c8dee2aaSAndroid Build Coastguard Worker return false;
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker // We always dither 565 or 4444 when requested.
43*c8dee2aaSAndroid Build Coastguard Worker if (dstCT == kRGB_565_SkColorType || dstCT == kARGB_4444_SkColorType) {
44*c8dee2aaSAndroid Build Coastguard Worker return true;
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker // Otherwise, dither is only needed for non-const paints.
48*c8dee2aaSAndroid Build Coastguard Worker return p.shader() && !as_SB(p.shader())->isConstant();
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
52*c8dee2aaSAndroid Build Coastguard Worker
PaintParams(const SkPaint & paint,sk_sp<SkBlender> primitiveBlender,const CircularRRectClip & analyticClip,sk_sp<SkShader> clipShader,DstReadRequirement dstReadReq,bool skipColorXform)53*c8dee2aaSAndroid Build Coastguard Worker PaintParams::PaintParams(const SkPaint& paint,
54*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkBlender> primitiveBlender,
55*c8dee2aaSAndroid Build Coastguard Worker const CircularRRectClip& analyticClip,
56*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> clipShader,
57*c8dee2aaSAndroid Build Coastguard Worker DstReadRequirement dstReadReq,
58*c8dee2aaSAndroid Build Coastguard Worker bool skipColorXform)
59*c8dee2aaSAndroid Build Coastguard Worker : fColor(paint.getColor4f())
60*c8dee2aaSAndroid Build Coastguard Worker , fFinalBlender(paint.refBlender())
61*c8dee2aaSAndroid Build Coastguard Worker , fShader(paint.refShader())
62*c8dee2aaSAndroid Build Coastguard Worker , fColorFilter(paint.refColorFilter())
63*c8dee2aaSAndroid Build Coastguard Worker , fPrimitiveBlender(std::move(primitiveBlender))
64*c8dee2aaSAndroid Build Coastguard Worker , fAnalyticClip(analyticClip)
65*c8dee2aaSAndroid Build Coastguard Worker , fClipShader(std::move(clipShader))
66*c8dee2aaSAndroid Build Coastguard Worker , fDstReadReq(dstReadReq)
67*c8dee2aaSAndroid Build Coastguard Worker , fSkipColorXform(skipColorXform)
68*c8dee2aaSAndroid Build Coastguard Worker , fDither(paint.isDither()) {}
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Worker PaintParams::PaintParams(const PaintParams& other) = default;
71*c8dee2aaSAndroid Build Coastguard Worker PaintParams::~PaintParams() = default;
72*c8dee2aaSAndroid Build Coastguard Worker PaintParams& PaintParams::operator=(const PaintParams& other) = default;
73*c8dee2aaSAndroid Build Coastguard Worker
asFinalBlendMode() const74*c8dee2aaSAndroid Build Coastguard Worker std::optional<SkBlendMode> PaintParams::asFinalBlendMode() const {
75*c8dee2aaSAndroid Build Coastguard Worker return fFinalBlender ? as_BB(fFinalBlender)->asBlendMode()
76*c8dee2aaSAndroid Build Coastguard Worker : SkBlendMode::kSrcOver;
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker
refFinalBlender() const79*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkBlender> PaintParams::refFinalBlender() const { return fFinalBlender; }
80*c8dee2aaSAndroid Build Coastguard Worker
refShader() const81*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> PaintParams::refShader() const { return fShader; }
82*c8dee2aaSAndroid Build Coastguard Worker
refColorFilter() const83*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorFilter> PaintParams::refColorFilter() const { return fColorFilter; }
84*c8dee2aaSAndroid Build Coastguard Worker
refPrimitiveBlender() const85*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkBlender> PaintParams::refPrimitiveBlender() const { return fPrimitiveBlender; }
86*c8dee2aaSAndroid Build Coastguard Worker
Color4fPrepForDst(SkColor4f srcColor,const SkColorInfo & dstColorInfo)87*c8dee2aaSAndroid Build Coastguard Worker SkColor4f PaintParams::Color4fPrepForDst(SkColor4f srcColor, const SkColorInfo& dstColorInfo) {
88*c8dee2aaSAndroid Build Coastguard Worker // xform from sRGB to the destination colorspace
89*c8dee2aaSAndroid Build Coastguard Worker SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
90*c8dee2aaSAndroid Build Coastguard Worker dstColorInfo.colorSpace(), kUnpremul_SkAlphaType);
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker SkColor4f result = srcColor;
93*c8dee2aaSAndroid Build Coastguard Worker steps.apply(result.vec());
94*c8dee2aaSAndroid Build Coastguard Worker return result;
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker
Blend(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer,AddToKeyFn addBlendToKey,AddToKeyFn addSrcToKey,AddToKeyFn addDstToKey)97*c8dee2aaSAndroid Build Coastguard Worker void Blend(const KeyContext& keyContext,
98*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* keyBuilder,
99*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
100*c8dee2aaSAndroid Build Coastguard Worker AddToKeyFn addBlendToKey,
101*c8dee2aaSAndroid Build Coastguard Worker AddToKeyFn addSrcToKey,
102*c8dee2aaSAndroid Build Coastguard Worker AddToKeyFn addDstToKey) {
103*c8dee2aaSAndroid Build Coastguard Worker BlendComposeBlock::BeginBlock(keyContext, keyBuilder, gatherer);
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker addSrcToKey();
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker addDstToKey();
108*c8dee2aaSAndroid Build Coastguard Worker
109*c8dee2aaSAndroid Build Coastguard Worker addBlendToKey();
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker keyBuilder->endBlock(); // BlendComposeBlock
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker
Compose(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer,AddToKeyFn addInnerToKey,AddToKeyFn addOuterToKey)114*c8dee2aaSAndroid Build Coastguard Worker void Compose(const KeyContext& keyContext,
115*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* keyBuilder,
116*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
117*c8dee2aaSAndroid Build Coastguard Worker AddToKeyFn addInnerToKey,
118*c8dee2aaSAndroid Build Coastguard Worker AddToKeyFn addOuterToKey) {
119*c8dee2aaSAndroid Build Coastguard Worker ComposeBlock::BeginBlock(keyContext, keyBuilder, gatherer);
120*c8dee2aaSAndroid Build Coastguard Worker
121*c8dee2aaSAndroid Build Coastguard Worker addInnerToKey();
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker addOuterToKey();
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker keyBuilder->endBlock(); // ComposeBlock
126*c8dee2aaSAndroid Build Coastguard Worker }
127*c8dee2aaSAndroid Build Coastguard Worker
AddFixedBlendMode(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkBlendMode bm)128*c8dee2aaSAndroid Build Coastguard Worker void AddFixedBlendMode(const KeyContext& keyContext,
129*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
130*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
131*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode bm) {
132*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(bm <= SkBlendMode::kLastMode);
133*c8dee2aaSAndroid Build Coastguard Worker BuiltInCodeSnippetID id = static_cast<BuiltInCodeSnippetID>(kFixedBlendIDOffset +
134*c8dee2aaSAndroid Build Coastguard Worker static_cast<int>(bm));
135*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(id);
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker
AddBlendMode(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkBlendMode bm)138*c8dee2aaSAndroid Build Coastguard Worker void AddBlendMode(const KeyContext& keyContext,
139*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
140*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
141*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode bm) {
142*c8dee2aaSAndroid Build Coastguard Worker // For non-fixed blends, coefficient blend modes are combined into the same shader snippet.
143*c8dee2aaSAndroid Build Coastguard Worker // The same goes for the HSLC advanced blends. The remaining advanced blends are fairly unique
144*c8dee2aaSAndroid Build Coastguard Worker // in their implementations. To avoid having to compile all of their SkSL, they are treated as
145*c8dee2aaSAndroid Build Coastguard Worker // fixed blend modes.
146*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const float> coeffs = skgpu::GetPorterDuffBlendConstants(bm);
147*c8dee2aaSAndroid Build Coastguard Worker if (!coeffs.empty()) {
148*c8dee2aaSAndroid Build Coastguard Worker PorterDuffBlenderBlock::AddBlock(keyContext, builder, gatherer, coeffs);
149*c8dee2aaSAndroid Build Coastguard Worker } else if (bm >= SkBlendMode::kHue) {
150*c8dee2aaSAndroid Build Coastguard Worker ReducedBlendModeInfo blendInfo = GetReducedBlendModeInfo(bm);
151*c8dee2aaSAndroid Build Coastguard Worker HSLCBlenderBlock::AddBlock(keyContext, builder, gatherer, blendInfo.fUniformData);
152*c8dee2aaSAndroid Build Coastguard Worker } else {
153*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, builder, gatherer, bm);
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker
AddDitherBlock(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer,SkColorType ct)157*c8dee2aaSAndroid Build Coastguard Worker void AddDitherBlock(const KeyContext& keyContext,
158*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
159*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer,
160*c8dee2aaSAndroid Build Coastguard Worker SkColorType ct) {
161*c8dee2aaSAndroid Build Coastguard Worker static const SkBitmap gLUT = skgpu::MakeDitherLUT();
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> proxy = RecorderPriv::CreateCachedProxy(keyContext.recorder(), gLUT,
164*c8dee2aaSAndroid Build Coastguard Worker "DitherLUT");
165*c8dee2aaSAndroid Build Coastguard Worker if (keyContext.recorder() && !proxy) {
166*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Couldn't create dither shader's LUT");
167*c8dee2aaSAndroid Build Coastguard Worker builder->addBlock(BuiltInCodeSnippetID::kPriorOutput);
168*c8dee2aaSAndroid Build Coastguard Worker return;
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker DitherShaderBlock::DitherData data(skgpu::DitherRangeForConfig(ct), std::move(proxy));
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker DitherShaderBlock::AddBlock(keyContext, builder, gatherer, data);
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker
addPaintColorToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer) const176*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::addPaintColorToKey(const KeyContext& keyContext,
177*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* keyBuilder,
178*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
179*c8dee2aaSAndroid Build Coastguard Worker if (fShader) {
180*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, keyBuilder, gatherer, fShader.get());
181*c8dee2aaSAndroid Build Coastguard Worker } else {
182*c8dee2aaSAndroid Build Coastguard Worker RGBPaintColorBlock::AddBlock(keyContext, keyBuilder, gatherer);
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker }
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker /**
187*c8dee2aaSAndroid Build Coastguard Worker * Primitive blend blocks are used to blend either the paint color or the output of another shader
188*c8dee2aaSAndroid Build Coastguard Worker * with a primitive color emitted by certain draw geometry calls (drawVertices, drawAtlas, etc.).
189*c8dee2aaSAndroid Build Coastguard Worker * Dst: primitiveColor Src: Paint color/shader output
190*c8dee2aaSAndroid Build Coastguard Worker */
handlePrimitiveColor(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer) const191*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::handlePrimitiveColor(const KeyContext& keyContext,
192*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* keyBuilder,
193*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
194*c8dee2aaSAndroid Build Coastguard Worker if (fPrimitiveBlender) {
195*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, keyBuilder, gatherer,
196*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&] () -> void {
197*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, keyBuilder, gatherer, fPrimitiveBlender.get());
198*c8dee2aaSAndroid Build Coastguard Worker },
199*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&]() -> void {
200*c8dee2aaSAndroid Build Coastguard Worker this->addPaintColorToKey(keyContext, keyBuilder, gatherer);
201*c8dee2aaSAndroid Build Coastguard Worker },
202*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
203*c8dee2aaSAndroid Build Coastguard Worker PrimitiveColorBlock::AddBlock(keyContext, keyBuilder, gatherer);
204*c8dee2aaSAndroid Build Coastguard Worker });
205*c8dee2aaSAndroid Build Coastguard Worker } else {
206*c8dee2aaSAndroid Build Coastguard Worker this->addPaintColorToKey(keyContext, keyBuilder, gatherer);
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker // Apply the paint's alpha value.
handlePaintAlpha(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer) const211*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::handlePaintAlpha(const KeyContext& keyContext,
212*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* keyBuilder,
213*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker if (!fShader && !fPrimitiveBlender) {
216*c8dee2aaSAndroid Build Coastguard Worker // If there is no shader and no primitive blending the input to the colorFilter stage
217*c8dee2aaSAndroid Build Coastguard Worker // is just the premultiplied paint color.
218*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f paintColor = PaintParams::Color4fPrepForDst(fColor,
219*c8dee2aaSAndroid Build Coastguard Worker keyContext.dstColorInfo()).premul();
220*c8dee2aaSAndroid Build Coastguard Worker SolidColorShaderBlock::AddBlock(keyContext, keyBuilder, gatherer, paintColor);
221*c8dee2aaSAndroid Build Coastguard Worker return;
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker if (fColor.fA != 1.0f) {
225*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, keyBuilder, gatherer,
226*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&] () -> void {
227*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, keyBuilder, gatherer, SkBlendMode::kSrcIn);
228*c8dee2aaSAndroid Build Coastguard Worker },
229*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&]() -> void {
230*c8dee2aaSAndroid Build Coastguard Worker this->handlePrimitiveColor(keyContext, keyBuilder, gatherer);
231*c8dee2aaSAndroid Build Coastguard Worker },
232*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
233*c8dee2aaSAndroid Build Coastguard Worker AlphaOnlyPaintColorBlock::AddBlock(keyContext, keyBuilder, gatherer);
234*c8dee2aaSAndroid Build Coastguard Worker });
235*c8dee2aaSAndroid Build Coastguard Worker } else {
236*c8dee2aaSAndroid Build Coastguard Worker this->handlePrimitiveColor(keyContext, keyBuilder, gatherer);
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker
handleColorFilter(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const240*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::handleColorFilter(const KeyContext& keyContext,
241*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
242*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
243*c8dee2aaSAndroid Build Coastguard Worker if (fColorFilter) {
244*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
245*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
246*c8dee2aaSAndroid Build Coastguard Worker this->handlePaintAlpha(keyContext, builder, gatherer);
247*c8dee2aaSAndroid Build Coastguard Worker },
248*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
249*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, fColorFilter.get());
250*c8dee2aaSAndroid Build Coastguard Worker });
251*c8dee2aaSAndroid Build Coastguard Worker } else {
252*c8dee2aaSAndroid Build Coastguard Worker this->handlePaintAlpha(keyContext, builder, gatherer);
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker }
255*c8dee2aaSAndroid Build Coastguard Worker
handleDithering(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const256*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::handleDithering(const KeyContext& keyContext,
257*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
258*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker #ifndef SK_IGNORE_GPU_DITHER
261*c8dee2aaSAndroid Build Coastguard Worker SkColorType ct = keyContext.dstColorInfo().colorType();
262*c8dee2aaSAndroid Build Coastguard Worker if (should_dither(*this, ct)) {
263*c8dee2aaSAndroid Build Coastguard Worker Compose(keyContext, builder, gatherer,
264*c8dee2aaSAndroid Build Coastguard Worker /* addInnerToKey= */ [&]() -> void {
265*c8dee2aaSAndroid Build Coastguard Worker this->handleColorFilter(keyContext, builder, gatherer);
266*c8dee2aaSAndroid Build Coastguard Worker },
267*c8dee2aaSAndroid Build Coastguard Worker /* addOuterToKey= */ [&]() -> void {
268*c8dee2aaSAndroid Build Coastguard Worker AddDitherBlock(keyContext, builder, gatherer, ct);
269*c8dee2aaSAndroid Build Coastguard Worker });
270*c8dee2aaSAndroid Build Coastguard Worker } else
271*c8dee2aaSAndroid Build Coastguard Worker #endif
272*c8dee2aaSAndroid Build Coastguard Worker {
273*c8dee2aaSAndroid Build Coastguard Worker this->handleColorFilter(keyContext, builder, gatherer);
274*c8dee2aaSAndroid Build Coastguard Worker }
275*c8dee2aaSAndroid Build Coastguard Worker }
276*c8dee2aaSAndroid Build Coastguard Worker
handleClipping(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const277*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::handleClipping(const KeyContext& keyContext,
278*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
279*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
280*c8dee2aaSAndroid Build Coastguard Worker if (!fAnalyticClip.isEmpty()) {
281*c8dee2aaSAndroid Build Coastguard Worker float radius = fAnalyticClip.fRadius + 0.5f;
282*c8dee2aaSAndroid Build Coastguard Worker // N.B.: Because the clip data is normally used with depth-based clipping,
283*c8dee2aaSAndroid Build Coastguard Worker // the shape is inverted from its usual state. We re-invert here to
284*c8dee2aaSAndroid Build Coastguard Worker // match what the shader snippet expects.
285*c8dee2aaSAndroid Build Coastguard Worker SkPoint radiusPair = {(fAnalyticClip.fInverted) ? radius : -radius, 1.0f/radius};
286*c8dee2aaSAndroid Build Coastguard Worker CircularRRectClipBlock::CircularRRectClipData data(
287*c8dee2aaSAndroid Build Coastguard Worker fAnalyticClip.fBounds.makeOutset(0.5f).asSkRect(),
288*c8dee2aaSAndroid Build Coastguard Worker radiusPair,
289*c8dee2aaSAndroid Build Coastguard Worker fAnalyticClip.edgeSelectRect());
290*c8dee2aaSAndroid Build Coastguard Worker if (fClipShader) {
291*c8dee2aaSAndroid Build Coastguard Worker // For both an analytic clip and clip shader, we need to compose them together into
292*c8dee2aaSAndroid Build Coastguard Worker // a single clipping root node.
293*c8dee2aaSAndroid Build Coastguard Worker Blend(keyContext, builder, gatherer,
294*c8dee2aaSAndroid Build Coastguard Worker /* addBlendToKey= */ [&]() -> void {
295*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, builder, gatherer, SkBlendMode::kModulate);
296*c8dee2aaSAndroid Build Coastguard Worker },
297*c8dee2aaSAndroid Build Coastguard Worker /* addSrcToKey= */ [&]() -> void {
298*c8dee2aaSAndroid Build Coastguard Worker CircularRRectClipBlock::AddBlock(keyContext, builder, gatherer, data);
299*c8dee2aaSAndroid Build Coastguard Worker },
300*c8dee2aaSAndroid Build Coastguard Worker /* addDstToKey= */ [&]() -> void {
301*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, fClipShader.get());
302*c8dee2aaSAndroid Build Coastguard Worker });
303*c8dee2aaSAndroid Build Coastguard Worker } else {
304*c8dee2aaSAndroid Build Coastguard Worker // Without a clip shader, the analytic clip can be the clipping root node.
305*c8dee2aaSAndroid Build Coastguard Worker CircularRRectClipBlock::AddBlock(keyContext, builder, gatherer, data);
306*c8dee2aaSAndroid Build Coastguard Worker }
307*c8dee2aaSAndroid Build Coastguard Worker } else if (fClipShader) {
308*c8dee2aaSAndroid Build Coastguard Worker // Since there's no analytic clip, the clipping root node can be fClipShader directly.
309*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, fClipShader.get());
310*c8dee2aaSAndroid Build Coastguard Worker }
311*c8dee2aaSAndroid Build Coastguard Worker }
312*c8dee2aaSAndroid Build Coastguard Worker
toKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const313*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::toKey(const KeyContext& keyContext,
314*c8dee2aaSAndroid Build Coastguard Worker PaintParamsKeyBuilder* builder,
315*c8dee2aaSAndroid Build Coastguard Worker PipelineDataGatherer* gatherer) const {
316*c8dee2aaSAndroid Build Coastguard Worker // Root Node 0 is the source color, which is the output of all effects post dithering
317*c8dee2aaSAndroid Build Coastguard Worker this->handleDithering(keyContext, builder, gatherer);
318*c8dee2aaSAndroid Build Coastguard Worker
319*c8dee2aaSAndroid Build Coastguard Worker // Root Node 1 is the final blender
320*c8dee2aaSAndroid Build Coastguard Worker std::optional<SkBlendMode> finalBlendMode = this->asFinalBlendMode();
321*c8dee2aaSAndroid Build Coastguard Worker if (finalBlendMode) {
322*c8dee2aaSAndroid Build Coastguard Worker if (fDstReadReq == DstReadRequirement::kNone) {
323*c8dee2aaSAndroid Build Coastguard Worker // With no shader blending, be as explicit as possible about the final blend
324*c8dee2aaSAndroid Build Coastguard Worker AddFixedBlendMode(keyContext, builder, gatherer, *finalBlendMode);
325*c8dee2aaSAndroid Build Coastguard Worker } else {
326*c8dee2aaSAndroid Build Coastguard Worker // With shader blending, use AddBlendMode() to select the more universal blend functions
327*c8dee2aaSAndroid Build Coastguard Worker // when possible. Technically we could always use a fixed blend mode but would then
328*c8dee2aaSAndroid Build Coastguard Worker // over-generate when encountering certain classes of blends. This is most problematic
329*c8dee2aaSAndroid Build Coastguard Worker // on devices that wouldn't support dual-source blending, so help them out by at least
330*c8dee2aaSAndroid Build Coastguard Worker // not requiring lots of pipelines.
331*c8dee2aaSAndroid Build Coastguard Worker AddBlendMode(keyContext, builder, gatherer, *finalBlendMode);
332*c8dee2aaSAndroid Build Coastguard Worker }
333*c8dee2aaSAndroid Build Coastguard Worker } else {
334*c8dee2aaSAndroid Build Coastguard Worker AddToKey(keyContext, builder, gatherer, fFinalBlender.get());
335*c8dee2aaSAndroid Build Coastguard Worker }
336*c8dee2aaSAndroid Build Coastguard Worker
337*c8dee2aaSAndroid Build Coastguard Worker // Optional Root Node 2 is the clip
338*c8dee2aaSAndroid Build Coastguard Worker this->handleClipping(keyContext, builder, gatherer);
339*c8dee2aaSAndroid Build Coastguard Worker }
340*c8dee2aaSAndroid Build Coastguard Worker
341*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/330864257): Can be deleted once keys are determined by the Device draw.
notifyImagesInUse(Recorder * recorder,DrawContext * drawContext) const342*c8dee2aaSAndroid Build Coastguard Worker void PaintParams::notifyImagesInUse(Recorder* recorder,
343*c8dee2aaSAndroid Build Coastguard Worker DrawContext* drawContext) const {
344*c8dee2aaSAndroid Build Coastguard Worker if (fShader) {
345*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, fShader.get());
346*c8dee2aaSAndroid Build Coastguard Worker }
347*c8dee2aaSAndroid Build Coastguard Worker if (fPrimitiveBlender) {
348*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, fPrimitiveBlender.get());
349*c8dee2aaSAndroid Build Coastguard Worker }
350*c8dee2aaSAndroid Build Coastguard Worker if (fColorFilter) {
351*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, fColorFilter.get());
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker if (fFinalBlender) {
354*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, fFinalBlender.get());
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker if (fClipShader) {
357*c8dee2aaSAndroid Build Coastguard Worker NotifyImagesInUse(recorder, drawContext, fClipShader.get());
358*c8dee2aaSAndroid Build Coastguard Worker }
359*c8dee2aaSAndroid Build Coastguard Worker }
360*c8dee2aaSAndroid Build Coastguard Worker
361*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
362