• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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/FactoryFunctions.h"
9 #include "src/gpu/graphite/KeyContext.h"
10 #include "src/gpu/graphite/KeyHelpers.h"
11 #include "src/gpu/graphite/PaintParamsKey.h"
12 #include "src/gpu/graphite/Precompile.h"
13 #include "src/gpu/graphite/PrecompileBasePriv.h"
14 #include "src/gpu/graphite/ShaderCodeDictionary.h"
15 
16 namespace skgpu::graphite {
17 
18 //--------------------------------------------------------------------------------------------------
makeWithLocalMatrix()19 sk_sp<PrecompileShader> PrecompileShader::makeWithLocalMatrix() {
20     if (this->priv().isALocalMatrixShader()) {
21         // SkShader::makeWithLocalMatrix collapses chains of localMatrix shaders so we need to
22         // follow suit here
23         return sk_ref_sp(this);
24     }
25 
26     return PrecompileShaders::LocalMatrix(sk_ref_sp(this));
27 }
28 
makeWithColorFilter(sk_sp<PrecompileColorFilter> cf)29 sk_sp<PrecompileShader> PrecompileShader::makeWithColorFilter(sk_sp<PrecompileColorFilter> cf) {
30     if (!cf) {
31         return sk_ref_sp(this);
32     }
33 
34     return PrecompileShaders::ColorFilter(sk_ref_sp(this), std::move(cf));
35 }
36 
37 //--------------------------------------------------------------------------------------------------
numShaderCombinations() const38 int PaintOptions::numShaderCombinations() const {
39     int numShaderCombinations = 0;
40     for (const sk_sp<PrecompileShader>& s : fShaderOptions) {
41         numShaderCombinations += s->numCombinations();
42     }
43 
44     // If no shader option is specified we will add a solid color shader option
45     return numShaderCombinations ? numShaderCombinations : 1;
46 }
47 
numMaskFilterCombinations() const48 int PaintOptions::numMaskFilterCombinations() const {
49     int numMaskFilterCombinations = 0;
50     for (const sk_sp<PrecompileMaskFilter>& mf : fMaskFilterOptions) {
51         numMaskFilterCombinations += mf->numCombinations();
52     }
53 
54     // If no mask filter options are specified we will use the geometry's coverage
55     return numMaskFilterCombinations ? numMaskFilterCombinations : 1;
56 }
57 
numColorFilterCombinations() const58 int PaintOptions::numColorFilterCombinations() const {
59     int numColorFilterCombinations = 0;
60     for (const sk_sp<PrecompileColorFilter>& cf : fColorFilterOptions) {
61         numColorFilterCombinations += cf->numCombinations();
62     }
63 
64     // If no color filter options are specified we will use the unmodified result color
65     return numColorFilterCombinations ? numColorFilterCombinations : 1;
66 }
67 
numBlendModeCombinations() const68 int PaintOptions::numBlendModeCombinations() const {
69     bool bmBased = false;
70     int numBlendCombos = 0;
71     for (auto b: fBlenderOptions) {
72         if (b->asBlendMode().has_value()) {
73             bmBased = true;
74         } else {
75             numBlendCombos += b->numChildCombinations();
76         }
77     }
78 
79     if (bmBased || !numBlendCombos) {
80         // If numBlendCombos is zero we will fallback to kSrcOver blending
81         ++numBlendCombos;
82     }
83 
84     return numBlendCombos;
85 }
86 
numCombinations() const87 int PaintOptions::numCombinations() const {
88     // TODO: we need to handle ImageFilters separately
89     return this->numShaderCombinations() *
90            this->numMaskFilterCombinations() *
91            this->numColorFilterCombinations() *
92            this->numBlendModeCombinations();
93 }
94 
createKey(const KeyContext & keyContext,int desiredCombination,PaintParamsKeyBuilder * keyBuilder,bool addPrimitiveBlender) const95 void PaintOptions::createKey(const KeyContext& keyContext,
96                              int desiredCombination,
97                              PaintParamsKeyBuilder* keyBuilder,
98                              bool addPrimitiveBlender) const {
99     SkDEBUGCODE(keyBuilder->checkReset();)
100     SkASSERT(desiredCombination < this->numCombinations());
101 
102     const int numBlendModeCombos = this->numBlendModeCombinations();
103     const int numColorFilterCombinations = this->numColorFilterCombinations();
104     const int numMaskFilterCombinations = this->numMaskFilterCombinations();
105 
106     const int desiredBlendCombination = desiredCombination % numBlendModeCombos;
107     int remainingCombinations = desiredCombination / numBlendModeCombos;
108 
109     const int desiredColorFilterCombination = remainingCombinations % numColorFilterCombinations;
110     remainingCombinations /= numColorFilterCombinations;
111 
112     const int desiredMaskFilterCombination = remainingCombinations % numMaskFilterCombinations;
113     remainingCombinations /= numMaskFilterCombinations;
114 
115     const int desiredShaderCombination = remainingCombinations;
116     SkASSERT(desiredShaderCombination < this->numShaderCombinations());
117 
118     // TODO: eliminate this block for the Paint's color when it isn't needed
119     SolidColorShaderBlock::BeginBlock(keyContext, keyBuilder, /* gatherer= */ nullptr,
120                                       {1, 0, 0, 1});
121     keyBuilder->endBlock();
122 
123     if (!fShaderOptions.empty()) {
124         PrecompileBase::AddToKey(keyContext, keyBuilder, fShaderOptions, desiredShaderCombination);
125     }
126 
127     if (addPrimitiveBlender) {
128         PrimitiveBlendModeBlock::BeginBlock(keyContext, keyBuilder, /* gatherer= */ nullptr,
129                                             SkBlendMode::kSrcOver);
130         keyBuilder->endBlock();
131     }
132 
133     PrecompileBase::AddToKey(keyContext, keyBuilder, fMaskFilterOptions,
134                              desiredMaskFilterCombination);
135     PrecompileBase::AddToKey(keyContext, keyBuilder, fColorFilterOptions,
136                              desiredColorFilterCombination);
137 
138     if (fBlenderOptions.empty()) {
139         BlendModeBlock::BeginBlock(keyContext, keyBuilder, /* gatherer= */ nullptr,
140                                    SkBlendMode::kSrcOver);
141         keyBuilder->endBlock();
142     } else {
143         PrecompileBase::AddToKey(keyContext, keyBuilder, fBlenderOptions, desiredBlendCombination);
144     }
145 }
146 
buildCombinations(const KeyContext & keyContext,bool addPrimitiveBlender,const std::function<void (UniquePaintParamsID)> & processCombination) const147 void PaintOptions::buildCombinations(
148         const KeyContext& keyContext,
149         bool addPrimitiveBlender,
150         const std::function<void(UniquePaintParamsID)>& processCombination) const {
151 
152     PaintParamsKeyBuilder builder(keyContext.dict());
153 
154     int numCombinations = this->numCombinations();
155     for (int i = 0; i < numCombinations; ++i) {
156         this->createKey(keyContext, i, &builder, addPrimitiveBlender);
157 
158         // The 'findOrCreate' calls lockAsKey on builder and then destroys the returned
159         // PaintParamsKey. This serves to reset the builder.
160         auto entry = keyContext.dict()->findOrCreate(&builder);
161 
162         processCombination(entry->uniqueID());
163     }
164 }
165 
166 } // namespace skgpu::graphite
167