aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-03-13 09:11:58 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-03-13 14:26:52 +0000
commit8d2f90b37b9caa120599a71530545dd11853c0bc (patch)
tree627b9063ec6e3367084e9723a9683c8c7cece6dc
parent766fcbb01cece88ad88808581b4ecc5a5cb60e01 (diff)
Changes to GrProcessorSet::FragmentProcessorAnalysis to prepare for deferred pipeline creation.
This compacts the object so that it is more efficient for ops to store it. It also adds a new constructor and query that will allow ops to use the analysis to also store the GrPaint's color. This has the side effect of limiting the number of color processors on a GrProcessorSet to 64K which is just under 64K more than should ever be needed. Change-Id: I4e6bc8e3f81bb2ff6a73af685beb6fb928a3de67 Reviewed-on: https://skia-review.googlesource.com/8972 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
-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());