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