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