Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | List of all members
skgpu::ganesh::TessellationPathRenderer Class Referencefinal

#include <TessellationPathRenderer.h>

Inheritance diagram for skgpu::ganesh::TessellationPathRenderer:
skgpu::ganesh::PathRenderer SkRefCnt SkRefCntBase

Public Member Functions

const char * name () const override
 
- Public Member Functions inherited from skgpu::ganesh::PathRenderer
 PathRenderer ()=default
 
StencilSupport getStencilSupport (const GrStyledShape &shape) const
 
CanDrawPath canDrawPath (const CanDrawPathArgs &args) const
 
bool drawPath (const DrawPathArgs &args)
 
void stencilPath (const StencilPathArgs &args)
 
- Public Member Functions inherited from SkRefCntBase
 SkRefCntBase ()
 
virtual ~SkRefCntBase ()
 
bool unique () const
 
void ref () const
 
void unref () const
 

Static Public Member Functions

static bool IsSupported (const GrCaps &)
 

Private Member Functions

StencilSupport onGetStencilSupport (const GrStyledShape &) const override
 
CanDrawPath onCanDrawPath (const CanDrawPathArgs &) const override
 
bool onDrawPath (const DrawPathArgs &) override
 
void onStencilPath (const StencilPathArgs &) override
 

Additional Inherited Members

- Public Types inherited from skgpu::ganesh::PathRenderer
enum  StencilSupport { kNoSupport_StencilSupport , kStencilOnly_StencilSupport , kNoRestriction_StencilSupport }
 
enum class  CanDrawPath { kNo , kAsBackup , kYes }
 
- Static Protected Member Functions inherited from skgpu::ganesh::PathRenderer
static void GetPathDevBounds (const SkPath &path, SkISize devSize, const SkMatrix &matrix, SkRect *bounds)
 

Detailed Description

Definition at line 22 of file TessellationPathRenderer.h.

Member Function Documentation

◆ IsSupported()

bool skgpu::ganesh::TessellationPathRenderer::IsSupported ( const GrCaps caps)
static

Definition at line 73 of file TessellationPathRenderer.cpp.

73 {
74 return !caps.avoidStencilBuffers() &&
75 caps.drawInstancedSupport() &&
77}
bool avoidStencilBuffers() const
Definition GrCaps.h:139
bool drawInstancedSupport() const
Definition GrCaps.h:80
bool disableTessellationPathRenderer() const
Definition GrCaps.h:441

◆ name()

const char * skgpu::ganesh::TessellationPathRenderer::name ( ) const
inlineoverridevirtual

Implements skgpu::ganesh::PathRenderer.

Definition at line 26 of file TessellationPathRenderer.h.

26{ return "Tessellation"; }

◆ onCanDrawPath()

PathRenderer::CanDrawPath skgpu::ganesh::TessellationPathRenderer::onCanDrawPath ( const CanDrawPathArgs args) const
overrideprivatevirtual

Subclass implementation of canDrawPath()

Implements skgpu::ganesh::PathRenderer.

Definition at line 89 of file TessellationPathRenderer.cpp.

90 {
91 const GrStyledShape& shape = *args.fShape;
92 if (args.fAAType == GrAAType::kCoverage ||
93 shape.style().hasPathEffect() ||
94 args.fViewMatrix->hasPerspective() ||
96 !args.fProxy->canUseStencil(*args.fCaps)) {
97 return CanDrawPath::kNo;
98 }
99 if (!shape.style().isSimpleFill()) {
100 if (shape.inverseFilled()) {
101 return CanDrawPath::kNo;
102 }
103 if (shape.style().strokeRec().getWidth() * args.fViewMatrix->getMaxScale() > 10000) {
104 // crbug.com/1266446 -- Don't draw massively wide strokes with the tessellator. Since we
105 // outset the viewport by stroke width for pre-chopping, astronomically wide strokes can
106 // result in an astronomical viewport size, and therefore an exponential explosion chops
107 // and memory usage. It is also simply inefficient to tessellate these strokes due to
108 // the number of radial edges required. We're better off just converting them to a path
109 // after a certain point.
110 return CanDrawPath::kNo;
111 }
112 }
113 if (args.fHasUserStencilSettings) {
114 // Non-convex paths and strokes use the stencil buffer internally, so they can't support
115 // draws with stencil settings.
116 if (!shape.style().isSimpleFill() || !shape.knownToBeConvex() || shape.inverseFilled()) {
117 return CanDrawPath::kNo;
118 }
119 }
120 return CanDrawPath::kYes;
121}
bool hasPathEffect() const
Definition GrStyle.h:122
bool isSimpleFill() const
Definition GrStyle.h:114
const SkStrokeRec & strokeRec() const
Definition GrStyle.h:140
bool knownToBeConvex() const
bool inverseFilled() const
const GrStyle & style() const
Style getStyle() const
@ kStrokeAndFill_Style
Definition SkStrokeRec.h:36
SkScalar getWidth() const
Definition SkStrokeRec.h:42
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args

