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