Home | History | Annotate | Download | only in gpu
      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