1 /* 2 * Copyright 2021 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 #ifndef PathStencilCoverOp_DEFINED 8 #define PathStencilCoverOp_DEFINED 9 10 #include "include/core/SkPath.h" 11 #include "include/core/SkRect.h" 12 #include "include/core/SkRefCnt.h" 13 #include "include/private/SkColorData.h" 14 #include "include/private/base/SkDebug.h" 15 #include "include/private/gpu/ganesh/GrTypesPriv.h" 16 #include "src/base/SkArenaAlloc.h" 17 #include "src/gpu/ganesh/GrBuffer.h" 18 #include "src/gpu/ganesh/GrCaps.h" 19 #include "src/gpu/ganesh/GrGpuBuffer.h" 20 #include "src/gpu/ganesh/GrPaint.h" 21 #include "src/gpu/ganesh/GrProcessorSet.h" 22 #include "src/gpu/ganesh/ops/GrDrawOp.h" 23 #include "src/gpu/ganesh/ops/GrOp.h" 24 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h" 25 #include "src/gpu/ganesh/tessellate/PathTessellator.h" 26 27 #include <utility> 28 29 class GrAppliedClip; 30 class GrDstProxyView; 31 class GrOpFlushState; 32 class GrProgramInfo; 33 class GrRecordingContext; 34 class GrSurfaceProxyView; 35 class SkMatrix; 36 enum class GrXferBarrierFlags; 37 enum class SkPathFillType; 38 39 namespace skgpu::ganesh { 40 41 enum class FillPathFlags; 42 43 // Draws paths using a standard Redbook "stencil then cover" method. Curves get linearized by either 44 // GPU tessellation shaders or indirect draws. This Op doesn't apply analytic AA, so it requires 45 // MSAA if AA is desired. 46 class PathStencilCoverOp final : public GrDrawOp { 47 private: 48 DEFINE_OP_CLASS_ID 49 50 using PathDrawList = PathTessellator::PathDrawList; 51 52 // If the path is inverse filled, drawBounds must be the entire backing store dimensions of the 53 // render target. PathStencilCoverOp(SkArenaAlloc * arena,const SkMatrix & viewMatrix,const SkPath & path,GrPaint && paint,GrAAType aaType,FillPathFlags pathFlags,const SkRect & drawBounds)54 PathStencilCoverOp(SkArenaAlloc* arena, 55 const SkMatrix& viewMatrix, 56 const SkPath& path, 57 GrPaint&& paint, 58 GrAAType aaType, 59 FillPathFlags pathFlags, 60 const SkRect& drawBounds) 61 : GrDrawOp(ClassID()) 62 , fPathDrawList(arena->make<PathDrawList>(viewMatrix, path, SK_PMColor4fTRANSPARENT)) 63 , fTotalCombinedPathVerbCnt(path.countVerbs()) 64 , fPathCount(1) 65 , fPathFlags(pathFlags) 66 , fAAType(aaType) 67 , fColor(paint.getColor4f()) 68 , fProcessors(std::move(paint)) { 69 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo); 70 SkDEBUGCODE(fOriginalDrawBounds = drawBounds;) 71 } 72 73 // Constructs a PathStencilCoverOp from an existing draw list. 74 // FIXME: The only user of this method is the atlas. We should move the GrProgramInfos into 75 // PathTessellator so the atlas can use that directly instead of going through this class. PathStencilCoverOp(const PathDrawList * pathDrawList,int totalCombinedVerbCnt,int pathCount,GrPaint && paint,GrAAType aaType,FillPathFlags pathFlags,const SkRect & drawBounds)76 PathStencilCoverOp(const PathDrawList* pathDrawList, 77 int totalCombinedVerbCnt, 78 int pathCount, 79 GrPaint&& paint, 80 GrAAType aaType, 81 FillPathFlags pathFlags, 82 const SkRect& drawBounds) 83 : GrDrawOp(ClassID()) 84 , fPathDrawList(pathDrawList) 85 , fTotalCombinedPathVerbCnt(totalCombinedVerbCnt) 86 , fPathCount(pathCount) 87 , fPathFlags(pathFlags) 88 , fAAType(aaType) 89 , fColor(paint.getColor4f()) 90 , fProcessors(std::move(paint)) { 91 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo); 92 SkDEBUGCODE(fOriginalDrawBounds = drawBounds;) 93 } 94 name()95 const char* name() const override { return "PathStencilCoverOp"; } 96 void visitProxies(const GrVisitProxyFunc&) const override; 97 FixedFunctionFlags fixedFunctionFlags() const override; 98 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override; 99 100 // All paths in fPathDrawList are required to have the same fill type. pathFillType()101 SkPathFillType pathFillType() const { 102 return fPathDrawList->fPath.getFillType(); 103 } 104 105 // Chooses the rendering method we will use and creates the corresponding tessellator and 106 // stencil/cover programs. 107 void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&& clip); 108 109 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*, 110 const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override; 111 void onPrepare(GrOpFlushState*) override; 112 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; 113 114 const PathDrawList* fPathDrawList; 115 const int fTotalCombinedPathVerbCnt; 116 const int fPathCount; 117 const FillPathFlags fPathFlags; 118 const GrAAType fAAType; 119 SkPMColor4f fColor; 120 GrProcessorSet fProcessors; 121 SkDEBUGCODE(SkRect fOriginalDrawBounds;) 122 123 // Decided during prePreparePrograms. 124 PathTessellator* fTessellator = nullptr; 125 const GrProgramInfo* fStencilFanProgram = nullptr; 126 const GrProgramInfo* fStencilPathProgram = nullptr; 127 const GrProgramInfo* fCoverBBoxProgram = nullptr; 128 129 // Filled during onPrepare. 130 sk_sp<const GrBuffer> fFanBuffer; 131 int fFanBaseVertex = 0; 132 int fFanVertexCount = 0; 133 134 sk_sp<const GrBuffer> fBBoxBuffer; 135 int fBBoxBaseInstance = 0; 136 137 // Only used if sk_VertexID is not supported. 138 sk_sp<const GrGpuBuffer> fBBoxVertexBufferIfNoIDSupport; 139 140 friend class GrOp; // For ctor. 141 }; 142 143 } // namespace skgpu::ganesh 144 145 #endif // PathStencilCoverOp_DEFINED 146