Add dynamic stroke attribs to tessellated stroking
Allows us to batch together strokes that have different SkStrokeRecs.
Bug: chromium:1172543
Bug: skia:10419
Change-Id: I11dc01e60bc17a6bb3c3b635f9edb2944a2f2edc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/369579
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.h b/src/gpu/tessellate/GrStrokeTessellateOp.h
index 4a63d0a..2278fbc 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.h
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.h
@@ -12,37 +12,61 @@
#include "src/gpu/GrSTArenaList.h"
#include "src/gpu/ops/GrMeshDrawOp.h"
#include "src/gpu/tessellate/GrPathShader.h"
+#include "src/gpu/tessellate/GrStrokeTessellateShader.h"
class GrRecordingContext;
// Prepares GPU data for, and then draws a stroke's tessellated geometry.
class GrStrokeTessellator {
public:
- // Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
- virtual void prepare(GrMeshDrawOp::Target*, const SkMatrix&, const GrSTArenaList<SkPath>&,
- const SkStrokeRec&, int totalCombinedVerbCnt) = 0;
+ using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
- // Issues draw calls for the tessellated stroie. The caller is responsible for binding its
+ GrStrokeTessellator(ShaderFlags shaderFlags) : fShaderFlags(shaderFlags) {}
+
+ struct PathStroke {
+ PathStroke(const SkPath& path, const SkStrokeRec& stroke) : fPath(path), fStroke(stroke) {}
+ SkPath fPath;
+ SkStrokeRec fStroke;
+ };
+
+ // Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
+ virtual void prepare(GrMeshDrawOp::Target*, const SkMatrix&, const GrSTArenaList<PathStroke>&,
+ int totalCombinedVerbCnt) = 0;
+
+ // Issues draw calls for the tessellated stroke. The caller is responsible for binding its
// desired pipeline ahead of time.
virtual void draw(GrOpFlushState*) const = 0;
virtual ~GrStrokeTessellator() {}
-};
-
-// Base class for ops that render opaque, constant-color strokes by linearizing them into sorted
-// "parametric" and "radial" edges. See GrStrokeTessellateShader.
-class GrStrokeTessellateOp : public GrDrawOp {
-public:
- // The provided matrix must be a similarity matrix for the time being. This is so we can
- // bootstrap this Op on top of GrStrokeGeometry with minimal modifications.
- //
- // Patches can overlap, so until a stencil technique is implemented, the provided paint must be
- // a constant blended color.
- GrStrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
protected:
+ const ShaderFlags fShaderFlags;
+};
+
+// Renders strokes by linearizing them into sorted "parametric" and "radial" edges. See
+// GrStrokeTessellateShader.
+class GrStrokeTessellateOp : public GrDrawOp {
+public:
+ GrStrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
+
+private:
+ using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
+ using PathStroke = GrStrokeTessellator::PathStroke;
DEFINE_OP_CLASS_ID
+ SkStrokeRec& headStroke() { return fPathStrokeList.head().fStroke; }
+
+ // 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
+ // have many verbs.
+ constexpr static int kMaxVerbsToEnableDynamicState = 50;
+ return (fShaderFlags & dynamicState) ||
+ (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
+ }
+
const char* name() const override { return "GrStrokeTessellateOp"; }
void visitProxies(const VisitProxyFunc& fn) const override;
FixedFunctionFlags fixedFunctionFlags() const override;
@@ -63,14 +87,13 @@
const GrAAType fAAType;
const SkMatrix fViewMatrix;
- const SkStrokeRec fStroke;
SkPMColor4f fColor;
bool fNeedsStencil = false;
GrProcessorSet fProcessors;
- GrSTArenaList<SkPath> fPathList;
+ ShaderFlags fShaderFlags = ShaderFlags::kNone;
+ GrSTArenaList<PathStroke> fPathStrokeList;
int fTotalCombinedVerbCnt = 0;
- bool fHasConics = false;
GrStrokeTessellator* fTessellator = nullptr;
const GrProgramInfo* fStencilProgram = nullptr; // Only used if the stroke has transparency.