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 GrTessellatePathOp_DEFINED
9#define GrTessellatePathOp_DEFINED
10
11#include "src/gpu/ops/GrDrawOp.h"
12
13class GrAppliedHardClip;
14class GrFillPathShader;
15class GrStencilPathShader;
16
17// Renders paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by
18// GPU tessellation shaders. This Op doesn't apply analytic AA, so it requires a render target that
19// supports either MSAA or mixed samples if AA is desired.
20class GrTessellatePathOp : public GrDrawOp {
21public:
22 enum class Flags {
23 kNone = 0,
24 kStencilOnly = (1 << 0),
25 kWireframe = (1 << 1)
26 };
27
28private:
29 DEFINE_OP_CLASS_ID
30
31 GrTessellatePathOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
32 GrAAType aaType, Flags flags = Flags::kNone)
33 : GrDrawOp(ClassID())
34 , fFlags(flags)
35 , fViewMatrix(viewMatrix)
36 , fPath(path)
37 , fAAType(aaType)
38 , fColor(paint.getColor4f())
39 , fProcessors(std::move(paint)) {
40 SkRect devBounds;
41 fViewMatrix.mapRect(&devBounds, path.getBounds());
42 this->setBounds(devBounds, HasAABloat(GrAAType::kCoverage == fAAType), IsHairline::kNo);
43 }
44
45 const char* name() const override { return "GrTessellatePathOp"; }
46 void visitProxies(const VisitProxyFunc& fn) const override { fProcessors.visitProxies(fn); }
47 GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
48 bool hasMixedSampledCoverage,
49 GrClampType clampType) override {
50 return fProcessors.finalize(
51 fColor, GrProcessorAnalysisCoverage::kNone, clip, &GrUserStencilSettings::kUnused,
52 hasMixedSampledCoverage, caps, clampType, &fColor);
53 }
54
55 FixedFunctionFlags fixedFunctionFlags() const override;
56 void onPrePrepare(GrRecordingContext*,
57 const GrSurfaceProxyView* writeView,
58 GrAppliedClip*,
59 const GrXferProcessor::DstProxyView&) override;
60 void onPrepare(GrOpFlushState* state) override;
61 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
62
63 void drawStencilPass(GrOpFlushState*);
64 void drawCoverPass(GrOpFlushState*);
65
66 const Flags fFlags;
67 const SkMatrix fViewMatrix;
68 const SkPath fPath;
69 const GrAAType fAAType;
70 SkPMColor4f fColor;
71 GrProcessorSet fProcessors;
72
73 // These path shaders get created during onPrepare for drawing the below path vertex data.
74 //
75 // If fFillPathShader is null, then we just stencil the full path using fStencilPathShader and
76 // fCubicInstanceBuffer, and then fill it using a simple bounding box.
77 //
78 // If fFillPathShader is not null, then we fill the path using it plus cubic hulls from
79 // fCubicInstanceBuffer instead of a bounding box.
80 //
81 // If fFillPathShader is not null and fStencilPathShader *is* null, then the vertex data
82 // contains non-overlapping path geometry that can be drawn directly to the final render target.
83 // We only need to stencil curves from fCubicInstanceBuffer, and then draw the rest of the path
84 // directly.
85 GrStencilPathShader* fStencilPathShader = nullptr;
86 GrFillPathShader* fFillPathShader = nullptr;
87
88 // The "path vertex data" is made up of cubic wedges or inner polygon triangles (either red book
89 // style or fully tessellated). The geometry is generated by
90 // GrPathParser::EmitCenterWedgePatches, GrPathParser::EmitInnerPolygonTriangles,
91 // or GrTriangulator::PathToTriangles.
92 sk_sp<const GrBuffer> fPathVertexBuffer;
93 int fBasePathVertex;
94 int fPathVertexCount;
95
96 // The cubic instance buffer defines standalone cubics to tessellate into the stencil buffer, in
97 // addition to the above path geometry.
98 sk_sp<const GrBuffer> fCubicInstanceBuffer;
99 int fBaseCubicInstance;
100 int fCubicInstanceCount;
101
102 friend class GrOpMemoryPool; // For ctor.
103};
104
105GR_MAKE_BITFIELD_CLASS_OPS(GrTessellatePathOp::Flags);
106
107#endif
108