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 "GrColorSpaceXform.h" 9 #include "SkColorSpace.h" 10 #include "SkColorSpacePriv.h" 11 #include "glsl/GrGLSLColorSpaceXformHelper.h" 12 #include "glsl/GrGLSLFragmentProcessor.h" 13 #include "glsl/GrGLSLFragmentShaderBuilder.h" 14 15 sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(SkColorSpace* src, SkAlphaType srcAT, 16 SkColorSpace* dst, SkAlphaType dstAT) { 17 SkColorSpaceXformSteps steps(src, srcAT, dst, dstAT); 18 return steps.flags.mask() == 0 ? nullptr /* Noop transform */ 19 : sk_make_sp<GrColorSpaceXform>(steps); 20 } 21 22 bool GrColorSpaceXform::Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b) { 23 if (a == b) { 24 return true; 25 } 26 27 if (!a || !b || a->fSteps.flags.mask() != b->fSteps.flags.mask()) { 28 return false; 29 } 30 31 if (a->fSteps.flags.linearize && 32 0 != memcmp(&a->fSteps.srcTF, &b->fSteps.srcTF, sizeof(a->fSteps.srcTF))) { 33 return false; 34 } 35 36 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))) { 44 return false; 45 } 46 47 return true; 48 } 49 50 SkColor4f GrColorSpaceXform::apply(const SkColor4f& srcColor) { 51 SkColor4f result = srcColor; 52 fSteps.apply(result.vec()); 53 return result; 54 } 55 56 ////////////////////////////////////////////////////////////////////////////// 57 58 class GrGLColorSpaceXformEffect : public GrGLSLFragmentProcessor { 59 public: 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 67 if (this->numChildProcessors()) { 68 SkString childColor("src_color"); 69 this->emitChild(0, &childColor, args); 70 71 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 { 76 SkString xformedColor; 77 fragBuilder->appendColorGamutXform(&xformedColor, args.fInputColor, &fColorSpaceHelper); 78 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, xformedColor.c_str()); 79 } 80 } 81 82 private: 83 void onSetData(const GrGLSLProgramDataManager& pdman, 84 const GrFragmentProcessor& processor) override { 85 const GrColorSpaceXformEffect& csxe = processor.cast<GrColorSpaceXformEffect>(); 86 fColorSpaceHelper.setData(pdman, csxe.colorXform()); 87 } 88 89 GrGLSLColorSpaceXformHelper fColorSpaceHelper; 90 91 typedef GrGLSLFragmentProcessor INHERITED; 92 }; 93 94 ////////////////////////////////////////////////////////////////////////////// 95 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 if (child) { 101 this->registerChildProcessor(std::move(child)); 102 } 103 } 104 105 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::clone() const { 106 std::unique_ptr<GrFragmentProcessor> child = 107 this->numChildProcessors() ? this->childProcessor(0).clone() : nullptr; 108 return std::unique_ptr<GrFragmentProcessor>( 109 new GrColorSpaceXformEffect(std::move(child), fColorXform)); 110 } 111 112 bool GrColorSpaceXformEffect::onIsEqual(const GrFragmentProcessor& s) const { 113 const GrColorSpaceXformEffect& other = s.cast<GrColorSpaceXformEffect>(); 114 return GrColorSpaceXform::Equals(fColorXform.get(), other.fColorXform.get()); 115 } 116 117 void GrColorSpaceXformEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, 118 GrProcessorKeyBuilder* b) const { 119 b->add32(GrColorSpaceXform::XformKey(fColorXform.get())); 120 } 121 122 GrGLSLFragmentProcessor* GrColorSpaceXformEffect::onCreateGLSLInstance() const { 123 return new GrGLColorSpaceXformEffect(); 124 } 125 126 GrFragmentProcessor::OptimizationFlags GrColorSpaceXformEffect::OptFlags( 127 const GrFragmentProcessor* child) { 128 // TODO: Implement constant output for constant input 129 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; 141 } 142 } 143 144 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make(SkColorSpace* src, 145 SkAlphaType srcAT, 146 SkColorSpace* dst, 147 SkAlphaType dstAT) { 148 auto xform = GrColorSpaceXform::Make(src, srcAT, 149 dst, dstAT); 150 if (!xform) { 151 return nullptr; 152 } 153 154 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(nullptr, 155 std::move(xform))); 156 } 157 158 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make( 159 std::unique_ptr<GrFragmentProcessor> child, 160 SkColorSpace* src, SkAlphaType srcAT, SkColorSpace* dst) { 161 if (!child) { 162 return nullptr; 163 } 164 165 auto xform = GrColorSpaceXform::Make(src, srcAT, 166 dst, kPremul_SkAlphaType); 167 if (!xform) { 168 return child; 169 } 170 171 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child), 172 std::move(xform))); 173 } 174 175 std::unique_ptr<GrFragmentProcessor> GrColorSpaceXformEffect::Make( 176 std::unique_ptr<GrFragmentProcessor> child, sk_sp<GrColorSpaceXform> colorXform) { 177 if (!child) { 178 return nullptr; 179 } 180 if (!colorXform) { 181 return child; 182 } 183 184 return std::unique_ptr<GrFragmentProcessor>(new GrColorSpaceXformEffect(std::move(child), 185 std::move(colorXform))); 186 } 187