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 "src/core/SkBlendModePriv.h" 9#include "src/gpu/GrAppliedClip.h" 10#include "src/gpu/GrCaps.h" 11#include "src/gpu/GrProcessorSet.h" 12#include "src/gpu/GrUserStencilSettings.h" 13#include "src/gpu/GrXferProcessor.h" 14#include "src/gpu/effects/GrPorterDuffXferProcessor.h" 15 16const GrProcessorSet& GrProcessorSet::EmptySet() { 17 static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty); 18 return gEmpty; 19} 20 21GrProcessorSet GrProcessorSet::MakeEmptySet() { 22 return GrProcessorSet(GrProcessorSet::Empty::kEmpty); 23} 24 25GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) { 26 fColorFragmentProcessor = std::move(paint.fColorFragmentProcessor); 27 fCoverageFragmentProcessor = std::move(paint.fCoverageFragmentProcessor); 28 29 SkDEBUGCODE(paint.fAlive = false;) 30} 31 32GrProcessorSet::GrProcessorSet(SkBlendMode mode) : fXP(SkBlendMode_AsXPFactory(mode)) {} 33 34GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP) 35 : fXP((const GrXPFactory*)nullptr) { 36 SkASSERT(colorFP); 37 fColorFragmentProcessor = std::move(colorFP); 38} 39 40GrProcessorSet::GrProcessorSet(GrProcessorSet&& that) 41 : fColorFragmentProcessor(std::move(that.fColorFragmentProcessor)) 42 , fCoverageFragmentProcessor(std::move(that.fCoverageFragmentProcessor)) 43 , fXP(std::move(that.fXP)) 44 , fFlags(that.fFlags) {} 45 46GrProcessorSet::~GrProcessorSet() { 47 if (this->isFinalized() && this->xferProcessor()) { 48 this->xferProcessor()->unref(); 49 } 50} 51 52#if GR_TEST_UTILS 53SkString GrProcessorSet::dumpProcessors() const { 54 SkString result; 55 if (this->hasColorFragmentProcessor()) { 56 result.append("Color Fragment Processor:\n"); 57 result += this->colorFragmentProcessor()->dumpTreeInfo(); 58 } else { 59 result.append("No color fragment processor.\n"); 60 } 61 if (this->hasCoverageFragmentProcessor()) { 62 result.append("Coverage Fragment Processor:\n"); 63 result += this->coverageFragmentProcessor()->dumpTreeInfo(); 64 } else { 65 result.append("No coverage fragment processors.\n"); 66 } 67 if (this->isFinalized()) { 68 result.append("Xfer Processor: "); 69 if (this->xferProcessor()) { 70 result.appendf("%s\n", this->xferProcessor()->name()); 71 } else { 72 result.append("SrcOver\n"); 73 } 74 } else { 75 result.append("XP Factory dumping not implemented.\n"); 76 } 77 return result; 78} 79#endif 80 81bool GrProcessorSet::operator==(const GrProcessorSet& that) const { 82 SkASSERT(this->isFinalized()); 83 SkASSERT(that.isFinalized()); 84 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || 85 this->hasColorFragmentProcessor() != that.hasColorFragmentProcessor() || 86 this->hasCoverageFragmentProcessor() != that.hasCoverageFragmentProcessor()) { 87 return false; 88 } 89 90 if (this->hasColorFragmentProcessor()) { 91 if (!colorFragmentProcessor()->isEqual(*that.colorFragmentProcessor())) { 92 return false; 93 } 94 } 95 96 if (this->hasCoverageFragmentProcessor()) { 97 if (!coverageFragmentProcessor()->isEqual(*that.coverageFragmentProcessor())) { 98 return false; 99 } 100 } 101 102 // Most of the time both of these are null 103 if (!this->xferProcessor() && !that.xferProcessor()) { 104 return true; 105 } 106 const GrXferProcessor& thisXP = this->xferProcessor() 107 ? *this->xferProcessor() 108 : GrPorterDuffXPFactory::SimpleSrcOverXP(); 109 const GrXferProcessor& thatXP = that.xferProcessor() 110 ? *that.xferProcessor() 111 : GrPorterDuffXPFactory::SimpleSrcOverXP(); 112 return thisXP.isEqual(thatXP); 113} 114 115GrProcessorSet::Analysis GrProcessorSet::finalize( 116 const GrProcessorAnalysisColor& colorInput, const GrProcessorAnalysisCoverage coverageInput, 117 const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, 118 const GrCaps& caps, GrClampType clampType, SkPMColor4f* overrideInputColor) { 119 SkASSERT(!this->isFinalized()); 120 121 GrProcessorSet::Analysis analysis; 122 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput; 123 124 GrColorFragmentProcessorAnalysis colorAnalysis(colorInput, &fColorFragmentProcessor, 125 this->hasColorFragmentProcessor() ? 1 : 0); 126 bool hasCoverageFP = this->hasCoverageFragmentProcessor(); 127 bool coverageUsesLocalCoords = false; 128 if (hasCoverageFP) { 129 if (!fCoverageFragmentProcessor->compatibleWithCoverageAsAlpha()) { 130 analysis.fCompatibleWithCoverageAsAlpha = false; 131 } 132 coverageUsesLocalCoords |= fCoverageFragmentProcessor->usesSampleCoords(); 133 } 134 if (clip && clip->hasCoverageFragmentProcessor()) { 135 hasCoverageFP = true; 136 const GrFragmentProcessor* clipFP = clip->coverageFragmentProcessor(); 137 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha(); 138 coverageUsesLocalCoords |= clipFP->usesSampleCoords(); 139 } 140 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor); 141 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>( 142 colorFPsToEliminate ? Analysis::kOverridden_InputColorType 143 : Analysis::kOriginal_InputColorType); 144 145 GrProcessorAnalysisCoverage outputCoverage; 146 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) { 147 outputCoverage = GrProcessorAnalysisCoverage::kLCD; 148 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) { 149 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel; 150 } else { 151 outputCoverage = GrProcessorAnalysisCoverage::kNone; 152 } 153 154 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties( 155 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, clampType); 156 analysis.fRequiresDstTexture = (props & GrXPFactory::AnalysisProperties::kRequiresDstTexture) || 157 colorAnalysis.requiresDstTexture(caps); 158 analysis.fCompatibleWithCoverageAsAlpha &= 159 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha); 160 analysis.fRequiresNonOverlappingDraws = 161 (props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws) || 162 analysis.fRequiresDstTexture; 163 analysis.fUsesNonCoherentHWBlending = 164 SkToBool(props & GrXPFactory::AnalysisProperties::kUsesNonCoherentHWBlending); 165 analysis.fUnaffectedByDstValue = 166 SkToBool(props & GrXPFactory::AnalysisProperties::kUnaffectedByDstValue); 167 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) { 168 colorFPsToEliminate = this->hasColorFragmentProcessor() ? 1 : 0; 169 analysis.fInputColorType = 170 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType); 171 analysis.fUsesLocalCoords = coverageUsesLocalCoords; 172 } else { 173 analysis.fCompatibleWithCoverageAsAlpha &= 174 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha(); 175 analysis.fUsesLocalCoords = coverageUsesLocalCoords || colorAnalysis.usesLocalCoords(); 176 } 177 if (colorFPsToEliminate) { 178 SkASSERT(colorFPsToEliminate == 1); 179 fColorFragmentProcessor = nullptr; 180 } 181 analysis.fHasColorFragmentProcessor = this->hasColorFragmentProcessor(); 182 183 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(), 184 outputCoverage, caps, clampType); 185 fXP.fProcessor = xp.release(); 186 187 fFlags |= kFinalized_Flag; 188 analysis.fIsInitialized = true; 189#ifdef SK_DEBUG 190 bool hasXferBarrier = 191 fXP.fProcessor && 192 GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps); 193 bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier; 194 SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws); 195#endif 196 return analysis; 197} 198 199void GrProcessorSet::visitProxies(const GrVisitProxyFunc& func) const { 200 if (this->hasColorFragmentProcessor()) { 201 fColorFragmentProcessor->visitProxies(func); 202 } 203 if (this->hasCoverageFragmentProcessor()) { 204 fCoverageFragmentProcessor->visitProxies(func); 205 } 206} 207