blob: feb2f7868ae4f3b681f11c302bdbe9520a79f175 [file] [log] [blame]
Chris Dalton0e543092020-11-03 14:09:16 -07001/*
2 * Copyright 2020 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Chris Dalton05007df2021-02-04 00:24:52 -07008#ifndef GrStrokeTessellateOp_DEFINED
9#define GrStrokeTessellateOp_DEFINED
Chris Dalton0e543092020-11-03 14:09:16 -070010
11#include "include/core/SkStrokeRec.h"
Chris Dalton22241002021-02-04 09:47:40 -070012#include "src/gpu/ops/GrMeshDrawOp.h"
13#include "src/gpu/tessellate/GrPathShader.h"
Chris Dalton42582fc2021-02-18 11:29:49 -070014#include "src/gpu/tessellate/GrStrokeTessellateShader.h"
Chris Dalton0e543092020-11-03 14:09:16 -070015
Chris Dalton22241002021-02-04 09:47:40 -070016class GrRecordingContext;
17
18// Prepares GPU data for, and then draws a stroke's tessellated geometry.
19class GrStrokeTessellator {
20public:
Chris Dalton42582fc2021-02-18 11:29:49 -070021 using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
Chris Dalton22241002021-02-04 09:47:40 -070022
Chris Daltoned826862021-02-22 12:01:12 -070023 struct PathStrokeList {
24 PathStrokeList(const SkPath& path, const SkStrokeRec& stroke, const SkPMColor4f& color)
Chris Dalton1017a352021-02-18 15:22:54 -070025 : fPath(path), fStroke(stroke), fColor(color) {}
Chris Dalton42582fc2021-02-18 11:29:49 -070026 SkPath fPath;
27 SkStrokeRec fStroke;
Chris Dalton1017a352021-02-18 15:22:54 -070028 SkPMColor4f fColor;
Chris Daltoned826862021-02-22 12:01:12 -070029 PathStrokeList* fNext = nullptr;
Chris Dalton42582fc2021-02-18 11:29:49 -070030 };
31
Chris Daltoned826862021-02-22 12:01:12 -070032 GrStrokeTessellator(ShaderFlags shaderFlags, PathStrokeList* pathStrokeList)
33 : fShaderFlags(shaderFlags), fPathStrokeList(pathStrokeList) {}
Chris Dalton82094cd2021-02-19 01:11:27 -070034
Chris Dalton42582fc2021-02-18 11:29:49 -070035 // Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
Chris Dalton82094cd2021-02-19 01:11:27 -070036 virtual void prepare(GrMeshDrawOp::Target*, const SkMatrix&) = 0;
Chris Dalton42582fc2021-02-18 11:29:49 -070037
38 // Issues draw calls for the tessellated stroke. The caller is responsible for binding its
Chris Dalton22241002021-02-04 09:47:40 -070039 // desired pipeline ahead of time.
40 virtual void draw(GrOpFlushState*) const = 0;
41
42 virtual ~GrStrokeTessellator() {}
Chris Dalton0e543092020-11-03 14:09:16 -070043
Chris Dalton22241002021-02-04 09:47:40 -070044protected:
Chris Dalton42582fc2021-02-18 11:29:49 -070045 const ShaderFlags fShaderFlags;
Chris Daltoned826862021-02-22 12:01:12 -070046 PathStrokeList* fPathStrokeList;
Chris Dalton42582fc2021-02-18 11:29:49 -070047};
48
49// Renders strokes by linearizing them into sorted "parametric" and "radial" edges. See
50// GrStrokeTessellateShader.
51class GrStrokeTessellateOp : public GrDrawOp {
52public:
53 GrStrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
54
55private:
56 using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
Chris Daltoned826862021-02-22 12:01:12 -070057 using PathStrokeList = GrStrokeTessellator::PathStrokeList;
Chris Dalton22241002021-02-04 09:47:40 -070058 DEFINE_OP_CLASS_ID
59
Chris Daltoned826862021-02-22 12:01:12 -070060 SkStrokeRec& headStroke() { return fPathStrokeList.fStroke; }
61 SkPMColor4f& headColor() { return fPathStrokeList.fColor; }
Chris Dalton82094cd2021-02-19 01:11:27 -070062 GrStrokeTessellateOp* nextInChain() const {
63 return static_cast<GrStrokeTessellateOp*>(this->GrDrawOp::nextInChain());
64 }
Chris Dalton42582fc2021-02-18 11:29:49 -070065
Chris Dalton1017a352021-02-18 15:22:54 -070066 // Returns whether it is a good tradeoff to use the dynamic states flagged in the given
67 // bitfield. Dynamic states improve batching, but if they aren't already enabled, they come at
68 // the cost of having to write out more data with each patch or instance.
69 bool shouldUseDynamicStates(ShaderFlags neededDynamicStates) const {
70 // Use the dynamic states if either (1) they are all already enabled anyway, or (2) we don't
Chris Dalton42582fc2021-02-18 11:29:49 -070071 // have many verbs.
72 constexpr static int kMaxVerbsToEnableDynamicState = 50;
Chris Dalton1017a352021-02-18 15:22:54 -070073 bool anyStateDisabled = (bool)(~fShaderFlags & neededDynamicStates);
74 bool allStatesEnabled = !anyStateDisabled;
75 return allStatesEnabled || (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
76 }
77
78 bool canUseHardwareTessellation(const GrCaps& caps) {
79 SkASSERT(!fStencilProgram && !fFillProgram); // Ensure we haven't std::moved fProcessors.
80 // Our back door for HW tessellation shaders isn't currently capable of passing varyings to
81 // the fragment shader, so if the processors have varyings we need to use indirect draws.
82 return caps.shaderCaps()->tessellationSupport() && !fProcessors.usesVaryingCoords();
Chris Dalton42582fc2021-02-18 11:29:49 -070083 }
84
Chris Dalton05007df2021-02-04 00:24:52 -070085 const char* name() const override { return "GrStrokeTessellateOp"; }
Chris Daltonb0643342020-12-15 01:04:12 -070086 void visitProxies(const VisitProxyFunc& fn) const override;
Chris Dalton0e543092020-11-03 14:09:16 -070087 FixedFunctionFlags fixedFunctionFlags() const override;
88 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
89 bool hasMixedSampledCoverage, GrClampType) override;
90 CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) override;
91
Chris Dalton22241002021-02-04 09:47:40 -070092 // Creates the tessellator and the stencil/fill program(s) we will use with it.
93 void prePrepareTessellator(GrPathShader::ProgramArgs&&, GrAppliedClip&&);
Chris Dalton0e543092020-11-03 14:09:16 -070094
Chris Dalton22241002021-02-04 09:47:40 -070095 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
96 const GrXferProcessor::DstProxyView&, GrXferBarrierFlags,
97 GrLoadOp colorLoadOp) override;
Chris Dalton0e543092020-11-03 14:09:16 -070098
Chris Dalton22241002021-02-04 09:47:40 -070099 void onPrepare(GrOpFlushState*) override;
Chris Dalton0e543092020-11-03 14:09:16 -0700100
Chris Dalton22241002021-02-04 09:47:40 -0700101 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
Chris Dalton06b52ad2020-12-15 10:01:35 -0700102
Chris Dalton0e543092020-11-03 14:09:16 -0700103 const GrAAType fAAType;
104 const SkMatrix fViewMatrix;
Chris Dalton42582fc2021-02-18 11:29:49 -0700105 ShaderFlags fShaderFlags = ShaderFlags::kNone;
Chris Daltoned826862021-02-22 12:01:12 -0700106 PathStrokeList fPathStrokeList;
107 PathStrokeList** fPathStrokeTail = &fPathStrokeList.fNext;
Chris Dalton7b807262020-12-10 10:22:50 -0700108 int fTotalCombinedVerbCnt = 0;
Chris Dalton1017a352021-02-18 15:22:54 -0700109 GrProcessorSet fProcessors;
110 bool fNeedsStencil = false;
Chris Dalton0e543092020-11-03 14:09:16 -0700111
Chris Dalton22241002021-02-04 09:47:40 -0700112 GrStrokeTessellator* fTessellator = nullptr;
113 const GrProgramInfo* fStencilProgram = nullptr; // Only used if the stroke has transparency.
Chris Dalton55abaf52020-12-08 10:25:13 -0700114 const GrProgramInfo* fFillProgram = nullptr;
Chris Dalton0e543092020-11-03 14:09:16 -0700115};
116
117#endif