◆ onDrawPath()

bool skgpu::ganesh::TessellationPathRenderer::onDrawPath ( const DrawPathArgs args)
overrideprivatevirtual

Subclass implementation of drawPath()

Implements skgpu::ganesh::PathRenderer.

Definition at line 123 of file TessellationPathRenderer.cpp.

123 {
124 auto sdc = args.fSurfaceDrawContext;
125
126 SkPath path;
127 args.fShape->asPath(&path);
128
129 const SkRect pathDevBounds = args.fViewMatrix->mapRect(args.fShape->bounds());
131 pathDevBounds.width(),
132 pathDevBounds.height());
134 // The path is extremely large. Pre-chop its curves to keep the number of tessellation
135 // segments tractable. This will also flatten curves that fall completely outside the
136 // viewport.
137 SkRect viewport = SkRect::Make(*args.fClipConservativeBounds);
138 if (!args.fShape->style().isSimpleFill()) {
139 // Outset the viewport to pad for the stroke width.
140 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
141 float inflationRadius;
142 if (stroke.isHairlineStyle()) {
143 // SkStrokeRec::getInflationRadius() doesn't handle hairlines robustly. Instead
144 // find the inflation of an equivalent stroke in device space with a width of 1.
145 inflationRadius = SkStrokeRec::GetInflationRadius(stroke.getJoin(),
146 stroke.getMiter(),
147 stroke.getCap(), 1);
148 } else {
149 inflationRadius = stroke.getInflationRadius() * args.fViewMatrix->getMaxScale();
150 }
151 viewport.outset(inflationRadius, inflationRadius);
152 }
153 path = PreChopPathCurves(tess::kPrecision, path, *args.fViewMatrix, viewport);
154 }
155
156 // Handle strokes first.
157 if (!args.fShape->style().isSimpleFill()) {
158 SkASSERT(!path.isInverseFillType()); // See onGetStencilSupport().
159 SkASSERT(args.fUserStencilSettings->isUnused());
160 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
162 auto op = GrOp::Make<StrokeTessellateOp>(args.fContext, args.fAAType, *args.fViewMatrix,
163 path, stroke, std::move(args.fPaint));
164 sdc->addDrawOp(args.fClip, std::move(op));
165 return true;
166 }
167
168 // Handle empty paths.
169 if (pathDevBounds.isEmpty()) {
170 if (path.isInverseFillType()) {
171 args.fSurfaceDrawContext->drawPaint(args.fClip, std::move(args.fPaint),
172 *args.fViewMatrix);
173 }
174 return true;
175 }
176
177 // Handle convex paths. Make sure to check 'path' for convexity since it may have been
178 // pre-chopped, not 'fShape'.
179 if (path.isConvex() && !path.isInverseFillType()) {
180 auto op = GrOp::Make<PathTessellateOp>(args.fContext,
181 args.fSurfaceDrawContext->arenaAlloc(),
182 args.fAAType,
183 args.fUserStencilSettings,
184 *args.fViewMatrix,
185 path,
186 std::move(args.fPaint),
187 pathDevBounds);
188 sdc->addDrawOp(args.fClip, std::move(op));
189 return true;
190 }
191
192 SkASSERT(args.fUserStencilSettings->isUnused()); // See onGetStencilSupport().
193 const SkRect& drawBounds = path.isInverseFillType()
194 ? args.fSurfaceDrawContext->asSurfaceProxy()->backingStoreBoundsRect()
195 : pathDevBounds;
196 auto op = make_non_convex_fill_op(args.fContext,
197 args.fSurfaceDrawContext->arenaAlloc(),
199 args.fAAType,
200 drawBounds,
201 *args.fClipConservativeBounds,
202 *args.fViewMatrix,
203 path,
204 std::move(args.fPaint));
205 sdc->addDrawOp(args.fClip, std::move(op));
206 return true;
207}
#define SkASSERT(cond)
Definition SkAssert.h:116
static SkScalar GetInflationRadius(const SkPaint &, SkPaint::Style)
SkScalar getInflationRadius() const
bool isHairlineStyle() const
Definition SkStrokeRec.h:47
SkPaint::Join getJoin() const
Definition SkStrokeRec.h:45
SkPaint::Cap getCap() const
Definition SkStrokeRec.h:44
SkScalar getMiter() const
Definition SkStrokeRec.h:43
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
static constexpr float kMaxSegmentsPerCurve_p4
SkPath PreChopPathCurves(float tessellationPrecision, const SkPath &path, const SkMatrix &matrix, const SkRect &viewport)
static constexpr float kPrecision
AI float worst_case_cubic_p4(float precision, float devWidth, float devHeight)
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
void outset(float dx, float dy)
Definition SkRect.h:1077
constexpr float height() const
Definition SkRect.h:769
constexpr float width() const
Definition SkRect.h:762
bool isEmpty() const
Definition SkRect.h:693

