Home | History | Annotate | Download | only in effects
      1 /*
      2 * Copyright 2015 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 "effects/GrXfermodeFragmentProcessor.h"
      9 
     10 #include "GrFragmentProcessor.h"
     11 #include "GrInvariantOutput.h"
     12 #include "effects/GrConstColorProcessor.h"
     13 #include "glsl/GrGLSLFragmentProcessor.h"
     14 #include "glsl/GrGLSLBlend.h"
     15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     16 #include "SkGrPriv.h"
     17 
     18 class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
     19 public:
     20     ComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragmentProcessor* dst,
     21                     SkXfermode::Mode mode)
     22         : fMode(mode) {
     23         this->initClassID<ComposeTwoFragmentProcessor>();
     24         SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src);
     25         SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst);
     26         SkASSERT(0 == shaderAChildIndex);
     27         SkASSERT(1 == shaderBChildIndex);
     28     }
     29 
     30     const char* name() const override { return "ComposeTwo"; }
     31 
     32     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
     33         b->add32(fMode);
     34     }
     35 
     36     SkXfermode::Mode getMode() const { return fMode; }
     37 
     38 protected:
     39     bool onIsEqual(const GrFragmentProcessor& other) const override {
     40         const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
     41         return fMode == cs.fMode;
     42     }
     43 
     44     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
     45         inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
     46     }
     47 
     48 private:
     49     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     50 
     51     SkXfermode::Mode fMode;
     52 
     53     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     54 
     55     typedef GrFragmentProcessor INHERITED;
     56 };
     57 
     58 /////////////////////////////////////////////////////////////////////
     59 
     60 class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
     61 public:
     62     void emitCode(EmitArgs&) override;
     63 
     64 private:
     65     typedef GrGLSLFragmentProcessor INHERITED;
     66 };
     67 
     68 /////////////////////////////////////////////////////////////////////
     69 
     70 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
     71 
     72 const GrFragmentProcessor* ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
     73     // Create two random frag procs.
     74     SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChildFP(d));
     75     SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChildFP(d));
     76 
     77     SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
     78         d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
     79     return new ComposeTwoFragmentProcessor(fpA, fpB, mode);
     80 }
     81 
     82 GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
     83     return new GLComposeTwoFragmentProcessor;
     84 }
     85 
     86 /////////////////////////////////////////////////////////////////////
     87 
     88 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
     89 
     90     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     91     const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
     92 
     93     const char* inputColor = nullptr;
     94     if (args.fInputColor) {
     95         inputColor = "inputColor";
     96         fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
     97     }
     98 
     99     // declare outputColor and emit the code for each of the two children
    100     SkString srcColor("src");
    101     this->emitChild(0, inputColor, &srcColor, args);
    102 
    103     SkString dstColor("dst");
    104     this->emitChild(1, inputColor, &dstColor, args);
    105 
    106     // emit blend code
    107     SkXfermode::Mode mode = cs.getMode();
    108     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
    109     GrGLSLBlend::AppendMode(fragBuilder,
    110                             srcColor.c_str(),
    111                             dstColor.c_str(),
    112                             args.fOutputColor,
    113                             mode);
    114 
    115     // re-multiply the output color by the input color's alpha
    116     if (args.fInputColor) {
    117         fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
    118     }
    119 }
    120 
    121 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors(
    122          const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
    123     switch (mode) {
    124         case SkXfermode::kClear_Mode:
    125             return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
    126                                                  GrConstColorProcessor::kIgnore_InputMode);
    127         case SkXfermode::kSrc_Mode:
    128             return SkRef(src);
    129         case SkXfermode::kDst_Mode:
    130             return SkRef(dst);
    131         default:
    132             return new ComposeTwoFragmentProcessor(src, dst, mode);
    133     }
    134 }
    135 
    136 //////////////////////////////////////////////////////////////////////////////
    137 
    138 class ComposeOneFragmentProcessor : public GrFragmentProcessor {
    139 public:
    140     enum Child {
    141         kDst_Child,
    142         kSrc_Child,
    143     };
    144 
    145     ComposeOneFragmentProcessor(const GrFragmentProcessor* dst, SkXfermode::Mode mode, Child child)
    146         : fMode(mode)
    147         , fChild(child) {
    148         this->initClassID<ComposeOneFragmentProcessor>();
    149         SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst);
    150         SkASSERT(0 == dstIndex);
    151     }
    152 
    153     const char* name() const override { return "ComposeOne"; }
    154 
    155     SkString dumpInfo() const override {
    156         SkString str;
    157 
    158         for (int i = 0; i < this->numChildProcessors(); ++i) {
    159             str.append(this->childProcessor(i).dumpInfo());
    160         }
    161         return str;
    162     }
    163 
    164     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
    165         GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode);
    166         b->add32(fMode | (fChild << 16));
    167     }
    168 
    169     SkXfermode::Mode mode() const { return fMode; }
    170 
    171     Child child() const { return fChild; }
    172 
    173 protected:
    174     bool onIsEqual(const GrFragmentProcessor& that) const override {
    175         return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
    176     }
    177 
    178     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
    179         SkXfermode::Coeff skSrcCoeff, skDstCoeff;
    180         if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) {
    181             GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff);
    182             GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff);
    183             GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags, false);
    184             this->childProcessor(0).computeInvariantOutput(&childOutput);
    185             GrColor blendColor;
    186             GrColorComponentFlags blendFlags;
    187             if (kDst_Child == fChild) {
    188                 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
    189                                                inout->color(), inout->validFlags(),
    190                                                childOutput.color(), childOutput.validFlags(),
    191                                                &blendColor, &blendFlags);
    192             } else {
    193                 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
    194                                                childOutput.color(), childOutput.validFlags(),
    195                                                inout->color(), inout->validFlags(),
    196                                                &blendColor, &blendFlags);
    197             }
    198             // will the shader code reference the input color?
    199             GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNot_ReadInput;
    200             if (kDst_Child == fChild) {
    201                 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff)) {
    202                     readsInput = GrInvariantOutput::kWill_ReadInput;
    203                 }
    204             } else {
    205                 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) {
    206                     readsInput = GrInvariantOutput::kWill_ReadInput;
    207                 }
    208             }
    209             inout->setToOther(blendFlags, blendColor, readsInput);
    210         } else {
    211             inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
    212         }
    213     }
    214 
    215 private:
    216     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
    217 
    218     SkXfermode::Mode    fMode;
    219     Child               fChild;
    220 
    221     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
    222 
    223     typedef GrFragmentProcessor INHERITED;
    224 };
    225 
    226 //////////////////////////////////////////////////////////////////////////////
    227 
    228 class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
    229 public:
    230     void emitCode(EmitArgs& args) override {
    231         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    232         SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
    233         ComposeOneFragmentProcessor::Child child =
    234             args.fFp.cast<ComposeOneFragmentProcessor>().child();
    235         SkString childColor("child");
    236         this->emitChild(0, nullptr, &childColor, args);
    237 
    238         const char* inputColor = args.fInputColor;
    239         // We don't try to optimize for this case at all
    240         if (!inputColor) {
    241             fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
    242             inputColor = "ones";
    243         }
    244 
    245         // emit blend code
    246         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
    247         const char* childStr = childColor.c_str();
    248         if (ComposeOneFragmentProcessor::kDst_Child == child) {
    249             GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
    250         } else {
    251             GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
    252         }
    253     }
    254 
    255 private:
    256     typedef GrGLSLFragmentProcessor INHERITED;
    257 };
    258 
    259 /////////////////////////////////////////////////////////////////////
    260 
    261 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
    262 
    263 const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
    264     // Create one random frag procs.
    265     // For now, we'll prevent either children from being a shader with children to prevent the
    266     // possibility of an arbitrarily large tree of procs.
    267     SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d));
    268     SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
    269         d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
    270     ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
    271         ComposeOneFragmentProcessor::kDst_Child :
    272         ComposeOneFragmentProcessor::kSrc_Child;
    273     return new ComposeOneFragmentProcessor(dst, mode, child);
    274 }
    275 
    276 GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
    277     return new GLComposeOneFragmentProcessor;
    278 }
    279 
    280 //////////////////////////////////////////////////////////////////////////////
    281 
    282 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor(
    283     const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
    284     switch (mode) {
    285         case SkXfermode::kClear_Mode:
    286             return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
    287                                                  GrConstColorProcessor::kIgnore_InputMode);
    288         case SkXfermode::kSrc_Mode:
    289             return nullptr;
    290         default:
    291             return new ComposeOneFragmentProcessor(dst, mode,
    292                                                    ComposeOneFragmentProcessor::kDst_Child);
    293     }
    294 }
    295 
    296 const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor(
    297     const GrFragmentProcessor* src, SkXfermode::Mode mode) {
    298     switch (mode) {
    299         case SkXfermode::kClear_Mode:
    300             return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
    301                                                  GrConstColorProcessor::kIgnore_InputMode);
    302         case SkXfermode::kDst_Mode:
    303             return nullptr;
    304         default:
    305             return new ComposeOneFragmentProcessor(src, mode,
    306                                                    ComposeOneFragmentProcessor::kSrc_Child);
    307     }
    308 }
    309