blob: 0d8ff25b06ea75141af6b437a67dafac292c1f92 [file] [log] [blame]
senorblancod6ed19c2015-02-26 06:58:17 -08001/*
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
Chris Dalton17dc4182020-03-25 16:18:16 -06008#include "src/gpu/ops/GrTriangulatingPathRenderer.h"
Brian Salomon71fe9452020-03-02 16:59:40 -05009
10#include "include/private/SkIDChangeListener.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkGeometry.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "src/gpu/GrAuditTrail.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrCaps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrDefaultGeoProcFactory.h"
15#include "src/gpu/GrDrawOpTest.h"
Chris Daltond081dce2020-01-23 12:09:04 -070016#include "src/gpu/GrEagerVertexAllocator.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/gpu/GrOpFlushState.h"
Robert Phillips740d34f2020-03-11 09:36:13 -040018#include "src/gpu/GrProgramInfo.h"
Michael Ludwig7c12e282020-05-29 09:54:07 -040019#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrResourceCache.h"
21#include "src/gpu/GrResourceProvider.h"
Chris Daltoneb694b72020-03-16 09:25:50 -060022#include "src/gpu/GrSimpleMesh.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/GrStyle.h"
Chris Dalton17dc4182020-03-25 16:18:16 -060024#include "src/gpu/GrTriangulator.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040025#include "src/gpu/geometry/GrPathUtils.h"
Michael Ludwig2686d692020-04-17 20:21:37 +000026#include "src/gpu/geometry/GrStyledShape.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/gpu/ops/GrMeshDrawOp.h"
Robert Phillips55f681f2020-02-28 08:58:15 -050028#include "src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h"
joshualitt74417822015-08-07 11:42:16 -070029
Chris Dalton17dc4182020-03-25 16:18:16 -060030#include <cstdio>
Brian Salomon71fe9452020-03-02 16:59:40 -050031
Stephen Whitea7701e02018-01-23 15:35:05 -050032#ifndef GR_AA_TESSELLATOR_MAX_VERB_COUNT
33#define GR_AA_TESSELLATOR_MAX_VERB_COUNT 10
34#endif
35
senorblancod6ed19c2015-02-26 06:58:17 -080036/*
Chris Dalton17dc4182020-03-25 16:18:16 -060037 * This path renderer linearizes and decomposes the path into triangles using GrTriangulator,
38 * uploads the triangles to a vertex buffer, and renders them with a single draw call. It can do
39 * screenspace antialiasing with a one-pixel coverage ramp.
senorblancod6ed19c2015-02-26 06:58:17 -080040 */
senorblancod6ed19c2015-02-26 06:58:17 -080041namespace {
42
senorblanco84cd6212015-08-04 10:01:58 -070043struct TessInfo {
44 SkScalar fTolerance;
senorblanco06f989a2015-09-02 09:05:17 -070045 int fCount;
senorblanco84cd6212015-08-04 10:01:58 -070046};
47
Robert Phillips6cc9d8d2020-10-20 09:42:33 -040048static sk_sp<SkData> create_data(int vertexCount, int numCountedCurves, SkScalar tol) {
49 TessInfo info;
50 info.fTolerance = (numCountedCurves == 0) ? 0 : tol;
51 info.fCount = vertexCount;
52 return SkData::MakeWithCopy(&info, sizeof(info));
53}
54
55bool cache_match(const SkData* data, SkScalar tol, int* actualCount) {
56 SkASSERT(data);
57
58 const TessInfo* info = static_cast<const TessInfo*>(data->data());
59 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) {
60 *actualCount = info->fCount;
61 return true;
62 }
63 return false;
64}
65
ethannicholase9709e82016-01-07 13:34:16 -080066// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
Brian Salomon99a813c2020-03-02 12:50:47 -050067class UniqueKeyInvalidator : public SkIDChangeListener {
ethannicholase9709e82016-01-07 13:34:16 -080068public:
Brian Salomon99a813c2020-03-02 12:50:47 -050069 UniqueKeyInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID)
Brian Salomon238069b2018-07-11 15:58:57 -040070 : fMsg(key, contextUniqueID) {}
71
ethannicholase9709e82016-01-07 13:34:16 -080072private:
73 GrUniqueKeyInvalidatedMessage fMsg;
74
Brian Salomon99a813c2020-03-02 12:50:47 -050075 void changed() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
ethannicholase9709e82016-01-07 13:34:16 -080076};
77
Chris Daltond081dce2020-01-23 12:09:04 -070078class StaticVertexAllocator : public GrEagerVertexAllocator {
senorblanco6599eff2016-03-10 08:38:45 -080079public:
Chris Daltond081dce2020-01-23 12:09:04 -070080 StaticVertexAllocator(GrResourceProvider* resourceProvider, bool canMapVB)
Robert Phillips6ffcb232020-10-14 12:40:13 -040081 : fResourceProvider(resourceProvider)
82 , fCanMapVB(canMapVB)
83 , fVertices(nullptr) {
senorblanco6599eff2016-03-10 08:38:45 -080084 }
Robert Phillips6ffcb232020-10-14 12:40:13 -040085
Chris Daltond081dce2020-01-23 12:09:04 -070086#ifdef SK_DEBUG
87 ~StaticVertexAllocator() override {
88 SkASSERT(!fLockStride);
89 }
90#endif
91 void* lock(size_t stride, int eagerCount) override {
92 SkASSERT(!fLockStride);
93 SkASSERT(stride);
94 size_t size = eagerCount * stride;
Brian Salomonae64c192019-02-05 09:41:37 -050095 fVertexBuffer = fResourceProvider->createBuffer(size, GrGpuBufferType::kVertex,
Brian Salomondbf70722019-02-07 11:31:24 -050096 kStatic_GrAccessPattern);
John Stilesa008b0f2020-08-16 08:48:02 -040097 if (!fVertexBuffer) {
senorblanco6599eff2016-03-10 08:38:45 -080098 return nullptr;
99 }
100 if (fCanMapVB) {
senorblancof57372d2016-08-31 10:36:19 -0700101 fVertices = fVertexBuffer->map();
senorblanco6599eff2016-03-10 08:38:45 -0800102 } else {
Chris Daltond081dce2020-01-23 12:09:04 -0700103 fVertices = sk_malloc_throw(eagerCount * stride);
senorblanco6599eff2016-03-10 08:38:45 -0800104 }
Chris Daltond081dce2020-01-23 12:09:04 -0700105 fLockStride = stride;
senorblanco6599eff2016-03-10 08:38:45 -0800106 return fVertices;
107 }
108 void unlock(int actualCount) override {
Chris Daltond081dce2020-01-23 12:09:04 -0700109 SkASSERT(fLockStride);
senorblanco6599eff2016-03-10 08:38:45 -0800110 if (fCanMapVB) {
111 fVertexBuffer->unmap();
112 } else {
Chris Daltond081dce2020-01-23 12:09:04 -0700113 fVertexBuffer->updateData(fVertices, actualCount * fLockStride);
senorblancof57372d2016-08-31 10:36:19 -0700114 sk_free(fVertices);
senorblanco6599eff2016-03-10 08:38:45 -0800115 }
116 fVertices = nullptr;
Chris Daltond081dce2020-01-23 12:09:04 -0700117 fLockStride = 0;
senorblanco6599eff2016-03-10 08:38:45 -0800118 }
Brian Salomondbf70722019-02-07 11:31:24 -0500119 sk_sp<GrGpuBuffer> detachVertexBuffer() { return std::move(fVertexBuffer); }
Brian Salomon12d22642019-01-29 14:38:50 -0500120
senorblanco6599eff2016-03-10 08:38:45 -0800121private:
Brian Salomondbf70722019-02-07 11:31:24 -0500122 sk_sp<GrGpuBuffer> fVertexBuffer;
senorblanco6599eff2016-03-10 08:38:45 -0800123 GrResourceProvider* fResourceProvider;
124 bool fCanMapVB;
senorblancof57372d2016-08-31 10:36:19 -0700125 void* fVertices;
Chris Daltond081dce2020-01-23 12:09:04 -0700126 size_t fLockStride = 0;
senorblanco6599eff2016-03-10 08:38:45 -0800127};
128
ethannicholase9709e82016-01-07 13:34:16 -0800129} // namespace
senorblancod6ed19c2015-02-26 06:58:17 -0800130
Chris Dalton17dc4182020-03-25 16:18:16 -0600131GrTriangulatingPathRenderer::GrTriangulatingPathRenderer()
Stephen White8a3c0592019-05-29 11:26:16 -0400132 : fMaxVerbCount(GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
senorblancod6ed19c2015-02-26 06:58:17 -0800133}
134
Chris Dalton5ed44232017-09-07 13:22:46 -0600135GrPathRenderer::CanDrawPath
Chris Dalton17dc4182020-03-25 16:18:16 -0600136GrTriangulatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
Chris Daltone5ede4b2017-09-07 18:33:08 +0000137 // This path renderer can draw fill styles, and can do screenspace antialiasing via a
138 // one-pixel coverage ramp. It can do convex and concave paths, but we'll leave the convex
139 // ones to simpler algorithms. We pass on paths that have styles, though they may come back
Chris Dalton09e56892019-03-13 00:22:01 -0600140 // around after applying the styling information to the geometry to create a filled path.
Chris Daltone5ede4b2017-09-07 18:33:08 +0000141 if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
Chris Dalton5ed44232017-09-07 13:22:46 -0600142 return CanDrawPath::kNo;
senorblancof57372d2016-08-31 10:36:19 -0700143 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600144 switch (args.fAAType) {
145 case GrAAType::kNone:
146 case GrAAType::kMSAA:
147 // Prefer MSAA, if any antialiasing. In the non-analytic-AA case, We skip paths that
148 // don't have a key since the real advantage of this path renderer comes from caching
149 // the tessellated geometry.
150 if (!args.fShape->hasUnstyledKey()) {
151 return CanDrawPath::kNo;
152 }
153 break;
154 case GrAAType::kCoverage:
155 // Use analytic AA if we don't have MSAA. In this case, we do not cache, so we accept
156 // paths without keys.
157 SkPath path;
158 args.fShape->asPath(&path);
159 if (path.countVerbs() > fMaxVerbCount) {
160 return CanDrawPath::kNo;
161 }
162 break;
senorblancof57372d2016-08-31 10:36:19 -0700163 }
Chris Dalton5ed44232017-09-07 13:22:46 -0600164 return CanDrawPath::kYes;
senorblancod6ed19c2015-02-26 06:58:17 -0800165}
166
Brian Salomon9530f7e2017-07-11 09:03:10 -0400167namespace {
168
Chris Dalton17dc4182020-03-25 16:18:16 -0600169class TriangulatingPathOp final : public GrMeshDrawOp {
Brian Salomon9530f7e2017-07-11 09:03:10 -0400170private:
171 using Helper = GrSimpleMeshDrawOpHelperWithStencil;
172
senorblanco9ba39722015-03-05 07:13:42 -0800173public:
Brian Salomon25a88092016-12-01 09:36:50 -0500174 DEFINE_OP_CLASS_ID
senorblanco9ba39722015-03-05 07:13:42 -0800175
Herb Derbyc76d4092020-10-07 16:46:15 -0400176 static GrOp::Owner Make(GrRecordingContext* context,
177 GrPaint&& paint,
178 const GrStyledShape& shape,
179 const SkMatrix& viewMatrix,
180 SkIRect devClipBounds,
181 GrAAType aaType,
182 const GrUserStencilSettings* stencilSettings) {
Chris Dalton17dc4182020-03-25 16:18:16 -0600183 return Helper::FactoryHelper<TriangulatingPathOp>(context, std::move(paint), shape,
184 viewMatrix, devClipBounds, aaType,
185 stencilSettings);
senorblanco9ba39722015-03-05 07:13:42 -0800186 }
187
Chris Dalton17dc4182020-03-25 16:18:16 -0600188 const char* name() const override { return "TriangulatingPathOp"; }
senorblanco9ba39722015-03-05 07:13:42 -0800189
Chris Dalton1706cbf2019-05-21 19:35:29 -0600190 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillips740d34f2020-03-11 09:36:13 -0400191 if (fProgramInfo) {
Chris Daltonbe457422020-03-16 18:05:03 -0600192 fProgramInfo->visitFPProxies(func);
Robert Phillips740d34f2020-03-11 09:36:13 -0400193 } else {
194 fHelper.visitProxies(func);
195 }
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400196 }
197
Herb Derbyc76d4092020-10-07 16:46:15 -0400198 TriangulatingPathOp(GrProcessorSet* processorSet,
Chris Dalton17dc4182020-03-25 16:18:16 -0600199 const SkPMColor4f& color,
Michael Ludwig2686d692020-04-17 20:21:37 +0000200 const GrStyledShape& shape,
Chris Dalton17dc4182020-03-25 16:18:16 -0600201 const SkMatrix& viewMatrix,
202 const SkIRect& devClipBounds,
203 GrAAType aaType,
204 const GrUserStencilSettings* stencilSettings)
Brian Salomon9530f7e2017-07-11 09:03:10 -0400205 : INHERITED(ClassID())
Herb Derbyc76d4092020-10-07 16:46:15 -0400206 , fHelper(processorSet, aaType, stencilSettings)
Brian Salomon9530f7e2017-07-11 09:03:10 -0400207 , fColor(color)
208 , fShape(shape)
209 , fViewMatrix(viewMatrix)
210 , fDevClipBounds(devClipBounds)
211 , fAntiAlias(GrAAType::kCoverage == aaType) {
212 SkRect devBounds;
213 viewMatrix.mapRect(&devBounds, shape.bounds());
214 if (shape.inverseFilled()) {
215 // Because the clip bounds are used to add a contour for inverse fills, they must also
216 // include the path bounds.
217 devBounds.join(SkRect::Make(fDevClipBounds));
218 }
Greg Daniel5faf4742019-10-01 15:14:44 -0400219 this->setBounds(devBounds, HasAABloat::kNo, IsHairline::kNo);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400220 }
221
222 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
223
Chris Dalton6ce447a2019-06-23 18:07:38 -0600224 GrProcessorSet::Analysis finalize(
225 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
226 GrClampType clampType) override {
Brian Salomon9530f7e2017-07-11 09:03:10 -0400227 GrProcessorAnalysisCoverage coverage = fAntiAlias
228 ? GrProcessorAnalysisCoverage::kSingleChannel
229 : GrProcessorAnalysisCoverage::kNone;
Brian Osman8fa7ab42019-03-18 10:22:42 -0400230 // This Op uses uniform (not vertex) color, so doesn't need to track wide color.
231 return fHelper.finalizeProcessors(
Chris Dalton6ce447a2019-06-23 18:07:38 -0600232 caps, clip, hasMixedSampledCoverage, clampType, coverage, &fColor, nullptr);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400233 }
234
Brian Salomon92aee3d2016-12-21 09:20:25 -0500235private:
senorblancof57372d2016-08-31 10:36:19 -0700236 SkPath getPath() const {
237 SkASSERT(!fShape.style().applies());
bsalomonee432412016-06-27 07:18:18 -0700238 SkPath path;
239 fShape.asPath(&path);
senorblancof57372d2016-08-31 10:36:19 -0700240 return path;
241 }
242
Robert Phillips6ffcb232020-10-14 12:40:13 -0400243 static void CreateKey(GrUniqueKey* key,
244 const GrStyledShape& shape,
245 const SkIRect& devClipBounds) {
senorblanco84cd6212015-08-04 10:01:58 -0700246 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
Robert Phillips6ffcb232020-10-14 12:40:13 -0400247
248 bool inverseFill = shape.inverseFilled();
249
250 static constexpr int kClipBoundsCnt = sizeof(devClipBounds) / sizeof(uint32_t);
251 int shapeKeyDataCnt = shape.unstyledKeySize();
bsalomonee432412016-06-27 07:18:18 -0700252 SkASSERT(shapeKeyDataCnt >= 0);
Robert Phillips6ffcb232020-10-14 12:40:13 -0400253 GrUniqueKey::Builder builder(key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
254 shape.writeUnstyledKey(&builder[0]);
bsalomonee432412016-06-27 07:18:18 -0700255 // For inverse fills, the tessellation is dependent on clip bounds.
256 if (inverseFill) {
Robert Phillips6ffcb232020-10-14 12:40:13 -0400257 memcpy(&builder[shapeKeyDataCnt], &devClipBounds, sizeof(devClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700258 } else {
Robert Phillips6ffcb232020-10-14 12:40:13 -0400259 memset(&builder[shapeKeyDataCnt], 0, sizeof(devClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700260 }
Robert Phillips6ffcb232020-10-14 12:40:13 -0400261
bsalomonee432412016-06-27 07:18:18 -0700262 builder.finish();
Robert Phillips6ffcb232020-10-14 12:40:13 -0400263 }
264
Robert Phillips9dfc6d82020-10-20 10:05:58 -0400265 // 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 int* numCountedCurves) {
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,
286 GrTriangulator::Mode::kNormal, numCountedCurves);
287 }
288
Robert Phillips6ffcb232020-10-14 12:40:13 -0400289 void createNonAAMesh(Target* target) {
290 SkASSERT(!fAntiAlias);
291 GrResourceProvider* rp = target->resourceProvider();
292
293 GrUniqueKey key;
294 CreateKey(&key, fShape, fDevClipBounds);
295
Robert Phillips6cc9d8d2020-10-20 09:42:33 -0400296 SkScalar tol = GrPathUtils::scaleToleranceToSrc(GrPathUtils::kDefaultTolerance,
297 fViewMatrix, fShape.bounds());
298
Brian Salomondbf70722019-02-07 11:31:24 -0500299 sk_sp<GrGpuBuffer> cachedVertexBuffer(rp->findByUniqueKey<GrGpuBuffer>(key));
Robert Phillips6cc9d8d2020-10-20 09:42:33 -0400300 if (cachedVertexBuffer) {
301 int actualCount;
302
303 if (cache_match(cachedVertexBuffer->getUniqueKey().getCustomData(), tol,
304 &actualCount)) {
305 this->createMesh(target, std::move(cachedVertexBuffer), 0, actualCount);
306 return;
307 }
senorblanco84cd6212015-08-04 10:01:58 -0700308 }
309
senorblanco6599eff2016-03-10 08:38:45 -0800310 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
Chris Daltond081dce2020-01-23 12:09:04 -0700311 StaticVertexAllocator allocator(rp, canMapVB);
Robert Phillips9dfc6d82020-10-20 10:05:58 -0400312
313 int numCountedCurves;
314 int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
315 &numCountedCurves);
Chris Dalton8e2b6942020-04-22 15:55:00 -0600316 if (vertexCount == 0) {
senorblanco6599eff2016-03-10 08:38:45 -0800317 return;
318 }
Robert Phillips9dfc6d82020-10-20 10:05:58 -0400319
Brian Salomondbf70722019-02-07 11:31:24 -0500320 sk_sp<GrGpuBuffer> vb = allocator.detachVertexBuffer();
Robert Phillips6cc9d8d2020-10-20 09:42:33 -0400321
322 key.setCustomData(create_data(vertexCount, numCountedCurves, tol));
323
Brian Salomon99a813c2020-03-02 12:50:47 -0500324 fShape.addGenIDChangeListener(
325 sk_make_sp<UniqueKeyInvalidator>(key, target->contextUniqueID()));
Brian Salomon12d22642019-01-29 14:38:50 -0500326 rp->assignUniqueKeyToResource(key, vb.get());
327
Chris Dalton8e2b6942020-04-22 15:55:00 -0600328 this->createMesh(target, std::move(vb), 0, vertexCount);
senorblanco6599eff2016-03-10 08:38:45 -0800329 }
330
Robert Phillips6ffcb232020-10-14 12:40:13 -0400331 void createAAMesh(Target* target) {
senorblancof57372d2016-08-31 10:36:19 -0700332 SkASSERT(fAntiAlias);
Robert Phillips6ffcb232020-10-14 12:40:13 -0400333 SkPath path = this->getPath();
senorblancof57372d2016-08-31 10:36:19 -0700334 if (path.isEmpty()) {
335 return;
336 }
337 SkRect clipBounds = SkRect::Make(fDevClipBounds);
338 path.transform(fViewMatrix);
339 SkScalar tol = GrPathUtils::kDefaultTolerance;
Chris Daltond081dce2020-01-23 12:09:04 -0700340 sk_sp<const GrBuffer> vertexBuffer;
341 int firstVertex;
Chris Dalton8e2b6942020-04-22 15:55:00 -0600342 int numCountedCurves;
Chris Daltond081dce2020-01-23 12:09:04 -0700343 GrEagerDynamicVertexAllocator allocator(target, &vertexBuffer, &firstVertex);
Chris Dalton8e2b6942020-04-22 15:55:00 -0600344 int vertexCount = GrTriangulator::PathToTriangles(path, tol, clipBounds, &allocator,
345 GrTriangulator::Mode::kEdgeAntialias,
346 &numCountedCurves);
347 if (vertexCount == 0) {
senorblancof57372d2016-08-31 10:36:19 -0700348 return;
349 }
Chris Dalton8e2b6942020-04-22 15:55:00 -0600350 this->createMesh(target, std::move(vertexBuffer), firstVertex, vertexCount);
senorblancof57372d2016-08-31 10:36:19 -0700351 }
352
Robert Phillips2669a7b2020-03-12 12:07:19 -0400353 GrProgramInfo* programInfo() override { return fProgramInfo; }
354
Robert Phillips4133dc42020-03-11 15:55:55 -0400355 void onCreateProgramInfo(const GrCaps* caps,
356 SkArenaAlloc* arena,
Brian Salomon8afde5f2020-04-01 16:22:00 -0400357 const GrSurfaceProxyView* writeView,
Robert Phillips4133dc42020-03-11 15:55:55 -0400358 GrAppliedClip&& appliedClip,
Greg Danield358cbe2020-09-11 09:33:54 -0400359 const GrXferProcessor::DstProxyView& dstProxyView,
360 GrXferBarrierFlags renderPassXferBarriers) override {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500361 GrGeometryProcessor* gp;
joshualittdf0c5572015-08-03 11:35:28 -0700362 {
363 using namespace GrDefaultGeoProcFactory;
364
365 Color color(fColor);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400366 LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
Brian Salomon8c852be2017-01-04 10:44:42 -0500367 ? LocalCoords::kUsePosition_Type
368 : LocalCoords::kUnused_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700369 Coverage::Type coverageType;
senorblancof57372d2016-08-31 10:36:19 -0700370 if (fAntiAlias) {
Brian Osman605c6d52019-03-15 12:10:35 -0400371 if (fHelper.compatibleWithCoverageAsAlpha()) {
Brian Osman80879d42019-01-07 16:15:27 -0500372 coverageType = Coverage::kAttributeTweakAlpha_Type;
senorblancof57372d2016-08-31 10:36:19 -0700373 } else {
374 coverageType = Coverage::kAttribute_Type;
375 }
Brian Salomon8c852be2017-01-04 10:44:42 -0500376 } else {
joshualittdf0c5572015-08-03 11:35:28 -0700377 coverageType = Coverage::kSolid_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700378 }
senorblancof57372d2016-08-31 10:36:19 -0700379 if (fAntiAlias) {
Brian Osmanf0aee742020-03-12 09:28:44 -0400380 gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(arena, color, coverageType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500381 localCoordsType, fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700382 } else {
Brian Osmanf0aee742020-03-12 09:28:44 -0400383 gp = GrDefaultGeoProcFactory::Make(arena, color, coverageType, localCoordsType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500384 fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700385 }
joshualittdf0c5572015-08-03 11:35:28 -0700386 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500387 if (!gp) {
Robert Phillips4133dc42020-03-11 15:55:55 -0400388 return;
Stephen Whitecc700832017-02-15 11:45:16 -0500389 }
Robert Phillips740d34f2020-03-11 09:36:13 -0400390
Chris Daltondcc8c542020-01-28 17:55:56 -0700391#ifdef SK_DEBUG
Chris Dalton17dc4182020-03-25 16:18:16 -0600392 auto mode = (fAntiAlias) ? GrTriangulator::Mode::kEdgeAntialias
393 : GrTriangulator::Mode::kNormal;
394 SkASSERT(GrTriangulator::GetVertexStride(mode) == gp->vertexStride());
Chris Daltondcc8c542020-01-28 17:55:56 -0700395#endif
senorblanco84cd6212015-08-04 10:01:58 -0700396
Chris Dalton17dc4182020-03-25 16:18:16 -0600397 GrPrimitiveType primitiveType = TRIANGULATOR_WIREFRAME ? GrPrimitiveType::kLines
398 : GrPrimitiveType::kTriangles;
Robert Phillipse94cdd22019-11-04 14:15:58 -0500399
Brian Salomon8afde5f2020-04-01 16:22:00 -0400400 fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
Robert Phillips4133dc42020-03-11 15:55:55 -0400401 std::move(appliedClip), dstProxyView,
Greg Danield358cbe2020-09-11 09:33:54 -0400402 gp, primitiveType,
403 renderPassXferBarriers);
Robert Phillips740d34f2020-03-11 09:36:13 -0400404 }
405
Robert Phillips473a8482020-10-20 10:44:15 -0400406 void onPrePrepareDraws(GrRecordingContext* rContext,
407 const GrSurfaceProxyView* writeView,
408 GrAppliedClip* clip,
409 const GrXferProcessor::DstProxyView& dstProxyView,
410 GrXferBarrierFlags renderPassXferBarriers) override {
411 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
412
413 INHERITED::onPrePrepareDraws(rContext, writeView, clip, dstProxyView,
414 renderPassXferBarriers);
415 }
416
Robert Phillips740d34f2020-03-11 09:36:13 -0400417 void onPrepareDraws(Target* target) override {
418 if (fAntiAlias) {
Robert Phillips6ffcb232020-10-14 12:40:13 -0400419 this->createAAMesh(target);
Robert Phillips740d34f2020-03-11 09:36:13 -0400420 } else {
Robert Phillips6ffcb232020-10-14 12:40:13 -0400421 this->createNonAAMesh(target);
Robert Phillips740d34f2020-03-11 09:36:13 -0400422 }
423 }
424
425 void createMesh(Target* target, sk_sp<const GrBuffer> vb, int firstVertex, int count) {
426 fMesh = target->allocMesh();
Chris Dalton37c7bdd2020-03-13 09:21:12 -0600427 fMesh->set(std::move(vb), count, firstVertex);
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700428 }
429
430 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
Robert Phillips740d34f2020-03-11 09:36:13 -0400431 if (!fProgramInfo) {
Robert Phillips4133dc42020-03-11 15:55:55 -0400432 this->createProgramInfo(flushState);
Robert Phillips740d34f2020-03-11 09:36:13 -0400433 }
Robert Phillips3968fcb2019-12-05 16:40:31 -0500434
Robert Phillips740d34f2020-03-11 09:36:13 -0400435 if (!fProgramInfo || !fMesh) {
436 return;
437 }
438
Chris Dalton765ed362020-03-16 17:34:44 -0600439 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
440 flushState->bindTextures(fProgramInfo->primProc(), nullptr, fProgramInfo->pipeline());
441 flushState->drawMesh(*fMesh);
senorblanco9ba39722015-03-05 07:13:42 -0800442 }
443
John Stilesaf366522020-08-13 09:57:34 -0400444#if GR_TEST_UTILS
445 SkString onDumpInfo() const override {
446 return SkStringPrintf("Color 0x%08x, aa: %d\n%s",
447 fColor.toBytes_RGBA(), fAntiAlias, fHelper.dumpInfo().c_str());
448 }
449#endif
450
Robert Phillips740d34f2020-03-11 09:36:13 -0400451 Helper fHelper;
452 SkPMColor4f fColor;
Michael Ludwig2686d692020-04-17 20:21:37 +0000453 GrStyledShape fShape;
Robert Phillips740d34f2020-03-11 09:36:13 -0400454 SkMatrix fViewMatrix;
455 SkIRect fDevClipBounds;
456 bool fAntiAlias;
457
Chris Daltoneb694b72020-03-16 09:25:50 -0600458 GrSimpleMesh* fMesh = nullptr;
Robert Phillips740d34f2020-03-11 09:36:13 -0400459 GrProgramInfo* fProgramInfo = nullptr;
reed1b55a962015-09-17 20:16:13 -0700460
John Stiles7571f9e2020-09-02 22:42:33 -0400461 using INHERITED = GrMeshDrawOp;
senorblanco9ba39722015-03-05 07:13:42 -0800462};
463
Brian Salomon9530f7e2017-07-11 09:03:10 -0400464} // anonymous namespace
465
Chris Dalton17dc4182020-03-25 16:18:16 -0600466bool GrTriangulatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -0400467 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
Chris Dalton17dc4182020-03-25 16:18:16 -0600468 "GrTriangulatingPathRenderer::onDrawPath");
Michael Ludwig7c12e282020-05-29 09:54:07 -0400469
Herb Derbyc76d4092020-10-07 16:46:15 -0400470 GrOp::Owner op = TriangulatingPathOp::Make(
Michael Ludwig7c12e282020-05-29 09:54:07 -0400471 args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
472 *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings);
473 args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
senorblancod6ed19c2015-02-26 06:58:17 -0800474 return true;
475}
joshualitt2fbd4062015-05-07 13:06:41 -0700476
477///////////////////////////////////////////////////////////////////////////////////////////////////
478
Hal Canary6f6961e2017-01-31 13:50:44 -0500479#if GR_TEST_UTILS
joshualitt2fbd4062015-05-07 13:06:41 -0700480
Chris Dalton17dc4182020-03-25 16:18:16 -0600481GR_DRAW_OP_TEST_DEFINE(TriangulatingPathOp) {
joshualitt2fbd4062015-05-07 13:06:41 -0700482 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
John Stiles31954bf2020-08-07 17:35:54 -0400483 const SkPath& path = GrTest::TestPath(random);
bsalomond3030ac2016-09-01 07:20:29 -0700484 SkIRect devClipBounds = SkIRect::MakeLTRB(
senorblancof57372d2016-08-31 10:36:19 -0700485 random->nextU(), random->nextU(), random->nextU(), random->nextU());
bsalomond3030ac2016-09-01 07:20:29 -0700486 devClipBounds.sort();
Brian Salomon9530f7e2017-07-11 09:03:10 -0400487 static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
488 GrAAType aaType;
489 do {
490 aaType = kAATypes[random->nextULessThan(SK_ARRAY_COUNT(kAATypes))];
Chris Dalton6ce447a2019-06-23 18:07:38 -0600491 } while(GrAAType::kMSAA == aaType && numSamples <= 1);
bsalomon6663acf2016-05-10 09:14:17 -0700492 GrStyle style;
493 do {
494 GrTest::TestStyle(random, &style);
senorblancof57372d2016-08-31 10:36:19 -0700495 } while (!style.isSimpleFill());
Michael Ludwig2686d692020-04-17 20:21:37 +0000496 GrStyledShape shape(path, style);
Chris Dalton17dc4182020-03-25 16:18:16 -0600497 return TriangulatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
498 aaType, GrGetRandomStencil(random, context));
joshualitt2fbd4062015-05-07 13:06:41 -0700499}
500
501#endif