◆ onGetStencilSupport()

PathRenderer::StencilSupport skgpu::ganesh::TessellationPathRenderer::onGetStencilSupport ( const GrStyledShape ) const
overrideprivatevirtual

Subclass overrides if it has any limitations of stenciling support.

Reimplemented from skgpu::ganesh::PathRenderer.

Definition at line 79 of file TessellationPathRenderer.cpp.

80 {
81 if (!shape.style().isSimpleFill() || shape.inverseFilled()) {
82 // Don't bother with stroke stencilling or inverse fills yet. The Skia API doesn't support
83 // clipping by a stroke, and the stencilling code already knows how to invert a fill.
85 }
86 return shape.knownToBeConvex() ? kNoRestriction_StencilSupport : kStencilOnly_StencilSupport;
87}

◆ onStencilPath()

void skgpu::ganesh::TessellationPathRenderer::onStencilPath ( const StencilPathArgs args)
overrideprivatevirtual

Subclass implementation of stencilPath(). Subclass must override iff it ever returns kStencilOnly in onGetStencilSupport().

Reimplemented from skgpu::ganesh::PathRenderer.

Definition at line 209 of file TessellationPathRenderer.cpp.

209 {
210 SkASSERT(args.fShape->style().isSimpleFill()); // See onGetStencilSupport().
211 SkASSERT(!args.fShape->inverseFilled()); // See onGetStencilSupport().
212
213 auto sdc = args.fSurfaceDrawContext;
214 GrAAType aaType = (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
215
216 SkRect pathDevBounds;
217 args.fViewMatrix->mapRect(&pathDevBounds, args.fShape->bounds());
218
219 SkPath path;
220 args.fShape->asPath(&path);
221
223 pathDevBounds.width(),
224 pathDevBounds.height());
226 SkRect viewport = SkRect::Make(*args.fClipConservativeBounds);
227 path = PreChopPathCurves(tess::kPrecision, path, *args.fViewMatrix, viewport);
228 }
229
230 // Make sure to check 'path' for convexity since it may have been pre-chopped, not 'fShape'.
231 if (path.isConvex()) {
232 constexpr static GrUserStencilSettings kMarkStencil(
234 0x0001,
236 0xffff,
239 0xffff>());
240
241 GrPaint stencilPaint;
243 auto op = GrOp::Make<PathTessellateOp>(args.fContext,
244 args.fSurfaceDrawContext->arenaAlloc(),
245 aaType,
247 *args.fViewMatrix,
248 path,
249 std::move(stencilPaint),
250 pathDevBounds);
251 sdc->addDrawOp(args.fClip, std::move(op));
252 return;
253 }
254
255 auto op = make_non_convex_fill_op(args.fContext,
256 args.fSurfaceDrawContext->arenaAlloc(),
258 aaType,
259 pathDevBounds,
260 *args.fClipConservativeBounds,
261 *args.fViewMatrix,
262 path,
263 GrPaint());
264 sdc->addDrawOp(args.fClip, std::move(op));
265}
GrAAType
static const GrDisableColorXPFactory * Get()
void setXPFactory(const GrXPFactory *xpFactory)
Definition GrPaint.h:53
static constexpr GrUserStencilSettings kMarkStencil(GrUserStencilSettings::StaticInit< 0x0001, GrUserStencilTest::kLessIfInClip, 0x0000, GrUserStencilOp::kZero, GrUserStencilOp::kReplace, 0xffff >())
static constexpr Init< Ref, Test, TestMask, PassOp, FailOp, WriteMask > StaticInit()

The documentation for this class was generated from the following files: