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/PaintParams.h"
9
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkShader.h"
12 #include "src/core/SkBlenderBase.h"
13 #include "src/core/SkColorFilterBase.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/PaintParamsKey.h"
18 #include "src/gpu/graphite/PipelineData.h"
19 #include "src/gpu/graphite/Uniform.h"
20 #include "src/shaders/SkShaderBase.h"
21
22 namespace skgpu::graphite {
23
PaintParams(const SkColor4f & color,sk_sp<SkBlender> finalBlender,sk_sp<SkShader> shader,sk_sp<SkColorFilter> colorFilter,sk_sp<SkBlender> primitiveBlender,bool skipColorXform)24 PaintParams::PaintParams(const SkColor4f& color,
25 sk_sp<SkBlender> finalBlender,
26 sk_sp<SkShader> shader,
27 sk_sp<SkColorFilter> colorFilter,
28 sk_sp<SkBlender> primitiveBlender,
29 bool skipColorXform)
30 : fColor(color)
31 , fFinalBlender(std::move(finalBlender))
32 , fShader(std::move(shader))
33 , fColorFilter(std::move(colorFilter))
34 , fPrimitiveBlender(std::move(primitiveBlender))
35 , fSkipColorXform(skipColorXform) {}
36
PaintParams(const SkPaint & paint,sk_sp<SkBlender> primitiveBlender,bool skipColorXform)37 PaintParams::PaintParams(const SkPaint& paint,
38 sk_sp<SkBlender> primitiveBlender,
39 bool skipColorXform)
40 : fColor(paint.getColor4f())
41 , fFinalBlender(paint.refBlender())
42 , fShader(paint.refShader())
43 , fColorFilter(paint.refColorFilter())
44 , fPrimitiveBlender(std::move(primitiveBlender))
45 , fSkipColorXform(skipColorXform) {}
46
47 PaintParams::PaintParams(const PaintParams& other) = default;
48 PaintParams::~PaintParams() = default;
49 PaintParams& PaintParams::operator=(const PaintParams& other) = default;
50
asFinalBlendMode() const51 std::optional<SkBlendMode> PaintParams::asFinalBlendMode() const {
52 return fFinalBlender ? as_BB(fFinalBlender)->asBlendMode()
53 : SkBlendMode::kSrcOver;
54 }
55
refFinalBlender() const56 sk_sp<SkBlender> PaintParams::refFinalBlender() const { return fFinalBlender; }
57
refShader() const58 sk_sp<SkShader> PaintParams::refShader() const { return fShader; }
59
refColorFilter() const60 sk_sp<SkColorFilter> PaintParams::refColorFilter() const { return fColorFilter; }
61
refPrimitiveBlender() const62 sk_sp<SkBlender> PaintParams::refPrimitiveBlender() const { return fPrimitiveBlender; }
63
Color4fPrepForDst(SkColor4f srcColor,const SkColorInfo & dstColorInfo)64 SkColor4f PaintParams::Color4fPrepForDst(SkColor4f srcColor, const SkColorInfo& dstColorInfo) {
65 // xform from sRGB to the destination colorspace
66 SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
67 dstColorInfo.colorSpace(), kUnpremul_SkAlphaType);
68
69 SkColor4f result = srcColor;
70 steps.apply(result.vec());
71 return result;
72 }
73
toKey(const KeyContext & keyContext,PaintParamsKeyBuilder * builder,PipelineDataGatherer * gatherer) const74 void PaintParams::toKey(const KeyContext& keyContext,
75 PaintParamsKeyBuilder* builder,
76 PipelineDataGatherer* gatherer) const {
77
78 SkColor4f dstPaintColor = Color4fPrepForDst(fColor, keyContext.dstColorInfo());
79
80 // TODO: figure out how we can omit this block when the Paint's color isn't used.
81 SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer,
82 dstPaintColor.makeOpaque().premul());
83 builder->endBlock();
84
85 if (fShader) {
86 as_SB(fShader)->addToKey(keyContext, builder, gatherer);
87 }
88
89 if (fPrimitiveBlender) {
90 as_BB(fPrimitiveBlender)->addToKey(keyContext, builder, gatherer,
91 /* primitiveColorBlender= */ true);
92 }
93
94 // Apply the paint's alpha value.
95 auto alphaColorFilter = SkColorFilters::Blend({0, 0, 0, fColor.fA},
96 /* colorSpace= */ nullptr,
97 SkBlendMode::kDstIn);
98 if (alphaColorFilter) {
99 as_CFB(alphaColorFilter)->addToKey(keyContext, builder, gatherer);
100 }
101
102 if (fColorFilter) {
103 as_CFB(fColorFilter)->addToKey(keyContext, builder, gatherer);
104 }
105
106 if (fFinalBlender) {
107 as_BB(fFinalBlender)->addToKey(keyContext, builder, gatherer,
108 /* primitiveColorBlender= */ false);
109 } else {
110 BlendModeBlock::BeginBlock(keyContext, builder, gatherer, SkBlendMode::kSrcOver);
111 builder->endBlock();
112 }
113
114 SkASSERT(builder->sizeInBytes() > 0);
115 }
116
117 } // namespace skgpu::graphite
118