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