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