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