• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
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 "include/core/SkColorSpace.h"
9 #include "include/core/SkFlattenable.h"
10 #include "src/base/SkArenaAlloc.h"
11 #include "src/base/SkUtils.h"
12 #include "src/core/SkColorSpacePriv.h"
13 #include "src/core/SkColorSpaceXformSteps.h"
14 #include "src/core/SkRasterPipeline.h"
15 #include "src/core/SkReadBuffer.h"
16 #include "src/core/SkVM.h"
17 #include "src/core/SkWriteBuffer.h"
18 #include "src/shaders/SkShaderBase.h"
19 
20 #if defined(SK_GRAPHITE)
21 #include "src/gpu/graphite/KeyHelpers.h"
22 #include "src/gpu/graphite/PaintParamsKey.h"
23 #endif
24 
25 /** \class SkColorShader
26     A Shader that represents a single color. In general, this effect can be
27     accomplished by just using the color field on the paint, but if an
28     actual shader object is needed, this provides that feature.
29 */
30 class SkColorShader : public SkShaderBase {
31 public:
32     /** Create a ColorShader that ignores the color in the paint, and uses the
33         specified color. Note: like all shaders, at draw time the paint's alpha
34         will be respected, and is applied to the specified color.
35     */
36     explicit SkColorShader(SkColor c);
37 
38     bool isOpaque() const override;
isConstant() const39     bool isConstant() const override { return true; }
40 
41     GradientType asGradient(GradientInfo* info, SkMatrix* localMatrix) const override;
42 
43 #if defined(SK_GANESH)
44     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&,
45                                                              const MatrixRec&) const override;
46 #endif
47 
48 #if defined(SK_GRAPHITE)
49     void addToKey(const skgpu::graphite::KeyContext&,
50                   skgpu::graphite::PaintParamsKeyBuilder*,
51                   skgpu::graphite::PipelineDataGatherer*) const override;
52 #endif
53 
54 private:
55     friend void ::SkRegisterColorShaderFlattenable();
56     SK_FLATTENABLE_HOOKS(SkColorShader)
57 
58     void flatten(SkWriteBuffer&) const override;
59 
onAsLuminanceColor(SkColor * lum) const60     bool onAsLuminanceColor(SkColor* lum) const override {
61         *lum = fColor;
62         return true;
63     }
64 
65     bool appendStages(const SkStageRec&, const MatrixRec&) const override;
66 
67     skvm::Color program(skvm::Builder*,
68                         skvm::Coord device,
69                         skvm::Coord local,
70                         skvm::Color paint,
71                         const MatrixRec&,
72                         const SkColorInfo& dst,
73                         skvm::Uniforms* uniforms,
74                         SkArenaAlloc*) const override;
75 
76     SkColor fColor;
77 };
78 
79 class SkColor4Shader : public SkShaderBase {
80 public:
81     SkColor4Shader(const SkColor4f&, sk_sp<SkColorSpace>);
82 
isOpaque() const83     bool isOpaque()   const override { return fColor.isOpaque(); }
isConstant() const84     bool isConstant() const override { return true; }
85 
86 #if defined(SK_GANESH)
87     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&,
88                                                              const MatrixRec&) const override;
89 #endif
90 #if defined(SK_GRAPHITE)
91     void addToKey(const skgpu::graphite::KeyContext&,
92                   skgpu::graphite::PaintParamsKeyBuilder*,
93                   skgpu::graphite::PipelineDataGatherer*) const override;
94 #endif
95 
96 private:
97     friend void ::SkRegisterColor4ShaderFlattenable();
98     SK_FLATTENABLE_HOOKS(SkColor4Shader)
99 
100     void flatten(SkWriteBuffer&) const override;
101     bool appendStages(const SkStageRec&, const MatrixRec&) const override;
102 
103     skvm::Color program(skvm::Builder*,
104                         skvm::Coord device,
105                         skvm::Coord local,
106                         skvm::Color paint,
107                         const MatrixRec&,
108                         const SkColorInfo& dst,
109                         skvm::Uniforms* uniforms,
110                         SkArenaAlloc*) const override;
111 
112     sk_sp<SkColorSpace> fColorSpace;
113     const SkColor4f     fColor;
114 };
115 
SkColorShader(SkColor c)116 SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
117 
isOpaque() const118 bool SkColorShader::isOpaque() const {
119     return SkColorGetA(fColor) == 255;
120 }
121 
CreateProc(SkReadBuffer & buffer)122 sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
123     return sk_make_sp<SkColorShader>(buffer.readColor());
124 }
125 
flatten(SkWriteBuffer & buffer) const126 void SkColorShader::flatten(SkWriteBuffer& buffer) const {
127     buffer.writeColor(fColor);
128 }
129 
asGradient(GradientInfo * info,SkMatrix * localMatrix) const130 SkShaderBase::GradientType SkColorShader::asGradient(GradientInfo* info,
131                                                      SkMatrix* localMatrix) const {
132     if (info) {
133         if (info->fColors && info->fColorCount >= 1) {
134             info->fColors[0] = fColor;
135         }
136         info->fColorCount = 1;
137         info->fTileMode = SkTileMode::kRepeat;
138     }
139     if (localMatrix) {
140         *localMatrix = SkMatrix::I();
141     }
142     return GradientType::kColor;
143 }
144 
SkColor4Shader(const SkColor4f & color,sk_sp<SkColorSpace> space)145 SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
146     : fColorSpace(std::move(space))
147     , fColor({color.fR, color.fG, color.fB, SkTPin(color.fA, 0.0f, 1.0f)})
148 {}
149 
CreateProc(SkReadBuffer & buffer)150 sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
151     SkColor4f color;
152     sk_sp<SkColorSpace> colorSpace;
153     buffer.readColor4f(&color);
154     if (buffer.readBool()) {
155         sk_sp<SkData> data = buffer.readByteArrayAsData();
156         colorSpace = data ? SkColorSpace::Deserialize(data->data(), data->size()) : nullptr;
157     }
158     return SkShaders::Color(color, std::move(colorSpace));
159 }
160 
flatten(SkWriteBuffer & buffer) const161 void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
162     buffer.writeColor4f(fColor);
163     sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr;
164     if (colorSpaceData) {
165         buffer.writeBool(true);
166         buffer.writeDataAsByteArray(colorSpaceData.get());
167     } else {
168         buffer.writeBool(false);
169     }
170 }
171 
appendStages(const SkStageRec & rec,const MatrixRec &) const172 bool SkColorShader::appendStages(const SkStageRec& rec, const MatrixRec&) const {
173     SkColor4f color = SkColor4f::FromColor(fColor);
174     SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
175                            rec.fDstCS,          kUnpremul_SkAlphaType).apply(color.vec());
176     rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
177     return true;
178 }
179 
appendStages(const SkStageRec & rec,const MatrixRec &) const180 bool SkColor4Shader::appendStages(const SkStageRec& rec, const MatrixRec&) const {
181     SkColor4f color = fColor;
182     SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
183                            rec.fDstCS,        kUnpremul_SkAlphaType).apply(color.vec());
184     rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
185     return true;
186 }
187 
program(skvm::Builder * p,skvm::Coord,skvm::Coord,skvm::Color,const MatrixRec &,const SkColorInfo & dst,skvm::Uniforms * uniforms,SkArenaAlloc *) const188 skvm::Color SkColorShader::program(skvm::Builder* p,
189                                    skvm::Coord /*device*/,
190                                    skvm::Coord /*local*/,
191                                    skvm::Color /*paint*/,
192                                    const MatrixRec&,
193                                    const SkColorInfo& dst,
194                                    skvm::Uniforms* uniforms,
195                                    SkArenaAlloc*) const {
196     SkColor4f color = SkColor4f::FromColor(fColor);
197     SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
198                               dst.colorSpace(),   kPremul_SkAlphaType).apply(color.vec());
199     return p->uniformColor(color, uniforms);
200 }
program(skvm::Builder * p,skvm::Coord,skvm::Coord,skvm::Color,const MatrixRec &,const SkColorInfo & dst,skvm::Uniforms * uniforms,SkArenaAlloc *) const201 skvm::Color SkColor4Shader::program(skvm::Builder* p,
202                                     skvm::Coord /*device*/,
203                                     skvm::Coord /*local*/,
204                                     skvm::Color /*paint*/,
205                                     const MatrixRec&,
206                                     const SkColorInfo& dst,
207                                     skvm::Uniforms* uniforms,
208                                     SkArenaAlloc*) const {
209     SkColor4f color = fColor;
210     SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
211                             dst.colorSpace(),   kPremul_SkAlphaType).apply(color.vec());
212     return p->uniformColor(color, uniforms);
213 }
214 
215 #if defined(SK_GANESH)
216 
217 #include "src/gpu/ganesh/GrColorInfo.h"
218 #include "src/gpu/ganesh/GrColorSpaceXform.h"
219 #include "src/gpu/ganesh/GrFPArgs.h"
220 #include "src/gpu/ganesh/GrFragmentProcessor.h"
221 #include "src/gpu/ganesh/SkGr.h"
222 
asFragmentProcessor(const GrFPArgs & args,const MatrixRec &) const223 std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const GrFPArgs& args,
224                                                                         const MatrixRec&) const {
225     return GrFragmentProcessor::MakeColor(SkColorToPMColor4f(fColor, *args.fDstColorInfo));
226 }
227 
asFragmentProcessor(const GrFPArgs & args,const MatrixRec &) const228 std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const GrFPArgs& args,
229                                                                          const MatrixRec&) const {
230     SkColorSpaceXformSteps steps{ fColorSpace.get(),                kUnpremul_SkAlphaType,
231                                   args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType };
232     SkColor4f color = fColor;
233     steps.apply(color.vec());
234     return GrFragmentProcessor::MakeColor(color.premul());
235 }
236 
237 #endif
238 
239 #if defined(SK_GRAPHITE)
addToKey(const skgpu::graphite::KeyContext & keyContext,skgpu::graphite::PaintParamsKeyBuilder * builder,skgpu::graphite::PipelineDataGatherer * gatherer) const240 void SkColorShader::addToKey(const skgpu::graphite::KeyContext& keyContext,
241                              skgpu::graphite::PaintParamsKeyBuilder* builder,
242                              skgpu::graphite::PipelineDataGatherer* gatherer) const {
243     using namespace skgpu::graphite;
244 
245     SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer,
246                                       SkColor4f::FromColor(fColor).premul());
247     builder->endBlock();
248 }
249 
addToKey(const skgpu::graphite::KeyContext & keyContext,skgpu::graphite::PaintParamsKeyBuilder * builder,skgpu::graphite::PipelineDataGatherer * gatherer) const250 void SkColor4Shader::addToKey(const skgpu::graphite::KeyContext& keyContext,
251                               skgpu::graphite::PaintParamsKeyBuilder* builder,
252                               skgpu::graphite::PipelineDataGatherer* gatherer) const {
253     using namespace skgpu::graphite;
254 
255     SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer, fColor.premul());
256     builder->endBlock();
257 }
258 #endif
259 
Color(SkColor color)260 sk_sp<SkShader> SkShaders::Color(SkColor color) { return sk_make_sp<SkColorShader>(color); }
261 
Color(const SkColor4f & color,sk_sp<SkColorSpace> space)262 sk_sp<SkShader> SkShaders::Color(const SkColor4f& color, sk_sp<SkColorSpace> space) {
263     if (!SkScalarsAreFinite(color.vec(), 4)) {
264         return nullptr;
265     }
266     return sk_make_sp<SkColor4Shader>(color, std::move(space));
267 }
268 
SkRegisterColor4ShaderFlattenable()269 void SkRegisterColor4ShaderFlattenable() {
270     SK_REGISTER_FLATTENABLE(SkColor4Shader);
271 }
272 
SkRegisterColorShaderFlattenable()273 void SkRegisterColorShaderFlattenable() {
274     SK_REGISTER_FLATTENABLE(SkColorShader);
275 }
276