xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrColorSpaceXform.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/ganesh/GrColorSpaceXform.h"
9 
10 #include "include/core/SkString.h"
11 #include "modules/skcms/skcms.h"
12 #include "src/gpu/KeyBuilder.h"
13 #include "src/gpu/ganesh/GrColorInfo.h"
14 #include "src/gpu/ganesh/glsl/GrGLSLColorSpaceXformHelper.h"
15 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
16 
17 #include <cstring>
18 #include <utility>
19 
20 class GrGLSLProgramDataManager;
21 class GrGLSLUniformHandler;
22 enum SkAlphaType : int;
23 struct GrShaderCaps;
24 
Make(SkColorSpace * src,SkAlphaType srcAT,SkColorSpace * dst,SkAlphaType dstAT)25 sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(SkColorSpace* src, SkAlphaType srcAT,
26                                                  SkColorSpace* dst, SkAlphaType dstAT) {
27     SkColorSpaceXformSteps steps(src, srcAT, dst, dstAT);
28     return steps.flags.mask() == 0 ? nullptr  /* Noop transform */
29                                    : sk_make_sp<GrColorSpaceXform>(steps);
30 }
31 
Make(const GrColorInfo & srcInfo,const GrColorInfo & dstInfo)32 sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(const GrColorInfo& srcInfo,
33                                                  const GrColorInfo& dstInfo) {
34     return Make(srcInfo.colorSpace(), srcInfo.alphaType(),
35                 dstInfo.colorSpace(), dstInfo.alphaType());
36 }
37 
XformKey(const GrColorSpaceXform * xform)38 uint32_t GrColorSpaceXform::XformKey(const GrColorSpaceXform* xform) {
39     // Code generation depends on which steps we apply,
40     // and the kinds of transfer functions (if we're applying those).
41     if (!xform) { return 0; }
42 
43     const SkColorSpaceXformSteps& steps(xform->fSteps);
44     uint32_t key = steps.flags.mask();
45     if (steps.flags.linearize) {
46         key |= skcms_TransferFunction_getType(&steps.srcTF)    << 8;
47     }
48     if (steps.flags.encode) {
49         key |= skcms_TransferFunction_getType(&steps.dstTFInv) << 16;
50     }
51     return key;
52 }
53 
Equals(const GrColorSpaceXform * a,const GrColorSpaceXform * b)54 bool GrColorSpaceXform::Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b) {
55     if (a == b) {
56         return true;
57     }
58 
59     if (!a || !b || a->fSteps.flags.mask() != b->fSteps.flags.mask()) {
60         return false;
61     }
62 
63     if (a->fSteps.flags.linearize &&
64         0 != memcmp(&a->fSteps.srcTF, &b->fSteps.srcTF, sizeof(a->fSteps.srcTF))) {
65         return false;
66     }
67 
68     if (a->fSteps.flags.gamut_transform &&
69         0 != memcmp(&a->fSteps.src_to_dst_matrix, &b->fSteps.src_to_dst_matrix,
70                     sizeof(a->fSteps.src_to_dst_matrix))) {
71         return false;
72     }
73 
74     if (a->fSteps.flags.encode &&
75         0 != memcmp(&a->fSteps.dstTFInv, &b->fSteps.dstTFInv, sizeof(a->fSteps.dstTFInv))) {
76         return false;
77     }
78 
79     return true;
80 }
81 
apply(const SkColor4f & srcColor)82 SkColor4f GrColorSpaceXform::apply(const SkColor4f& srcColor) {
83     SkColor4f result = srcColor;
84     fSteps.apply(result.vec());
85     return result;
86 }
87 
88 //////////////////////////////////////////////////////////////////////////////
89 
GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child,sk_sp<GrColorSpaceXform> colorXform)90 GrColorSpaceXformEffect::GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child,
91                                                  sk_sp<GrColorSpaceXform> colorXform)
92         : INHERITED(kGrColorSpaceXformEffect_ClassID, OptFlags(child.get()))
93         , fColorXform(std::move(colorXform)) {
94     this->registerChild(std::move(child));
95 }
96 
GrColorSpaceXformEffect(const GrColorSpaceXformEffect & that)97 GrColorSpaceXformEffect::GrColorSpaceXformEffect(const GrColorSpaceXformEffect& that)
98         : INHERITED(that)
99         , fColorXform(that.fColorXform) {}
100 
clone() const101 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::clone() const {
102     return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(*this));
103 }
104 
onIsEqual(const GrFragmentProcessor & s) const105 bool GrColorSpaceXformEffect::onIsEqual(const GrFragmentProcessor& s) const {
106     const GrColorSpaceXformEffect& other = s.cast<GrColorSpaceXformEffect>();
107     return GrColorSpaceXform::Equals(fColorXform.get(), other.fColorXform.get());
108 }
109 
onAddToKey(const GrShaderCaps &,skgpu::KeyBuilder * b) const110 void GrColorSpaceXformEffect::onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder* b) const {
111     b->add32(GrColorSpaceXform::XformKey(fColorXform.get()));
112 }
113 
114 std::unique_ptr<GrFragmentProcessor::ProgramImpl>
onMakeProgramImpl() const115 GrColorSpaceXformEffect::onMakeProgramImpl() const {
116     class Impl : public ProgramImpl {
117     public:
118         void emitCode(EmitArgs& args) override {
119             const GrColorSpaceXformEffect& proc = args.fFp.cast<GrColorSpaceXformEffect>();
120             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
121             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
122 
123             fColorSpaceHelper.emitCode(uniformHandler, proc.colorXform());
124 
125             SkString childColor = this->invokeChild(0, args);
126 
127             SkString xformedColor;
128             fragBuilder->appendColorGamutXform(
129                     &xformedColor, childColor.c_str(), &fColorSpaceHelper);
130             fragBuilder->codeAppendf("return %s;", xformedColor.c_str());
131         }
132 
133     private:
134         void onSetData(const GrGLSLProgramDataManager& pdman,
135                        const GrFragmentProcessor& fp) override {
136             const GrColorSpaceXformEffect& proc = fp.cast<GrColorSpaceXformEffect>();
137             fColorSpaceHelper.setData(pdman, proc.colorXform());
138         }
139 
140         GrGLSLColorSpaceXformHelper fColorSpaceHelper;
141     };
142 
143     return std::make_unique<Impl>();
144 }
145 
OptFlags(const GrFragmentProcessor * child)146 GrFragmentProcessor::OptimizationFlags GrColorSpaceXformEffect::OptFlags(
147         const GrFragmentProcessor* child) {
148     return ProcessorOptimizationFlags(child) & (kCompatibleWithCoverageAsAlpha_OptimizationFlag |
149                                                 kPreservesOpaqueInput_OptimizationFlag |
150                                                 kConstantOutputForConstantInput_OptimizationFlag);
151 }
152 
constantOutputForConstantInput(const SkPMColor4f & input) const153 SkPMColor4f GrColorSpaceXformEffect::constantOutputForConstantInput(
154         const SkPMColor4f& input) const {
155     const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input);
156     return this->fColorXform->apply(c0.unpremul()).premul();
157 }
158 
Make(std::unique_ptr<GrFragmentProcessor> child,SkColorSpace * src,SkAlphaType srcAT,SkColorSpace * dst,SkAlphaType dstAT)159 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
160         std::unique_ptr<GrFragmentProcessor> child,
161         SkColorSpace* src, SkAlphaType srcAT,
162         SkColorSpace* dst, SkAlphaType dstAT) {
163     return Make(std::move(child), GrColorSpaceXform::Make(src, srcAT, dst, dstAT));
164 }
165 
Make(std::unique_ptr<GrFragmentProcessor> child,const GrColorInfo & srcInfo,const GrColorInfo & dstInfo)166 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
167         std::unique_ptr<GrFragmentProcessor> child,
168         const GrColorInfo& srcInfo,
169         const GrColorInfo& dstInfo) {
170     return Make(std::move(child), GrColorSpaceXform::Make(srcInfo, dstInfo));
171 }
172 
Make(std::unique_ptr<GrFragmentProcessor> child,sk_sp<GrColorSpaceXform> colorXform)173 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
174         std::unique_ptr<GrFragmentProcessor> child,
175         sk_sp<GrColorSpaceXform> colorXform) {
176     if (!colorXform) {
177         return child;
178     }
179 
180     return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child),
181                                                                             std::move(colorXform)));
182 }
183