Revert "Revert "Create GrXferProcessor while doing GrProcessorSet analysis.""
This reverts commit 5dac9b3b5bf7e9c06c207cb92e257535c7d9ec95.
Bug: skia:
Change-Id: I3db2ec6776eb10c1f863b3992a2c8048c54b130f
Reviewed-on: https://skia-review.googlesource.com/12620
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrProcessorSet.h b/src/gpu/GrProcessorSet.h
index 39ba013..072d238 100644
--- a/src/gpu/GrProcessorSet.h
+++ b/src/gpu/GrProcessorSet.h
@@ -14,6 +14,7 @@
#include "SkTemplates.h"
class GrAppliedClip;
+class GrXferProcessor;
class GrXPFactory;
class GrProcessorSet : private SkNoncopyable {
@@ -22,14 +23,6 @@
~GrProcessorSet();
- /**
- * If an op is recorded with this processor set then this must be called to ensure pending
- * reads and writes are propagated to resources referred to by the processors. Otherwise,
- * data hazards may occur.
- */
- void makePendingExecution();
- bool isPendingExecution() const { return SkToBool(kPendingExecution_Flag & fFlags); }
-
int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
int numCoverageFragmentProcessors() const {
return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
@@ -46,7 +39,10 @@
return fFragmentProcessors[idx + fColorFragmentProcessorCnt + fFragmentProcessorOffset];
}
- const GrXPFactory* xpFactory() const { return fXPFactory; }
+ const GrXferProcessor* xferProcessor() const {
+ SkASSERT(this->isFinalized());
+ return fXP.fProcessor;
+ }
bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
bool disableOutputConversionToSRGB() const {
@@ -54,74 +50,20 @@
}
bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
+ /** Comparisons are only legal on finalized processor sets. */
bool operator==(const GrProcessorSet& that) const;
bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
/**
- * This is used to track analysis of color and coverage values through the processors.
+ * This is used to report results of processor analysis when a processor set is finalized (see
+ * below).
*/
class Analysis {
public:
- /**
- * This constructor allows an op to record its initial color in an Analysis member and then
- * 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 Analysis(GrColor initialColor) : Analysis() {
- fInputColor = initialColor;
- fValidInputColor = true;
- }
+ Analysis(const Analysis&) = default;
+ Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; }
- Analysis()
- : fIsInitializedWithProcessorSet(false)
- , fCompatibleWithCoverageAsAlpha(true)
- , fValidInputColor(false)
- , fRequiresDstTexture(false)
- , fCanCombineOverlappedStencilAndCover(true)
- , fIgnoresInputColor(false)
- , fRequiresBarrierBetweenOverlappingDraws(false)
- , fOutputCoverageType(static_cast<unsigned>(GrProcessorAnalysisCoverage::kNone))
- , fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
- , fInitialColorProcessorsToEliminate(0) {}
-
- // This version is used by a unit test that assumes no clip and no fragment processors.
- Analysis(const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage, const GrXPFactory*,
- const GrCaps&);
-
- void init(const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage,
- const GrProcessorSet&, const GrAppliedClip*, const GrCaps&);
-
- bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; }
-
- /**
- * If the return is greater than or equal to zero then 'newInputColor' should be used as the
- * input color to the GrPipeline derived from this processor set, replacing the GrDrawOp's
- * initial color. If the return is less than zero then newInputColor has not been
- * modified and no modification need be made to the pipeline's input color by the op.
- */
- int getInputColorOverrideAndColorProcessorEliminationCount(GrColor* newInputColor) const {
- if (fValidInputColor) {
- *newInputColor = fInputColor;
- return fInitialColorProcessorsToEliminate;
- }
- SkASSERT(!fInitialColorProcessorsToEliminate);
- return -1;
- }
-
- /**
- * 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 isInitialized() const { return fIsInitialized; }
bool usesLocalCoords() const { return fUsesLocalCoords; }
bool requiresDstTexture() const { return fRequiresDstTexture; }
bool canCombineOverlappedStencilAndCover() const {
@@ -131,60 +73,54 @@
return fRequiresBarrierBetweenOverlappingDraws;
}
bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
- bool isInputColorIgnored() const { return fIgnoresInputColor; }
- GrProcessorAnalysisCoverage outputCoverage() const {
- return static_cast<GrProcessorAnalysisCoverage>(fOutputCoverageType);
- }
- GrProcessorAnalysisColor outputColor() const {
- switch (this->outputColorType()) {
- case ColorType::kConstant:
- return fKnownOutputColor;
- case ColorType::kOpaque:
- return GrProcessorAnalysisColor::Opaque::kYes;
- case ColorType::kUnknown:
- return GrProcessorAnalysisColor::Opaque::kNo;
- }
- SkFAIL("Unexpected color type");
- return GrProcessorAnalysisColor::Opaque::kNo;
+
+ bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; }
+ bool inputColorIsOverridden() const {
+ return fInputColorType == kOverridden_InputColorType;
}
private:
- enum class ColorType : unsigned { kUnknown, kConstant, kOpaque };
+ enum InputColorType : uint32_t {
+ kOriginal_InputColorType,
+ kOverridden_InputColorType,
+ kIgnored_InputColorType
+ };
- ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }
+ // MSVS 2015 won't pack different underlying types
+ using PackedBool = uint32_t;
+ using PackedInputColorType = uint32_t;
- void internalInit(const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage,
- 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;
PackedBool fRequiresDstTexture : 1;
PackedBool fCanCombineOverlappedStencilAndCover : 1;
- // These could be removed if we created the XP from the XPFactory when doing analysis.
- PackedBool fIgnoresInputColor : 1;
PackedBool fRequiresBarrierBetweenOverlappingDraws : 1;
- unsigned fOutputCoverageType : 2;
- unsigned fOutputColorType : 2;
-
- unsigned fInitialColorProcessorsToEliminate : 32 - 12;
-
- GrColor fInputColor;
- // This could be removed if we created the XP from the XPFactory when doing analysis.
- GrColor fKnownOutputColor;
+ PackedBool fIsInitialized : 1;
+ PackedInputColorType fInputColorType : 2;
friend class GrProcessorSet;
};
- GR_STATIC_ASSERT(sizeof(Analysis) == 2 * sizeof(GrColor) + sizeof(uint32_t));
+ GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t));
- void analyzeAndEliminateFragmentProcessors(Analysis*,
- const GrProcessorAnalysisColor& colorInput,
- const GrProcessorAnalysisCoverage coverageInput,
- const GrAppliedClip*, const GrCaps&);
+ /**
+ * This analyzes the processors given an op's input color and coverage as well as a clip. The
+ * state of the processor set may change to an equivalent but more optimal set of processors.
+ * This new state requires that the caller respect the returned 'inputColorOverride'. This is
+ * indicated by the returned Analysis's inputColorIsOverriden(). 'inputColorOverride' will not
+ * be written if the analysis does not override the input color.
+ *
+ * This must be called before the processor set is used to construct a GrPipeline and may only
+ * be called once.
+ *
+ * This also puts the processors in "pending execution" state and must be called when an op
+ * that owns a processor set is recorded to ensure pending and writes are propagated to
+ * resources referred to by the processors. Otherwise, data hazards may occur.
+ */
+ Analysis finalize(const GrProcessorAnalysisColor& colorInput,
+ const GrProcessorAnalysisCoverage coverageInput, const GrAppliedClip*,
+ bool isMixedSamples, const GrCaps&, GrColor* inputColorOverride);
+
+ bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }
private:
// This absurdly large limit allows Analysis and this to pack fields together.
@@ -194,11 +130,22 @@
kUseDistanceVectorField_Flag = 0x1,
kDisableOutputConversionToSRGB_Flag = 0x2,
kAllowSRGBInputs_Flag = 0x4,
- kPendingExecution_Flag = 0x8
+ kFinalized_Flag = 0x8
};
- const GrXPFactory* fXPFactory = nullptr;
+ union XP {
+ XP(const GrXPFactory* factory) : fFactory(factory) {}
+ const GrXPFactory* fFactory;
+ const GrXferProcessor* fProcessor;
+ };
+
+ const GrXPFactory* xpFactory() const {
+ SkASSERT(!this->isFinalized());
+ return fXP.fFactory;
+ }
+
SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
+ XP fXP;
uint8_t fColorFragmentProcessorCnt;
uint8_t fFragmentProcessorOffset = 0;
uint8_t fFlags;