blob: 2cd5e5a0ea0b6fb54d6908e8a62246fdf7d5ae61 [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
8#include "GrColorSpaceXform.h"
9#include "SkColorSpace.h"
Brian Osmanf06ead92017-10-30 13:47:41 -040010#include "SkColorSpacePriv.h"
Brian Osmanc4f93ca2017-10-17 17:15:52 -040011#include "glsl/GrGLSLColorSpaceXformHelper.h"
12#include "glsl/GrGLSLFragmentProcessor.h"
13#include "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 {
61 const GrColorSpaceXformEffect& csxe = args.fFp.cast<GrColorSpaceXformEffect>();
62 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
63 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
64
65 fColorSpaceHelper.emitCode(uniformHandler, csxe.colorXform());
66
Brian Osman3567c142018-06-18 10:20:32 -040067 if (this->numChildProcessors()) {
68 SkString childColor("src_color");
69 this->emitChild(0, &childColor, args);
Brian Osmanc4f93ca2017-10-17 17:15:52 -040070
Brian Osman3567c142018-06-18 10:20:32 -040071 SkString xformedColor;
72 fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper);
73 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, xformedColor.c_str(),
74 args.fInputColor);
75 } else {
Brian Osman3567c142018-06-18 10:20:32 -040076 SkString xformedColor;
77 fragBuilder->appendColorGamutXform(&xformedColor, args.fInputColor, &fColorSpaceHelper);
78 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, xformedColor.c_str());
79 }
Brian Osmanc4f93ca2017-10-17 17:15:52 -040080 }
81
82private:
83 void onSetData(const GrGLSLProgramDataManager& pdman,
84 const GrFragmentProcessor& processor) override {
85 const GrColorSpaceXformEffect& csxe = processor.cast<GrColorSpaceXformEffect>();
Brian Osmanc891b102018-06-14 14:50:17 -040086 fColorSpaceHelper.setData(pdman, csxe.colorXform());
Brian Osmanc4f93ca2017-10-17 17:15:52 -040087 }
88
89 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
90
91 typedef GrGLSLFragmentProcessor INHERITED;
92};
93
94//////////////////////////////////////////////////////////////////////////////
95
96GrColorSpaceXformEffect::GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child,
97 sk_sp<GrColorSpaceXform> colorXform)
98 : INHERITED(kGrColorSpaceXformEffect_ClassID, OptFlags(child.get()))
99 , fColorXform(std::move(colorXform)) {
Brian Osman3567c142018-06-18 10:20:32 -0400100 if (child) {
101 this->registerChildProcessor(std::move(child));
102 }
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400103}
104
105std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::clone() const {
Brian Osman3567c142018-06-18 10:20:32 -0400106 std::unique_ptr<GrFragmentProcessor> child =
107 this->numChildProcessors() ? this->childProcessor(0).clone() : nullptr;
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400108 return std::unique_ptr<GrFragmentProcessor>(
Brian Osman3567c142018-06-18 10:20:32 -0400109 new GrColorSpaceXformEffect(std::move(child), fColorXform));
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400110}
111
112bool GrColorSpaceXformEffect::onIsEqual(const GrFragmentProcessor& s) const {
113 const GrColorSpaceXformEffect& other = s.cast<GrColorSpaceXformEffect>();
114 return GrColorSpaceXform::Equals(fColorXform.get(), other.fColorXform.get());
115}
116
117void GrColorSpaceXformEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
118 GrProcessorKeyBuilder* b) const {
119 b->add32(GrColorSpaceXform::XformKey(fColorXform.get()));
120}
121
122GrGLSLFragmentProcessor* GrColorSpaceXformEffect::onCreateGLSLInstance() const {
123 return new GrGLColorSpaceXformEffect();
124}
125
126GrFragmentProcessor::OptimizationFlags GrColorSpaceXformEffect::OptFlags(
127 const GrFragmentProcessor* child) {
128 // TODO: Implement constant output for constant input
Brian Osman3567c142018-06-18 10:20:32 -0400129 if (child) {
130 OptimizationFlags flags = kNone_OptimizationFlags;
131 if (child->compatibleWithCoverageAsAlpha()) {
132 flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
133 }
134 if (child->preservesOpaqueInput()) {
135 flags |= kPreservesOpaqueInput_OptimizationFlag;
136 }
137 return flags;
138 } else {
139 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
140 kPreservesOpaqueInput_OptimizationFlag;
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400141 }
Brian Osman3567c142018-06-18 10:20:32 -0400142}
143
144std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(SkColorSpace* src,
Brian Osman21fc5ce2018-08-27 20:36:19 +0000145 SkAlphaType srcAT,
Brian Osman15f0f292018-10-01 14:14:46 -0400146 SkColorSpace* dst,
147 SkAlphaType dstAT) {
Brian Osman21fc5ce2018-08-27 20:36:19 +0000148 auto xform = GrColorSpaceXform::Make(src, srcAT,
Brian Osman15f0f292018-10-01 14:14:46 -0400149 dst, dstAT);
Brian Osman3567c142018-06-18 10:20:32 -0400150 if (!xform) {
151 return nullptr;
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400152 }
Brian Osman3567c142018-06-18 10:20:32 -0400153
154 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(nullptr,
155 std::move(xform)));
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400156}
157
158std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(
159 std::unique_ptr<GrFragmentProcessor> child,
Brian Osman21fc5ce2018-08-27 20:36:19 +0000160 SkColorSpace* src, SkAlphaType srcAT, SkColorSpace* dst) {
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400161 if (!child) {
162 return nullptr;
163 }
164
Brian Osman21fc5ce2018-08-27 20:36:19 +0000165 auto xform = GrColorSpaceXform::Make(src, srcAT,
Mike Kleine03a1762018-08-22 11:52:16 -0400166 dst, kPremul_SkAlphaType);
Brian Osman3567c142018-06-18 10:20:32 -0400167 if (!xform) {
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400168 return child;
169 }
Brian Osman3567c142018-06-18 10:20:32 -0400170
171 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child),
172 std::move(xform)));
Brian Osmanc4f93ca2017-10-17 17:15:52 -0400173}