LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/effects - GrXfermodeFragmentProcessor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 194 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "effects/GrConstColorProcessor.h"
      12             : #include "glsl/GrGLSLFragmentProcessor.h"
      13             : #include "glsl/GrGLSLBlend.h"
      14             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      15             : #include "SkGr.h"
      16             : 
      17             : // Some of the cpu implementations of blend modes differ too much from the GPU enough that
      18             : // we can't use the cpu implementation to implement constantOutputForConstantInput.
      19           0 : static inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) {
      20             :     // The non-seperable modes differ too much. So does SoftLight. ColorBurn differs too much on our
      21             :     // test iOS device (but we just disable it across the aboard since it may happen on untested
      22             :     // GPUs).
      23           0 :     return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight &&
      24           0 :            mode != SkBlendMode::kColorBurn;
      25             : }
      26             : 
      27             : //////////////////////////////////////////////////////////////////////////////
      28             : 
      29           0 : class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
      30             : public:
      31           0 :     ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
      32             :                                 SkBlendMode mode)
      33           0 :             : INHERITED(OptFlags(src.get(), dst.get(), mode)), fMode(mode) {
      34           0 :         this->initClassID<ComposeTwoFragmentProcessor>();
      35           0 :         SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
      36           0 :         SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
      37           0 :         SkASSERT(0 == shaderAChildIndex);
      38           0 :         SkASSERT(1 == shaderBChildIndex);
      39           0 :     }
      40             : 
      41           0 :     const char* name() const override { return "ComposeTwo"; }
      42             : 
      43           0 :     SkString dumpInfo() const override {
      44           0 :         SkString str;
      45             : 
      46           0 :         str.appendf("Mode: %s", SkBlendMode_Name(fMode));
      47             : 
      48           0 :         for (int i = 0; i < this->numChildProcessors(); ++i) {
      49           0 :             str.appendf(" [%s %s]",
      50           0 :                         this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
      51             :         }
      52           0 :         return str;
      53             :     }
      54             : 
      55           0 :     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
      56           0 :         b->add32((int)fMode);
      57           0 :     }
      58             : 
      59           0 :     SkBlendMode getMode() const { return fMode; }
      60             : 
      61             : private:
      62           0 :     static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
      63             :                                       const GrFragmentProcessor* dst, SkBlendMode mode) {
      64             :         OptimizationFlags flags;
      65           0 :         switch (mode) {
      66             :             case SkBlendMode::kClear:
      67             :             case SkBlendMode::kSrc:
      68             :             case SkBlendMode::kDst:
      69           0 :                 SkFAIL("Should never create clear, src, or dst compose two FP.");
      70           0 :                 flags = kNone_OptimizationFlags;
      71           0 :                 break;
      72             : 
      73             :             // Produces opaque if both src and dst are opaque.
      74             :             case SkBlendMode::kSrcIn:
      75             :             case SkBlendMode::kDstIn:
      76             :             case SkBlendMode::kModulate:
      77           0 :                 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
      78           0 :                                 ? kPreservesOpaqueInput_OptimizationFlag
      79             :                                 : kNone_OptimizationFlags;
      80           0 :                 break;
      81             : 
      82             :             // Produces zero when both are opaque, indeterminate if one is opaque.
      83             :             case SkBlendMode::kSrcOut:
      84             :             case SkBlendMode::kDstOut:
      85             :             case SkBlendMode::kXor:
      86           0 :                 flags = kNone_OptimizationFlags;
      87           0 :                 break;
      88             : 
      89             :             // Is opaque if the dst is opaque.
      90             :             case SkBlendMode::kSrcATop:
      91           0 :                 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
      92             :                                                     : kNone_OptimizationFlags;
      93           0 :                 break;
      94             : 
      95             :             // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
      96             :             case SkBlendMode::kDstATop:
      97             :             case SkBlendMode::kScreen:
      98           0 :                 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
      99             :                                                     : kNone_OptimizationFlags;
     100           0 :                 break;
     101             : 
     102             :             // These modes are all opaque if either src or dst is opaque. All the advanced modes
     103             :             // compute alpha as src-over.
     104             :             case SkBlendMode::kSrcOver:
     105             :             case SkBlendMode::kDstOver:
     106             :             case SkBlendMode::kPlus:
     107             :             case SkBlendMode::kOverlay:
     108             :             case SkBlendMode::kDarken:
     109             :             case SkBlendMode::kLighten:
     110             :             case SkBlendMode::kColorDodge:
     111             :             case SkBlendMode::kColorBurn:
     112             :             case SkBlendMode::kHardLight:
     113             :             case SkBlendMode::kSoftLight:
     114             :             case SkBlendMode::kDifference:
     115             :             case SkBlendMode::kExclusion:
     116             :             case SkBlendMode::kMultiply:
     117             :             case SkBlendMode::kHue:
     118             :             case SkBlendMode::kSaturation:
     119             :             case SkBlendMode::kColor:
     120             :             case SkBlendMode::kLuminosity:
     121           0 :                 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
     122           0 :                                 ? kPreservesOpaqueInput_OptimizationFlag
     123             :                                 : kNone_OptimizationFlags;
     124           0 :                 break;
     125             :         }
     126           0 :         if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
     127           0 :             dst->hasConstantOutputForConstantInput()) {
     128           0 :             flags |= kConstantOutputForConstantInput_OptimizationFlag;
     129             :         }
     130           0 :         return flags;
     131             :     }
     132             : 
     133           0 :     bool onIsEqual(const GrFragmentProcessor& other) const override {
     134           0 :         const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
     135           0 :         return fMode == cs.fMode;
     136             :     }
     137             : 
     138           0 :     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
     139           0 :         float alpha = input.fRGBA[3];
     140           0 :         input = input.opaque();
     141           0 :         GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
     142           0 :         GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
     143           0 :         SkPM4f src = GrColor4fToSkPM4f(srcColor);
     144           0 :         SkPM4f dst = GrColor4fToSkPM4f(dstColor);
     145           0 :         auto proc = SkXfermode::GetProc4f(fMode);
     146           0 :         return SkPM4fToGrColor4f(proc(src, dst)).mulByScalar(alpha);
     147             :     }
     148             : 
     149             :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     150             : 
     151             :     SkBlendMode fMode;
     152             : 
     153             :     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     154             : 
     155             :     typedef GrFragmentProcessor INHERITED;
     156             : };
     157             : 
     158             : /////////////////////////////////////////////////////////////////////
     159             : 
     160           0 : class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
     161             : public:
     162             :     void emitCode(EmitArgs&) override;
     163             : 
     164             : private:
     165             :     typedef GrGLSLFragmentProcessor INHERITED;
     166             : };
     167             : 
     168             : /////////////////////////////////////////////////////////////////////
     169             : 
     170             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
     171             : 
     172             : #if GR_TEST_UTILS
     173           0 : sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
     174             :     // Create two random frag procs.
     175           0 :     sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
     176           0 :     sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
     177             : 
     178             :     SkBlendMode mode;
     179           0 :     do {
     180           0 :         mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
     181           0 :     } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
     182             :     return sk_sp<GrFragmentProcessor>(
     183           0 :         new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
     184             : }
     185             : #endif
     186             : 
     187           0 : GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
     188           0 :     return new GLComposeTwoFragmentProcessor;
     189             : }
     190             : 
     191             : /////////////////////////////////////////////////////////////////////
     192             : 
     193           0 : void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
     194             : 
     195           0 :     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     196           0 :     const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
     197             : 
     198           0 :     const char* inputColor = nullptr;
     199           0 :     if (args.fInputColor) {
     200           0 :         inputColor = "inputColor";
     201           0 :         fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
     202             :     }
     203             : 
     204             :     // declare outputColor and emit the code for each of the two children
     205           0 :     SkString srcColor("xfer_src");
     206           0 :     this->emitChild(0, inputColor, &srcColor, args);
     207             : 
     208           0 :     SkString dstColor("xfer_dst");
     209           0 :     this->emitChild(1, inputColor, &dstColor, args);
     210             : 
     211             :     // emit blend code
     212           0 :     SkBlendMode mode = cs.getMode();
     213           0 :     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
     214           0 :     GrGLSLBlend::AppendMode(fragBuilder,
     215             :                             srcColor.c_str(),
     216             :                             dstColor.c_str(),
     217             :                             args.fOutputColor,
     218           0 :                             mode);
     219             : 
     220             :     // re-multiply the output color by the input color's alpha
     221           0 :     if (args.fInputColor) {
     222           0 :         fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
     223             :     }
     224           0 : }
     225             : 
     226           0 : sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
     227             :          sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
     228           0 :     switch (mode) {
     229             :         case SkBlendMode::kClear:
     230             :             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
     231           0 :                                                GrConstColorProcessor::kIgnore_InputMode);
     232             :         case SkBlendMode::kSrc:
     233           0 :             return src;
     234             :         case SkBlendMode::kDst:
     235           0 :             return dst;
     236             :         default:
     237             :             return sk_sp<GrFragmentProcessor>(
     238           0 :                 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
     239             :     }
     240             : }
     241             : 
     242             : //////////////////////////////////////////////////////////////////////////////
     243             : 
     244           0 : class ComposeOneFragmentProcessor : public GrFragmentProcessor {
     245             : public:
     246             :     enum Child {
     247             :         kDst_Child,
     248             :         kSrc_Child,
     249             :     };
     250             : 
     251           0 :     ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode, Child child)
     252           0 :             : INHERITED(OptFlags(fp.get(), mode, child)), fMode(mode), fChild(child) {
     253           0 :         this->initClassID<ComposeOneFragmentProcessor>();
     254           0 :         SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
     255           0 :         SkASSERT(0 == dstIndex);
     256           0 :     }
     257             : 
     258           0 :     const char* name() const override { return "ComposeOne"; }
     259             : 
     260           0 :     SkString dumpInfo() const override {
     261           0 :         SkString str;
     262             : 
     263           0 :         str.appendf("Mode: %s, Child: %s",
     264           0 :                     SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
     265             : 
     266           0 :         for (int i = 0; i < this->numChildProcessors(); ++i) {
     267           0 :             str.appendf(" [%s %s]",
     268           0 :                         this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
     269             :         }
     270           0 :         return str;
     271             :     }
     272             : 
     273           0 :     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
     274             :         GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
     275           0 :         b->add32((int)fMode | (fChild << 16));
     276           0 :     }
     277             : 
     278           0 :     SkBlendMode mode() const { return fMode; }
     279             : 
     280           0 :     Child child() const { return fChild; }
     281             : 
     282             : private:
     283           0 :     OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
     284             :         OptimizationFlags flags;
     285           0 :         switch (mode) {
     286             :             case SkBlendMode::kClear:
     287           0 :                 SkFAIL("Should never create clear compose one FP.");
     288           0 :                 flags = kNone_OptimizationFlags;
     289           0 :                 break;
     290             : 
     291             :             case SkBlendMode::kSrc:
     292           0 :                 SkASSERT(child == kSrc_Child);
     293           0 :                 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
     294             :                                                    : kNone_OptimizationFlags;
     295           0 :                 break;
     296             : 
     297             :             case SkBlendMode::kDst:
     298           0 :                 SkASSERT(child == kDst_Child);
     299           0 :                 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
     300             :                                                    : kNone_OptimizationFlags;
     301           0 :                 break;
     302             : 
     303             :             // Produces opaque if both src and dst are opaque. These also will modulate the child's
     304             :             // output by either the input color or alpha. However, if the child is not compatible
     305             :             // with the coverage as alpha then it may produce a color that is not valid premul.
     306             :             case SkBlendMode::kSrcIn:
     307             :             case SkBlendMode::kDstIn:
     308             :             case SkBlendMode::kModulate:
     309           0 :                 if (fp->compatibleWithCoverageAsAlpha()) {
     310           0 :                     if (fp->preservesOpaqueInput()) {
     311           0 :                         flags = kPreservesOpaqueInput_OptimizationFlag |
     312             :                                 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
     313             :                     } else {
     314           0 :                         flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
     315             :                     }
     316             :                 } else {
     317           0 :                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
     318             :                                                        : kNone_OptimizationFlags;
     319             :                 }
     320           0 :                 break;
     321             : 
     322             :             // Produces zero when both are opaque, indeterminate if one is opaque.
     323             :             case SkBlendMode::kSrcOut:
     324             :             case SkBlendMode::kDstOut:
     325             :             case SkBlendMode::kXor:
     326           0 :                 flags = kNone_OptimizationFlags;
     327           0 :                 break;
     328             : 
     329             :             // Is opaque if the dst is opaque.
     330             :             case SkBlendMode::kSrcATop:
     331           0 :                 if (child == kDst_Child) {
     332           0 :                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
     333             :                                                        : kNone_OptimizationFlags;
     334             :                 } else {
     335           0 :                     flags = kPreservesOpaqueInput_OptimizationFlag;
     336             :                 }
     337           0 :                 break;
     338             : 
     339             :             // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
     340             :             case SkBlendMode::kDstATop:
     341             :             case SkBlendMode::kScreen:
     342           0 :                 if (child == kSrc_Child) {
     343           0 :                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
     344             :                                                        : kNone_OptimizationFlags;
     345             :                 } else {
     346           0 :                     flags = kPreservesOpaqueInput_OptimizationFlag;
     347             :                 }
     348           0 :                 break;
     349             : 
     350             :             // These modes are all opaque if either src or dst is opaque. All the advanced modes
     351             :             // compute alpha as src-over.
     352             :             case SkBlendMode::kSrcOver:
     353             :             case SkBlendMode::kDstOver:
     354             :             case SkBlendMode::kPlus:
     355             :             case SkBlendMode::kOverlay:
     356             :             case SkBlendMode::kDarken:
     357             :             case SkBlendMode::kLighten:
     358             :             case SkBlendMode::kColorDodge:
     359             :             case SkBlendMode::kColorBurn:
     360             :             case SkBlendMode::kHardLight:
     361             :             case SkBlendMode::kSoftLight:
     362             :             case SkBlendMode::kDifference:
     363             :             case SkBlendMode::kExclusion:
     364             :             case SkBlendMode::kMultiply:
     365             :             case SkBlendMode::kHue:
     366             :             case SkBlendMode::kSaturation:
     367             :             case SkBlendMode::kColor:
     368             :             case SkBlendMode::kLuminosity:
     369           0 :                 flags = kPreservesOpaqueInput_OptimizationFlag;
     370           0 :                 break;
     371             :         }
     372           0 :         if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
     373           0 :             flags |= kConstantOutputForConstantInput_OptimizationFlag;
     374             :         }
     375           0 :         return flags;
     376             :     }
     377             : 
     378           0 :     bool onIsEqual(const GrFragmentProcessor& that) const override {
     379           0 :         return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
     380             :     }
     381             : 
     382           0 :     GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
     383             :         GrColor4f childColor =
     384           0 :                 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
     385             :         SkPM4f src, dst;
     386           0 :         if (kSrc_Child == fChild) {
     387           0 :             src = GrColor4fToSkPM4f(childColor);
     388           0 :             dst = GrColor4fToSkPM4f(inputColor);
     389             :         } else {
     390           0 :             src = GrColor4fToSkPM4f(inputColor);
     391           0 :             dst = GrColor4fToSkPM4f(childColor);
     392             :         }
     393           0 :         auto proc = SkXfermode::GetProc4f(fMode);
     394           0 :         return SkPM4fToGrColor4f(proc(src, dst));
     395             :     }
     396             : 
     397             : private:
     398             :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     399             : 
     400             :     SkBlendMode fMode;
     401             :     Child       fChild;
     402             : 
     403             :     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     404             : 
     405             :     typedef GrFragmentProcessor INHERITED;
     406             : };
     407             : 
     408             : //////////////////////////////////////////////////////////////////////////////
     409             : 
     410           0 : class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
     411             : public:
     412           0 :     void emitCode(EmitArgs& args) override {
     413           0 :         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     414           0 :         SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
     415             :         ComposeOneFragmentProcessor::Child child =
     416           0 :             args.fFp.cast<ComposeOneFragmentProcessor>().child();
     417           0 :         SkString childColor("child");
     418           0 :         this->emitChild(0, nullptr, &childColor, args);
     419             : 
     420           0 :         const char* inputColor = args.fInputColor;
     421             :         // We don't try to optimize for this case at all
     422           0 :         if (!inputColor) {
     423           0 :             fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
     424           0 :             inputColor = "ones";
     425             :         }
     426             : 
     427             :         // emit blend code
     428           0 :         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
     429           0 :         const char* childStr = childColor.c_str();
     430           0 :         if (ComposeOneFragmentProcessor::kDst_Child == child) {
     431           0 :             GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
     432             :         } else {
     433           0 :             GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
     434             :         }
     435           0 :     }
     436             : 
     437             : private:
     438             :     typedef GrGLSLFragmentProcessor INHERITED;
     439             : };
     440             : 
     441             : /////////////////////////////////////////////////////////////////////
     442             : 
     443             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
     444             : 
     445             : #if GR_TEST_UTILS
     446           0 : sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
     447             :     // Create one random frag procs.
     448             :     // For now, we'll prevent either children from being a shader with children to prevent the
     449             :     // possibility of an arbitrarily large tree of procs.
     450           0 :     sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
     451             :     SkBlendMode mode;
     452             :     ComposeOneFragmentProcessor::Child child;
     453           0 :     do {
     454           0 :         mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
     455           0 :         child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
     456           0 :     } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
     457           0 :              (SkBlendMode::kSrc == mode && child == kDst_Child));
     458           0 :     return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
     459             : }
     460             : #endif
     461             : 
     462           0 : GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
     463           0 :     return new GLComposeOneFragmentProcessor;
     464             : }
     465             : 
     466             : //////////////////////////////////////////////////////////////////////////////
     467             : 
     468             : // It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
     469             : // that these factories could simply return the input FP. However, that doesn't have quite
     470             : // the same effect as the returned compose FP will replace the FP's input with solid white and
     471             : // ignore the original input. This could be implemented as:
     472             : // RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
     473             : 
     474           0 : sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
     475             :     sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
     476           0 :     switch (mode) {
     477             :         case SkBlendMode::kClear:
     478             :             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
     479           0 :                                                GrConstColorProcessor::kIgnore_InputMode);
     480             :         case SkBlendMode::kSrc:
     481           0 :             return nullptr;
     482             :         default:
     483             :             return sk_sp<GrFragmentProcessor>(
     484           0 :                 new ComposeOneFragmentProcessor(std::move(dst), mode,
     485           0 :                                                 ComposeOneFragmentProcessor::kDst_Child));
     486             :     }
     487             : }
     488             : 
     489           0 : sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
     490             :     sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
     491           0 :     switch (mode) {
     492             :         case SkBlendMode::kClear:
     493             :             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
     494           0 :                                                GrConstColorProcessor::kIgnore_InputMode);
     495             :         case SkBlendMode::kDst:
     496           0 :             return nullptr;
     497             :         default:
     498             :             return sk_sp<GrFragmentProcessor>(
     499           0 :                 new ComposeOneFragmentProcessor(std::move(src), mode,
     500           0 :                                                 ComposeOneFragmentProcessor::kSrc_Child));
     501             :     }
     502             : }

Generated by: LCOV version 1.13