Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2017 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 "GrProcessorSet.h"
      9 #include "GrAppliedClip.h"
     10 #include "GrCaps.h"
     11 #include "GrXferProcessor.h"
     12 #include "SkBlendModePriv.h"
     13 #include "effects/GrPorterDuffXferProcessor.h"
     14 
     15 const GrProcessorSet& GrProcessorSet::EmptySet() {
     16     static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
     17     return gEmpty;
     18 }
     19 
     20 GrProcessorSet GrProcessorSet::MakeEmptySet() {
     21     return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
     22 }
     23 
     24 GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
     25     fFlags = 0;
     26     if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
     27         fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
     28         fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
     29         int i = 0;
     30         for (auto& fp : paint.fColorFragmentProcessors) {
     31             SkASSERT(fp.get());
     32             fFragmentProcessors[i++] = std::move(fp);
     33         }
     34         for (auto& fp : paint.fCoverageFragmentProcessors) {
     35             SkASSERT(fp.get());
     36             fFragmentProcessors[i++] = std::move(fp);
     37         }
     38     } else {
     39         SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
     40         fColorFragmentProcessorCnt = 0;
     41     }
     42 }
     43 
     44 GrProcessorSet::GrProcessorSet(SkBlendMode mode)
     45         : fXP(SkBlendMode_AsXPFactory(mode))
     46         , fColorFragmentProcessorCnt(0)
     47         , fFragmentProcessorOffset(0)
     48         , fFlags(0) {}
     49 
     50 GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
     51         : fFragmentProcessors(1)
     52         , fXP((const GrXPFactory*)nullptr)
     53         , fColorFragmentProcessorCnt(1)
     54         , fFragmentProcessorOffset(0)
     55         , fFlags(0) {
     56     SkASSERT(colorFP);
     57     fFragmentProcessors[0] = std::move(colorFP);
     58 }
     59 
     60 GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
     61         : fXP(std::move(that.fXP))
     62         , fColorFragmentProcessorCnt(that.fColorFragmentProcessorCnt)
     63         , fFragmentProcessorOffset(0)
     64         , fFlags(that.fFlags) {
     65     fFragmentProcessors.reset(that.fFragmentProcessors.count() - that.fFragmentProcessorOffset);
     66     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
     67         fFragmentProcessors[i] =
     68                 std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]);
     69     }
     70     that.fColorFragmentProcessorCnt = 0;
     71     that.fFragmentProcessors.reset(0);
     72 }
     73 
     74 GrProcessorSet::~GrProcessorSet() {
     75     if (this->isFinalized() && this->xferProcessor()) {
     76         this->xferProcessor()->unref();
     77     }
     78 }
     79 
     80 SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
     81     SkString result;
     82     SkString indentString;
     83     for (int i = 0; i < indentCnt; ++i) {
     84         indentString.append("    ");
     85     }
     86     result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
     87     if (fp->numChildProcessors()) {
     88         for (int i = 0; i < fp->numChildProcessors(); ++i) {
     89             result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
     90         }
     91     }
     92     return result;
     93 }
     94 
     95 SkString GrProcessorSet::dumpProcessors() const {
     96     SkString result;
     97     if (this->numFragmentProcessors()) {
     98         if (this->numColorFragmentProcessors()) {
     99             result.append("Color Fragment Processors:\n");
    100             for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
    101                 result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
    102             }
    103         } else {
    104             result.append("No color fragment processors.\n");
    105         }
    106         if (this->numCoverageFragmentProcessors()) {
    107             result.append("Coverage Fragment Processors:\n");
    108             for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
    109                 result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
    110             }
    111         } else {
    112             result.append("No coverage fragment processors.\n");
    113         }
    114     } else {
    115         result.append("No color or coverage fragment processors.\n");
    116     }
    117     if (this->isFinalized()) {
    118         result.append("Xfer Processor: ");
    119         if (this->xferProcessor()) {
    120             result.appendf("%s\n", this->xferProcessor()->name());
    121         } else {
    122             result.append("SrcOver\n");
    123         }
    124     } else {
    125         result.append("XP Factory dumping not implemented.\n");
    126     }
    127     return result;
    128 }
    129 
    130 bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
    131     SkASSERT(this->isFinalized());
    132     SkASSERT(that.isFinalized());
    133     int fpCount = this->numFragmentProcessors();
    134     if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
    135         fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
    136         return false;
    137     }
    138 
    139     for (int i = 0; i < fpCount; ++i) {
    140         int a = i + fFragmentProcessorOffset;
    141         int b = i + that.fFragmentProcessorOffset;
    142         if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
    143             return false;
    144         }
    145     }
    146     // Most of the time both of these are null
    147     if (!this->xferProcessor() && !that.xferProcessor()) {
    148         return true;
    149     }
    150     const GrXferProcessor& thisXP = this->xferProcessor()
    151                                             ? *this->xferProcessor()
    152                                             : GrPorterDuffXPFactory::SimpleSrcOverXP();
    153     const GrXferProcessor& thatXP = that.xferProcessor()
    154                                             ? *that.xferProcessor()
    155                                             : GrPorterDuffXPFactory::SimpleSrcOverXP();
    156     return thisXP.isEqual(thatXP);
    157 }
    158 
    159 GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
    160                                                   const GrProcessorAnalysisCoverage coverageInput,
    161                                                   const GrAppliedClip* clip, bool isMixedSamples,
    162                                                   const GrCaps& caps,
    163                                                   GrPixelConfigIsClamped dstIsClamped,
    164                                                   GrColor* overrideInputColor) {
    165     SkASSERT(!this->isFinalized());
    166     SkASSERT(!fFragmentProcessorOffset);
    167 
    168     GrProcessorSet::Analysis analysis;
    169     analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
    170 
    171     const std::unique_ptr<const GrFragmentProcessor>* fps =
    172             fFragmentProcessors.get() + fFragmentProcessorOffset;
    173     GrColorFragmentProcessorAnalysis colorAnalysis(
    174             colorInput, unique_ptr_address_as_pointer_address(fps), fColorFragmentProcessorCnt);
    175     analysis.fCompatibleWithCoverageAsAlpha &=
    176             colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
    177     fps += fColorFragmentProcessorCnt;
    178     int n = this->numCoverageFragmentProcessors();
    179     bool hasCoverageFP = n > 0;
    180     bool coverageUsesLocalCoords = false;
    181     for (int i = 0; i < n; ++i) {
    182         if (!fps[i]->compatibleWithCoverageAsAlpha()) {
    183             analysis.fCompatibleWithCoverageAsAlpha = false;
    184             // Other than tests that exercise atypical behavior we expect all coverage FPs to be
    185             // compatible with the coverage-as-alpha optimization.
    186             GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
    187         }
    188         coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
    189     }
    190     if (clip) {
    191         hasCoverageFP = hasCoverageFP || clip->numClipCoverageFragmentProcessors();
    192         for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) {
    193             const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i);
    194             analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
    195             coverageUsesLocalCoords |= clipFP->usesLocalCoords();
    196         }
    197     }
    198     int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
    199     analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
    200             colorFPsToEliminate ? Analysis::kOverridden_InputColorType
    201                                 : Analysis::kOriginal_InputColorType);
    202 
    203     GrProcessorAnalysisCoverage outputCoverage;
    204     if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
    205         outputCoverage = GrProcessorAnalysisCoverage::kLCD;
    206     } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
    207         outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
    208     } else {
    209         outputCoverage = GrProcessorAnalysisCoverage::kNone;
    210     }
    211 
    212     GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
    213             this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, dstIsClamped);
    214     if (!this->numCoverageFragmentProcessors() &&
    215         GrProcessorAnalysisCoverage::kNone == coverageInput) {
    216         analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
    217                 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
    218     } else {
    219         // If we have non-clipping coverage processors we don't try to merge stencil steps as its
    220         // unclear whether it will be correct. We don't expect this to happen in practice.
    221         analysis.fCanCombineOverlappedStencilAndCover = false;
    222     }
    223     analysis.fRequiresDstTexture =
    224             SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
    225     analysis.fCompatibleWithCoverageAsAlpha &=
    226             SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
    227     analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
    228             props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
    229     if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
    230         colorFPsToEliminate = this->numColorFragmentProcessors();
    231         analysis.fInputColorType =
    232                 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
    233         analysis.fUsesLocalCoords = coverageUsesLocalCoords;
    234     } else {
    235         analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
    236     }
    237     for (int i = 0; i < colorFPsToEliminate; ++i) {
    238         fFragmentProcessors[i].reset(nullptr);
    239     }
    240     for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
    241         fFragmentProcessors[i]->markPendingExecution();
    242     }
    243     fFragmentProcessorOffset = colorFPsToEliminate;
    244     fColorFragmentProcessorCnt -= colorFPsToEliminate;
    245 
    246     auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
    247                                              outputCoverage, isMixedSamples, caps, dstIsClamped);
    248     fXP.fProcessor = xp.release();
    249 
    250     fFlags |= kFinalized_Flag;
    251     analysis.fIsInitialized = true;
    252     return analysis;
    253 }
    254