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