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