diff options
-rw-r--r-- | src/gpu/GrProcessorSet.cpp | 75 | ||||
-rw-r--r-- | src/gpu/GrProcessorSet.h | 105 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 2 | ||||
-rw-r--r-- | src/gpu/ops/GrDrawOp.h | 4 | ||||
-rw-r--r-- | tests/GrPorterDuffTest.cpp | 2 |
5 files changed, 124 insertions, 64 deletions
diff --git a/src/gpu/GrProcessorSet.cpp b/src/gpu/GrProcessorSet.cpp index e5beca0382..c4b82621d1 100644 --- a/src/gpu/GrProcessorSet.cpp +++ b/src/gpu/GrProcessorSet.cpp @@ -12,18 +12,23 @@ GrProcessorSet::GrProcessorSet(GrPaint&& paint) { fXPFactory = paint.fXPFactory; - fColorFragmentProcessorCnt = paint.numColorFragmentProcessors(); - fFragmentProcessors.reset(paint.numTotalFragmentProcessors()); - int i = 0; - for (auto& fp : paint.fColorFragmentProcessors) { - fFragmentProcessors[i++] = fp.release(); - } - for (auto& fp : paint.fCoverageFragmentProcessors) { - fFragmentProcessors[i++] = fp.release(); - } fFlags = 0; - if (paint.usesDistanceVectorField()) { - fFlags |= kUseDistanceVectorField_Flag; + if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) { + fColorFragmentProcessorCnt = paint.numColorFragmentProcessors(); + fFragmentProcessors.reset(paint.numTotalFragmentProcessors()); + int i = 0; + for (auto& fp : paint.fColorFragmentProcessors) { + fFragmentProcessors[i++] = fp.release(); + } + for (auto& fp : paint.fCoverageFragmentProcessors) { + fFragmentProcessors[i++] = fp.release(); + } + if (paint.usesDistanceVectorField()) { + fFlags |= kUseDistanceVectorField_Flag; + } + } else { + SkDebugf("Insane number of color fragment processors in paint. Dropping all processors."); + fColorFragmentProcessorCnt = 0; } if (paint.getDisableOutputConversionToSRGB()) { fFlags |= kDisableOutputConversionToSRGB_Flag; @@ -35,13 +40,14 @@ GrProcessorSet::GrProcessorSet(GrPaint&& paint) { ////////////////////////////////////////////////////////////////////////////// -void GrProcessorSet::FragmentProcessorAnalysis::internalReset(const GrPipelineInput& colorInput, - const GrPipelineInput coverageInput, - const GrProcessorSet& processors, - const GrFragmentProcessor* clipFP, - const GrCaps& caps) { +void GrProcessorSet::FragmentProcessorAnalysis::internalInit(const GrPipelineInput& colorInput, + const GrPipelineInput coverageInput, + const GrProcessorSet& processors, + const GrFragmentProcessor* clipFP, + const GrCaps& caps) { GrProcOptInfo colorInfo(colorInput); fCompatibleWithCoverageAsAlpha = !coverageInput.isLCDCoverage(); + fValidInputColor = colorInput.isConstant(&fInputColor); const GrFragmentProcessor* const* fps = processors.fFragmentProcessors.get(); colorInfo.analyzeProcessors(fps, processors.fColorFragmentProcessorCnt); @@ -65,38 +71,41 @@ void GrProcessorSet::FragmentProcessorAnalysis::internalReset(const GrPipelineIn fUsesLocalCoords |= clipFP->usesLocalCoords(); hasCoverageFP = true; } - fInitialColorProcessorsToEliminate = - colorInfo.initialProcessorsToEliminate(&fOverrideInputColor); + fInitialColorProcessorsToEliminate = colorInfo.initialProcessorsToEliminate(&fInputColor); + fValidInputColor |= SkToBool(fInitialColorProcessorsToEliminate); bool opaque = colorInfo.isOpaque(); if (colorInfo.hasKnownOutputColor(&fKnownOutputColor)) { - fColorType = opaque ? ColorType::kOpaqueConstant : ColorType::kConstant; + fOutputColorType = static_cast<unsigned>(opaque ? ColorType::kOpaqueConstant + : ColorType::kConstant); } else if (opaque) { - fColorType = ColorType::kOpaque; + fOutputColorType = static_cast<unsigned>(ColorType::kOpaque); } else { - fColorType = ColorType::kUnknown; + fOutputColorType = static_cast<unsigned>(ColorType::kUnknown); } if (coverageInput.isLCDCoverage()) { - fCoverageType = CoverageType::kLCD; + fOutputCoverageType = static_cast<unsigned>(CoverageType::kLCD); } else { - fCoverageType = hasCoverageFP || !coverageInput.isSolidWhite() - ? CoverageType::kSingleChannel - : CoverageType::kNone; + fOutputCoverageType = hasCoverageFP || !coverageInput.isSolidWhite() + ? static_cast<unsigned>(CoverageType::kSingleChannel) + : static_cast<unsigned>(CoverageType::kNone); } } -void GrProcessorSet::FragmentProcessorAnalysis::reset(const GrPipelineInput& colorInput, - const GrPipelineInput coverageInput, - const GrProcessorSet& processors, - const GrAppliedClip& appliedClip, - const GrCaps& caps) { - this->internalReset(colorInput, coverageInput, processors, - appliedClip.clipCoverageFragmentProcessor(), caps); +void GrProcessorSet::FragmentProcessorAnalysis::init(const GrPipelineInput& colorInput, + const GrPipelineInput coverageInput, + const GrProcessorSet& processors, + const GrAppliedClip* appliedClip, + const GrCaps& caps) { + const GrFragmentProcessor* clipFP = + appliedClip ? appliedClip->clipCoverageFragmentProcessor() : nullptr; + this->internalInit(colorInput, coverageInput, processors, clipFP, caps); + fIsInitializedWithProcessorSet = true; } GrProcessorSet::FragmentProcessorAnalysis::FragmentProcessorAnalysis( const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, const GrCaps& caps) : FragmentProcessorAnalysis() { - this->internalReset(colorInput, coverageInput, GrProcessorSet(GrPaint()), nullptr, caps); + this->internalInit(colorInput, coverageInput, GrProcessorSet(GrPaint()), nullptr, caps); } diff --git a/src/gpu/GrProcessorSet.h b/src/gpu/GrProcessorSet.h index de8bd6944b..8203491435 100644 --- a/src/gpu/GrProcessorSet.h +++ b/src/gpu/GrProcessorSet.h @@ -55,63 +55,114 @@ public: */ class FragmentProcessorAnalysis { public: - FragmentProcessorAnalysis() = default; - // This version is used by a unit test that assumes no clip and no fragment processors. + /** + * This constructor allows an op to record its initial color in a FragmentProcessorAnalysis + * member and then run analysis later when the analysis inputs are available. If the + * analysis produces color fragment processor elimination then the input color is replaced + * by the expected input to the first non-eliminated processor. Otherwise, the original + * input color is preserved. The only reason to use this is to save space on the op by not + * separately storing the initial color. + */ + explicit FragmentProcessorAnalysis(GrColor initialColor) : FragmentProcessorAnalysis() { + fInputColor = initialColor; + fValidInputColor = true; + } + + FragmentProcessorAnalysis() + : fIsInitializedWithProcessorSet(false) + , fCompatibleWithCoverageAsAlpha(true) + , fValidInputColor(false) + , fOutputCoverageType(static_cast<unsigned>(CoverageType::kNone)) + , fOutputColorType(static_cast<unsigned>(ColorType::kUnknown)) + , fInitialColorProcessorsToEliminate(0) {} + + // This version is used by a unit test that assumes no clip, no processors, and no PLS. FragmentProcessorAnalysis(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, const GrCaps&); - void reset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, - const GrProcessorSet&, const GrAppliedClip&, const GrCaps&); + void init(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, + const GrProcessorSet&, const GrAppliedClip*, const GrCaps&); + + bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; } int initialColorProcessorsToEliminate(GrColor* newInputColor) const { if (fInitialColorProcessorsToEliminate > 0) { - *newInputColor = fOverrideInputColor; + SkASSERT(fValidInputColor); + *newInputColor = fInputColor; } return fInitialColorProcessorsToEliminate; } + /** + * Valid if initialProcessorsToEliminate returns true or this analysis was initialized with + * a known color via constructor or init(). If color fragment processors are eliminated then + * this returns the expected input to the first non-eliminated processors. Otherwise it is + * the color passed to the constructor or init(). + */ + GrColor inputColor() const { + SkASSERT(fValidInputColor); + return fInputColor; + } + bool usesLocalCoords() const { return fUsesLocalCoords; } bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } bool isOutputColorOpaque() const { - return ColorType::kOpaque == fColorType || ColorType::kOpaqueConstant == fColorType; + return ColorType::kOpaque == this->outputColorType() || + ColorType::kOpaqueConstant == this->outputColorType(); } bool hasKnownOutputColor(GrColor* color = nullptr) const { - bool constant = - ColorType::kConstant == fColorType || ColorType::kOpaqueConstant == fColorType; + bool constant = ColorType::kConstant == this->outputColorType() || + ColorType::kOpaqueConstant == this->outputColorType(); if (constant && color) { *color = fKnownOutputColor; } return constant; } - bool hasCoverage() const { return CoverageType::kNone != fCoverageType; } - bool hasLCDCoverage() const { return CoverageType::kLCD == fCoverageType; } + bool hasCoverage() const { return CoverageType::kNone != this->outputCoverageType(); } + bool hasLCDCoverage() const { return CoverageType::kLCD == this->outputCoverageType(); } private: - void internalReset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, - const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&); - - enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque }; - enum class CoverageType { kNone, kSingleChannel, kLCD }; - - bool fCompatibleWithCoverageAsAlpha = true; - bool fUsesLocalCoords = false; - CoverageType fCoverageType = CoverageType::kNone; - ColorType fColorType = ColorType::kUnknown; - int fInitialColorProcessorsToEliminate = 0; - GrColor fOverrideInputColor; + enum class ColorType : unsigned { kUnknown, kOpaqueConstant, kConstant, kOpaque }; + enum class CoverageType : unsigned { kNone, kSingleChannel, kLCD }; + + CoverageType outputCoverageType() const { + return static_cast<CoverageType>(fOutputCoverageType); + } + ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); } + + void internalInit(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, + const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&); + + // MSVS 2015 won't pack a bool with an unsigned. + using PackedBool = unsigned; + + PackedBool fIsInitializedWithProcessorSet : 1; + PackedBool fUsesLocalCoords : 1; + PackedBool fCompatibleWithCoverageAsAlpha : 1; + PackedBool fValidInputColor : 1; + unsigned fOutputCoverageType : 2; + unsigned fOutputColorType : 2; + unsigned fInitialColorProcessorsToEliminate : 32 - 8; + + GrColor fInputColor; GrColor fKnownOutputColor; }; + GR_STATIC_ASSERT(sizeof(FragmentProcessorAnalysis) == 2 * sizeof(GrColor) + sizeof(uint32_t)); private: - const GrXPFactory* fXPFactory = nullptr; - SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors; - int fColorFragmentProcessorCnt; - enum Flags : uint32_t { + // This absurdly large limit allows FragmentProcessorAnalysis and this to pack fields together. + static constexpr int kMaxColorProcessors = SK_MaxU16; + + enum Flags : uint16_t { kUseDistanceVectorField_Flag = 0x1, kDisableOutputConversionToSRGB_Flag = 0x2, kAllowSRGBInputs_Flag = 0x4 }; - uint32_t fFlags; + + const GrXPFactory* fXPFactory = nullptr; + SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors; + uint16_t fColorFragmentProcessorCnt; + uint16_t fFlags; }; #endif diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 051af824b0..7a6abe0e73 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1714,7 +1714,7 @@ uint32_t GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuild } GrProcessorSet::FragmentProcessorAnalysis analysis; - op->analyzeProcessors(&analysis, pipelineBuilder.processors(), appliedClip, *this->caps()); + op->analyzeProcessors(&analysis, pipelineBuilder.processors(), &appliedClip, *this->caps()); GrPipeline::InitArgs args; pipelineBuilder.getPipelineInitArgs(&args); diff --git a/src/gpu/ops/GrDrawOp.h b/src/gpu/ops/GrDrawOp.h index 18c218fc9a..62a16887ee 100644 --- a/src/gpu/ops/GrDrawOp.h +++ b/src/gpu/ops/GrDrawOp.h @@ -66,11 +66,11 @@ public: */ void analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis* analysis, const GrProcessorSet& processors, - const GrAppliedClip& appliedClip, + const GrAppliedClip* appliedClip, const GrCaps& caps) const { FragmentProcessorAnalysisInputs input; this->getFragmentProcessorAnalysisInputs(&input); - analysis->reset(*input.colorInput(), *input.coverageInput(), processors, appliedClip, caps); + analysis->init(*input.colorInput(), *input.coverageInput(), processors, appliedClip, caps); } protected: diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp index 89067cfe69..b09192e3bf 100644 --- a/tests/GrPorterDuffTest.cpp +++ b/tests/GrPorterDuffTest.cpp @@ -969,7 +969,7 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const GrProcessorSet::FragmentProcessorAnalysis analysis; GrAppliedClip clip(SkRect::MakeLargest()); - testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), clip, caps); + testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), &clip, caps); SkASSERT(analysis.hasKnownOutputColor()); SkASSERT(analysis.hasLCDCoverage()); |