blob: ba1e853daedd3d4f7c29e95c2c6fff71a50c5153 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/ops/GrTessellatingPathRenderer.h"
Brian Salomon653f42f2018-07-10 10:07:31 -04009#include <stdio.h>
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/core/SkGeometry.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040011#include "src/gpu/GrAuditTrail.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrCaps.h"
13#include "src/gpu/GrClip.h"
14#include "src/gpu/GrDefaultGeoProcFactory.h"
15#include "src/gpu/GrDrawOpTest.h"
16#include "src/gpu/GrMesh.h"
17#include "src/gpu/GrOpFlushState.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrResourceCache.h"
19#include "src/gpu/GrResourceProvider.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrStyle.h"
21#include "src/gpu/GrTessellator.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040022#include "src/gpu/geometry/GrPathUtils.h"
23#include "src/gpu/geometry/GrShape.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/ops/GrMeshDrawOp.h"
25#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
joshualitt74417822015-08-07 11:42:16 -070026
Stephen Whitea7701e02018-01-23 15:35:05 -050027#ifndef GR_AA_TESSELLATOR_MAX_VERB_COUNT
28#define GR_AA_TESSELLATOR_MAX_VERB_COUNT 10
29#endif
30
senorblancod6ed19c2015-02-26 06:58:17 -080031/*
senorblancof57372d2016-08-31 10:36:19 -070032 * This path renderer tessellates the path into triangles using GrTessellator, uploads the
33 * triangles to a vertex buffer, and renders them with a single draw call. It can do screenspace
34 * antialiasing with a one-pixel coverage ramp.
senorblancod6ed19c2015-02-26 06:58:17 -080035 */
senorblancod6ed19c2015-02-26 06:58:17 -080036namespace {
37
senorblanco84cd6212015-08-04 10:01:58 -070038struct TessInfo {
39 SkScalar fTolerance;
senorblanco06f989a2015-09-02 09:05:17 -070040 int fCount;
senorblanco84cd6212015-08-04 10:01:58 -070041};
42
ethannicholase9709e82016-01-07 13:34:16 -080043// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
44class PathInvalidator : public SkPathRef::GenIDChangeListener {
45public:
Brian Salomon238069b2018-07-11 15:58:57 -040046 PathInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID)
47 : fMsg(key, contextUniqueID) {}
48
ethannicholase9709e82016-01-07 13:34:16 -080049private:
50 GrUniqueKeyInvalidatedMessage fMsg;
51
52 void onChange() override {
53 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
54 }
55};
56
Brian Salomondbf70722019-02-07 11:31:24 -050057bool cache_match(GrGpuBuffer* vertexBuffer, SkScalar tol, int* actualCount) {
senorblanco84cd6212015-08-04 10:01:58 -070058 if (!vertexBuffer) {
59 return false;
60 }
61 const SkData* data = vertexBuffer->getUniqueKey().getCustomData();
62 SkASSERT(data);
63 const TessInfo* info = static_cast<const TessInfo*>(data->data());
64 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) {
senorblanco06f989a2015-09-02 09:05:17 -070065 *actualCount = info->fCount;
senorblanco84cd6212015-08-04 10:01:58 -070066 return true;
67 }
68 return false;
69}
70
senorblanco6599eff2016-03-10 08:38:45 -080071class StaticVertexAllocator : public GrTessellator::VertexAllocator {
72public:
senorblancof57372d2016-08-31 10:36:19 -070073 StaticVertexAllocator(size_t stride, GrResourceProvider* resourceProvider, bool canMapVB)
74 : VertexAllocator(stride)
75 , fResourceProvider(resourceProvider)
senorblanco6599eff2016-03-10 08:38:45 -080076 , fCanMapVB(canMapVB)
77 , fVertices(nullptr) {
78 }
senorblancof57372d2016-08-31 10:36:19 -070079 void* lock(int vertexCount) override {
80 size_t size = vertexCount * stride();
Brian Salomonae64c192019-02-05 09:41:37 -050081 fVertexBuffer = fResourceProvider->createBuffer(size, GrGpuBufferType::kVertex,
Brian Salomondbf70722019-02-07 11:31:24 -050082 kStatic_GrAccessPattern);
senorblanco6599eff2016-03-10 08:38:45 -080083 if (!fVertexBuffer.get()) {
84 return nullptr;
85 }
86 if (fCanMapVB) {
senorblancof57372d2016-08-31 10:36:19 -070087 fVertices = fVertexBuffer->map();
senorblanco6599eff2016-03-10 08:38:45 -080088 } else {
senorblancof57372d2016-08-31 10:36:19 -070089 fVertices = sk_malloc_throw(vertexCount * stride());
senorblanco6599eff2016-03-10 08:38:45 -080090 }
91 return fVertices;
92 }
93 void unlock(int actualCount) override {
94 if (fCanMapVB) {
95 fVertexBuffer->unmap();
96 } else {
senorblancof57372d2016-08-31 10:36:19 -070097 fVertexBuffer->updateData(fVertices, actualCount * stride());
98 sk_free(fVertices);
senorblanco6599eff2016-03-10 08:38:45 -080099 }
100 fVertices = nullptr;
101 }
Brian Salomondbf70722019-02-07 11:31:24 -0500102 sk_sp<GrGpuBuffer> detachVertexBuffer() { return std::move(fVertexBuffer); }
Brian Salomon12d22642019-01-29 14:38:50 -0500103
senorblanco6599eff2016-03-10 08:38:45 -0800104private:
Brian Salomondbf70722019-02-07 11:31:24 -0500105 sk_sp<GrGpuBuffer> fVertexBuffer;
senorblanco6599eff2016-03-10 08:38:45 -0800106 GrResourceProvider* fResourceProvider;
107 bool fCanMapVB;
senorblancof57372d2016-08-31 10:36:19 -0700108 void* fVertices;
109};
110
111class DynamicVertexAllocator : public GrTessellator::VertexAllocator {
112public:
Brian Salomone5b399e2017-07-19 13:50:54 -0400113 DynamicVertexAllocator(size_t stride, GrMeshDrawOp::Target* target)
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400114 : VertexAllocator(stride)
115 , fTarget(target)
116 , fVertexBuffer(nullptr)
117 , fVertices(nullptr) {}
senorblancof57372d2016-08-31 10:36:19 -0700118 void* lock(int vertexCount) override {
119 fVertexCount = vertexCount;
120 fVertices = fTarget->makeVertexSpace(stride(), vertexCount, &fVertexBuffer, &fFirstVertex);
121 return fVertices;
122 }
123 void unlock(int actualCount) override {
124 fTarget->putBackVertices(fVertexCount - actualCount, stride());
125 fVertices = nullptr;
126 }
Brian Salomon12d22642019-01-29 14:38:50 -0500127 sk_sp<const GrBuffer> detachVertexBuffer() const { return std::move(fVertexBuffer); }
senorblancof57372d2016-08-31 10:36:19 -0700128 int firstVertex() const { return fFirstVertex; }
Brian Salomon12d22642019-01-29 14:38:50 -0500129
senorblancof57372d2016-08-31 10:36:19 -0700130private:
Brian Salomone5b399e2017-07-19 13:50:54 -0400131 GrMeshDrawOp::Target* fTarget;
Brian Salomon12d22642019-01-29 14:38:50 -0500132 sk_sp<const GrBuffer> fVertexBuffer;
senorblancof57372d2016-08-31 10:36:19 -0700133 int fVertexCount;
134 int fFirstVertex;
135 void* fVertices;
senorblanco6599eff2016-03-10 08:38:45 -0800136};
137
ethannicholase9709e82016-01-07 13:34:16 -0800138} // namespace
senorblancod6ed19c2015-02-26 06:58:17 -0800139
Stephen White8a3c0592019-05-29 11:26:16 -0400140GrTessellatingPathRenderer::GrTessellatingPathRenderer()
141 : fMaxVerbCount(GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
senorblancod6ed19c2015-02-26 06:58:17 -0800142}
143
Chris Dalton5ed44232017-09-07 13:22:46 -0600144GrPathRenderer::CanDrawPath
145GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
Chris Daltone5ede4b2017-09-07 18:33:08 +0000146 // This path renderer can draw fill styles, and can do screenspace antialiasing via a
147 // one-pixel coverage ramp. It can do convex and concave paths, but we'll leave the convex
148 // ones to simpler algorithms. We pass on paths that have styles, though they may come back
Chris Dalton09e56892019-03-13 00:22:01 -0600149 // around after applying the styling information to the geometry to create a filled path.
Chris Daltone5ede4b2017-09-07 18:33:08 +0000150 if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
Chris Dalton5ed44232017-09-07 13:22:46 -0600151 return CanDrawPath::kNo;
senorblancof57372d2016-08-31 10:36:19 -0700152 }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600153 switch (args.fAAType) {
154 case GrAAType::kNone:
155 case GrAAType::kMSAA:
156 // Prefer MSAA, if any antialiasing. In the non-analytic-AA case, We skip paths that
157 // don't have a key since the real advantage of this path renderer comes from caching
158 // the tessellated geometry.
159 if (!args.fShape->hasUnstyledKey()) {
160 return CanDrawPath::kNo;
161 }
162 break;
163 case GrAAType::kCoverage:
164 // Use analytic AA if we don't have MSAA. In this case, we do not cache, so we accept
165 // paths without keys.
166 SkPath path;
167 args.fShape->asPath(&path);
168 if (path.countVerbs() > fMaxVerbCount) {
169 return CanDrawPath::kNo;
170 }
171 break;
senorblancof57372d2016-08-31 10:36:19 -0700172 }
Chris Dalton5ed44232017-09-07 13:22:46 -0600173 return CanDrawPath::kYes;
senorblancod6ed19c2015-02-26 06:58:17 -0800174}
175
Brian Salomon9530f7e2017-07-11 09:03:10 -0400176namespace {
177
178class TessellatingPathOp final : public GrMeshDrawOp {
179private:
180 using Helper = GrSimpleMeshDrawOpHelperWithStencil;
181
senorblanco9ba39722015-03-05 07:13:42 -0800182public:
Brian Salomon25a88092016-12-01 09:36:50 -0500183 DEFINE_OP_CLASS_ID
senorblanco9ba39722015-03-05 07:13:42 -0800184
Robert Phillipsb97da532019-02-12 15:24:12 -0500185 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7c525e62018-06-12 10:11:12 -0400186 GrPaint&& paint,
Brian Salomon9530f7e2017-07-11 09:03:10 -0400187 const GrShape& shape,
188 const SkMatrix& viewMatrix,
189 SkIRect devClipBounds,
190 GrAAType aaType,
191 const GrUserStencilSettings* stencilSettings) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400192 return Helper::FactoryHelper<TessellatingPathOp>(context, std::move(paint), shape,
193 viewMatrix, devClipBounds,
194 aaType, stencilSettings);
senorblanco9ba39722015-03-05 07:13:42 -0800195 }
196
Brian Salomona6aa5902016-12-16 09:32:00 -0500197 const char* name() const override { return "TessellatingPathOp"; }
senorblanco9ba39722015-03-05 07:13:42 -0800198
Chris Dalton1706cbf2019-05-21 19:35:29 -0600199 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400200 fHelper.visitProxies(func);
201 }
202
Brian Osman9a390ac2018-11-12 09:47:48 -0500203#ifdef SK_DEBUG
Brian Salomon7c3e7182016-12-01 09:35:30 -0500204 SkString dumpInfo() const override {
205 SkString string;
Brian Osmancf860852018-10-31 14:04:39 -0400206 string.appendf("Color 0x%08x, aa: %d\n", fColor.toBytes_RGBA(), fAntiAlias);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400207 string += fHelper.dumpInfo();
208 string += INHERITED::dumpInfo();
Brian Salomon7c3e7182016-12-01 09:35:30 -0500209 return string;
210 }
Brian Osman9a390ac2018-11-12 09:47:48 -0500211#endif
Brian Salomon7c3e7182016-12-01 09:35:30 -0500212
Brian Salomon9530f7e2017-07-11 09:03:10 -0400213 TessellatingPathOp(Helper::MakeArgs helperArgs,
Brian Osmancf860852018-10-31 14:04:39 -0400214 const SkPMColor4f& color,
Brian Salomon9530f7e2017-07-11 09:03:10 -0400215 const GrShape& shape,
216 const SkMatrix& viewMatrix,
217 const SkIRect& devClipBounds,
218 GrAAType aaType,
219 const GrUserStencilSettings* stencilSettings)
220 : INHERITED(ClassID())
221 , fHelper(helperArgs, aaType, stencilSettings)
222 , fColor(color)
223 , fShape(shape)
224 , fViewMatrix(viewMatrix)
225 , fDevClipBounds(devClipBounds)
226 , fAntiAlias(GrAAType::kCoverage == aaType) {
227 SkRect devBounds;
228 viewMatrix.mapRect(&devBounds, shape.bounds());
229 if (shape.inverseFilled()) {
230 // Because the clip bounds are used to add a contour for inverse fills, they must also
231 // include the path bounds.
232 devBounds.join(SkRect::Make(fDevClipBounds));
233 }
Greg Daniel5faf4742019-10-01 15:14:44 -0400234 this->setBounds(devBounds, HasAABloat::kNo, IsHairline::kNo);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400235 }
236
237 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
238
Chris Dalton6ce447a2019-06-23 18:07:38 -0600239 GrProcessorSet::Analysis finalize(
240 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
241 GrClampType clampType) override {
Brian Salomon9530f7e2017-07-11 09:03:10 -0400242 GrProcessorAnalysisCoverage coverage = fAntiAlias
243 ? GrProcessorAnalysisCoverage::kSingleChannel
244 : GrProcessorAnalysisCoverage::kNone;
Brian Osman8fa7ab42019-03-18 10:22:42 -0400245 // This Op uses uniform (not vertex) color, so doesn't need to track wide color.
246 return fHelper.finalizeProcessors(
Chris Dalton6ce447a2019-06-23 18:07:38 -0600247 caps, clip, hasMixedSampledCoverage, clampType, coverage, &fColor, nullptr);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400248 }
249
Brian Salomon92aee3d2016-12-21 09:20:25 -0500250private:
senorblancof57372d2016-08-31 10:36:19 -0700251 SkPath getPath() const {
252 SkASSERT(!fShape.style().applies());
bsalomonee432412016-06-27 07:18:18 -0700253 SkPath path;
254 fShape.asPath(&path);
senorblancof57372d2016-08-31 10:36:19 -0700255 return path;
256 }
257
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500258 void draw(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) {
senorblancof57372d2016-08-31 10:36:19 -0700259 SkASSERT(!fAntiAlias);
260 GrResourceProvider* rp = target->resourceProvider();
261 bool inverseFill = fShape.inverseFilled();
senorblanco84cd6212015-08-04 10:01:58 -0700262 // construct a cache key from the path's genID and the view matrix
263 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
264 GrUniqueKey key;
senorblancof57372d2016-08-31 10:36:19 -0700265 static constexpr int kClipBoundsCnt = sizeof(fDevClipBounds) / sizeof(uint32_t);
bsalomonee432412016-06-27 07:18:18 -0700266 int shapeKeyDataCnt = fShape.unstyledKeySize();
267 SkASSERT(shapeKeyDataCnt >= 0);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400268 GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
bsalomonee432412016-06-27 07:18:18 -0700269 fShape.writeUnstyledKey(&builder[0]);
270 // For inverse fills, the tessellation is dependent on clip bounds.
271 if (inverseFill) {
senorblancof57372d2016-08-31 10:36:19 -0700272 memcpy(&builder[shapeKeyDataCnt], &fDevClipBounds, sizeof(fDevClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700273 } else {
senorblancof57372d2016-08-31 10:36:19 -0700274 memset(&builder[shapeKeyDataCnt], 0, sizeof(fDevClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700275 }
276 builder.finish();
Brian Salomondbf70722019-02-07 11:31:24 -0500277 sk_sp<GrGpuBuffer> cachedVertexBuffer(rp->findByUniqueKey<GrGpuBuffer>(key));
bsalomonee432412016-06-27 07:18:18 -0700278 int actualCount;
senorblancof57372d2016-08-31 10:36:19 -0700279 SkScalar tol = GrPathUtils::kDefaultTolerance;
280 tol = GrPathUtils::scaleToleranceToSrc(tol, fViewMatrix, fShape.bounds());
bsalomonee432412016-06-27 07:18:18 -0700281 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500282 this->drawVertices(target, gp, std::move(cachedVertexBuffer), 0, actualCount);
bsalomonee432412016-06-27 07:18:18 -0700283 return;
senorblanco84cd6212015-08-04 10:01:58 -0700284 }
285
senorblancof57372d2016-08-31 10:36:19 -0700286 SkRect clipBounds = SkRect::Make(fDevClipBounds);
287
288 SkMatrix vmi;
289 if (!fViewMatrix.invert(&vmi)) {
290 return;
291 }
292 vmi.mapRect(&clipBounds);
senorblanco6599eff2016-03-10 08:38:45 -0800293 bool isLinear;
294 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
Brian Salomon92be2f72018-06-19 14:33:47 -0400295 StaticVertexAllocator allocator(vertexStride, rp, canMapVB);
Brian Osman80879d42019-01-07 16:15:27 -0500296 int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator, false,
Brian Osman80879d42019-01-07 16:15:27 -0500297 &isLinear);
senorblanco6599eff2016-03-10 08:38:45 -0800298 if (count == 0) {
299 return;
300 }
Brian Salomondbf70722019-02-07 11:31:24 -0500301 sk_sp<GrGpuBuffer> vb = allocator.detachVertexBuffer();
bsalomonee432412016-06-27 07:18:18 -0700302 TessInfo info;
303 info.fTolerance = isLinear ? 0 : tol;
304 info.fCount = count;
Brian Salomon238069b2018-07-11 15:58:57 -0400305 fShape.addGenIDChangeListener(sk_make_sp<PathInvalidator>(key, target->contextUniqueID()));
Brian Salomon12d22642019-01-29 14:38:50 -0500306 key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info)));
307 rp->assignUniqueKeyToResource(key, vb.get());
308
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500309 this->drawVertices(target, gp, std::move(vb), 0, count);
senorblanco6599eff2016-03-10 08:38:45 -0800310 }
311
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500312 void drawAA(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) {
senorblancof57372d2016-08-31 10:36:19 -0700313 SkASSERT(fAntiAlias);
314 SkPath path = getPath();
315 if (path.isEmpty()) {
316 return;
317 }
318 SkRect clipBounds = SkRect::Make(fDevClipBounds);
319 path.transform(fViewMatrix);
320 SkScalar tol = GrPathUtils::kDefaultTolerance;
321 bool isLinear;
Brian Salomon92be2f72018-06-19 14:33:47 -0400322 DynamicVertexAllocator allocator(vertexStride, target);
Brian Osman80879d42019-01-07 16:15:27 -0500323 int count = GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true,
Brian Osman80879d42019-01-07 16:15:27 -0500324 &isLinear);
senorblancof57372d2016-08-31 10:36:19 -0700325 if (count == 0) {
326 return;
327 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500328 this->drawVertices(target, gp, allocator.detachVertexBuffer(),
Brian Salomon12d22642019-01-29 14:38:50 -0500329 allocator.firstVertex(), count);
senorblancof57372d2016-08-31 10:36:19 -0700330 }
331
Brian Salomon91326c32017-08-09 16:02:19 -0400332 void onPrepareDraws(Target* target) override {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500333 GrGeometryProcessor* gp;
joshualittdf0c5572015-08-03 11:35:28 -0700334 {
335 using namespace GrDefaultGeoProcFactory;
336
337 Color color(fColor);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400338 LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
Brian Salomon8c852be2017-01-04 10:44:42 -0500339 ? LocalCoords::kUsePosition_Type
340 : LocalCoords::kUnused_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700341 Coverage::Type coverageType;
senorblancof57372d2016-08-31 10:36:19 -0700342 if (fAntiAlias) {
Brian Osman605c6d52019-03-15 12:10:35 -0400343 if (fHelper.compatibleWithCoverageAsAlpha()) {
Brian Osman80879d42019-01-07 16:15:27 -0500344 coverageType = Coverage::kAttributeTweakAlpha_Type;
senorblancof57372d2016-08-31 10:36:19 -0700345 } else {
346 coverageType = Coverage::kAttribute_Type;
347 }
Brian Salomon8c852be2017-01-04 10:44:42 -0500348 } else {
joshualittdf0c5572015-08-03 11:35:28 -0700349 coverageType = Coverage::kSolid_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700350 }
senorblancof57372d2016-08-31 10:36:19 -0700351 if (fAntiAlias) {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500352 gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(target->allocator(),
353 target->caps().shaderCaps(),
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400354 color, coverageType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500355 localCoordsType, fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700356 } else {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500357 gp = GrDefaultGeoProcFactory::Make(target->allocator(), target->caps().shaderCaps(),
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400358 color, coverageType, localCoordsType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500359 fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700360 }
joshualittdf0c5572015-08-03 11:35:28 -0700361 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500362 if (!gp) {
Stephen Whitecc700832017-02-15 11:45:16 -0500363 return;
364 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500365 size_t vertexStride = gp->vertexStride();
senorblancof57372d2016-08-31 10:36:19 -0700366 if (fAntiAlias) {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500367 this->drawAA(target, gp, vertexStride);
senorblancof57372d2016-08-31 10:36:19 -0700368 } else {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500369 this->draw(target, gp, vertexStride);
senorblancof57372d2016-08-31 10:36:19 -0700370 }
senorblanco6599eff2016-03-10 08:38:45 -0800371 }
senorblanco84cd6212015-08-04 10:01:58 -0700372
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500373 void drawVertices(Target* target, const GrGeometryProcessor* gp, sk_sp<const GrBuffer> vb,
Brian Salomon91326c32017-08-09 16:02:19 -0400374 int firstVertex, int count) {
Robert Phillipse94cdd22019-11-04 14:15:58 -0500375 GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines
376 : GrPrimitiveType::kTriangles;
377
378 GrMesh* mesh = target->allocMesh(primitiveType);
Brian Salomon7eae3e02018-08-07 14:02:38 +0000379 mesh->setNonIndexedNonInstanced(count);
Brian Salomon12d22642019-01-29 14:38:50 -0500380 mesh->setVertexData(std::move(vb), firstVertex);
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500381 target->recordDraw(gp, mesh, 1, primitiveType);
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700382 }
383
384 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
385 fHelper.executeDrawsAndUploads(this, flushState, chainBounds);
senorblanco9ba39722015-03-05 07:13:42 -0800386 }
387
Robert Phillipse94cdd22019-11-04 14:15:58 -0500388 Helper fHelper;
Brian Osmancf860852018-10-31 14:04:39 -0400389 SkPMColor4f fColor;
bsalomonee432412016-06-27 07:18:18 -0700390 GrShape fShape;
bsalomon91d844d2015-08-10 10:47:29 -0700391 SkMatrix fViewMatrix;
senorblancof57372d2016-08-31 10:36:19 -0700392 SkIRect fDevClipBounds;
393 bool fAntiAlias;
reed1b55a962015-09-17 20:16:13 -0700394
Brian Salomon9530f7e2017-07-11 09:03:10 -0400395 typedef GrMeshDrawOp INHERITED;
senorblanco9ba39722015-03-05 07:13:42 -0800396};
397
Brian Salomon9530f7e2017-07-11 09:03:10 -0400398} // anonymous namespace
399
bsalomon0aff2fa2015-07-31 06:48:27 -0700400bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -0400401 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -0800402 "GrTessellatingPathRenderer::onDrawPath");
senorblancod6ed19c2015-02-26 06:58:17 -0800403 SkIRect clipBoundsI;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500404 args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
405 args.fRenderTargetContext->height(),
robertphillips976f5f02016-06-03 10:59:20 -0700406 &clipBoundsI);
Chris Dalton09e56892019-03-13 00:22:01 -0600407 std::unique_ptr<GrDrawOp> op = TessellatingPathOp::Make(
408 args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, clipBoundsI,
Chris Dalton6ce447a2019-06-23 18:07:38 -0600409 args.fAAType, args.fUserStencilSettings);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400410 args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
senorblancod6ed19c2015-02-26 06:58:17 -0800411 return true;
412}
joshualitt2fbd4062015-05-07 13:06:41 -0700413
414///////////////////////////////////////////////////////////////////////////////////////////////////
415
Hal Canary6f6961e2017-01-31 13:50:44 -0500416#if GR_TEST_UTILS
joshualitt2fbd4062015-05-07 13:06:41 -0700417
Brian Salomon9530f7e2017-07-11 09:03:10 -0400418GR_DRAW_OP_TEST_DEFINE(TesselatingPathOp) {
joshualitt2fbd4062015-05-07 13:06:41 -0700419 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
420 SkPath path = GrTest::TestPath(random);
bsalomond3030ac2016-09-01 07:20:29 -0700421 SkIRect devClipBounds = SkIRect::MakeLTRB(
senorblancof57372d2016-08-31 10:36:19 -0700422 random->nextU(), random->nextU(), random->nextU(), random->nextU());
bsalomond3030ac2016-09-01 07:20:29 -0700423 devClipBounds.sort();
Brian Salomon9530f7e2017-07-11 09:03:10 -0400424 static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
425 GrAAType aaType;
426 do {
427 aaType = kAATypes[random->nextULessThan(SK_ARRAY_COUNT(kAATypes))];
Chris Dalton6ce447a2019-06-23 18:07:38 -0600428 } while(GrAAType::kMSAA == aaType && numSamples <= 1);
bsalomon6663acf2016-05-10 09:14:17 -0700429 GrStyle style;
430 do {
431 GrTest::TestStyle(random, &style);
senorblancof57372d2016-08-31 10:36:19 -0700432 } while (!style.isSimpleFill());
bsalomonee432412016-06-27 07:18:18 -0700433 GrShape shape(path, style);
Robert Phillips7c525e62018-06-12 10:11:12 -0400434 return TessellatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
435 aaType, GrGetRandomStencil(random, context));
joshualitt2fbd4062015-05-07 13:06:41 -0700436}
437
438#endif