blob: 37ce7936b8589169ecb09bafa26c3b78e413a72f [file] [log] [blame]
brianosman54f30c12016-07-18 10:53:52 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkColorSpace.h"
9#include "src/core/SkColorSpacePriv.h"
10#include "src/gpu/GrColorSpaceXform.h"
11#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
12#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
13#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
Brian Osman7c2114f2016-10-20 15:34:06 -040014
Mike Kleine03a1762018-08-22 11:52:16 -040015sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(SkColorSpace* src, SkAlphaType srcAT,
16 SkColorSpace* dst, SkAlphaType dstAT) {
Mike Kleine03a1762018-08-22 11:52:16 -040017 SkColorSpaceXformSteps steps(src, srcAT, dst, dstAT);
Brian Osman3567c142018-06-18 10:20:32 -040018 return steps.flags.mask() == 0 ? nullptr /* Noop transform */
19 : sk_make_sp<GrColorSpaceXform>(steps);
brianosman54f30c12016-07-18 10:53:52 -070020}
brianosman5a7ae7e2016-09-12 12:07:25 -070021
brianosmanb9c51372016-09-15 11:09:45 -070022bool GrColorSpaceXform::Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b) {
23 if (a == b) {
24 return true;
25 }
26
Brian Osman3567c142018-06-18 10:20:32 -040027 if (!a || !b || a->fSteps.flags.mask() != b->fSteps.flags.mask()) {
brianosmanb9c51372016-09-15 11:09:45 -070028 return false;
29 }
30
Brian Osman3567c142018-06-18 10:20:32 -040031 if (a->fSteps.flags.linearize &&
32 0 != memcmp(&a->fSteps.srcTF, &b->fSteps.srcTF, sizeof(a->fSteps.srcTF))) {
Brian Osmanf06ead92017-10-30 13:47:41 -040033 return false;
34 }
35
Brian Osman3567c142018-06-18 10:20:32 -040036 if (a->fSteps.flags.gamut_transform &&
37 0 != memcmp(&a->fSteps.src_to_dst_matrix, &b->fSteps.src_to_dst_matrix,
38 sizeof(a->fSteps.src_to_dst_matrix))) {
39 return false;
40 }
41
42 if (a->fSteps.flags.encode &&
43 0 != memcmp(&a->fSteps.dstTFInv, &b->fSteps.dstTFInv, sizeof(a->fSteps.dstTFInv))) {
Brian Osmanf06ead92017-10-30 13:47:41 -040044 return false;
45 }
46
47 return true;
brianosmanb9c51372016-09-15 11:09:45 -070048}
49
Brian Osmanf28e55d2018-10-03 16:35:54 -040050SkColor4f GrColorSpaceXform::apply(const SkColor4f& srcColor) {
51 SkColor4f result = srcColor;
52 fSteps.apply(result.vec());
53 return result;
54}
55
Brian Osmanc4f93ca2017-10-17 17:15:52 -040056//////////////////////////////////////////////////////////////////////////////
57
58class GrGLColorSpaceXformEffect : public GrGLSLFragmentProcessor {
59public:
60 void emitCode(EmitArgs& args) override {
John Stiles3e627622020-06-29 12:47:04 -040061 const GrColorSpaceXformEffect& proc = args.fFp.cast<GrColorSpaceXformEffect>();
Brian Osmanc4f93ca2017-10-17 17:15:52 -040062 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
63 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
64
John Stiles3e627622020-06-29 12:47:04 -040065 fColorSpaceHelper.emitCode(uniformHandler, proc.colorXform());
Brian Osmanc4f93ca2017-10-17 17:15:52 -040066
Brian Osman12c5d292020-07-13 16:11:35 -040067 SkString childColor = this->invokeChild(0, args.fInputColor, args);
Brian Osmanc4f93ca2017-10-17 17:15:52 -040068
John Stiles3e627622020-06-29 12:47:04 -040069 SkString xformedColor;
70 fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper);
71 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, xformedColor.c_str());
Brian Osmanc4f93ca2017-10-17 17:15:52 -040072 }
73
74private:
75 void onSetData(const GrGLSLProgramDataManager& pdman,
John Stiles3e627622020-06-29 12:47:04 -040076 const GrFragmentProcessor& fp) override {
77 const GrColorSpaceXformEffect& proc = fp.cast<GrColorSpaceXformEffect>();
78 fColorSpaceHelper.setData(pdman, proc.colorXform());
Brian Osmanc4f93ca2017-10-17 17:15:52 -040079 }
80
81 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
82
83 typedef GrGLSLFragmentProcessor INHERITED;
84};
85
86//////////////////////////////////////////////////////////////////////////////
87
88GrColorSpaceXformEffect::GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child,
89 sk_sp<GrColorSpaceXform> colorXform)
90 : INHERITED(kGrColorSpaceXformEffect_ClassID, OptFlags(child.get()))
91 , fColorXform(std::move(colorXform)) {
Brian Osman54867de2020-07-10 14:22:57 -040092 this->registerChild(std::move(child));
Brian Osmanc4f93ca2017-10-17 17:15:52 -040093}
94
John Stiles3e627622020-06-29 12:47:04 -040095GrColorSpaceXformEffect::GrColorSpaceXformEffect(const GrColorSpaceXformEffect& that)
96 : INHERITED(kGrColorSpaceXformEffect_ClassID, that.optimizationFlags())
97 , fColorXform(that.fColorXform) {
98 this->cloneAndRegisterAllChildProcessors(that);
99}
100
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400101std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::clone() const {
John Stiles3e627622020-06-29 12:47:04 -0400102 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(*this));
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400103}
104
105bool GrColorSpaceXformEffect::onIsEqual(const GrFragmentProcessor& s) const {
106 const GrColorSpaceXformEffect& other = s.cast<GrColorSpaceXformEffect>();
107 return GrColorSpaceXform::Equals(fColorXform.get(), other.fColorXform.get());
108}
109
110void GrColorSpaceXformEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
111 GrProcessorKeyBuilder* b) const {
112 b->add32(GrColorSpaceXform::XformKey(fColorXform.get()));
113}
114
115GrGLSLFragmentProcessor* GrColorSpaceXformEffect::onCreateGLSLInstance() const {
116 return new GrGLColorSpaceXformEffect();
117}
118
119GrFragmentProcessor::OptimizationFlags GrColorSpaceXformEffect::OptFlags(
120 const GrFragmentProcessor* child) {
John Stiles3e627622020-06-29 12:47:04 -0400121 return (child ? ProcessorOptimizationFlags(child) : kAll_OptimizationFlags) &
122 (kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Osman5d92ae22020-01-31 15:54:33 -0500123 kPreservesOpaqueInput_OptimizationFlag |
John Stiles3e627622020-06-29 12:47:04 -0400124 kConstantOutputForConstantInput_OptimizationFlag);
Brian Osman3567c142018-06-18 10:20:32 -0400125}
126
Brian Osman5d92ae22020-01-31 15:54:33 -0500127SkPMColor4f GrColorSpaceXformEffect::constantOutputForConstantInput(
128 const SkPMColor4f& input) const {
Brian Osman12c5d292020-07-13 16:11:35 -0400129 const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input);
Brian Osman5d92ae22020-01-31 15:54:33 -0500130 return this->fColorXform->apply(c0.unpremul()).premul();
131}
132
John Stiles3e627622020-06-29 12:47:04 -0400133std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
134 std::unique_ptr<GrFragmentProcessor> child,
135 SkColorSpace* src, SkAlphaType srcAT,
136 SkColorSpace* dst, SkAlphaType dstAT) {
137 return Make(std::move(child), GrColorSpaceXform::Make(src, srcAT, dst, dstAT));
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400138}
139
140std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
141 std::unique_ptr<GrFragmentProcessor> child,
John Stiles3e627622020-06-29 12:47:04 -0400142 sk_sp<GrColorSpaceXform> colorXform) {
Michael Ludwiga3c45c72019-01-17 17:26:48 -0500143 if (!colorXform) {
144 return child;
145 }
146
147 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child),
148 std::move(colorXform)));
149}