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 "src/gpu/GrColorSpaceXform.h"
9
10 #include "include/core/SkColorSpace.h"
11 #include "src/core/SkColorSpacePriv.h"
12 #include "src/gpu/GrColorInfo.h"
13 #include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
14 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
15
Make(SkColorSpace* src, SkAlphaType srcAT, SkColorSpace* dst, SkAlphaType dstAT)16 sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(SkColorSpace* src, SkAlphaType srcAT,
17 SkColorSpace* dst, SkAlphaType dstAT) {
18 SkColorSpaceXformSteps steps(src, srcAT, dst, dstAT);
19 return steps.flags.mask() == 0 ? nullptr /* Noop transform */
20 : sk_make_sp<GrColorSpaceXform>(steps);
21 }
22
Make(const GrColorInfo& srcInfo, const GrColorInfo& dstInfo)23 sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(const GrColorInfo& srcInfo,
24 const GrColorInfo& dstInfo) {
25 return Make(srcInfo.colorSpace(), srcInfo.alphaType(),
26 dstInfo.colorSpace(), dstInfo.alphaType());
27 }
28
Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b)29 bool GrColorSpaceXform::Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b) {
30 if (a == b) {
31 return true;
32 }
33
34 if (!a || !b || a->fSteps.flags.mask() != b->fSteps.flags.mask()) {
35 return false;
36 }
37
38 if (a->fSteps.flags.linearize &&
39 0 != memcmp(&a->fSteps.srcTF, &b->fSteps.srcTF, sizeof(a->fSteps.srcTF))) {
40 return false;
41 }
42
43 if (a->fSteps.flags.gamut_transform &&
44 0 != memcmp(&a->fSteps.src_to_dst_matrix, &b->fSteps.src_to_dst_matrix,
45 sizeof(a->fSteps.src_to_dst_matrix))) {
46 return false;
47 }
48
49 if (a->fSteps.flags.encode &&
50 0 != memcmp(&a->fSteps.dstTFInv, &b->fSteps.dstTFInv, sizeof(a->fSteps.dstTFInv))) {
51 return false;
52 }
53
54 return true;
55 }
56
apply(const SkColor4f& srcColor)57 SkColor4f GrColorSpaceXform::apply(const SkColor4f& srcColor) {
58 SkColor4f result = srcColor;
59 fSteps.apply(result.vec());
60 return result;
61 }
62
63 //////////////////////////////////////////////////////////////////////////////
64
GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child, sk_sp<GrColorSpaceXform> colorXform)65 GrColorSpaceXformEffect::GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child,
66 sk_sp<GrColorSpaceXform> colorXform)
67 : INHERITED(kGrColorSpaceXformEffect_ClassID, OptFlags(child.get()))
68 , fColorXform(std::move(colorXform)) {
69 this->registerChild(std::move(child));
70 }
71
GrColorSpaceXformEffect(const GrColorSpaceXformEffect& that)72 GrColorSpaceXformEffect::GrColorSpaceXformEffect(const GrColorSpaceXformEffect& that)
73 : INHERITED(that)
74 , fColorXform(that.fColorXform) {}
75
clone() const76 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::clone() const {
77 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(*this));
78 }
79
onIsEqual(const GrFragmentProcessor& s) const80 bool GrColorSpaceXformEffect::onIsEqual(const GrFragmentProcessor& s) const {
81 const GrColorSpaceXformEffect& other = s.cast<GrColorSpaceXformEffect>();
82 return GrColorSpaceXform::Equals(fColorXform.get(), other.fColorXform.get());
83 }
84
getShaderDfxInfo() const85 SkString GrColorSpaceXformEffect::getShaderDfxInfo() const
86 {
87 SkString format;
88 format.printf("ShaderDfx_GrColorSpaceXformEffect_%d", GrColorSpaceXform::XformKey(fColorXform.get()));
89 return format;
90 }
91
onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const92 void GrColorSpaceXformEffect::onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
93 b->add32(GrColorSpaceXform::XformKey(fColorXform.get()));
94 }
95
96 std::unique_ptr<GrFragmentProcessor::ProgramImpl>
onMakeProgramImpl() const97 GrColorSpaceXformEffect::onMakeProgramImpl() const {
98 class Impl : public ProgramImpl {
99 public:
100 void emitCode(EmitArgs& args) override {
101 const GrColorSpaceXformEffect& proc = args.fFp.cast<GrColorSpaceXformEffect>();
102 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
103 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
104
105 fColorSpaceHelper.emitCode(uniformHandler, proc.colorXform());
106
107 SkString childColor = this->invokeChild(0, args);
108
109 SkString xformedColor;
110 fragBuilder->appendColorGamutXform(
111 &xformedColor, childColor.c_str(), &fColorSpaceHelper);
112 fragBuilder->codeAppendf("return %s;", xformedColor.c_str());
113 }
114
115 private:
116 void onSetData(const GrGLSLProgramDataManager& pdman,
117 const GrFragmentProcessor& fp) override {
118 const GrColorSpaceXformEffect& proc = fp.cast<GrColorSpaceXformEffect>();
119 fColorSpaceHelper.setData(pdman, proc.colorXform());
120 }
121
122 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
123 };
124
125 return std::make_unique<Impl>();
126 }
127
OptFlags( const GrFragmentProcessor* child)128 GrFragmentProcessor::OptimizationFlags GrColorSpaceXformEffect::OptFlags(
129 const GrFragmentProcessor* child) {
130 return ProcessorOptimizationFlags(child) & (kCompatibleWithCoverageAsAlpha_OptimizationFlag |
131 kPreservesOpaqueInput_OptimizationFlag |
132 kConstantOutputForConstantInput_OptimizationFlag);
133 }
134
constantOutputForConstantInput( const SkPMColor4f& input) const135 SkPMColor4f GrColorSpaceXformEffect::constantOutputForConstantInput(
136 const SkPMColor4f& input) const {
137 const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input);
138 return this->fColorXform->apply(c0.unpremul()).premul();
139 }
140
Make( std::unique_ptr<GrFragmentProcessor> child, SkColorSpace* src, SkAlphaType srcAT, SkColorSpace* dst, SkAlphaType dstAT)141 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
142 std::unique_ptr<GrFragmentProcessor> child,
143 SkColorSpace* src, SkAlphaType srcAT,
144 SkColorSpace* dst, SkAlphaType dstAT) {
145 return Make(std::move(child), GrColorSpaceXform::Make(src, srcAT, dst, dstAT));
146 }
147
Make( std::unique_ptr<GrFragmentProcessor> child, const GrColorInfo& srcInfo, const GrColorInfo& dstInfo)148 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
149 std::unique_ptr<GrFragmentProcessor> child,
150 const GrColorInfo& srcInfo,
151 const GrColorInfo& dstInfo) {
152 return Make(std::move(child), GrColorSpaceXform::Make(srcInfo, dstInfo));
153 }
154
Make( std::unique_ptr<GrFragmentProcessor> child, sk_sp<GrColorSpaceXform> colorXform)155 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
156 std::unique_ptr<GrFragmentProcessor> child,
157 sk_sp<GrColorSpaceXform> colorXform) {
158 if (!colorXform) {
159 return child;
160 }
161
162 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child),
163 std::move(colorXform)));
164 }
165