Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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) {
67 SkASSERT(data);
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:
164 sk_sp<GrGpuBuffer> fVertexBuffer;
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 {
228 GrProcessorAnalysisCoverage coverage = fAntiAlias
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 {
237 SkASSERT(!fShape.style().applies());
238 SkPath path;
239 fShape.asPath(&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
297 fViewMatrix, fShape.bounds());
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.
348 fShape.addGenIDChangeListener(
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
456 fViewMatrix, fShape.bounds());
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.
492 fShape.addGenIDChangeListener(
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;
537 GrStyledShape fShape;
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
585
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
624 GR_AUDIT_TRAIL_AUTO_FRAME(args.fContext->priv().auditTrail(),
625 "GrTriangulatingPathRenderer::onDrawPath");
626
627 GrOp::Owner op = TriangulatingPathOp::Make(
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
#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename)
#define DEFINE_OP_CLASS_ID
Definition GrOp.h:64
GrProcessorAnalysisCoverage
#define TRIANGULATOR_WIREFRAME
GrClampType
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
GrPrimitiveType
Definition GrTypesPriv.h:42
GrAAType
@ kStatic_GrAccessPattern
GrLoadOp
GrXferBarrierFlags
SkColor4f color
#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:3824
#define INHERITED(method,...)
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
#define TRACE_FUNC
#define GR_AA_TESSELLATOR_MAX_VERB_COUNT
static int PathToAATriangles(const SkPath &path, SkScalar tolerance, const SkRect &clipBounds, GrEagerVertexAllocator *vertexAllocator)
uint32_t contextID() const
@ 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
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)
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
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
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
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)
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
static void Post(Message m)
static Domain GenerateDomain()
bool onDrawPath(const DrawPathArgs &) override
CanDrawPath onCanDrawPath(const CanDrawPathArgs &) const override
const Paint & paint
float SkScalar
Definition extension.cpp:12
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint32_t * target
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)
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
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
#define TRACE_EVENT0(category_group, name)