aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/GrProcessorSet.cpp75
-rw-r--r--src/gpu/GrProcessorSet.h105
-rw-r--r--src/gpu/GrRenderTargetContext.cpp2
-rw-r--r--src/gpu/ops/GrDrawOp.h4
-rw-r--r--tests/GrPorterDuffTest.cpp2
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());