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
onAddToKey(const GrShaderCaps &,GrProcessorKeyBuilder * b) const85 void GrColorSpaceXformEffect::onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
86 b->add32(GrColorSpaceXform::XformKey(fColorXform.get()));
87 }
88
89 std::unique_ptr<GrFragmentProcessor::ProgramImpl>
onMakeProgramImpl() const90 GrColorSpaceXformEffect::onMakeProgramImpl() const {
91 class Impl : public ProgramImpl {
92 public:
93 void emitCode(EmitArgs& args) override {
94 const GrColorSpaceXformEffect& proc = args.fFp.cast<GrColorSpaceXformEffect>();
95 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
96 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
97
98 fColorSpaceHelper.emitCode(uniformHandler, proc.colorXform());
99
100 SkString childColor = this->invokeChild(0, args);
101
102 SkString xformedColor;
103 fragBuilder->appendColorGamutXform(
104 &xformedColor, childColor.c_str(), &fColorSpaceHelper);
105 fragBuilder->codeAppendf("return %s;", xformedColor.c_str());
106 }
107
108 private:
109 void onSetData(const GrGLSLProgramDataManager& pdman,
110 const GrFragmentProcessor& fp) override {
111 const GrColorSpaceXformEffect& proc = fp.cast<GrColorSpaceXformEffect>();
112 fColorSpaceHelper.setData(pdman, proc.colorXform());
113 }
114
115 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
116 };
117
118 return std::make_unique<Impl>();
119 }
120
OptFlags(const GrFragmentProcessor * child)121 GrFragmentProcessor::OptimizationFlags GrColorSpaceXformEffect::OptFlags(
122 const GrFragmentProcessor* child) {
123 return ProcessorOptimizationFlags(child) & (kCompatibleWithCoverageAsAlpha_OptimizationFlag |
124 kPreservesOpaqueInput_OptimizationFlag |
125 kConstantOutputForConstantInput_OptimizationFlag);
126 }
127
constantOutputForConstantInput(const SkPMColor4f & input) const128 SkPMColor4f GrColorSpaceXformEffect::constantOutputForConstantInput(
129 const SkPMColor4f& input) const {
130 const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input);
131 return this->fColorXform->apply(c0.unpremul()).premul();
132 }
133
Make(std::unique_ptr<GrFragmentProcessor> child,SkColorSpace * src,SkAlphaType srcAT,SkColorSpace * dst,SkAlphaType dstAT)134 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
135 std::unique_ptr<GrFragmentProcessor> child,
136 SkColorSpace* src, SkAlphaType srcAT,
137 SkColorSpace* dst, SkAlphaType dstAT) {
138 return Make(std::move(child), GrColorSpaceXform::Make(src, srcAT, dst, dstAT));
139 }
140
Make(std::unique_ptr<GrFragmentProcessor> child,const GrColorInfo & srcInfo,const GrColorInfo & dstInfo)141 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
142 std::unique_ptr<GrFragmentProcessor> child,
143 const GrColorInfo& srcInfo,
144 const GrColorInfo& dstInfo) {
145 return Make(std::move(child), GrColorSpaceXform::Make(srcInfo, dstInfo));
146 }
147
Make(std::unique_ptr<GrFragmentProcessor> child,sk_sp<GrColorSpaceXform> colorXform)148 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
149 std::unique_ptr<GrFragmentProcessor> child,
150 sk_sp<GrColorSpaceXform> colorXform) {
151 if (!colorXform) {
152 return child;
153 }
154
155 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child),
156 std::move(colorXform)));
157 }
158