Flutter Engine
The Flutter Engine
TriangulatingPathRenderer.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 Google Inc.
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
10
12#include "src/core/SkGeometry.h"
33
34#include <cstdio>
35
36#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
37
38#ifndef GR_AA_TESSELLATOR_MAX_VERB_COUNT
39#define GR_AA_TESSELLATOR_MAX_VERB_COUNT 10
40#endif
41
42/*
43 * This path renderer linearizes and decomposes the path into triangles using GrTriangulator,
44 * uploads the triangles to a vertex buffer, and renders them with a single draw call. It can do
45 * screenspace antialiasing with a one-pixel coverage ramp.
46 */
47namespace {
48
49// The TessInfo struct contains ancillary data not specifically required for the triangle
50// data (which is stored in a GrThreadSafeCache::VertexData object).
51// The 'fNumVertices' field is a temporary exception. It is still needed to support the
52// AA triangulated path case - which doesn't use the GrThreadSafeCache nor the VertexData object).
53// When there is an associated VertexData, its numVertices should always match the TessInfo's
54// value.
55struct TessInfo {
56 int fNumVertices;
57 bool fIsLinear;
58 SkScalar fTolerance;
59};
60
61static sk_sp<SkData> create_data(int numVertices, bool isLinear, SkScalar tol) {
62 TessInfo info { numVertices, isLinear, tol };
63 return SkData::MakeWithCopy(&info, sizeof(info));
64}
65
66bool cache_match(const SkData* data, SkScalar tol) {
68
69 const TessInfo* info = static_cast<const TessInfo*>(data->data());
70
71 return info->fIsLinear || info->fTolerance < 3.0f * tol;
72}
73
74// Should 'challenger' replace 'incumbent' in the cache if there is a collision?
75bool is_newer_better(SkData* incumbent, SkData* challenger) {
76 const TessInfo* i = static_cast<const TessInfo*>(incumbent->data());
77 const TessInfo* c = static_cast<const TessInfo*>(challenger->data());
78
79 if (i->fIsLinear || i->fTolerance <= c->fTolerance) {
80 return false; // prefer the incumbent
81 }
82
83 return true;
84}
85
86// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
87class UniqueKeyInvalidator : public SkIDChangeListener {
88public:
89 UniqueKeyInvalidator(const skgpu::UniqueKey& key, uint32_t contextUniqueID)
90 : fMsg(key, contextUniqueID, /* inThreadSafeCache */ true) {}
91
92private:
94
95 void changed() override {
97 }
98};
99
100class StaticVertexAllocator : public GrEagerVertexAllocator {
101public:
102 StaticVertexAllocator(GrResourceProvider* resourceProvider, bool canMapVB)
103 : fResourceProvider(resourceProvider)
104 , fCanMapVB(canMapVB) {
105 }
106
107#ifdef SK_DEBUG
108 ~StaticVertexAllocator() override {
109 SkASSERT(!fLockStride && !fVertices && !fVertexBuffer && !fVertexData);
110 }
111#endif
112
113 void* lock(size_t stride, int eagerCount) override {
114 SkASSERT(!fLockStride && !fVertices && !fVertexBuffer && !fVertexData);
115 SkASSERT(stride && eagerCount);
116
117 size_t size = eagerCount * stride;
118 fVertexBuffer = fResourceProvider->createBuffer(size,
122 if (!fVertexBuffer) {
123 return nullptr;
124 }
125 if (fCanMapVB) {
126 fVertices = fVertexBuffer->map();
127 }
128 if (!fVertices) {
129 fVertices = sk_malloc_throw(eagerCount * stride);
130 fCanMapVB = false;
131 }
132 fLockStride = stride;
133 return fVertices;
134 }
135
136 void unlock(int actualCount) override {
137 SkASSERT(fLockStride && fVertices && fVertexBuffer && !fVertexData);
138
139 if (fCanMapVB) {
140 fVertexBuffer->unmap();
141 } else {
142 fVertexBuffer->updateData(fVertices,
143 /*offset=*/0,
144 /*size=*/actualCount*fLockStride,
145 /*preserve=*/false);
146 sk_free(fVertices);
147 }
148
149 fVertexData = GrThreadSafeCache::MakeVertexData(std::move(fVertexBuffer),
150 actualCount, fLockStride);
151
152 fVertices = nullptr;
153 fLockStride = 0;
154 }
155
156 sk_sp<GrThreadSafeCache::VertexData> detachVertexData() {
157 SkASSERT(!fLockStride && !fVertices && !fVertexBuffer && fVertexData);
158
159 return std::move(fVertexData);
160 }
161
162private:
165 GrResourceProvider* fResourceProvider;
166 bool fCanMapVB;
167 void* fVertices = nullptr;
168 size_t fLockStride = 0;
169};
170
171class TriangulatingPathOp final : public GrMeshDrawOp {
172private:
174
175public:
177
178 static GrOp::Owner Make(GrRecordingContext* context,
179 GrPaint&& paint,
180 const GrStyledShape& shape,
181 const SkMatrix& viewMatrix,
182 SkIRect devClipBounds,
183 GrAAType aaType,
184 const GrUserStencilSettings* stencilSettings) {
185 return Helper::FactoryHelper<TriangulatingPathOp>(context, std::move(paint), shape,
186 viewMatrix, devClipBounds, aaType,
187 stencilSettings);
188 }
189
190 const char* name() const override { return "TriangulatingPathOp"; }
191
192 void visitProxies(const GrVisitProxyFunc& func) const override {
193 if (fProgramInfo) {
194 fProgramInfo->visitFPProxies(func);
195 } else {
196 fHelper.visitProxies(func);
197 }
198 }
199
200 TriangulatingPathOp(GrProcessorSet* processorSet,
201 const SkPMColor4f& color,
202 const GrStyledShape& shape,
203 const SkMatrix& viewMatrix,
204 const SkIRect& devClipBounds,
205 GrAAType aaType,
206 const GrUserStencilSettings* stencilSettings)
207 : INHERITED(ClassID())
208 , fHelper(processorSet, aaType, stencilSettings)
209 , fColor(color)
210 , fShape(shape)
211 , fViewMatrix(viewMatrix)
212 , fDevClipBounds(devClipBounds)
213 , fAntiAlias(GrAAType::kCoverage == aaType) {
214 SkRect devBounds;
215 viewMatrix.mapRect(&devBounds, shape.bounds());
216 if (shape.inverseFilled()) {
217 // Because the clip bounds are used to add a contour for inverse fills, they must also
218 // include the path bounds.
219 devBounds.join(SkRect::Make(fDevClipBounds));
220 }
221 this->setBounds(devBounds, HasAABloat(fAntiAlias), IsHairline::kNo);
222 }
223
224 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
225
227 GrClampType clampType) override {
231 // This Op uses uniform (not vertex) color, so doesn't need to track wide color.
232 return fHelper.finalizeProcessors(caps, clip, clampType, coverage, &fColor, nullptr);
233 }
234
235private:
236 SkPath getPath() const {
238 SkPath path;
240 return path;
241 }
242
243 static void CreateKey(skgpu::UniqueKey* key,
244 const GrStyledShape& shape,
245 const SkIRect& devClipBounds) {
247
248 bool inverseFill = shape.inverseFilled();
249
250 static constexpr int kClipBoundsCnt = sizeof(devClipBounds) / sizeof(uint32_t);
251 int shapeKeyDataCnt = shape.unstyledKeySize();
252 SkASSERT(shapeKeyDataCnt >= 0);
253 skgpu::UniqueKey::Builder builder(key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
254 shape.writeUnstyledKey(&builder[0]);
255 // For inverse fills, the tessellation is dependent on clip bounds.
256 if (inverseFill) {
257 memcpy(&builder[shapeKeyDataCnt], &devClipBounds, sizeof(devClipBounds));
258 } else {
259 memset(&builder[shapeKeyDataCnt], 0, sizeof(devClipBounds));
260 }
261
262 builder.finish();
263 }
264
265 // Triangulate the provided 'shape' in the shape's coordinate space. 'tol' should already
266 // have been mapped back from device space.
267 static int Triangulate(GrEagerVertexAllocator* allocator,
268 const SkMatrix& viewMatrix,
269 const GrStyledShape& shape,
270 const SkIRect& devClipBounds,
271 SkScalar tol,
272 bool* isLinear) {
273 SkRect clipBounds = SkRect::Make(devClipBounds);
274
275 SkMatrix vmi;
276 if (!viewMatrix.invert(&vmi)) {
277 return 0;
278 }
279 vmi.mapRect(&clipBounds);
280
281 SkASSERT(!shape.style().applies());
282 SkPath path;
283 shape.asPath(&path);
284
285 return GrTriangulator::PathToTriangles(path, tol, clipBounds, allocator, isLinear);
286 }
287
288 void createNonAAMesh(GrMeshDrawTarget* target) {
289 SkASSERT(!fAntiAlias);
290 GrResourceProvider* rp = target->resourceProvider();
291 auto threadSafeCache = target->threadSafeCache();
292
294 CreateKey(&key, fShape, fDevClipBounds);
295
298
299 if (!fVertexData) {
300 auto [cachedVerts, data] = threadSafeCache->findVertsWithData(key);
301 if (cachedVerts && cache_match(data.get(), tol)) {
302 fVertexData = std::move(cachedVerts);
303 }
304 }
305
306 if (fVertexData) {
307 if (!fVertexData->gpuBuffer()) {
308 sk_sp<GrGpuBuffer> buffer = rp->createBuffer(fVertexData->vertices(),
309 fVertexData->size(),
312 if (!buffer) {
313 return;
314 }
315
316 // Since we have a direct context and a ref on 'fVertexData' we need not worry
317 // about any threading issues in this call.
318 fVertexData->setGpuBuffer(std::move(buffer));
319 }
320
321 fMesh = CreateMesh(target, fVertexData->refGpuBuffer(), 0, fVertexData->numVertices());
322 return;
323 }
324
325 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
326 StaticVertexAllocator allocator(rp, canMapVB);
327
328 bool isLinear;
329 int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
330 &isLinear);
331 if (vertexCount == 0) {
332 return;
333 }
334
335 fVertexData = allocator.detachVertexData();
336
337 key.setCustomData(create_data(vertexCount, isLinear, tol));
338
339 auto [tmpV, tmpD] = threadSafeCache->addVertsWithData(key, fVertexData, is_newer_better);
340 if (tmpV != fVertexData) {
341 SkASSERT(!tmpV->gpuBuffer());
342 // In this case, although the different triangulation found in the cache is better,
343 // we will continue on with the current triangulation since it is already on the gpu.
344 } else {
345 // This isn't perfect. The current triangulation is in the cache but it may have
346 // replaced a pre-existing one. A duplicated listener is unlikely and not that
347 // expensive so we just roll with it.
349 sk_make_sp<UniqueKeyInvalidator>(key, target->contextUniqueID()));
350 }
351
352 fMesh = CreateMesh(target, fVertexData->refGpuBuffer(), 0, fVertexData->numVertices());
353 }
354
355 void createAAMesh(GrMeshDrawTarget* target) {
356 SkASSERT(!fVertexData);
357 SkASSERT(fAntiAlias);
358 SkPath path = this->getPath();
359 if (path.isEmpty()) {
360 return;
361 }
362 SkRect clipBounds = SkRect::Make(fDevClipBounds);
363 path.transform(fViewMatrix);
365 sk_sp<const GrBuffer> vertexBuffer;
366 int firstVertex;
367 GrEagerDynamicVertexAllocator allocator(target, &vertexBuffer, &firstVertex);
368 int vertexCount = GrAATriangulator::PathToAATriangles(path, tol, clipBounds, &allocator);
369 if (vertexCount == 0) {
370 return;
371 }
372 fMesh = CreateMesh(target, std::move(vertexBuffer), firstVertex, vertexCount);
373 }
374
375 GrProgramInfo* programInfo() override { return fProgramInfo; }
376
377 void onCreateProgramInfo(const GrCaps* caps,
378 SkArenaAlloc* arena,
379 const GrSurfaceProxyView& writeView,
380 bool usesMSAASurface,
381 GrAppliedClip&& appliedClip,
382 const GrDstProxyView& dstProxyView,
383 GrXferBarrierFlags renderPassXferBarriers,
384 GrLoadOp colorLoadOp) override {
386 {
387 using namespace GrDefaultGeoProcFactory;
388
389 Color color(fColor);
390 LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
391 ? LocalCoords::kUsePosition_Type
392 : LocalCoords::kUnused_Type;
393 Coverage::Type coverageType;
394 if (fAntiAlias) {
395 if (fHelper.compatibleWithCoverageAsAlpha()) {
396 coverageType = Coverage::kAttributeTweakAlpha_Type;
397 } else {
398 coverageType = Coverage::kAttribute_Type;
399 }
400 } else {
401 coverageType = Coverage::kSolid_Type;
402 }
403 if (fAntiAlias) {
404 gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(arena, color, coverageType,
405 localCoordsType, fViewMatrix);
406 } else {
407 gp = GrDefaultGeoProcFactory::Make(arena, color, coverageType, localCoordsType,
409 }
410 }
411 if (!gp) {
412 return;
413 }
414
415#ifdef SK_DEBUG
416 auto vertexStride = sizeof(SkPoint);
417 if (fAntiAlias) {
418 vertexStride += sizeof(float);
419 }
420 SkASSERT(vertexStride == gp->vertexStride());
421#endif
422
425
426 fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
427 usesMSAASurface,
428 std::move(appliedClip), dstProxyView,
429 gp, primitiveType,
430 renderPassXferBarriers, colorLoadOp);
431 }
432
434 const GrSurfaceProxyView& writeView,
436 const GrDstProxyView& dstProxyView,
437 GrXferBarrierFlags renderPassXferBarriers,
438 GrLoadOp colorLoadOp) override {
439 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
440
441 INHERITED::onPrePrepareDraws(rContext, writeView, clip, dstProxyView,
442 renderPassXferBarriers, colorLoadOp);
443
444 if (fAntiAlias) {
445 // TODO: pull the triangulation work forward to the recording thread for the AA case
446 // too.
447 return;
448 }
449
450 auto threadSafeViewCache = rContext->priv().threadSafeCache();
451
453 CreateKey(&key, fShape, fDevClipBounds);
454
457
458 auto [cachedVerts, data] = threadSafeViewCache->findVertsWithData(key);
459 if (cachedVerts && cache_match(data.get(), tol)) {
460 fVertexData = std::move(cachedVerts);
461 return;
462 }
463
464 GrCpuVertexAllocator allocator;
465
466 bool isLinear;
467 int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
468 &isLinear);
469 if (vertexCount == 0) {
470 return;
471 }
472
473 fVertexData = allocator.detachVertexData();
474
475 key.setCustomData(create_data(vertexCount, isLinear, tol));
476
477 // If some other thread created and cached its own triangulation, the 'is_newer_better'
478 // predicate will replace the version in the cache if 'fVertexData' is a more accurate
479 // triangulation. This will leave some other recording threads using a poorer triangulation
480 // but will result in a version with greater applicability being in the cache.
481 auto [tmpV, tmpD] = threadSafeViewCache->addVertsWithData(key, fVertexData,
482 is_newer_better);
483 if (tmpV != fVertexData) {
484 // Someone beat us to creating the triangulation (and it is better than ours) so
485 // just go ahead and use it.
486 SkASSERT(cache_match(tmpD.get(), tol));
487 fVertexData = std::move(tmpV);
488 } else {
489 // This isn't perfect. The current triangulation is in the cache but it may have
490 // replaced a pre-existing one. A duplicated listener is unlikely and not that
491 // expensive so we just roll with it.
493 sk_make_sp<UniqueKeyInvalidator>(key, rContext->priv().contextID()));
494 }
495 }
496
497 void onPrepareDraws(GrMeshDrawTarget* target) override {
498 if (fAntiAlias) {
499 this->createAAMesh(target);
500 } else {
501 this->createNonAAMesh(target);
502 }
503 }
504
505 static GrSimpleMesh* CreateMesh(GrMeshDrawTarget* target,
507 int firstVertex,
508 int count) {
509 auto mesh = target->allocMesh();
510 mesh->set(std::move(vb), count, firstVertex);
511 return mesh;
512 }
513
514 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
515 if (!fProgramInfo) {
516 this->createProgramInfo(flushState);
517 }
518
519 if (!fProgramInfo || !fMesh) {
520 return;
521 }
522
523 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
524 flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
525 flushState->drawMesh(*fMesh);
526 }
527
528#if defined(GR_TEST_UTILS)
529 SkString onDumpInfo() const override {
530 return SkStringPrintf("Color 0x%08x, aa: %d\n%s",
531 fColor.toBytes_RGBA(), fAntiAlias, fHelper.dumpInfo().c_str());
532 }
533#endif
534
535 Helper fHelper;
536 SkPMColor4f fColor;
539 SkIRect fDevClipBounds;
540 bool fAntiAlias;
541
542 GrSimpleMesh* fMesh = nullptr;
543 GrProgramInfo* fProgramInfo = nullptr;
544
546
547 using INHERITED = GrMeshDrawOp;
548};
549
550} // anonymous namespace
551
552///////////////////////////////////////////////////////////////////////////////////////////////////
553
554#if defined(GR_TEST_UTILS)
555
556GR_DRAW_OP_TEST_DEFINE(TriangulatingPathOp) {
557 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
558 const SkPath& path = GrTest::TestPath(random);
559 SkIRect devClipBounds = SkIRect::MakeLTRB(
560 random->nextU(), random->nextU(), random->nextU(), random->nextU());
561 devClipBounds.sort();
562 static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
563 GrAAType aaType;
564 do {
565 aaType = kAATypes[random->nextULessThan(std::size(kAATypes))];
566 } while(GrAAType::kMSAA == aaType && numSamples <= 1);
567 GrStyle style;
568 do {
569 GrTest::TestStyle(random, &style);
570 } while (!style.isSimpleFill());
571 GrStyledShape shape(path, style);
572 return TriangulatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
573 aaType, GrGetRandomStencil(random, context));
574}
575
576#endif
577
578///////////////////////////////////////////////////////////////////////////////////////////////////
579
580namespace skgpu::ganesh {
581
583 : fMaxVerbCount(GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
584}
585
586PathRenderer::CanDrawPath TriangulatingPathRenderer::onCanDrawPath(
587 const CanDrawPathArgs& args) const {
588
589 // Don't use this path renderer with dynamic MSAA. DMSAA tries to not rely on caching.
590 if (args.fSurfaceProps->flags() & SkSurfaceProps::kDynamicMSAA_Flag) {
591 return CanDrawPath::kNo;
592 }
593 // This path renderer can draw fill styles, and can do screenspace antialiasing via a
594 // one-pixel coverage ramp. It can do convex and concave paths, but we'll leave the convex
595 // ones to simpler algorithms. We pass on paths that have styles, though they may come back
596 // around after applying the styling information to the geometry to create a filled path.
597 if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
598 return CanDrawPath::kNo;
599 }
600 switch (args.fAAType) {
601 case GrAAType::kNone:
602 case GrAAType::kMSAA:
603 // Prefer MSAA, if any antialiasing. In the non-analytic-AA case, We skip paths that
604 // don't have a key since the real advantage of this path renderer comes from caching
605 // the tessellated geometry.
606 if (!args.fShape->hasUnstyledKey()) {
607 return CanDrawPath::kNo;
608 }
609 break;
611 // Use analytic AA if we don't have MSAA. In this case, we do not cache, so we accept
612 // paths without keys.
613 SkPath path;
614 args.fShape->asPath(&path);
615 if (path.countVerbs() > fMaxVerbCount) {
616 return CanDrawPath::kNo;
617 }
618 break;
619 }
620 return CanDrawPath::kYes;
621}
622
623bool TriangulatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
624 GR_AUDIT_TRAIL_AUTO_FRAME(args.fContext->priv().auditTrail(),
625 "GrTriangulatingPathRenderer::onDrawPath");
626
628 args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
629 *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings);
630 args.fSurfaceDrawContext->addDrawOp(args.fClip, std::move(op));
631 return true;
632}
633
634} // namespace skgpu::ganesh
635
636#endif // SK_ENABLE_OPTIMIZE_SIZE
SkMatrix fViewMatrix
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int count
Definition: FontMgrTest.cpp:50
#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename)
Definition: GrAuditTrail.h:167
#define DEFINE_OP_CLASS_ID
Definition: GrOp.h:64
GrProcessorAnalysisCoverage
#define TRIANGULATOR_WIREFRAME
GrClampType
Definition: GrTypesPriv.h:228
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
Definition: GrTypesPriv.h:943
GrPrimitiveType
Definition: GrTypesPriv.h:43
GrAAType
Definition: GrTypesPriv.h:200
@ kStatic_GrAccessPattern
Definition: GrTypesPriv.h:428
GrLoadOp
Definition: GrTypesPriv.h:155
GrXferBarrierFlags
#define SkASSERT(cond)
Definition: SkAssert.h:116
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
sk_sp< const GrBuffer > fVertexBuffer
GrStyledShape fShape
#define GR_AA_TESSELLATOR_MAX_VERB_COUNT
static int PathToAATriangles(const SkPath &path, SkScalar tolerance, const SkRect &clipBounds, GrEagerVertexAllocator *vertexAllocator)
uint32_t contextID() const
Definition: GrCaps.h:57
@ kNone_MapFlags
Definition: GrCaps.h:197
sk_sp< GrThreadSafeCache::VertexData > detachVertexData()
friend class GrSimpleMeshDrawOpHelperWithStencil
Definition: GrDrawOp.h:119
virtual FixedFunctionFlags fixedFunctionFlags() const
Definition: GrDrawOp.h:112
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
virtual void unlock(int actualCount)=0
virtual void * lock(size_t stride, int eagerCount)=0
size_t vertexStride() const
virtual GrProgramInfo * programInfo()=0
void createProgramInfo(const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
Definition: GrMeshDrawOp.h:39
GrMeshDrawOp(uint32_t classID)
virtual void onPrePrepareDraws(GrRecordingContext *, const GrSurfaceProxyView &writeView, GrAppliedClip *, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
virtual void onCreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
virtual void onPrepareDraws(GrMeshDrawTarget *)=0
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
static Owner Make(GrRecordingContext *context, Args &&... args)
Definition: GrOp.h:75
std::unique_ptr< GrOp > Owner
Definition: GrOp.h:72
HasAABloat
Definition: GrOp.h:266
virtual const char * name() const =0
virtual void visitProxies(const GrVisitProxyFunc &) const
Definition: GrOp.h:95
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
Definition: GrOp.h:279
const GrPipeline & pipeline() const
Definition: GrProgramInfo.h:39
const GrGeometryProcessor & geomProc() const
Definition: GrProgramInfo.h:40
void visitFPProxies(const GrVisitProxyFunc &func) const
Definition: GrProgramInfo.h:64
GrThreadSafeCache * threadSafeCache()
GrRecordingContextPriv priv()
sk_sp< GrGpuBuffer > createBuffer(size_t size, GrGpuBufferType, GrAccessPattern, ZeroInit)
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
void visitProxies(const GrVisitProxyFunc &func) const
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const
GrProgramInfo * createProgramInfoWithStencil(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
bool applies() const
Definition: GrStyle.h:143
bool isSimpleFill() const
Definition: GrStyle.h:114
void asPath(SkPath *out) const
void writeUnstyledKey(uint32_t *key) const
int unstyledKeySize() const
bool inverseFilled() const
const GrStyle & style() const
SkRect bounds() const
void addGenIDChangeListener(sk_sp< SkIDChangeListener >) const
static sk_sp< VertexData > MakeVertexData(const void *vertices, int vertexCount, size_t vertexSize)
static int PathToTriangles(const SkPath &path, SkScalar tolerance, const SkRect &clipBounds, GrEagerVertexAllocator *vertexAllocator, bool *isLinear)
Definition: SkData.h:25
const void * data() const
Definition: SkData.h:37
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition: SkData.cpp:111
virtual void changed()=0
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
static void Post(Message m)
Definition: SkMessageBus.h:130
Definition: SkPath.h:59
static Domain GenerateDomain()
Definition: ResourceKey.cpp:27
const Paint & paint
Definition: color_source.cc:38
DlColor color
float SkScalar
Definition: extension.cpp:12
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t * target
static sk_sp< SkData > create_data(const SkIRect &drawRect, const SkIRect &origDevBounds)
GrGeometryProcessor * Make(SkArenaAlloc *, const Color &, const Coverage &, const LocalCoords &, const SkMatrix &viewMatrix)
GrGeometryProcessor * MakeForDeviceSpace(SkArenaAlloc *, const Color &, const Coverage &, const LocalCoords &, const SkMatrix &viewMatrix)
static const SkScalar kDefaultTolerance
Definition: GrPathUtils.h:32
SkScalar scaleToleranceToSrc(SkScalar devTol, const SkMatrix &viewM, const SkRect &pathBounds)
Definition: GrPathUtils.cpp:41
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
SkMesh mesh
Definition: SkRecords.h:345
void Helper(uword arg)
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
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
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 keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: SkRect.h:32
void sort()
Definition: SkRect.h:553
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition: SkRect.h:91
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
void join(const SkRect &r)
Definition: SkRect.cpp:126
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131