/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "GrProcessorSet.h" #include "GrAppliedClip.h" #include "GrCaps.h" #include "GrPipelineAnalysis.h" GrProcessorSet::GrProcessorSet(GrPaint&& paint) { fXPFactory = paint.fXPFactory; fFlags = 0; 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; } if (paint.getAllowSRGBInputs()) { fFlags |= kAllowSRGBInputs_Flag; } } GrProcessorSet::~GrProcessorSet() { for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) { if (this->isPendingExecution()) { fFragmentProcessors[i]->completedExecution(); } else { fFragmentProcessors[i]->unref(); } } } void GrProcessorSet::makePendingExecution() { SkASSERT(!(kPendingExecution_Flag & fFlags)); fFlags |= kPendingExecution_Flag; for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) { fFragmentProcessors[i]->addPendingExecution(); fFragmentProcessors[i]->unref(); } } bool GrProcessorSet::operator==(const GrProcessorSet& that) const { int fpCount = this->numFragmentProcessors(); if (((fFlags ^ that.fFlags) & ~kPendingExecution_Flag) || fpCount != that.numFragmentProcessors() || fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) { return false; } for (int i = 0; i < fpCount; ++i) { int a = i + fFragmentProcessorOffset; int b = i + that.fFragmentProcessorOffset; if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) { return false; } } if (fXPFactory != that.fXPFactory) { return false; } return true; } ////////////////////////////////////////////////////////////////////////////// void GrProcessorSet::FragmentProcessorAnalysis::internalInit( const GrPipelineAnalysisColor& colorInput, const GrPipelineAnalysisCoverage coverageInput, const GrProcessorSet& processors, const GrFragmentProcessor* clipFP, const GrCaps& caps) { GrColorFragmentProcessorAnalysis colorInfo(colorInput); fCompatibleWithCoverageAsAlpha = GrPipelineAnalysisCoverage::kLCD != coverageInput; fValidInputColor = colorInput.isConstant(&fInputColor); const GrFragmentProcessor* const* fps = processors.fFragmentProcessors.get() + processors.fFragmentProcessorOffset; colorInfo.analyzeProcessors(fps, processors.fColorFragmentProcessorCnt); fCompatibleWithCoverageAsAlpha &= colorInfo.allProcessorsCompatibleWithCoverageAsAlpha(); fps += processors.fColorFragmentProcessorCnt; int n = processors.numCoverageFragmentProcessors(); bool hasCoverageFP = n > 0; fUsesLocalCoords = colorInfo.usesLocalCoords(); for (int i = 0; i < n; ++i) { if (!fps[i]->compatibleWithCoverageAsAlpha()) { fCompatibleWithCoverageAsAlpha = false; // Other than tests that exercise atypical behavior we expect all coverage FPs to be // compatible with the coverage-as-alpha optimization. GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n"); } fUsesLocalCoords |= fps[i]->usesLocalCoords(); } if (clipFP) { fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha(); fUsesLocalCoords |= clipFP->usesLocalCoords(); hasCoverageFP = true; } fInitialColorProcessorsToEliminate = colorInfo.initialProcessorsToEliminate(&fInputColor); fValidInputColor |= SkToBool(fInitialColorProcessorsToEliminate); GrPipelineAnalysisColor outputColor = colorInfo.outputColor(); if (outputColor.isConstant(&fKnownOutputColor)) { fOutputColorType = static_cast<unsigned>(outputColor.isOpaque() ? ColorType::kOpaqueConstant : ColorType::kConstant); } else if (outputColor.isOpaque()) { fOutputColorType = static_cast<unsigned>(ColorType::kOpaque); } else { fOutputColorType = static_cast<unsigned>(ColorType::kUnknown); } if (GrPipelineAnalysisCoverage::kLCD == coverageInput) { fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kLCD); } else if (hasCoverageFP || GrPipelineAnalysisCoverage::kSingleChannel == coverageInput) { fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kSingleChannel); } else { fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kNone); } } void GrProcessorSet::FragmentProcessorAnalysis::init(const GrPipelineAnalysisColor& colorInput, const GrPipelineAnalysisCoverage 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 GrPipelineAnalysisColor& colorInput, const GrPipelineAnalysisCoverage coverageInput, const GrCaps& caps) : FragmentProcessorAnalysis() { this->internalInit(colorInput, coverageInput, GrProcessorSet(GrPaint()), nullptr, caps); } void GrProcessorSet::analyzeAndEliminateFragmentProcessors( FragmentProcessorAnalysis* analysis, const GrPipelineAnalysisColor& colorInput, const GrPipelineAnalysisCoverage coverageInput, const GrAppliedClip* clip, const GrCaps& caps) { analysis->init(colorInput, coverageInput, *this, clip, caps); if (analysis->fInitialColorProcessorsToEliminate > 0) { for (unsigned i = 0; i < analysis->fInitialColorProcessorsToEliminate; ++i) { if (this->isPendingExecution()) { fFragmentProcessors[i + fFragmentProcessorOffset]->completedExecution(); } else { fFragmentProcessors[i + fFragmentProcessorOffset]->unref(); } fFragmentProcessors[i + fFragmentProcessorOffset] = nullptr; } fFragmentProcessorOffset += analysis->fInitialColorProcessorsToEliminate; fColorFragmentProcessorCnt -= analysis->fInitialColorProcessorsToEliminate; SkASSERT(fFragmentProcessorOffset + fColorFragmentProcessorCnt <= fFragmentProcessors.count()); analysis->fInitialColorProcessorsToEliminate = 0; } }