xref: /aosp_15_r20/external/skia/src/gpu/graphite/precompile/PaintOption.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2024 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PaintOption.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlender.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileBlender.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/precompile/PrecompileShader.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyContext.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/KeyHelpers.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParams.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PaintParamsKey.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PrecompileInternal.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileBasePriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileBlenderPriv.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/precompile/PrecompileShaderPriv.h"
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
24*c8dee2aaSAndroid Build Coastguard Worker 
toKey(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer) const25*c8dee2aaSAndroid Build Coastguard Worker void PaintOption::toKey(const KeyContext& keyContext,
26*c8dee2aaSAndroid Build Coastguard Worker                         PaintParamsKeyBuilder* keyBuilder,
27*c8dee2aaSAndroid Build Coastguard Worker                         PipelineDataGatherer* gatherer) const {
28*c8dee2aaSAndroid Build Coastguard Worker     // Root Node 0 is the source color, which is the output of all effects post dithering
29*c8dee2aaSAndroid Build Coastguard Worker     this->handleDithering(keyContext, keyBuilder, gatherer);
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker     // Root Node 1 is the final blender
32*c8dee2aaSAndroid Build Coastguard Worker     std::optional<SkBlendMode> finalBlendMode = this->finalBlender()
33*c8dee2aaSAndroid Build Coastguard Worker                                                         ? this->finalBlender()->priv().asBlendMode()
34*c8dee2aaSAndroid Build Coastguard Worker                                                         : SkBlendMode::kSrcOver;
35*c8dee2aaSAndroid Build Coastguard Worker     if (finalBlendMode) {
36*c8dee2aaSAndroid Build Coastguard Worker         if (fDstReadReq == DstReadRequirement::kNone) {
37*c8dee2aaSAndroid Build Coastguard Worker             AddFixedBlendMode(keyContext, keyBuilder, gatherer, *finalBlendMode);
38*c8dee2aaSAndroid Build Coastguard Worker         } else {
39*c8dee2aaSAndroid Build Coastguard Worker             AddBlendMode(keyContext, keyBuilder, gatherer, *finalBlendMode);
40*c8dee2aaSAndroid Build Coastguard Worker         }
41*c8dee2aaSAndroid Build Coastguard Worker     } else {
42*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->finalBlender());
43*c8dee2aaSAndroid Build Coastguard Worker         fFinalBlender.first->priv().addToKey(keyContext, keyBuilder, gatherer,
44*c8dee2aaSAndroid Build Coastguard Worker                                              fFinalBlender.second);
45*c8dee2aaSAndroid Build Coastguard Worker     }
46*c8dee2aaSAndroid Build Coastguard Worker 
47*c8dee2aaSAndroid Build Coastguard Worker     // Optional Root Node 2 is the clip
48*c8dee2aaSAndroid Build Coastguard Worker     // TODO(b/372221436): Also include analytic clippiing in this node.
49*c8dee2aaSAndroid Build Coastguard Worker     if (fClipShader.first) {
50*c8dee2aaSAndroid Build Coastguard Worker         fClipShader.first->priv().addToKey(keyContext, keyBuilder, gatherer,
51*c8dee2aaSAndroid Build Coastguard Worker                                            fClipShader.second);
52*c8dee2aaSAndroid Build Coastguard Worker     }
53*c8dee2aaSAndroid Build Coastguard Worker }
54*c8dee2aaSAndroid Build Coastguard Worker 
addPaintColorToKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const55*c8dee2aaSAndroid Build Coastguard Worker void PaintOption::addPaintColorToKey(const KeyContext& keyContext,
56*c8dee2aaSAndroid Build Coastguard Worker                                      PaintParamsKeyBuilder* builder,
57*c8dee2aaSAndroid Build Coastguard Worker                                      PipelineDataGatherer* gatherer) const {
58*c8dee2aaSAndroid Build Coastguard Worker     if (fShader.first) {
59*c8dee2aaSAndroid Build Coastguard Worker         fShader.first->priv().addToKey(keyContext, builder, gatherer, fShader.second);
60*c8dee2aaSAndroid Build Coastguard Worker     } else {
61*c8dee2aaSAndroid Build Coastguard Worker         RGBPaintColorBlock::AddBlock(keyContext, builder, gatherer);
62*c8dee2aaSAndroid Build Coastguard Worker     }
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker 
handlePrimitiveColor(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer) const65*c8dee2aaSAndroid Build Coastguard Worker void PaintOption::handlePrimitiveColor(const KeyContext& keyContext,
66*c8dee2aaSAndroid Build Coastguard Worker                                        PaintParamsKeyBuilder* keyBuilder,
67*c8dee2aaSAndroid Build Coastguard Worker                                        PipelineDataGatherer* gatherer) const {
68*c8dee2aaSAndroid Build Coastguard Worker     if (fHasPrimitiveBlender) {
69*c8dee2aaSAndroid Build Coastguard Worker         Blend(keyContext, keyBuilder, gatherer,
70*c8dee2aaSAndroid Build Coastguard Worker               /* addBlendToKey= */ [&] () -> void {
71*c8dee2aaSAndroid Build Coastguard Worker                   // TODO: Support runtime blenders for primitive blending in the precompile API.
72*c8dee2aaSAndroid Build Coastguard Worker                   // In the meantime, assume for now that we're using kSrcOver here.
73*c8dee2aaSAndroid Build Coastguard Worker                   AddToKey(keyContext, keyBuilder, gatherer,
74*c8dee2aaSAndroid Build Coastguard Worker                            SkBlender::Mode(SkBlendMode::kSrcOver).get());
75*c8dee2aaSAndroid Build Coastguard Worker               },
76*c8dee2aaSAndroid Build Coastguard Worker               /* addSrcToKey= */ [&]() -> void {
77*c8dee2aaSAndroid Build Coastguard Worker                   this->addPaintColorToKey(keyContext, keyBuilder, gatherer);
78*c8dee2aaSAndroid Build Coastguard Worker               },
79*c8dee2aaSAndroid Build Coastguard Worker               /* addDstToKey= */ [&]() -> void {
80*c8dee2aaSAndroid Build Coastguard Worker                   PrimitiveColorBlock::AddBlock(keyContext, keyBuilder, gatherer);
81*c8dee2aaSAndroid Build Coastguard Worker               });
82*c8dee2aaSAndroid Build Coastguard Worker     } else {
83*c8dee2aaSAndroid Build Coastguard Worker         this->addPaintColorToKey(keyContext, keyBuilder, gatherer);
84*c8dee2aaSAndroid Build Coastguard Worker     }
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker 
handlePaintAlpha(const KeyContext & keyContext,PaintParamsKeyBuilder * keyBuilder,PipelineDataGatherer * gatherer) const87*c8dee2aaSAndroid Build Coastguard Worker void PaintOption::handlePaintAlpha(const KeyContext& keyContext,
88*c8dee2aaSAndroid Build Coastguard Worker                                    PaintParamsKeyBuilder* keyBuilder,
89*c8dee2aaSAndroid Build Coastguard Worker                                    PipelineDataGatherer* gatherer) const {
90*c8dee2aaSAndroid Build Coastguard Worker 
91*c8dee2aaSAndroid Build Coastguard Worker     if (!fShader.first && !fHasPrimitiveBlender) {
92*c8dee2aaSAndroid Build Coastguard Worker         // If there is no shader and no primitive blending the input to the colorFilter stage
93*c8dee2aaSAndroid Build Coastguard Worker         // is just the premultiplied paint color.
94*c8dee2aaSAndroid Build Coastguard Worker         SolidColorShaderBlock::AddBlock(keyContext, keyBuilder, gatherer, SK_PMColor4fWHITE);
95*c8dee2aaSAndroid Build Coastguard Worker         return;
96*c8dee2aaSAndroid Build Coastguard Worker     }
97*c8dee2aaSAndroid Build Coastguard Worker 
98*c8dee2aaSAndroid Build Coastguard Worker     if (!fOpaquePaintColor) {
99*c8dee2aaSAndroid Build Coastguard Worker         Blend(keyContext, keyBuilder, gatherer,
100*c8dee2aaSAndroid Build Coastguard Worker               /* addBlendToKey= */ [&] () -> void {
101*c8dee2aaSAndroid Build Coastguard Worker                   AddFixedBlendMode(keyContext, keyBuilder, gatherer, SkBlendMode::kSrcIn);
102*c8dee2aaSAndroid Build Coastguard Worker               },
103*c8dee2aaSAndroid Build Coastguard Worker               /* addSrcToKey= */ [&]() -> void {
104*c8dee2aaSAndroid Build Coastguard Worker                   this->handlePrimitiveColor(keyContext, keyBuilder, gatherer);
105*c8dee2aaSAndroid Build Coastguard Worker               },
106*c8dee2aaSAndroid Build Coastguard Worker               /* addDstToKey= */ [&]() -> void {
107*c8dee2aaSAndroid Build Coastguard Worker                   AlphaOnlyPaintColorBlock::AddBlock(keyContext, keyBuilder, gatherer);
108*c8dee2aaSAndroid Build Coastguard Worker               });
109*c8dee2aaSAndroid Build Coastguard Worker     } else {
110*c8dee2aaSAndroid Build Coastguard Worker         this->handlePrimitiveColor(keyContext, keyBuilder, gatherer);
111*c8dee2aaSAndroid Build Coastguard Worker     }
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker 
handleColorFilter(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const114*c8dee2aaSAndroid Build Coastguard Worker void PaintOption::handleColorFilter(const KeyContext& keyContext,
115*c8dee2aaSAndroid Build Coastguard Worker                                     PaintParamsKeyBuilder* builder,
116*c8dee2aaSAndroid Build Coastguard Worker                                     PipelineDataGatherer* gatherer) const {
117*c8dee2aaSAndroid Build Coastguard Worker     if (fColorFilter.first) {
118*c8dee2aaSAndroid Build Coastguard Worker         Compose(keyContext, builder, gatherer,
119*c8dee2aaSAndroid Build Coastguard Worker                 /* addInnerToKey= */ [&]() -> void {
120*c8dee2aaSAndroid Build Coastguard Worker                     this->handlePaintAlpha(keyContext, builder, gatherer);
121*c8dee2aaSAndroid Build Coastguard Worker                 },
122*c8dee2aaSAndroid Build Coastguard Worker                 /* addOuterToKey= */ [&]() -> void {
123*c8dee2aaSAndroid Build Coastguard Worker                     fColorFilter.first->priv().addToKey(keyContext, builder, gatherer,
124*c8dee2aaSAndroid Build Coastguard Worker                                                         fColorFilter.second);
125*c8dee2aaSAndroid Build Coastguard Worker                 });
126*c8dee2aaSAndroid Build Coastguard Worker     } else {
127*c8dee2aaSAndroid Build Coastguard Worker         this->handlePaintAlpha(keyContext, builder, gatherer);
128*c8dee2aaSAndroid Build Coastguard Worker     }
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker // This should be kept in sync w/ SkPaintPriv::ShouldDither and PaintParams::should_dither
shouldDither(SkColorType dstCT) const132*c8dee2aaSAndroid Build Coastguard Worker bool PaintOption::shouldDither(SkColorType dstCT) const {
133*c8dee2aaSAndroid Build Coastguard Worker     // The paint dither flag can veto.
134*c8dee2aaSAndroid Build Coastguard Worker     if (!fDither) {
135*c8dee2aaSAndroid Build Coastguard Worker         return false;
136*c8dee2aaSAndroid Build Coastguard Worker     }
137*c8dee2aaSAndroid Build Coastguard Worker 
138*c8dee2aaSAndroid Build Coastguard Worker     if (dstCT == kUnknown_SkColorType) {
139*c8dee2aaSAndroid Build Coastguard Worker         return false;
140*c8dee2aaSAndroid Build Coastguard Worker     }
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker     // We always dither 565 or 4444 when requested.
143*c8dee2aaSAndroid Build Coastguard Worker     if (dstCT == kRGB_565_SkColorType || dstCT == kARGB_4444_SkColorType) {
144*c8dee2aaSAndroid Build Coastguard Worker         return true;
145*c8dee2aaSAndroid Build Coastguard Worker     }
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker     // Otherwise, dither is only needed for non-const paints.
148*c8dee2aaSAndroid Build Coastguard Worker     return fShader.first && !fShader.first->priv().isConstant(fShader.second);
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker 
handleDithering(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const151*c8dee2aaSAndroid Build Coastguard Worker void PaintOption::handleDithering(const KeyContext& keyContext,
152*c8dee2aaSAndroid Build Coastguard Worker                                   PaintParamsKeyBuilder* builder,
153*c8dee2aaSAndroid Build Coastguard Worker                                   PipelineDataGatherer* gatherer) const {
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker #ifndef SK_IGNORE_GPU_DITHER
156*c8dee2aaSAndroid Build Coastguard Worker     SkColorType ct = keyContext.dstColorInfo().colorType();
157*c8dee2aaSAndroid Build Coastguard Worker     if (this->shouldDither(ct)) {
158*c8dee2aaSAndroid Build Coastguard Worker         Compose(keyContext, builder, gatherer,
159*c8dee2aaSAndroid Build Coastguard Worker                 /* addInnerToKey= */ [&]() -> void {
160*c8dee2aaSAndroid Build Coastguard Worker                     this->handleColorFilter(keyContext, builder, gatherer);
161*c8dee2aaSAndroid Build Coastguard Worker                 },
162*c8dee2aaSAndroid Build Coastguard Worker                 /* addOuterToKey= */ [&]() -> void {
163*c8dee2aaSAndroid Build Coastguard Worker                     AddDitherBlock(keyContext, builder, gatherer, ct);
164*c8dee2aaSAndroid Build Coastguard Worker                 });
165*c8dee2aaSAndroid Build Coastguard Worker     } else
166*c8dee2aaSAndroid Build Coastguard Worker #endif
167*c8dee2aaSAndroid Build Coastguard Worker     {
168*c8dee2aaSAndroid Build Coastguard Worker         this->handleColorFilter(keyContext, builder, gatherer);
169*c8dee2aaSAndroid Build Coastguard Worker     }
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
173