Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3 * Copyright 2015 Google Inc.
      4 *
      5 * Use of this source code is governed by a BSD-style license that can be
      6 * found in the LICENSE file.
      7 */
      8 
      9 #include "GrFragmentProcessor.h"
     10 #include "GrCoordTransform.h"
     11 #include "GrInvariantOutput.h"
     12 #include "GrProcOptInfo.h"
     13 #include "glsl/GrGLSLFragmentProcessor.h"
     14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     15 #include "glsl/GrGLSLProgramDataManager.h"
     16 #include "glsl/GrGLSLUniformHandler.h"
     17 #include "effects/GrConstColorProcessor.h"
     18 #include "effects/GrXfermodeFragmentProcessor.h"
     19 
     20 GrFragmentProcessor::~GrFragmentProcessor() {
     21     // If we got here then our ref count must have reached zero, so we will have converted refs
     22     // to pending executions for all children.
     23     for (int i = 0; i < fChildProcessors.count(); ++i) {
     24         fChildProcessors[i]->completedExecution();
     25     }
     26 }
     27 
     28 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that,
     29                                   bool ignoreCoordTransforms) const {
     30     if (this->classID() != that.classID() ||
     31         !this->hasSameTextureAccesses(that)) {
     32         return false;
     33     }
     34     if (ignoreCoordTransforms) {
     35         if (this->numTransforms() != that.numTransforms()) {
     36             return false;
     37         }
     38     } else if (!this->hasSameTransforms(that)) {
     39         return false;
     40     }
     41     if (!this->onIsEqual(that)) {
     42         return false;
     43     }
     44     if (this->numChildProcessors() != that.numChildProcessors()) {
     45         return false;
     46     }
     47     for (int i = 0; i < this->numChildProcessors(); ++i) {
     48         if (!this->childProcessor(i).isEqual(that.childProcessor(i), ignoreCoordTransforms)) {
     49             return false;
     50         }
     51     }
     52     return true;
     53 }
     54 
     55 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
     56     GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
     57     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
     58     for (int i = 0; i < fChildProcessors.count(); ++i) {
     59         glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
     60     }
     61     return glFragProc;
     62 }
     63 
     64 void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
     65     // Can't add texture accesses after registering any children since their texture accesses have
     66     // already been bubbled up into our fTextureAccesses array
     67     SkASSERT(fChildProcessors.empty());
     68 
     69     INHERITED::addTextureAccess(textureAccess);
     70     fNumTexturesExclChildren++;
     71 }
     72 
     73 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
     74     // Can't add transforms after registering any children since their transforms have already been
     75     // bubbled up into our fCoordTransforms array
     76     SkASSERT(fChildProcessors.empty());
     77 
     78     fCoordTransforms.push_back(transform);
     79     fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
     80     SkDEBUGCODE(transform->setInProcessor();)
     81     fNumTransformsExclChildren++;
     82 }
     83 
     84 int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) {
     85     // Append the child's transforms to our transforms array and the child's textures array to our
     86     // textures array
     87     if (!child->fCoordTransforms.empty()) {
     88         fCoordTransforms.push_back_n(child->fCoordTransforms.count(),
     89                                      child->fCoordTransforms.begin());
     90     }
     91     if (!child->fTextureAccesses.empty()) {
     92         fTextureAccesses.push_back_n(child->fTextureAccesses.count(),
     93                                      child->fTextureAccesses.begin());
     94     }
     95 
     96     int index = fChildProcessors.count();
     97     fChildProcessors.push_back(SkRef(child));
     98 
     99     if (child->willReadFragmentPosition()) {
    100         this->setWillReadFragmentPosition();
    101     }
    102 
    103     if (child->usesLocalCoords()) {
    104         fUsesLocalCoords = true;
    105     }
    106 
    107     return index;
    108 }
    109 
    110 void GrFragmentProcessor::notifyRefCntIsZero() const {
    111     // See comment above GrProgramElement for a detailed explanation of why we do this.
    112     for (int i = 0; i < fChildProcessors.count(); ++i) {
    113         fChildProcessors[i]->addPendingExecution();
    114         fChildProcessors[i]->unref();
    115     }
    116 }
    117 
    118 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
    119     if (this->numTransforms() != that.numTransforms()) {
    120         return false;
    121     }
    122     int count = this->numTransforms();
    123     for (int i = 0; i < count; ++i) {
    124         if (this->coordTransform(i) != that.coordTransform(i)) {
    125             return false;
    126         }
    127     }
    128     return true;
    129 }
    130 
    131 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha(
    132     const GrFragmentProcessor* fp) {
    133     if (!fp) {
    134         return nullptr;
    135     }
    136     return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode);
    137 }
    138 
    139 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor(
    140     const GrFragmentProcessor* fp) {
    141 
    142     class PremulFragmentProcessor : public GrFragmentProcessor {
    143     public:
    144         PremulFragmentProcessor(const GrFragmentProcessor* processor) {
    145             this->initClassID<PremulFragmentProcessor>();
    146             this->registerChildProcessor(processor);
    147         }
    148 
    149         const char* name() const override { return "Premultiply"; }
    150 
    151     private:
    152         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
    153             class GLFP : public GrGLSLFragmentProcessor {
    154             public:
    155                 void emitCode(EmitArgs& args) override {
    156                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    157                     this->emitChild(0, nullptr, args);
    158                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
    159                                                                 args.fInputColor);
    160                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
    161                 }
    162             };
    163             return new GLFP;
    164         }
    165 
    166         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
    167 
    168         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
    169 
    170         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
    171             // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
    172             if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
    173                 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
    174                 return;
    175             }
    176 
    177             GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false);
    178             this->childProcessor(0).computeInvariantOutput(&childOutput);
    179 
    180             if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) {
    181                 inout->mulByKnownFourComponents(0x0);
    182                 return;
    183             }
    184             GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags();
    185             GrColor c0 = GrPremulColor(inout->color());
    186             GrColor c1 = childOutput.color();
    187             GrColor color = 0x0;
    188             if (commonFlags & kR_GrColorComponentFlag) {
    189                 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) <<
    190                     GrColor_SHIFT_R;
    191             }
    192             if (commonFlags & kG_GrColorComponentFlag) {
    193                 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) <<
    194                     GrColor_SHIFT_G;
    195             }
    196             if (commonFlags & kB_GrColorComponentFlag) {
    197                 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) <<
    198                     GrColor_SHIFT_B;
    199             }
    200             inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput);
    201         }
    202     };
    203     if (!fp) {
    204         return nullptr;
    205     }
    206     return new PremulFragmentProcessor(fp);
    207 }
    208 
    209 //////////////////////////////////////////////////////////////////////////////
    210 
    211 const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp,
    212                                                               GrColor color) {
    213     class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
    214     public:
    215         ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color)
    216             : fColor(color) {
    217             this->initClassID<ReplaceInputFragmentProcessor>();
    218             this->registerChildProcessor(child);
    219         }
    220 
    221         const char* name() const override { return "Replace Color"; }
    222 
    223         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
    224             class GLFP : public GrGLSLFragmentProcessor {
    225             public:
    226                 GLFP() : fHaveSetColor(false) {}
    227                 void emitCode(EmitArgs& args) override {
    228                     const char* colorName;
    229                     fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
    230                                                                  kVec4f_GrSLType,
    231                                                                  kDefault_GrSLPrecision,
    232                                                                  "Color", &colorName);
    233                     this->emitChild(0, colorName, args);
    234                 }
    235 
    236             private:
    237                 void onSetData(const GrGLSLProgramDataManager& pdman,
    238                                const GrProcessor& fp) override {
    239                     GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
    240                     if (!fHaveSetColor || color != fPreviousColor) {
    241                         static const float scale = 1.f / 255.f;
    242                         float floatColor[4] = {
    243                             GrColorUnpackR(color) * scale,
    244                             GrColorUnpackG(color) * scale,
    245                             GrColorUnpackB(color) * scale,
    246                             GrColorUnpackA(color) * scale,
    247                         };
    248                         pdman.set4fv(fColorUni, 1, floatColor);
    249                         fPreviousColor = color;
    250                         fHaveSetColor = true;
    251                     }
    252                 }
    253 
    254                 GrGLSLProgramDataManager::UniformHandle fColorUni;
    255                 bool    fHaveSetColor;
    256                 GrColor fPreviousColor;
    257             };
    258 
    259             return new GLFP;
    260         }
    261 
    262     private:
    263         void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override
    264         {}
    265 
    266         bool onIsEqual(const GrFragmentProcessor& that) const override {
    267             return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
    268         }
    269 
    270         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
    271             inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
    272                               GrInvariantOutput::kWillNot_ReadInput);
    273             this->childProcessor(0).computeInvariantOutput(inout);
    274         }
    275 
    276         GrColor fColor;
    277     };
    278 
    279     GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false);
    280     fp->computeInvariantOutput(&childOut);
    281     if (childOut.willUseInputColor()) {
    282         return new ReplaceInputFragmentProcessor(fp, color);
    283     } else {
    284         return SkRef(fp);
    285     }
    286 }
    287 
    288 const GrFragmentProcessor* GrFragmentProcessor::RunInSeries(const GrFragmentProcessor* series[],
    289                                                             int cnt) {
    290     class SeriesFragmentProcessor : public GrFragmentProcessor {
    291     public:
    292         SeriesFragmentProcessor(const GrFragmentProcessor* children[], int cnt){
    293             SkASSERT(cnt > 1);
    294             this->initClassID<SeriesFragmentProcessor>();
    295             for (int i = 0; i < cnt; ++i) {
    296                 this->registerChildProcessor(children[i]);
    297             }
    298         }
    299 
    300         const char* name() const override { return "Series"; }
    301 
    302         GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
    303             class GLFP : public GrGLSLFragmentProcessor {
    304             public:
    305                 void emitCode(EmitArgs& args) override {
    306                     SkString input(args.fInputColor);
    307                     for (int i = 0; i < this->numChildProcessors() - 1; ++i) {
    308                         SkString temp;
    309                         temp.printf("out%d", i);
    310                         this->emitChild(i, input.c_str(), &temp, args);
    311                         input = temp;
    312                     }
    313                     // Last guy writes to our output variable.
    314                     this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
    315                 }
    316             };
    317             return new GLFP;
    318         }
    319 
    320     private:
    321         void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {}
    322 
    323         bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
    324 
    325         void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
    326             GrProcOptInfo info;
    327             SkTDArray<const GrFragmentProcessor*> children;
    328             children.setCount(this->numChildProcessors());
    329             for (int i = 0; i < children.count(); ++i) {
    330                 children[i] = &this->childProcessor(i);
    331             }
    332             info.calcWithInitialValues(children.begin(), children.count(), inout->color(),
    333                                        inout->validFlags(), false, false);
    334             for (int i = 0; i < this->numChildProcessors(); ++i) {
    335                 this->childProcessor(i).computeInvariantOutput(inout);
    336             }
    337         }
    338     };
    339 
    340     if (!cnt) {
    341         return nullptr;
    342     }
    343 
    344     // Run the through the series, do the invariant output processing, and look for eliminations.
    345     SkTDArray<const GrFragmentProcessor*> replacementSeries;
    346     SkAutoTUnref<const GrFragmentProcessor> colorFP;
    347     GrProcOptInfo info;
    348 
    349     info.calcWithInitialValues(series, cnt, 0x0, kNone_GrColorComponentFlags, false, false);
    350     if (kRGBA_GrColorComponentFlags == info.validFlags()) {
    351         return GrConstColorProcessor::Create(info.color(),
    352                                              GrConstColorProcessor::kIgnore_InputMode);
    353     } else {
    354         int firstIdx = info.firstEffectiveProcessorIndex();
    355         cnt -= firstIdx;
    356         if (firstIdx > 0 && info.inputColorIsUsed()) {
    357             colorFP.reset(GrConstColorProcessor::Create(info.inputColorToFirstEffectiveProccesor(),
    358                                                         GrConstColorProcessor::kIgnore_InputMode));
    359             cnt += 1;
    360             replacementSeries.setCount(cnt);
    361             replacementSeries[0] = colorFP;
    362             for (int i = 0; i < cnt - 1; ++i) {
    363                 replacementSeries[i + 1] = series[firstIdx + i];
    364             }
    365             series = replacementSeries.begin();
    366         } else {
    367             series += firstIdx;
    368             cnt -= firstIdx;
    369         }
    370     }
    371 
    372     if (1 == cnt) {
    373         return SkRef(series[0]);
    374     } else {
    375         return new SeriesFragmentProcessor(series, cnt);
    376     }
    377 }
    378 
    379