• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #ifndef StrokeTessellateOp_DEFINED
9 #define StrokeTessellateOp_DEFINED
10 
11 #include "include/core/SkStrokeRec.h"
12 #include "src/gpu/ganesh/ops/GrDrawOp.h"
13 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h"
14 #include "src/gpu/ganesh/tessellate/StrokeTessellator.h"
15 
16 class GrRecordingContext;
17 class GrStrokeTessellationShader;
18 
19 namespace skgpu::v1 {
20 
21 // Renders strokes by linearizing them into sorted "parametric" and "radial" edges. See
22 // GrStrokeTessellationShader.
23 class StrokeTessellateOp final : public GrDrawOp {
24 public:
25     StrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
26 
27 private:
28     using PatchAttribs = StrokeTessellator::PatchAttribs;
29     using PathStrokeList = StrokeTessellator::PathStrokeList;
30 
31     DEFINE_OP_CLASS_ID
32 
headStroke()33     SkStrokeRec& headStroke() { return fPathStrokeList.fStroke; }
headColor()34     SkPMColor4f& headColor() { return fPathStrokeList.fColor; }
35 
36     // Returns whether it is a good tradeoff to use the dynamic states flagged in the given
37     // bitfield. Dynamic states improve batching, but if they aren't already enabled, they come at
38     // the cost of having to write out more data with each patch or instance.
shouldUseDynamicStates(PatchAttribs neededDynamicStates)39     bool shouldUseDynamicStates(PatchAttribs neededDynamicStates) const {
40         // Use the dynamic states if either (1) they are all already enabled anyway, or (2) we don't
41         // have many verbs.
42         constexpr static int kMaxVerbsToEnableDynamicState = 50;
43         bool anyStateDisabled = (bool)(~fPatchAttribs & neededDynamicStates);
44         bool allStatesEnabled = !anyStateDisabled;
45         return allStatesEnabled || (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
46     }
47 
name()48     const char* name() const override { return "StrokeTessellateOp"; }
49     void visitProxies(const GrVisitProxyFunc&) const override;
usesMSAA()50     bool usesMSAA() const override { return fAAType == GrAAType::kMSAA; }
51     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
usesStencil()52     bool usesStencil() const override {
53         // This must be called after finalize(). fNeedsStencil can change in finalize().
54         SkASSERT(fProcessors.isFinalized());
55         return fNeedsStencil;
56     }
57     CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) override;
58 
59     // Creates the tessellator and the stencil/fill program(s) we will use with it.
60     void prePrepareTessellator(GrTessellationShader::ProgramArgs&&, GrAppliedClip&&);
61 
62     void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
63                       const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
64 
65     void onPrepare(GrOpFlushState*) override;
66 
67     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
68 
69     const GrAAType fAAType;
70     const SkMatrix fViewMatrix;
71     PatchAttribs fPatchAttribs = PatchAttribs::kNone;
72     PathStrokeList fPathStrokeList;
73     PathStrokeList** fPathStrokeTail = &fPathStrokeList.fNext;
74     int fTotalCombinedVerbCnt = 0;
75     GrProcessorSet fProcessors;
76     bool fNeedsStencil;
77 
78     StrokeTessellator* fTessellator = nullptr;
79     GrStrokeTessellationShader* fTessellationShader;
80     const GrProgramInfo* fStencilProgram = nullptr;  // Only used if the stroke has transparency.
81     const GrProgramInfo* fFillProgram = nullptr;
82 };
83 
84 } // namespace skgpu::v1
85 
86 #endif // StrokeTessellateOp_DEFINED
87