blob: 39031e2d2d3aa7e5903610a286ba2ecba928c01f [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
8#include "GrTessellatingPathRenderer.h"
Brian Salomon653f42f2018-07-10 10:07:31 -04009#include <stdio.h>
robertphillips976f5f02016-06-03 10:59:20 -070010#include "GrAuditTrail.h"
robertphillips976f5f02016-06-03 10:59:20 -070011#include "GrClip.h"
senorblancod6ed19c2015-02-26 06:58:17 -080012#include "GrDefaultGeoProcFactory.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050013#include "GrDrawOpTest.h"
egdaniel0e1853c2016-03-17 11:35:45 -070014#include "GrMesh.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050015#include "GrOpFlushState.h"
senorblancod6ed19c2015-02-26 06:58:17 -080016#include "GrPathUtils.h"
senorblanco84cd6212015-08-04 10:01:58 -070017#include "GrResourceCache.h"
18#include "GrResourceProvider.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040019#include "GrShape.h"
20#include "GrSimpleMeshDrawOpHelper.h"
21#include "GrStyle.h"
ethannicholase9709e82016-01-07 13:34:16 -080022#include "GrTessellator.h"
senorblancod6ed19c2015-02-26 06:58:17 -080023#include "SkGeometry.h"
Brian Salomon89527432016-12-16 09:52:16 -050024#include "ops/GrMeshDrawOp.h"
joshualitt74417822015-08-07 11:42:16 -070025
Stephen Whitea7701e02018-01-23 15:35:05 -050026#ifndef GR_AA_TESSELLATOR_MAX_VERB_COUNT
27#define GR_AA_TESSELLATOR_MAX_VERB_COUNT 10
28#endif
29
senorblancod6ed19c2015-02-26 06:58:17 -080030/*
senorblancof57372d2016-08-31 10:36:19 -070031 * This path renderer tessellates the path into triangles using GrTessellator, uploads the
32 * triangles to a vertex buffer, and renders them with a single draw call. It can do screenspace
33 * antialiasing with a one-pixel coverage ramp.
senorblancod6ed19c2015-02-26 06:58:17 -080034 */
senorblancod6ed19c2015-02-26 06:58:17 -080035namespace {
36
senorblanco84cd6212015-08-04 10:01:58 -070037struct TessInfo {
38 SkScalar fTolerance;
senorblanco06f989a2015-09-02 09:05:17 -070039 int fCount;
senorblanco84cd6212015-08-04 10:01:58 -070040};
41
ethannicholase9709e82016-01-07 13:34:16 -080042// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
43class PathInvalidator : public SkPathRef::GenIDChangeListener {
44public:
Brian Salomon238069b2018-07-11 15:58:57 -040045 PathInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID)
46 : fMsg(key, contextUniqueID) {}
47
ethannicholase9709e82016-01-07 13:34:16 -080048private:
49 GrUniqueKeyInvalidatedMessage fMsg;
50
51 void onChange() override {
52 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
53 }
54};
55
cdalton397536c2016-03-25 12:15:03 -070056bool cache_match(GrBuffer* vertexBuffer, SkScalar tol, int* actualCount) {
senorblanco84cd6212015-08-04 10:01:58 -070057 if (!vertexBuffer) {
58 return false;
59 }
60 const SkData* data = vertexBuffer->getUniqueKey().getCustomData();
61 SkASSERT(data);
62 const TessInfo* info = static_cast<const TessInfo*>(data->data());
63 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) {
senorblanco06f989a2015-09-02 09:05:17 -070064 *actualCount = info->fCount;
senorblanco84cd6212015-08-04 10:01:58 -070065 return true;
66 }
67 return false;
68}
69
senorblanco6599eff2016-03-10 08:38:45 -080070class StaticVertexAllocator : public GrTessellator::VertexAllocator {
71public:
senorblancof57372d2016-08-31 10:36:19 -070072 StaticVertexAllocator(size_t stride, GrResourceProvider* resourceProvider, bool canMapVB)
73 : VertexAllocator(stride)
74 , fResourceProvider(resourceProvider)
senorblanco6599eff2016-03-10 08:38:45 -080075 , fCanMapVB(canMapVB)
76 , fVertices(nullptr) {
77 }
senorblancof57372d2016-08-31 10:36:19 -070078 void* lock(int vertexCount) override {
79 size_t size = vertexCount * stride();
cdalton397536c2016-03-25 12:15:03 -070080 fVertexBuffer.reset(fResourceProvider->createBuffer(
Chris Daltond004e0b2018-09-27 09:28:03 -060081 size, kVertex_GrBufferType, kStatic_GrAccessPattern, GrResourceProvider::Flags::kNone));
senorblanco6599eff2016-03-10 08:38:45 -080082 if (!fVertexBuffer.get()) {
83 return nullptr;
84 }
85 if (fCanMapVB) {
senorblancof57372d2016-08-31 10:36:19 -070086 fVertices = fVertexBuffer->map();
senorblanco6599eff2016-03-10 08:38:45 -080087 } else {
senorblancof57372d2016-08-31 10:36:19 -070088 fVertices = sk_malloc_throw(vertexCount * stride());
senorblanco6599eff2016-03-10 08:38:45 -080089 }
90 return fVertices;
91 }
92 void unlock(int actualCount) override {
93 if (fCanMapVB) {
94 fVertexBuffer->unmap();
95 } else {
senorblancof57372d2016-08-31 10:36:19 -070096 fVertexBuffer->updateData(fVertices, actualCount * stride());
97 sk_free(fVertices);
senorblanco6599eff2016-03-10 08:38:45 -080098 }
99 fVertices = nullptr;
100 }
cdalton397536c2016-03-25 12:15:03 -0700101 GrBuffer* vertexBuffer() { return fVertexBuffer.get(); }
senorblanco6599eff2016-03-10 08:38:45 -0800102private:
Hal Canary144caf52016-11-07 17:57:18 -0500103 sk_sp<GrBuffer> fVertexBuffer;
senorblanco6599eff2016-03-10 08:38:45 -0800104 GrResourceProvider* fResourceProvider;
105 bool fCanMapVB;
senorblancof57372d2016-08-31 10:36:19 -0700106 void* fVertices;
107};
108
109class DynamicVertexAllocator : public GrTessellator::VertexAllocator {
110public:
Brian Salomone5b399e2017-07-19 13:50:54 -0400111 DynamicVertexAllocator(size_t stride, GrMeshDrawOp::Target* target)
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400112 : VertexAllocator(stride)
113 , fTarget(target)
114 , fVertexBuffer(nullptr)
115 , fVertices(nullptr) {}
senorblancof57372d2016-08-31 10:36:19 -0700116 void* lock(int vertexCount) override {
117 fVertexCount = vertexCount;
118 fVertices = fTarget->makeVertexSpace(stride(), vertexCount, &fVertexBuffer, &fFirstVertex);
119 return fVertices;
120 }
121 void unlock(int actualCount) override {
122 fTarget->putBackVertices(fVertexCount - actualCount, stride());
123 fVertices = nullptr;
124 }
125 const GrBuffer* vertexBuffer() const { return fVertexBuffer; }
126 int firstVertex() const { return fFirstVertex; }
127private:
Brian Salomone5b399e2017-07-19 13:50:54 -0400128 GrMeshDrawOp::Target* fTarget;
senorblancof57372d2016-08-31 10:36:19 -0700129 const GrBuffer* fVertexBuffer;
130 int fVertexCount;
131 int fFirstVertex;
132 void* fVertices;
senorblanco6599eff2016-03-10 08:38:45 -0800133};
134
ethannicholase9709e82016-01-07 13:34:16 -0800135} // namespace
senorblancod6ed19c2015-02-26 06:58:17 -0800136
137GrTessellatingPathRenderer::GrTessellatingPathRenderer() {
138}
139
Chris Dalton5ed44232017-09-07 13:22:46 -0600140GrPathRenderer::CanDrawPath
141GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
Chris Daltone5ede4b2017-09-07 18:33:08 +0000142 // This path renderer can draw fill styles, and can do screenspace antialiasing via a
143 // one-pixel coverage ramp. It can do convex and concave paths, but we'll leave the convex
144 // ones to simpler algorithms. We pass on paths that have styles, though they may come back
145 // around after applying the styling information to the geometry to create a filled path. In
Chris Dalton5ed44232017-09-07 13:22:46 -0600146 // the non-AA case, We skip paths that don't have a key since the real advantage of this path
senorblancof57372d2016-08-31 10:36:19 -0700147 // renderer comes from caching the tessellated geometry. In the AA case, we do not cache, so we
148 // accept paths without keys.
Chris Daltone5ede4b2017-09-07 18:33:08 +0000149 if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
Chris Dalton5ed44232017-09-07 13:22:46 -0600150 return CanDrawPath::kNo;
senorblancof57372d2016-08-31 10:36:19 -0700151 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500152 if (GrAAType::kCoverage == args.fAAType) {
Stephan White021f9272017-01-03 21:06:16 +0000153 SkPath path;
154 args.fShape->asPath(&path);
Stephen Whitea7701e02018-01-23 15:35:05 -0500155 if (path.countVerbs() > GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
Chris Dalton5ed44232017-09-07 13:22:46 -0600156 return CanDrawPath::kNo;
Stephan White021f9272017-01-03 21:06:16 +0000157 }
senorblancof57372d2016-08-31 10:36:19 -0700158 } else if (!args.fShape->hasUnstyledKey()) {
Chris Dalton5ed44232017-09-07 13:22:46 -0600159 return CanDrawPath::kNo;
senorblancof57372d2016-08-31 10:36:19 -0700160 }
Chris Dalton5ed44232017-09-07 13:22:46 -0600161 return CanDrawPath::kYes;
senorblancod6ed19c2015-02-26 06:58:17 -0800162}
163
Brian Salomon9530f7e2017-07-11 09:03:10 -0400164namespace {
165
166class TessellatingPathOp final : public GrMeshDrawOp {
167private:
168 using Helper = GrSimpleMeshDrawOpHelperWithStencil;
169
senorblanco9ba39722015-03-05 07:13:42 -0800170public:
Brian Salomon25a88092016-12-01 09:36:50 -0500171 DEFINE_OP_CLASS_ID
senorblanco9ba39722015-03-05 07:13:42 -0800172
Robert Phillips7c525e62018-06-12 10:11:12 -0400173 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
174 GrPaint&& paint,
Brian Salomon9530f7e2017-07-11 09:03:10 -0400175 const GrShape& shape,
176 const SkMatrix& viewMatrix,
177 SkIRect devClipBounds,
178 GrAAType aaType,
179 const GrUserStencilSettings* stencilSettings) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400180 return Helper::FactoryHelper<TessellatingPathOp>(context, std::move(paint), shape,
181 viewMatrix, devClipBounds,
182 aaType, stencilSettings);
senorblanco9ba39722015-03-05 07:13:42 -0800183 }
184
Brian Salomona6aa5902016-12-16 09:32:00 -0500185 const char* name() const override { return "TessellatingPathOp"; }
senorblanco9ba39722015-03-05 07:13:42 -0800186
Brian Salomon7d94bb52018-10-12 14:37:19 -0400187 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400188 fHelper.visitProxies(func);
189 }
190
Brian Osman9a390ac2018-11-12 09:47:48 -0500191#ifdef SK_DEBUG
Brian Salomon7c3e7182016-12-01 09:35:30 -0500192 SkString dumpInfo() const override {
193 SkString string;
Brian Osmancf860852018-10-31 14:04:39 -0400194 string.appendf("Color 0x%08x, aa: %d\n", fColor.toBytes_RGBA(), fAntiAlias);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400195 string += fHelper.dumpInfo();
196 string += INHERITED::dumpInfo();
Brian Salomon7c3e7182016-12-01 09:35:30 -0500197 return string;
198 }
Brian Osman9a390ac2018-11-12 09:47:48 -0500199#endif
Brian Salomon7c3e7182016-12-01 09:35:30 -0500200
Brian Salomon9530f7e2017-07-11 09:03:10 -0400201 TessellatingPathOp(Helper::MakeArgs helperArgs,
Brian Osmancf860852018-10-31 14:04:39 -0400202 const SkPMColor4f& color,
Brian Salomon9530f7e2017-07-11 09:03:10 -0400203 const GrShape& shape,
204 const SkMatrix& viewMatrix,
205 const SkIRect& devClipBounds,
206 GrAAType aaType,
207 const GrUserStencilSettings* stencilSettings)
208 : INHERITED(ClassID())
209 , fHelper(helperArgs, aaType, stencilSettings)
210 , fColor(color)
211 , fShape(shape)
212 , fViewMatrix(viewMatrix)
213 , fDevClipBounds(devClipBounds)
214 , fAntiAlias(GrAAType::kCoverage == aaType) {
215 SkRect devBounds;
216 viewMatrix.mapRect(&devBounds, shape.bounds());
217 if (shape.inverseFilled()) {
218 // Because the clip bounds are used to add a contour for inverse fills, they must also
219 // include the path bounds.
220 devBounds.join(SkRect::Make(fDevClipBounds));
221 }
222 this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo);
223 }
224
225 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
226
Brian Osman532b3f92018-07-11 10:02:07 -0400227 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
Brian Salomon9530f7e2017-07-11 09:03:10 -0400228 GrProcessorAnalysisCoverage coverage = fAntiAlias
229 ? GrProcessorAnalysisCoverage::kSingleChannel
230 : GrProcessorAnalysisCoverage::kNone;
Brian Osman532b3f92018-07-11 10:02:07 -0400231 return fHelper.xpRequiresDstTexture(caps, clip, coverage, &fColor);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400232 }
233
Brian Salomon92aee3d2016-12-21 09:20:25 -0500234private:
senorblancof57372d2016-08-31 10:36:19 -0700235 SkPath getPath() const {
236 SkASSERT(!fShape.style().applies());
bsalomonee432412016-06-27 07:18:18 -0700237 SkPath path;
238 fShape.asPath(&path);
senorblancof57372d2016-08-31 10:36:19 -0700239 return path;
240 }
241
Brian Salomon7eae3e02018-08-07 14:02:38 +0000242 void draw(Target* target, sk_sp<const GrGeometryProcessor> gp, size_t vertexStride) {
senorblancof57372d2016-08-31 10:36:19 -0700243 SkASSERT(!fAntiAlias);
244 GrResourceProvider* rp = target->resourceProvider();
245 bool inverseFill = fShape.inverseFilled();
senorblanco84cd6212015-08-04 10:01:58 -0700246 // construct a cache key from the path's genID and the view matrix
247 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
248 GrUniqueKey key;
senorblancof57372d2016-08-31 10:36:19 -0700249 static constexpr int kClipBoundsCnt = sizeof(fDevClipBounds) / sizeof(uint32_t);
bsalomonee432412016-06-27 07:18:18 -0700250 int shapeKeyDataCnt = fShape.unstyledKeySize();
251 SkASSERT(shapeKeyDataCnt >= 0);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400252 GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
bsalomonee432412016-06-27 07:18:18 -0700253 fShape.writeUnstyledKey(&builder[0]);
254 // For inverse fills, the tessellation is dependent on clip bounds.
255 if (inverseFill) {
senorblancof57372d2016-08-31 10:36:19 -0700256 memcpy(&builder[shapeKeyDataCnt], &fDevClipBounds, sizeof(fDevClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700257 } else {
senorblancof57372d2016-08-31 10:36:19 -0700258 memset(&builder[shapeKeyDataCnt], 0, sizeof(fDevClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700259 }
260 builder.finish();
Brian Salomond28a79d2017-10-16 13:01:07 -0400261 sk_sp<GrBuffer> cachedVertexBuffer(rp->findByUniqueKey<GrBuffer>(key));
bsalomonee432412016-06-27 07:18:18 -0700262 int actualCount;
senorblancof57372d2016-08-31 10:36:19 -0700263 SkScalar tol = GrPathUtils::kDefaultTolerance;
264 tol = GrPathUtils::scaleToleranceToSrc(tol, fViewMatrix, fShape.bounds());
bsalomonee432412016-06-27 07:18:18 -0700265 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000266 this->drawVertices(target, std::move(gp), cachedVertexBuffer.get(), 0, actualCount);
bsalomonee432412016-06-27 07:18:18 -0700267 return;
senorblanco84cd6212015-08-04 10:01:58 -0700268 }
269
senorblancof57372d2016-08-31 10:36:19 -0700270 SkRect clipBounds = SkRect::Make(fDevClipBounds);
271
272 SkMatrix vmi;
273 if (!fViewMatrix.invert(&vmi)) {
274 return;
275 }
276 vmi.mapRect(&clipBounds);
senorblanco6599eff2016-03-10 08:38:45 -0800277 bool isLinear;
278 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
Brian Salomon92be2f72018-06-19 14:33:47 -0400279 StaticVertexAllocator allocator(vertexStride, rp, canMapVB);
Brian Osman80879d42019-01-07 16:15:27 -0500280 int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator, false,
Brian Osman80879d42019-01-07 16:15:27 -0500281 &isLinear);
senorblanco6599eff2016-03-10 08:38:45 -0800282 if (count == 0) {
283 return;
284 }
Brian Salomon7eae3e02018-08-07 14:02:38 +0000285 this->drawVertices(target, std::move(gp), allocator.vertexBuffer(), 0, count);
bsalomonee432412016-06-27 07:18:18 -0700286 TessInfo info;
287 info.fTolerance = isLinear ? 0 : tol;
288 info.fCount = count;
bungeman38d909e2016-08-02 14:40:46 -0700289 key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info)));
bsalomonee432412016-06-27 07:18:18 -0700290 rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
Brian Salomon238069b2018-07-11 15:58:57 -0400291 fShape.addGenIDChangeListener(sk_make_sp<PathInvalidator>(key, target->contextUniqueID()));
senorblanco6599eff2016-03-10 08:38:45 -0800292 }
293
Brian Salomon7eae3e02018-08-07 14:02:38 +0000294 void drawAA(Target* target, sk_sp<const GrGeometryProcessor> gp, size_t vertexStride) {
senorblancof57372d2016-08-31 10:36:19 -0700295 SkASSERT(fAntiAlias);
296 SkPath path = getPath();
297 if (path.isEmpty()) {
298 return;
299 }
300 SkRect clipBounds = SkRect::Make(fDevClipBounds);
301 path.transform(fViewMatrix);
302 SkScalar tol = GrPathUtils::kDefaultTolerance;
303 bool isLinear;
Brian Salomon92be2f72018-06-19 14:33:47 -0400304 DynamicVertexAllocator allocator(vertexStride, target);
Brian Osman80879d42019-01-07 16:15:27 -0500305 int count = GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true,
Brian Osman80879d42019-01-07 16:15:27 -0500306 &isLinear);
senorblancof57372d2016-08-31 10:36:19 -0700307 if (count == 0) {
308 return;
309 }
Brian Salomon7eae3e02018-08-07 14:02:38 +0000310 this->drawVertices(target, std::move(gp), allocator.vertexBuffer(), allocator.firstVertex(),
311 count);
senorblancof57372d2016-08-31 10:36:19 -0700312 }
313
Brian Salomon91326c32017-08-09 16:02:19 -0400314 void onPrepareDraws(Target* target) override {
bungeman06ca8ec2016-06-09 08:01:03 -0700315 sk_sp<GrGeometryProcessor> gp;
joshualittdf0c5572015-08-03 11:35:28 -0700316 {
317 using namespace GrDefaultGeoProcFactory;
318
319 Color color(fColor);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400320 LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
Brian Salomon8c852be2017-01-04 10:44:42 -0500321 ? LocalCoords::kUsePosition_Type
322 : LocalCoords::kUnused_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700323 Coverage::Type coverageType;
senorblancof57372d2016-08-31 10:36:19 -0700324 if (fAntiAlias) {
Brian Salomon9530f7e2017-07-11 09:03:10 -0400325 if (fHelper.compatibleWithAlphaAsCoverage()) {
Brian Osman80879d42019-01-07 16:15:27 -0500326 coverageType = Coverage::kAttributeTweakAlpha_Type;
senorblancof57372d2016-08-31 10:36:19 -0700327 } else {
328 coverageType = Coverage::kAttribute_Type;
329 }
Brian Salomon8c852be2017-01-04 10:44:42 -0500330 } else {
joshualittdf0c5572015-08-03 11:35:28 -0700331 coverageType = Coverage::kSolid_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700332 }
senorblancof57372d2016-08-31 10:36:19 -0700333 if (fAntiAlias) {
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400334 gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(target->caps().shaderCaps(),
335 color, coverageType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500336 localCoordsType, fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700337 } else {
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400338 gp = GrDefaultGeoProcFactory::Make(target->caps().shaderCaps(),
339 color, coverageType, localCoordsType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500340 fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700341 }
joshualittdf0c5572015-08-03 11:35:28 -0700342 }
Stephen Whitecc700832017-02-15 11:45:16 -0500343 if (!gp.get()) {
344 return;
345 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500346 size_t vertexStride = gp->vertexStride();
senorblancof57372d2016-08-31 10:36:19 -0700347 if (fAntiAlias) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000348 this->drawAA(target, std::move(gp), vertexStride);
senorblancof57372d2016-08-31 10:36:19 -0700349 } else {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000350 this->draw(target, std::move(gp), vertexStride);
senorblancof57372d2016-08-31 10:36:19 -0700351 }
senorblanco6599eff2016-03-10 08:38:45 -0800352 }
senorblanco84cd6212015-08-04 10:01:58 -0700353
Brian Salomon7eae3e02018-08-07 14:02:38 +0000354 void drawVertices(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrBuffer* vb,
Brian Salomon91326c32017-08-09 16:02:19 -0400355 int firstVertex, int count) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000356 GrMesh* mesh = target->allocMesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines
357 : GrPrimitiveType::kTriangles);
358 mesh->setNonIndexedNonInstanced(count);
359 mesh->setVertexData(vb, firstVertex);
Brian Salomon49348902018-06-26 09:12:38 -0400360 auto pipe = fHelper.makePipeline(target);
Brian Salomon7eae3e02018-08-07 14:02:38 +0000361 target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
senorblanco9ba39722015-03-05 07:13:42 -0800362 }
363
Brian Salomon9530f7e2017-07-11 09:03:10 -0400364 Helper fHelper;
Brian Osmancf860852018-10-31 14:04:39 -0400365 SkPMColor4f fColor;
bsalomonee432412016-06-27 07:18:18 -0700366 GrShape fShape;
bsalomon91d844d2015-08-10 10:47:29 -0700367 SkMatrix fViewMatrix;
senorblancof57372d2016-08-31 10:36:19 -0700368 SkIRect fDevClipBounds;
369 bool fAntiAlias;
reed1b55a962015-09-17 20:16:13 -0700370
Brian Salomon9530f7e2017-07-11 09:03:10 -0400371 typedef GrMeshDrawOp INHERITED;
senorblanco9ba39722015-03-05 07:13:42 -0800372};
373
Brian Salomon9530f7e2017-07-11 09:03:10 -0400374} // anonymous namespace
375
bsalomon0aff2fa2015-07-31 06:48:27 -0700376bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -0400377 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -0800378 "GrTessellatingPathRenderer::onDrawPath");
senorblancod6ed19c2015-02-26 06:58:17 -0800379 SkIRect clipBoundsI;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500380 args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
381 args.fRenderTargetContext->height(),
robertphillips976f5f02016-06-03 10:59:20 -0700382 &clipBoundsI);
Robert Phillips7c525e62018-06-12 10:11:12 -0400383 std::unique_ptr<GrDrawOp> op = TessellatingPathOp::Make(args.fContext,
384 std::move(args.fPaint),
Brian Salomon9530f7e2017-07-11 09:03:10 -0400385 *args.fShape,
386 *args.fViewMatrix,
387 clipBoundsI,
388 args.fAAType,
389 args.fUserStencilSettings);
390 args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
senorblancod6ed19c2015-02-26 06:58:17 -0800391 return true;
392}
joshualitt2fbd4062015-05-07 13:06:41 -0700393
394///////////////////////////////////////////////////////////////////////////////////////////////////
395
Hal Canary6f6961e2017-01-31 13:50:44 -0500396#if GR_TEST_UTILS
joshualitt2fbd4062015-05-07 13:06:41 -0700397
Brian Salomon9530f7e2017-07-11 09:03:10 -0400398GR_DRAW_OP_TEST_DEFINE(TesselatingPathOp) {
joshualitt2fbd4062015-05-07 13:06:41 -0700399 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
400 SkPath path = GrTest::TestPath(random);
bsalomond3030ac2016-09-01 07:20:29 -0700401 SkIRect devClipBounds = SkIRect::MakeLTRB(
senorblancof57372d2016-08-31 10:36:19 -0700402 random->nextU(), random->nextU(), random->nextU(), random->nextU());
bsalomond3030ac2016-09-01 07:20:29 -0700403 devClipBounds.sort();
Brian Salomon9530f7e2017-07-11 09:03:10 -0400404 static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
405 GrAAType aaType;
406 do {
407 aaType = kAATypes[random->nextULessThan(SK_ARRAY_COUNT(kAATypes))];
408 } while(GrAAType::kMSAA == aaType && GrFSAAType::kUnifiedMSAA != fsaaType);
bsalomon6663acf2016-05-10 09:14:17 -0700409 GrStyle style;
410 do {
411 GrTest::TestStyle(random, &style);
senorblancof57372d2016-08-31 10:36:19 -0700412 } while (!style.isSimpleFill());
bsalomonee432412016-06-27 07:18:18 -0700413 GrShape shape(path, style);
Robert Phillips7c525e62018-06-12 10:11:12 -0400414 return TessellatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
415 aaType, GrGetRandomStencil(random, context));
joshualitt2fbd4062015-05-07 13:06:41 -0700416}
417
418#endif