LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrFragmentProcessor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 286 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 95 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 "GrFragmentProcessor.h"
       9             : #include "GrCoordTransform.h"
      10             : #include "GrPipeline.h"
      11             : #include "GrProcessorAnalysis.h"
      12             : #include "effects/GrConstColorProcessor.h"
      13             : #include "effects/GrXfermodeFragmentProcessor.h"
      14             : #include "glsl/GrGLSLFragmentProcessor.h"
      15             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      16             : #include "glsl/GrGLSLProgramDataManager.h"
      17             : #include "glsl/GrGLSLUniformHandler.h"
      18             : 
      19           0 : GrFragmentProcessor::~GrFragmentProcessor() {
      20             :     // If we got here then our ref count must have reached zero, so we will have converted refs
      21             :     // to pending executions for all children.
      22           0 :     for (int i = 0; i < fChildProcessors.count(); ++i) {
      23           0 :         fChildProcessors[i]->completedExecution();
      24             :     }
      25           0 : }
      26             : 
      27           0 : bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
      28           0 :     if (this->classID() != that.classID() ||
      29           0 :         !this->hasSameSamplersAndAccesses(that)) {
      30           0 :         return false;
      31             :     }
      32           0 :     if (!this->hasSameTransforms(that)) {
      33           0 :         return false;
      34             :     }
      35           0 :     if (!this->onIsEqual(that)) {
      36           0 :         return false;
      37             :     }
      38           0 :     if (this->numChildProcessors() != that.numChildProcessors()) {
      39           0 :         return false;
      40             :     }
      41           0 :     for (int i = 0; i < this->numChildProcessors(); ++i) {
      42           0 :         if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
      43           0 :             return false;
      44             :         }
      45             :     }
      46           0 :     return true;
      47             : }
      48             : 
      49           0 : GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
      50           0 :     GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
      51           0 :     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
      52           0 :     for (int i = 0; i < fChildProcessors.count(); ++i) {
      53           0 :         glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
      54             :     }
      55           0 :     return glFragProc;
      56             : }
      57             : 
      58           0 : void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
      59           0 :     fCoordTransforms.push_back(transform);
      60           0 :     fFlags |= kUsesLocalCoords_Flag;
      61           0 :     SkDEBUGCODE(transform->setInProcessor();)
      62           0 : }
      63             : 
      64           0 : int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
      65           0 :     this->combineRequiredFeatures(*child);
      66             : 
      67           0 :     if (child->usesLocalCoords()) {
      68           0 :         fFlags |= kUsesLocalCoords_Flag;
      69             :     }
      70           0 :     if (child->usesDistanceVectorField()) {
      71           0 :         fFlags |= kUsesDistanceVectorField_Flag;
      72             :     }
      73             : 
      74           0 :     int index = fChildProcessors.count();
      75           0 :     fChildProcessors.push_back(child.release());
      76             : 
      77           0 :     return index;
      78             : }
      79             : 
      80           0 : void GrFragmentProcessor::notifyRefCntIsZero() const {
      81             :     // See comment above GrProgramElement for a detailed explanation of why we do this.
      82           0 :     for (int i = 0; i < fChildProcessors.count(); ++i) {
      83           0 :         fChildProcessors[i]->addPendingExecution();
      84           0 :         fChildProcessors[i]->unref();
      85             :     }
      86           0 : }
      87             : 
      88           0 : bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
      89           0 :     if (this->numCoordTransforms() != that.numCoordTransforms()) {
      90           0 :         return false;
      91             :     }
      92           0 :     int count = this->numCoordTransforms();
      93           0 :     for (int i = 0; i < count; ++i) {
      94           0 :         if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
      95           0 :             return false;
      96             :         }
      97             :     }
      98           0 :     return true;
      99             : }
     100             : 
     101           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
     102             :     sk_sp<GrFragmentProcessor> fp) {
     103           0 :     if (!fp) {
     104           0 :         return nullptr;
     105             :     }
     106           0 :     return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
     107             : }
     108             : 
     109             : namespace {
     110             : 
     111           0 : class PremulInputFragmentProcessor : public GrFragmentProcessor {
     112             : public:
     113           0 :     PremulInputFragmentProcessor()
     114           0 :             : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
     115           0 :                         kConstantOutputForConstantInput_OptimizationFlag) {
     116           0 :         this->initClassID<PremulInputFragmentProcessor>();
     117           0 :     }
     118             : 
     119           0 :     const char* name() const override { return "PremultiplyInput"; }
     120             : 
     121             : private:
     122           0 :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     123           0 :         class GLFP : public GrGLSLFragmentProcessor {
     124             :         public:
     125           0 :             void emitCode(EmitArgs& args) override {
     126           0 :                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     127             : 
     128           0 :                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
     129           0 :                 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
     130           0 :                                             args.fOutputColor, args.fInputColor);
     131           0 :             }
     132             :         };
     133           0 :         return new GLFP;
     134             :     }
     135             : 
     136           0 :     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
     137             : 
     138           0 :     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
     139             : 
     140           0 :     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
     141           0 :         return input.premul();
     142             :     }
     143             : 
     144             :     typedef GrFragmentProcessor INHERITED;
     145             : };
     146             : 
     147           0 : class UnpremulInputFragmentProcessor : public GrFragmentProcessor {
     148             : public:
     149           0 :     UnpremulInputFragmentProcessor()
     150           0 :             : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
     151           0 :                         kConstantOutputForConstantInput_OptimizationFlag) {
     152           0 :         this->initClassID<UnpremulInputFragmentProcessor>();
     153           0 :     }
     154             : 
     155           0 :     const char* name() const override { return "UnpremultiplyInput"; }
     156             : 
     157             : private:
     158           0 :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     159           0 :         class GLFP : public GrGLSLFragmentProcessor {
     160             :         public:
     161           0 :             void emitCode(EmitArgs& args) override {
     162           0 :                 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     163             : 
     164           0 :                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
     165           0 :                 fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
     166           0 :                                          args.fInputColor, args.fInputColor);
     167           0 :                 fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
     168           0 :             }
     169             :         };
     170           0 :         return new GLFP;
     171             :     }
     172             : 
     173           0 :     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
     174             : 
     175           0 :     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
     176             : 
     177           0 :     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
     178           0 :         return input.unpremul();
     179             :     }
     180             : 
     181             :     typedef GrFragmentProcessor INHERITED;
     182             : };
     183             : 
     184             : }
     185             : 
     186           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
     187           0 :     if (!fp) {
     188           0 :         return nullptr;
     189             :     }
     190           0 :     sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
     191           0 :     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
     192             : }
     193             : 
     194           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulOutput(sk_sp<GrFragmentProcessor> fp) {
     195           0 :     if (!fp) {
     196           0 :         return nullptr;
     197             :     }
     198           0 :     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<PremulInputFragmentProcessor>() };
     199           0 :     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
     200             : }
     201             : 
     202           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::UnpremulOutput(sk_sp<GrFragmentProcessor> fp) {
     203           0 :     if (!fp) {
     204           0 :         return nullptr;
     205             :     }
     206           0 :     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<UnpremulInputFragmentProcessor>() };
     207           0 :     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
     208             : }
     209             : 
     210           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(sk_sp<GrFragmentProcessor> fp,
     211             :                                                               const GrSwizzle& swizzle) {
     212           0 :     class SwizzleFragmentProcessor : public GrFragmentProcessor {
     213             :     public:
     214           0 :         SwizzleFragmentProcessor(const GrSwizzle& swizzle)
     215           0 :                 : INHERITED(kAll_OptimizationFlags)
     216           0 :                 , fSwizzle(swizzle) {
     217           0 :             this->initClassID<SwizzleFragmentProcessor>();
     218           0 :         }
     219             : 
     220           0 :         const char* name() const override { return "Swizzle"; }
     221           0 :         const GrSwizzle& swizzle() const { return fSwizzle; }
     222             : 
     223             :     private:
     224           0 :         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     225           0 :             class GLFP : public GrGLSLFragmentProcessor {
     226             :             public:
     227           0 :                 void emitCode(EmitArgs& args) override {
     228           0 :                     const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
     229           0 :                     const GrSwizzle& swizzle = sfp.swizzle();
     230           0 :                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     231             : 
     232           0 :                     fragBuilder->codeAppendf("%s = %s.%s;",
     233           0 :                                              args.fOutputColor, args.fInputColor, swizzle.c_str());
     234           0 :                 }
     235             :             };
     236           0 :             return new GLFP;
     237             :         }
     238             : 
     239           0 :         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
     240           0 :             b->add32(fSwizzle.asKey());
     241           0 :         }
     242             : 
     243           0 :         bool onIsEqual(const GrFragmentProcessor& other) const override {
     244           0 :             const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
     245           0 :             return fSwizzle == sfp.fSwizzle;
     246             :         }
     247             : 
     248           0 :         GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
     249           0 :             return fSwizzle.applyTo(input);
     250             :         }
     251             : 
     252             :         GrSwizzle fSwizzle;
     253             : 
     254             :         typedef GrFragmentProcessor INHERITED;
     255             :     };
     256             : 
     257           0 :     if (!fp) {
     258           0 :         return nullptr;
     259             :     }
     260           0 :     if (GrSwizzle::RGBA() == swizzle) {
     261           0 :         return fp;
     262             :     }
     263           0 :     sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<SwizzleFragmentProcessor>(swizzle) };
     264           0 :     return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
     265             : }
     266             : 
     267           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
     268             :         sk_sp<GrFragmentProcessor> fp) {
     269             : 
     270           0 :     class PremulFragmentProcessor : public GrFragmentProcessor {
     271             :     public:
     272           0 :         PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
     273           0 :                 : INHERITED(OptFlags(processor.get())) {
     274           0 :             this->initClassID<PremulFragmentProcessor>();
     275           0 :             this->registerChildProcessor(processor);
     276           0 :         }
     277             : 
     278           0 :         const char* name() const override { return "Premultiply"; }
     279             : 
     280             :     private:
     281           0 :         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     282           0 :             class GLFP : public GrGLSLFragmentProcessor {
     283             :             public:
     284           0 :                 void emitCode(EmitArgs& args) override {
     285           0 :                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     286           0 :                     this->emitChild(0, nullptr, args);
     287           0 :                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
     288           0 :                                                                 args.fInputColor);
     289           0 :                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
     290           0 :                 }
     291             :             };
     292           0 :             return new GLFP;
     293             :         }
     294             : 
     295           0 :         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
     296             : 
     297           0 :         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
     298             : 
     299           0 :         static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
     300           0 :             OptimizationFlags flags = kNone_OptimizationFlags;
     301           0 :             if (inner->preservesOpaqueInput()) {
     302           0 :                 flags |= kPreservesOpaqueInput_OptimizationFlag;
     303             :             }
     304           0 :             if (inner->hasConstantOutputForConstantInput()) {
     305           0 :                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
     306             :             }
     307           0 :             return flags;
     308             :         }
     309             : 
     310           0 :         GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
     311             :             GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
     312           0 :                                                                   GrColor4f::OpaqueWhite());
     313           0 :             return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
     314           0 :                              input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
     315           0 :                              input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
     316           0 :                              input.fRGBA[3] * childColor.fRGBA[3]);
     317             :         }
     318             : 
     319             :         typedef GrFragmentProcessor INHERITED;
     320             :     };
     321           0 :     if (!fp) {
     322           0 :         return nullptr;
     323             :     }
     324           0 :     return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
     325             : }
     326             : 
     327             : //////////////////////////////////////////////////////////////////////////////
     328             : 
     329           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
     330             :                                                               GrColor4f color) {
     331           0 :     class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
     332             :     public:
     333           0 :         ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
     334           0 :                 : INHERITED(OptFlags(child.get(), color)), fColor(color) {
     335           0 :             this->initClassID<ReplaceInputFragmentProcessor>();
     336           0 :             this->registerChildProcessor(std::move(child));
     337           0 :         }
     338             : 
     339           0 :         const char* name() const override { return "Replace Color"; }
     340             : 
     341           0 :         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     342           0 :             class GLFP : public GrGLSLFragmentProcessor {
     343             :             public:
     344           0 :                 GLFP() : fHaveSetColor(false) {}
     345           0 :                 void emitCode(EmitArgs& args) override {
     346             :                     const char* colorName;
     347           0 :                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
     348             :                                                                  kVec4f_GrSLType,
     349             :                                                                  kDefault_GrSLPrecision,
     350           0 :                                                                  "Color", &colorName);
     351           0 :                     this->emitChild(0, colorName, args);
     352           0 :                 }
     353             : 
     354             :             private:
     355           0 :                 void onSetData(const GrGLSLProgramDataManager& pdman,
     356             :                                const GrFragmentProcessor& fp) override {
     357           0 :                     GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
     358           0 :                     if (!fHaveSetColor || color != fPreviousColor) {
     359           0 :                         pdman.set4fv(fColorUni, 1, color.fRGBA);
     360           0 :                         fPreviousColor = color;
     361           0 :                         fHaveSetColor = true;
     362             :                     }
     363           0 :                 }
     364             : 
     365             :                 GrGLSLProgramDataManager::UniformHandle fColorUni;
     366             :                 bool      fHaveSetColor;
     367             :                 GrColor4f fPreviousColor;
     368             :             };
     369             : 
     370           0 :             return new GLFP;
     371             :         }
     372             : 
     373             :     private:
     374           0 :         static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
     375           0 :             OptimizationFlags childFlags = child->optimizationFlags();
     376           0 :             OptimizationFlags flags = kNone_OptimizationFlags;
     377           0 :             if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
     378           0 :                 flags |= kConstantOutputForConstantInput_OptimizationFlag;
     379             :             }
     380           0 :             if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
     381           0 :                 flags |= kPreservesOpaqueInput_OptimizationFlag;
     382             :             }
     383           0 :             return flags;
     384             :         }
     385             : 
     386           0 :         void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
     387           0 :         {}
     388             : 
     389           0 :         bool onIsEqual(const GrFragmentProcessor& that) const override {
     390           0 :             return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
     391             :         }
     392             : 
     393           0 :         GrColor4f constantOutputForConstantInput(GrColor4f) const override {
     394           0 :             return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
     395             :         }
     396             : 
     397             :         GrColor4f fColor;
     398             : 
     399             :         typedef GrFragmentProcessor INHERITED;
     400             :     };
     401             : 
     402           0 :     return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
     403             : }
     404             : 
     405           0 : sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
     406             :                                                             int cnt) {
     407           0 :     class SeriesFragmentProcessor : public GrFragmentProcessor {
     408             :     public:
     409           0 :         SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
     410           0 :                 : INHERITED(OptFlags(children, cnt)) {
     411           0 :             SkASSERT(cnt > 1);
     412           0 :             this->initClassID<SeriesFragmentProcessor>();
     413           0 :             for (int i = 0; i < cnt; ++i) {
     414           0 :                 this->registerChildProcessor(std::move(children[i]));
     415             :             }
     416           0 :         }
     417             : 
     418           0 :         const char* name() const override { return "Series"; }
     419             : 
     420           0 :         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     421           0 :             class GLFP : public GrGLSLFragmentProcessor {
     422             :             public:
     423           0 :                 void emitCode(EmitArgs& args) override {
     424             :                     // First guy's input might be nil.
     425           0 :                     SkString temp("out0");
     426           0 :                     this->emitChild(0, args.fInputColor, &temp, args);
     427           0 :                     SkString input = temp;
     428           0 :                     for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
     429           0 :                         temp.printf("out%d", i);
     430           0 :                         this->emitChild(i, input.c_str(), &temp, args);
     431           0 :                         input = temp;
     432             :                     }
     433             :                     // Last guy writes to our output variable.
     434           0 :                     this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
     435           0 :                 }
     436             :             };
     437           0 :             return new GLFP;
     438             :         }
     439             :     private:
     440           0 :         static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
     441           0 :             OptimizationFlags flags = kAll_OptimizationFlags;
     442           0 :             for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
     443           0 :                 flags &= children[i]->optimizationFlags();
     444             :             }
     445           0 :             return flags;
     446             :         }
     447           0 :         void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
     448             : 
     449           0 :         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
     450             : 
     451           0 :         GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
     452           0 :             int childCnt = this->numChildProcessors();
     453           0 :             for (int i = 0; i < childCnt; ++i) {
     454           0 :                 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
     455             :             }
     456           0 :             return color;
     457             :         }
     458             : 
     459             :         typedef GrFragmentProcessor INHERITED;
     460             :     };
     461             : 
     462           0 :     if (!cnt) {
     463           0 :         return nullptr;
     464             :     }
     465           0 :     if (1 == cnt) {
     466           0 :         return series[0];
     467             :     }
     468             :     // Run the through the series, do the invariant output processing, and look for eliminations.
     469           0 :     GrColorFragmentProcessorAnalysis info;
     470           0 :     info.analyzeProcessors(sk_sp_address_as_pointer_address(series), cnt);
     471           0 :     SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
     472           0 :     GrColor4f knownColor;
     473           0 :     int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
     474           0 :     if (leadingFPsToEliminate) {
     475             :         sk_sp<GrFragmentProcessor> colorFP(
     476           0 :                 GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
     477           0 :         if (leadingFPsToEliminate == cnt) {
     478           0 :             return colorFP;
     479             :         }
     480           0 :         cnt = cnt - leadingFPsToEliminate + 1;
     481           0 :         replacementSeries.reserve(cnt);
     482           0 :         replacementSeries.emplace_back(std::move(colorFP));
     483           0 :         for (int i = 0; i < cnt - 1; ++i) {
     484           0 :             replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
     485             :         }
     486           0 :         series = replacementSeries.begin();
     487             :     }
     488           0 :     return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
     489             : }
     490             : 
     491             : //////////////////////////////////////////////////////////////////////////////
     492             : 
     493           0 : GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
     494           0 :     for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
     495           0 :         fFPStack.push_back(&pipeline.getFragmentProcessor(i));
     496             :     }
     497           0 : }
     498             : 
     499           0 : const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
     500           0 :     if (fFPStack.empty()) {
     501           0 :         return nullptr;
     502             :     }
     503           0 :     const GrFragmentProcessor* back = fFPStack.back();
     504           0 :     fFPStack.pop_back();
     505           0 :     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
     506           0 :         fFPStack.push_back(&back->childProcessor(i));
     507             :     }
     508           0 :     return back;
     509             : }
     510             : 

Generated by: LCOV version 1.13