Add a dynamic color attrib to hw tessellated stroking
Only adds color to the hardware tessellator. The indirect tessellator
reorders draws with is log2 binning, so we can't have different
colors.
Bug: chromium:1172543
Bug: skia:10419
Change-Id: I2a3700cd4572e8222002bfb028af05c6ec447708
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/369976
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.h b/src/gpu/tessellate/GrStrokeTessellateOp.h
index 2278fbc..42b8d45 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.h
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.h
@@ -24,9 +24,11 @@
GrStrokeTessellator(ShaderFlags shaderFlags) : fShaderFlags(shaderFlags) {}
struct PathStroke {
- PathStroke(const SkPath& path, const SkStrokeRec& stroke) : fPath(path), fStroke(stroke) {}
+ PathStroke(const SkPath& path, const SkStrokeRec& stroke, const SkPMColor4f& color)
+ : fPath(path), fStroke(stroke), fColor(color) {}
SkPath fPath;
SkStrokeRec fStroke;
+ SkPMColor4f fColor;
};
// Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
@@ -55,16 +57,25 @@
DEFINE_OP_CLASS_ID
SkStrokeRec& headStroke() { return fPathStrokeList.head().fStroke; }
+ SkPMColor4f& headColor() { return fPathStrokeList.head().fColor; }
- // Returns whether it is a good tradeoff to use the given dynamic state. Dynamic state improves
- // batching, but if it isn't already enabled, it comes at the cost of having to write out more
- // data with each patch or instance.
- bool shouldUseDynamicState(ShaderFlags dynamicState) const {
- // Use the dynamic state if either (1) the state is already enabled anyway, or (2) we don't
+ // Returns whether it is a good tradeoff to use the dynamic states flagged in the given
+ // bitfield. Dynamic states improve batching, but if they aren't already enabled, they come at
+ // the cost of having to write out more data with each patch or instance.
+ bool shouldUseDynamicStates(ShaderFlags neededDynamicStates) const {
+ // Use the dynamic states if either (1) they are all already enabled anyway, or (2) we don't
// have many verbs.
constexpr static int kMaxVerbsToEnableDynamicState = 50;
- return (fShaderFlags & dynamicState) ||
- (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
+ bool anyStateDisabled = (bool)(~fShaderFlags & neededDynamicStates);
+ bool allStatesEnabled = !anyStateDisabled;
+ return allStatesEnabled || (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
+ }
+
+ bool canUseHardwareTessellation(const GrCaps& caps) {
+ SkASSERT(!fStencilProgram && !fFillProgram); // Ensure we haven't std::moved fProcessors.
+ // Our back door for HW tessellation shaders isn't currently capable of passing varyings to
+ // the fragment shader, so if the processors have varyings we need to use indirect draws.
+ return caps.shaderCaps()->tessellationSupport() && !fProcessors.usesVaryingCoords();
}
const char* name() const override { return "GrStrokeTessellateOp"; }
@@ -87,13 +98,11 @@
const GrAAType fAAType;
const SkMatrix fViewMatrix;
- SkPMColor4f fColor;
- bool fNeedsStencil = false;
- GrProcessorSet fProcessors;
-
ShaderFlags fShaderFlags = ShaderFlags::kNone;
GrSTArenaList<PathStroke> fPathStrokeList;
int fTotalCombinedVerbCnt = 0;
+ GrProcessorSet fProcessors;
+ bool fNeedsStencil = false;
GrStrokeTessellator* fTessellator = nullptr;
const GrProgramInfo* fStencilProgram = nullptr; // Only used if the stroke has transparency.