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