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