Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
PathTessellatorsSlide.cpp
Go to the documentation of this file.
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
11
12#if defined(SK_GANESH)
13
14#include "include/core/SkFont.h"
29
30namespace skgpu::ganesh {
31
32namespace {
33
34enum class Mode {
35 kWedgeMiddleOut,
36 kCurveMiddleOut
37};
38
39static const char* ModeName(Mode mode) {
40 switch (mode) {
41 case Mode::kWedgeMiddleOut:
42 return "MiddleOutShader (kWedges)";
43 case Mode::kCurveMiddleOut:
44 return "MiddleOutShader (kCurves)";
45 }
47}
48
49// Draws a path directly to the screen using a specific tessellator.
50class SamplePathTessellatorOp : public GrDrawOp {
51private:
53
54 SamplePathTessellatorOp(const SkRect& drawBounds, const SkPath& path, const SkMatrix& m,
55 GrPipeline::InputFlags pipelineFlags, Mode mode)
56 : GrDrawOp(ClassID())
57 , fPath(path)
58 , fMatrix(m)
59 , fPipelineFlags(pipelineFlags)
60 , fMode(mode) {
61 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
62 }
63 const char* name() const override { return "SamplePathTessellatorOp"; }
64 void visitProxies(const GrVisitProxyFunc&) const override {}
65 FixedFunctionFlags fixedFunctionFlags() const override {
66 return FixedFunctionFlags::kUsesHWAA;
67 }
68 GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
69 GrClampType clampType) override {
71 return fProcessors.finalize(SK_PMColor4fWHITE, GrProcessorAnalysisCoverage::kNone, clip,
72 nullptr, caps, clampType, &color);
73 }
74 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
75 const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override {}
76 void onPrepare(GrOpFlushState* flushState) override {
77 constexpr static SkPMColor4f kCyan = {0,1,1,1};
78 auto alloc = flushState->allocator();
79 const SkMatrix& shaderMatrix = SkMatrix::I();
80 const SkMatrix& pathMatrix = fMatrix;
81 const GrCaps& caps = flushState->caps();
82 const GrShaderCaps& shaderCaps = *caps.shaderCaps();
83
84 PathTessellator::PathDrawList pathList{pathMatrix, fPath, kCyan};
85 if (fMode == Mode::kCurveMiddleOut) {
86#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
87 // This emulates what PathStencilCoverOp does when using curves, except we include the
88 // middle-out triangles directly in the written patches for convenience (normally they
89 // use a simple triangle pipeline). But PathCurveTessellator only knows how to read
90 // extra triangles from BreadcrumbTriangleList, so build on from the middle-out stack.
91 SkArenaAlloc storage{256};
93 for (tess::PathMiddleOutFanIter it(fPath); !it.done();) {
94 for (auto [p0, p1, p2] : it.nextStack()) {
95 triangles.append(&storage,
96 pathMatrix.mapPoint(p0),
97 pathMatrix.mapPoint(p1),
98 pathMatrix.mapPoint(p2),
99 /*winding=*/1);
100 }
101 }
102
103 auto* tess = PathCurveTessellator::Make(alloc, shaderCaps.fInfinitySupport);
104 tess->prepareWithTriangles(flushState, shaderMatrix, &triangles, pathList,
105 fPath.countVerbs());
106 fTessellator = tess;
107#else
108 auto* tess = PathCurveTessellator::Make(alloc, shaderCaps.fInfinitySupport);
109 tess->prepareWithTriangles(flushState, shaderMatrix, nullptr, pathList,
110 fPath.countVerbs());
111 fTessellator = tess;
112#endif
113 } else {
114 // This emulates what PathStencilCoverOp does when using wedges.
115 fTessellator = PathWedgeTessellator::Make(alloc, shaderCaps.fInfinitySupport);
116 fTessellator->prepare(flushState, shaderMatrix, pathList, fPath.countVerbs());
117 }
118
119 auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState, std::move(fProcessors),
120 fPipelineFlags);
121 auto* tessShader = GrPathTessellationShader::Make(*caps.shaderCaps(),
122 alloc,
123 shaderMatrix,
124 kCyan,
125 fTessellator->patchAttribs());
126 fProgram = GrTessellationShader::MakeProgram({alloc, flushState->writeView(),
127 flushState->usesMSAASurface(),
128 &flushState->dstProxyView(),
129 flushState->renderPassBarriers(),
130 GrLoadOp::kClear, &flushState->caps()},
131 tessShader,
132 pipeline,
134 }
135
136 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
137 flushState->bindPipeline(*fProgram, chainBounds);
138 fTessellator->draw(flushState);
139 }
140
141 const SkPath fPath;
142 const SkMatrix fMatrix;
143 const GrPipeline::InputFlags fPipelineFlags;
144 const Mode fMode;
145 PathTessellator* fTessellator = nullptr;
146 GrProgramInfo* fProgram;
148
149 friend class GrOp; // For ctor.
150};
151
152} // namespace
153
154// This slide enables wireframe and visualizes the triangles generated by path tessellators.
155class PathTessellatorsSlide : public ClickHandlerSlide {
156public:
157 PathTessellatorsSlide() {
158#if 0
159 // For viewing middle-out triangulations of the inner fan.
160 fPath.moveTo(1, 0);
161 int numSides = 32 * 3;
162 for (int i = 1; i < numSides; ++i) {
163 float theta = 2*3.1415926535897932384626433832785 * i / numSides;
164 fPath.lineTo(std::cos(theta), std::sin(theta));
165 }
168#else
169 fPath.moveTo(100, 500);
170 fPath.cubicTo(300, 400, -100, 300, 100, 200);
171 fPath.quadTo(250, 0, 400, 200);
172 fPath.conicTo(600, 350, 400, 500, fConicWeight);
173 fPath.close();
174#endif
175 fName = "PathTessellators";
176 }
177
178 bool onChar(SkUnichar) override;
179
180 void draw(SkCanvas*) override;
181
182protected:
183 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
184 bool onClick(Click*) override;
185
188 Mode fMode = Mode::kWedgeMiddleOut;
189
190 float fConicWeight = .5;
191
192 class Click;
193};
194
195void PathTessellatorsSlide::draw(SkCanvas* canvas) {
196 canvas->clear(SK_ColorBLACK);
197
198 auto ctx = canvas->recordingContext();
200
202 if (!sdc || !ctx) {
203 error = "GPU Only.";
204 } else if (!skgpu::ganesh::TessellationPathRenderer::IsSupported(*ctx->priv().caps())) {
205 error = "TessellationPathRenderer not supported.";
206 }
207 if (!error.isEmpty()) {
208 canvas->clear(SK_ColorRED);
210 SkPaint captionPaint;
211 captionPaint.setColor(SK_ColorWHITE);
212 canvas->drawString(error.c_str(), 10, 30, font, captionPaint);
213 return;
214 }
215
216 sdc->addDrawOp(GrOp::Make<SamplePathTessellatorOp>(ctx,
217 sdc->asRenderTargetProxy()->getBoundsRect(),
218 fPath, canvas->getTotalMatrix(),
219 fPipelineFlags, fMode));
220
221 // Draw the path points.
222 SkPaint pointsPaint;
223 pointsPaint.setColor(SK_ColorBLUE);
224 pointsPaint.setStrokeWidth(8);
225 SkPath devPath = fPath;
226 devPath.transform(canvas->getTotalMatrix());
227 {
228 SkAutoCanvasRestore acr(canvas, true);
229 canvas->setMatrix(SkMatrix::I());
230 SkString caption(ModeName(fMode));
231 caption.appendf(" (w=%g)", fConicWeight);
233 SkPaint captionPaint;
234 captionPaint.setColor(SK_ColorWHITE);
235 canvas->drawString(caption, 10, 30, font, captionPaint);
237 SkPathPriv::PointData(devPath), pointsPaint);
238 }
239}
240
241class PathTessellatorsSlide::Click : public ClickHandlerSlide::Click {
242public:
243 Click(int ptIdx) : fPtIdx(ptIdx) {}
244
245 void doClick(SkPath* path) {
246 SkPoint pt = path->getPoint(fPtIdx);
247 SkPathPriv::UpdatePathPoint(path, fPtIdx, pt + fCurr - fPrev);
248 }
249
250private:
251 int fPtIdx;
252};
253
254ClickHandlerSlide::Click* PathTessellatorsSlide::onFindClickHandler(SkScalar x, SkScalar y,
256 const SkPoint* pts = SkPathPriv::PointData(fPath);
257 float fuzz = 30;
258 for (int i = 0; i < fPath.countPoints(); ++i) {
259 if (fabs(x - pts[i].x()) < fuzz && fabsf(y - pts[i].y()) < fuzz) {
260 return new Click(i);
261 }
262 }
263 return nullptr;
264}
265
266bool PathTessellatorsSlide::onClick(ClickHandlerSlide::Click* click) {
267 Click* myClick = (Click*)click;
268 myClick->doClick(&fPath);
269 return true;
270}
271
272static SkPath update_weight(const SkPath& path, float w) {
273 SkPath path_;
274 for (auto [verb, pts, _] : SkPathPriv::Iterate(path)) {
275 switch (verb) {
277 path_.moveTo(pts[0]);
278 break;
280 path_.lineTo(pts[1]);
281 break;
283 path_.quadTo(pts[1], pts[2]);
284 break;
286 path_.cubicTo(pts[1], pts[2], pts[3]);
287 break;
289 path_.conicTo(pts[1], pts[2], (w != 1) ? w : .99f);
290 break;
292 break;
293 }
294 }
295 return path_;
296}
297
298bool PathTessellatorsSlide::onChar(SkUnichar unichar) {
299 switch (unichar) {
300 case 'w':
301 fPipelineFlags = (GrPipeline::InputFlags)(
302 (int)fPipelineFlags ^ (int)GrPipeline::InputFlags::kWireframe);
303 return true;
304 case 'D': {
305 fPath.dump();
306 return true;
307 }
308 case '+':
309 fConicWeight *= 2;
310 fPath = update_weight(fPath, fConicWeight);
311 return true;
312 case '=':
313 fConicWeight *= 5/4.f;
314 fPath = update_weight(fPath, fConicWeight);
315 return true;
316 case '_':
317 fConicWeight *= .5f;
318 fPath = update_weight(fPath, fConicWeight);
319 return true;
320 case '-':
321 fConicWeight *= 4/5.f;
322 fPath = update_weight(fPath, fConicWeight);
323 return true;
324 case '1':
325 case '2':
326 fMode = (Mode)(unichar - '1');
327 return true;
328 }
329 return false;
330}
331
332DEF_SLIDE( return new PathTessellatorsSlide; )
333
334} // namespace skgpu::ganesh
335
336#endif // defined(SK_GANESH)
SkPath fPath
const char * fName
#define DEFINE_OP_CLASS_ID
Definition GrOp.h:64
GrClampType
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
GrLoadOp
GrXferBarrierFlags
SkColor4f color
#define SkUNREACHABLE
Definition SkAssert.h:135
@ kSrcOver
r = s + (1-sa)*d
constexpr SkPMColor4f SK_PMColor4fWHITE
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
int32_t SkUnichar
Definition SkTypes.h:175
#define DEF_SLIDE(code)
Definition Slide.h:25
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
Type::kYUV Type::kRGBA() int(0.7 *637)
const GrShaderCaps * shaderCaps() const
Definition GrCaps.h:63
const GrDstProxyView & dstProxyView() const final
GrXferBarrierFlags renderPassBarriers() const final
SkArenaAlloc * allocator() override
const GrSurfaceProxyView & writeView() const final
const GrCaps & caps() const final
void bindPipeline(const GrProgramInfo &programInfo, const SkRect &drawBounds)
bool usesMSAASurface() const final
Definition GrOp.h:70
static GrPathTessellationShader * Make(const GrShaderCaps &, SkArenaAlloc *, const SkMatrix &viewMatrix, const SkPMColor4f &, PatchAttribs)
static const GrPipeline * CreatePipeline(const GrCaps *, SkArenaAlloc *, skgpu::Swizzle writeViewSwizzle, GrAppliedClip &&, const GrDstProxyView &, GrProcessorSet &&, GrPipeline::InputFlags pipelineFlags)
static GrProgramInfo * MakeProgram(const ProgramArgs &args, const GrTessellationShader *shader, const GrPipeline *pipeline, const GrUserStencilSettings *stencil)
void append(SkArenaAlloc *alloc, SkPoint a, SkPoint b, SkPoint c, int winding)
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
virtual GrRecordingContext * recordingContext() const
void clear(SkColor color)
Definition SkCanvas.h:1199
SkMatrix getTotalMatrix() const
void setMatrix(const SkM44 &matrix)
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition SkCanvas.h:1803
@ kPoints_PointMode
draw each point separately
Definition SkCanvas.h:1241
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition SkMatrix.h:75
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition SkMatrix.h:91
SkPoint mapPoint(SkPoint pt) const
Definition SkMatrix.h:1374
static const SkMatrix & I()
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
static void UpdatePathPoint(SkPath *path, int index, const SkPoint &pt)
Definition SkPathPriv.h:400
static const SkPoint * PointData(const SkPath &path)
Definition SkPathPriv.h:203
int countPoints() const
Definition SkPath.cpp:525
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition SkPath.cpp:736
int countVerbs() const
Definition SkPath.cpp:546
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition SkPath.cpp:789
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition SkPath.cpp:756
SkPath & close()
Definition SkPath.cpp:813
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition SkPath.cpp:1647
void dump(SkWStream *stream, bool dumpAsHex) const
Definition SkPath.cpp:1976
float SkScalar
Definition extension.cpp:12
const uint8_t uint32_t uint32_t GError ** error
const char * name
Definition fuchsia.cc:50
double y
double x
constexpr SkColor4f kCyan
Definition SkColor.h:444
sk_sp< SkTypeface > DefaultTypeface()
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition switches.h:228
font
Font Metadata and Metrics.
SurfaceDrawContext * TopDeviceSurfaceDrawContext(const SkCanvas *canvas)
Definition GrCanvas.cpp:20
ModifierKey
Definition ModifierKey.h:9
SkScalar w
static const GrUserStencilSettings & kUnused
bool fInfinitySupport
Definition SkSLUtil.h:103
SkBlendMode fMode
Definition xfermodes.cpp:52