1 /* 2 * Copyright 2019 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 PathInnerTriangulateOp_DEFINED 9 #define PathInnerTriangulateOp_DEFINED 10 11 #include "include/core/SkTypes.h" 12 13 #if !defined(SK_ENABLE_OPTIMIZE_SIZE) 14 15 #include "include/core/SkMatrix.h" 16 #include "include/core/SkPath.h" 17 #include "include/core/SkRefCnt.h" 18 #include "include/private/SkColorData.h" 19 #include "include/private/base/SkTArray.h" 20 #include "include/private/gpu/ganesh/GrTypesPriv.h" 21 #include "src/gpu/ganesh/GrBuffer.h" 22 #include "src/gpu/ganesh/GrCaps.h" 23 #include "src/gpu/ganesh/GrGpuBuffer.h" 24 #include "src/gpu/ganesh/GrPaint.h" 25 #include "src/gpu/ganesh/GrProcessorSet.h" 26 #include "src/gpu/ganesh/geometry/GrInnerFanTriangulator.h" 27 #include "src/gpu/ganesh/geometry/GrTriangulator.h" 28 #include "src/gpu/ganesh/ops/GrDrawOp.h" 29 #include "src/gpu/ganesh/ops/GrOp.h" 30 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h" 31 32 #include <utility> 33 34 class GrAppliedClip; 35 class GrDstProxyView; 36 class GrOpFlushState; 37 class GrPipeline; 38 class GrProgramInfo; 39 class GrRecordingContext; 40 class GrSurfaceProxyView; 41 enum class GrXferBarrierFlags; 42 struct GrUserStencilSettings; 43 struct SkRect; 44 45 namespace skgpu::ganesh { 46 47 class PathCurveTessellator; 48 enum class FillPathFlags; 49 50 // This op is a 3-pass twist on the standard Redbook "stencil then cover" algorithm: 51 // 52 // 1) Tessellate the path's outer curves into the stencil buffer. 53 // 2) Triangulate the path's inner fan and fill it with a stencil test against the curves. 54 // 3) Draw convex hulls around each curve that fill in remaining samples. 55 // 56 // In practice, a path's inner fan takes up a large majority of its pixels. So from a GPU load 57 // perspective, this op is effectively as fast as a single-pass algorithm. 58 class PathInnerTriangulateOp final : public GrDrawOp { 59 private: 60 DEFINE_OP_CLASS_ID 61 PathInnerTriangulateOp(const SkMatrix & viewMatrix,const SkPath & path,GrPaint && paint,GrAAType aaType,FillPathFlags pathFlags,const SkRect & drawBounds)62 PathInnerTriangulateOp(const SkMatrix& viewMatrix, 63 const SkPath& path, 64 GrPaint&& paint, 65 GrAAType aaType, 66 FillPathFlags pathFlags, 67 const SkRect& drawBounds) 68 : GrDrawOp(ClassID()) 69 , fPathFlags(pathFlags) 70 , fViewMatrix(viewMatrix) 71 , fPath(path) 72 , fAAType(aaType) 73 , fColor(paint.getColor4f()) 74 , fProcessors(std::move(paint)) { 75 SkASSERT(!fPath.isInverseFillType()); 76 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo); 77 } 78 name()79 const char* name() const override { return "PathInnerTriangulateOp"; } 80 void visitProxies(const GrVisitProxyFunc&) const override; 81 FixedFunctionFlags fixedFunctionFlags() const override; 82 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override; 83 84 // These calls set up the stencil & fill programs we will use prior to preparing and executing. 85 void pushFanStencilProgram(const GrTessellationShader::ProgramArgs&, 86 const GrPipeline* pipelineForStencils, const GrUserStencilSettings*); 87 void pushFanFillProgram(const GrTessellationShader::ProgramArgs&, const GrUserStencilSettings*); 88 void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&&); 89 90 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*, 91 const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override; 92 void onPrepare(GrOpFlushState*) override; 93 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; 94 95 const FillPathFlags fPathFlags; 96 const SkMatrix fViewMatrix; 97 const SkPath fPath; 98 const GrAAType fAAType; 99 SkPMColor4f fColor; 100 GrProcessorSet fProcessors; 101 102 // Triangulates the inner fan. 103 GrInnerFanTriangulator* fFanTriangulator = nullptr; 104 GrTriangulator::Poly* fFanPolys = nullptr; 105 GrInnerFanTriangulator::BreadcrumbTriangleList fFanBreadcrumbs; 106 107 // This pipeline is shared by all programs that do filling. 108 const GrPipeline* fPipelineForFills = nullptr; 109 110 // Tessellates the outer curves. 111 PathCurveTessellator* fTessellator = nullptr; 112 113 // Pass 1: Tessellate the outer curves into the stencil buffer. 114 const GrProgramInfo* fStencilCurvesProgram = nullptr; 115 116 // Pass 2: Fill the path's inner fan with a stencil test against the curves. (In extenuating 117 // circumstances this might require two separate draws.) 118 skia_private::STArray<2, const GrProgramInfo*> fFanPrograms; 119 120 // Pass 3: Draw convex hulls around each curve. 121 const GrProgramInfo* fCoverHullsProgram = nullptr; 122 123 // This buffer gets created by fFanTriangulator during onPrepare. 124 sk_sp<const GrBuffer> fFanBuffer; 125 int fBaseFanVertex = 0; 126 int fFanVertexCount = 0; 127 128 // Only used if sk_VertexID is not supported. 129 sk_sp<const GrGpuBuffer> fHullVertexBufferIfNoIDSupport; 130 131 friend class GrOp; // For ctor. 132 }; 133 134 } // namespace skgpu::ganesh 135 136 #endif // SK_ENABLE_OPTIMIZE_SIZE 137 138 #endif // PathInnerTriangulateOp_DEFINED 139