blob: f7228683efc9436ff48b6deba923643cfdd80c7f [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(
cdaltone2e71c22016-04-07 18:13:29 -070081 size, kVertex_GrBufferType, kStatic_GrAccessPattern, 0));
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
Robert Phillipsf1748f52017-09-14 14:11:24 -0400187 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400188 fHelper.visitProxies(func);
189 }
190
Brian Salomon7c3e7182016-12-01 09:35:30 -0500191 SkString dumpInfo() const override {
192 SkString string;
193 string.appendf("Color 0x%08x, aa: %d\n", fColor, fAntiAlias);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400194 string += fHelper.dumpInfo();
195 string += INHERITED::dumpInfo();
Brian Salomon7c3e7182016-12-01 09:35:30 -0500196 return string;
197 }
198
Brian Salomon9530f7e2017-07-11 09:03:10 -0400199 TessellatingPathOp(Helper::MakeArgs helperArgs,
200 GrColor color,
201 const GrShape& shape,
202 const SkMatrix& viewMatrix,
203 const SkIRect& devClipBounds,
204 GrAAType aaType,
205 const GrUserStencilSettings* stencilSettings)
206 : INHERITED(ClassID())
207 , fHelper(helperArgs, aaType, stencilSettings)
208 , fColor(color)
209 , fShape(shape)
210 , fViewMatrix(viewMatrix)
211 , fDevClipBounds(devClipBounds)
212 , fAntiAlias(GrAAType::kCoverage == aaType) {
213 SkRect devBounds;
214 viewMatrix.mapRect(&devBounds, shape.bounds());
215 if (shape.inverseFilled()) {
216 // Because the clip bounds are used to add a contour for inverse fills, they must also
217 // include the path bounds.
218 devBounds.join(SkRect::Make(fDevClipBounds));
219 }
220 this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo);
221 }
222
223 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
224
Brian Osman532b3f92018-07-11 10:02:07 -0400225 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
Brian Salomon9530f7e2017-07-11 09:03:10 -0400226 GrProcessorAnalysisCoverage coverage = fAntiAlias
227 ? GrProcessorAnalysisCoverage::kSingleChannel
228 : GrProcessorAnalysisCoverage::kNone;
Brian Osman532b3f92018-07-11 10:02:07 -0400229 return fHelper.xpRequiresDstTexture(caps, clip, coverage, &fColor);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400230 }
231
Brian Salomon92aee3d2016-12-21 09:20:25 -0500232private:
senorblancof57372d2016-08-31 10:36:19 -0700233 SkPath getPath() const {
234 SkASSERT(!fShape.style().applies());
bsalomonee432412016-06-27 07:18:18 -0700235 SkPath path;
236 fShape.asPath(&path);
senorblancof57372d2016-08-31 10:36:19 -0700237 return path;
238 }
239
Brian Salomon7eae3e02018-08-07 14:02:38 +0000240 void draw(Target* target, sk_sp<const GrGeometryProcessor> gp, size_t vertexStride) {
senorblancof57372d2016-08-31 10:36:19 -0700241 SkASSERT(!fAntiAlias);
242 GrResourceProvider* rp = target->resourceProvider();
243 bool inverseFill = fShape.inverseFilled();
senorblanco84cd6212015-08-04 10:01:58 -0700244 // construct a cache key from the path's genID and the view matrix
245 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
246 GrUniqueKey key;
senorblancof57372d2016-08-31 10:36:19 -0700247 static constexpr int kClipBoundsCnt = sizeof(fDevClipBounds) / sizeof(uint32_t);
bsalomonee432412016-06-27 07:18:18 -0700248 int shapeKeyDataCnt = fShape.unstyledKeySize();
249 SkASSERT(shapeKeyDataCnt >= 0);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400250 GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
bsalomonee432412016-06-27 07:18:18 -0700251 fShape.writeUnstyledKey(&builder[0]);
252 // For inverse fills, the tessellation is dependent on clip bounds.
253 if (inverseFill) {
senorblancof57372d2016-08-31 10:36:19 -0700254 memcpy(&builder[shapeKeyDataCnt], &fDevClipBounds, sizeof(fDevClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700255 } else {
senorblancof57372d2016-08-31 10:36:19 -0700256 memset(&builder[shapeKeyDataCnt], 0, sizeof(fDevClipBounds));
bsalomonee432412016-06-27 07:18:18 -0700257 }
258 builder.finish();
Brian Salomond28a79d2017-10-16 13:01:07 -0400259 sk_sp<GrBuffer> cachedVertexBuffer(rp->findByUniqueKey<GrBuffer>(key));
bsalomonee432412016-06-27 07:18:18 -0700260 int actualCount;
senorblancof57372d2016-08-31 10:36:19 -0700261 SkScalar tol = GrPathUtils::kDefaultTolerance;
262 tol = GrPathUtils::scaleToleranceToSrc(tol, fViewMatrix, fShape.bounds());
bsalomonee432412016-06-27 07:18:18 -0700263 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000264 this->drawVertices(target, std::move(gp), cachedVertexBuffer.get(), 0, actualCount);
bsalomonee432412016-06-27 07:18:18 -0700265 return;
senorblanco84cd6212015-08-04 10:01:58 -0700266 }
267
senorblancof57372d2016-08-31 10:36:19 -0700268 SkRect clipBounds = SkRect::Make(fDevClipBounds);
269
270 SkMatrix vmi;
271 if (!fViewMatrix.invert(&vmi)) {
272 return;
273 }
274 vmi.mapRect(&clipBounds);
senorblanco6599eff2016-03-10 08:38:45 -0800275 bool isLinear;
276 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
Brian Salomon92be2f72018-06-19 14:33:47 -0400277 StaticVertexAllocator allocator(vertexStride, rp, canMapVB);
senorblancof57372d2016-08-31 10:36:19 -0700278 int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator,
279 false, GrColor(), false, &isLinear);
senorblanco6599eff2016-03-10 08:38:45 -0800280 if (count == 0) {
281 return;
282 }
Brian Salomon7eae3e02018-08-07 14:02:38 +0000283 this->drawVertices(target, std::move(gp), allocator.vertexBuffer(), 0, count);
bsalomonee432412016-06-27 07:18:18 -0700284 TessInfo info;
285 info.fTolerance = isLinear ? 0 : tol;
286 info.fCount = count;
bungeman38d909e2016-08-02 14:40:46 -0700287 key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info)));
bsalomonee432412016-06-27 07:18:18 -0700288 rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
Brian Salomon238069b2018-07-11 15:58:57 -0400289 fShape.addGenIDChangeListener(sk_make_sp<PathInvalidator>(key, target->contextUniqueID()));
senorblanco6599eff2016-03-10 08:38:45 -0800290 }
291
Brian Salomon7eae3e02018-08-07 14:02:38 +0000292 void drawAA(Target* target, sk_sp<const GrGeometryProcessor> gp, size_t vertexStride) {
senorblancof57372d2016-08-31 10:36:19 -0700293 SkASSERT(fAntiAlias);
294 SkPath path = getPath();
295 if (path.isEmpty()) {
296 return;
297 }
298 SkRect clipBounds = SkRect::Make(fDevClipBounds);
299 path.transform(fViewMatrix);
300 SkScalar tol = GrPathUtils::kDefaultTolerance;
301 bool isLinear;
Brian Salomon92be2f72018-06-19 14:33:47 -0400302 DynamicVertexAllocator allocator(vertexStride, target);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400303 int count =
304 GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true, fColor,
305 fHelper.compatibleWithAlphaAsCoverage(), &isLinear);
senorblancof57372d2016-08-31 10:36:19 -0700306 if (count == 0) {
307 return;
308 }
Brian Salomon7eae3e02018-08-07 14:02:38 +0000309 this->drawVertices(target, std::move(gp), allocator.vertexBuffer(), allocator.firstVertex(),
310 count);
senorblancof57372d2016-08-31 10:36:19 -0700311 }
312
Brian Salomon91326c32017-08-09 16:02:19 -0400313 void onPrepareDraws(Target* target) override {
bungeman06ca8ec2016-06-09 08:01:03 -0700314 sk_sp<GrGeometryProcessor> gp;
Brian Salomon92be2f72018-06-19 14:33:47 -0400315 size_t vertexStride;
joshualittdf0c5572015-08-03 11:35:28 -0700316 {
317 using namespace GrDefaultGeoProcFactory;
318
Brian Salomon92be2f72018-06-19 14:33:47 -0400319 vertexStride = sizeof(SkPoint); // position
320
joshualittdf0c5572015-08-03 11:35:28 -0700321 Color color(fColor);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400322 LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
Brian Salomon8c852be2017-01-04 10:44:42 -0500323 ? LocalCoords::kUsePosition_Type
324 : LocalCoords::kUnused_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700325 Coverage::Type coverageType;
senorblancof57372d2016-08-31 10:36:19 -0700326 if (fAntiAlias) {
Brian Salomon3de0aee2017-01-29 09:34:17 -0500327 color = Color(Color::kPremulGrColorAttribute_Type);
Brian Salomon92be2f72018-06-19 14:33:47 -0400328 vertexStride += sizeof(uint32_t);
Brian Salomon9530f7e2017-07-11 09:03:10 -0400329 if (fHelper.compatibleWithAlphaAsCoverage()) {
senorblancof57372d2016-08-31 10:36:19 -0700330 coverageType = Coverage::kSolid_Type;
331 } else {
332 coverageType = Coverage::kAttribute_Type;
Brian Salomon92be2f72018-06-19 14:33:47 -0400333 vertexStride += 4;
senorblancof57372d2016-08-31 10:36:19 -0700334 }
Brian Salomon8c852be2017-01-04 10:44:42 -0500335 } else {
joshualittdf0c5572015-08-03 11:35:28 -0700336 coverageType = Coverage::kSolid_Type;
joshualittdf0c5572015-08-03 11:35:28 -0700337 }
senorblancof57372d2016-08-31 10:36:19 -0700338 if (fAntiAlias) {
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400339 gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(target->caps().shaderCaps(),
340 color, coverageType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500341 localCoordsType, fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700342 } else {
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400343 gp = GrDefaultGeoProcFactory::Make(target->caps().shaderCaps(),
344 color, coverageType, localCoordsType,
Brian Salomon8c852be2017-01-04 10:44:42 -0500345 fViewMatrix);
senorblancof57372d2016-08-31 10:36:19 -0700346 }
joshualittdf0c5572015-08-03 11:35:28 -0700347 }
Stephen Whitecc700832017-02-15 11:45:16 -0500348 if (!gp.get()) {
349 return;
350 }
Brian Salomon92be2f72018-06-19 14:33:47 -0400351 SkASSERT(vertexStride == gp->debugOnly_vertexStride());
senorblancof57372d2016-08-31 10:36:19 -0700352 if (fAntiAlias) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000353 this->drawAA(target, std::move(gp), vertexStride);
senorblancof57372d2016-08-31 10:36:19 -0700354 } else {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000355 this->draw(target, std::move(gp), vertexStride);
senorblancof57372d2016-08-31 10:36:19 -0700356 }
senorblanco6599eff2016-03-10 08:38:45 -0800357 }
senorblanco84cd6212015-08-04 10:01:58 -0700358
Brian Salomon7eae3e02018-08-07 14:02:38 +0000359 void drawVertices(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrBuffer* vb,
Brian Salomon91326c32017-08-09 16:02:19 -0400360 int firstVertex, int count) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000361 GrMesh* mesh = target->allocMesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines
362 : GrPrimitiveType::kTriangles);
363 mesh->setNonIndexedNonInstanced(count);
364 mesh->setVertexData(vb, firstVertex);
Brian Salomon49348902018-06-26 09:12:38 -0400365 auto pipe = fHelper.makePipeline(target);
Brian Salomon7eae3e02018-08-07 14:02:38 +0000366 target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
senorblanco9ba39722015-03-05 07:13:42 -0800367 }
368
Brian Salomon9530f7e2017-07-11 09:03:10 -0400369 Helper fHelper;
bsalomon91d844d2015-08-10 10:47:29 -0700370 GrColor fColor;
bsalomonee432412016-06-27 07:18:18 -0700371 GrShape fShape;
bsalomon91d844d2015-08-10 10:47:29 -0700372 SkMatrix fViewMatrix;
senorblancof57372d2016-08-31 10:36:19 -0700373 SkIRect fDevClipBounds;
374 bool fAntiAlias;
reed1b55a962015-09-17 20:16:13 -0700375
Brian Salomon9530f7e2017-07-11 09:03:10 -0400376 typedef GrMeshDrawOp INHERITED;
senorblanco9ba39722015-03-05 07:13:42 -0800377};
378
Brian Salomon9530f7e2017-07-11 09:03:10 -0400379} // anonymous namespace
380
bsalomon0aff2fa2015-07-31 06:48:27 -0700381bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -0400382 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -0800383 "GrTessellatingPathRenderer::onDrawPath");
senorblancod6ed19c2015-02-26 06:58:17 -0800384 SkIRect clipBoundsI;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500385 args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
386 args.fRenderTargetContext->height(),
robertphillips976f5f02016-06-03 10:59:20 -0700387 &clipBoundsI);
Robert Phillips7c525e62018-06-12 10:11:12 -0400388 std::unique_ptr<GrDrawOp> op = TessellatingPathOp::Make(args.fContext,
389 std::move(args.fPaint),
Brian Salomon9530f7e2017-07-11 09:03:10 -0400390 *args.fShape,
391 *args.fViewMatrix,
392 clipBoundsI,
393 args.fAAType,
394 args.fUserStencilSettings);
395 args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
senorblancod6ed19c2015-02-26 06:58:17 -0800396 return true;
397}
joshualitt2fbd4062015-05-07 13:06:41 -0700398
399///////////////////////////////////////////////////////////////////////////////////////////////////
400
Hal Canary6f6961e2017-01-31 13:50:44 -0500401#if GR_TEST_UTILS
joshualitt2fbd4062015-05-07 13:06:41 -0700402
Brian Salomon9530f7e2017-07-11 09:03:10 -0400403GR_DRAW_OP_TEST_DEFINE(TesselatingPathOp) {
joshualitt2fbd4062015-05-07 13:06:41 -0700404 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
405 SkPath path = GrTest::TestPath(random);
bsalomond3030ac2016-09-01 07:20:29 -0700406 SkIRect devClipBounds = SkIRect::MakeLTRB(
senorblancof57372d2016-08-31 10:36:19 -0700407 random->nextU(), random->nextU(), random->nextU(), random->nextU());
bsalomond3030ac2016-09-01 07:20:29 -0700408 devClipBounds.sort();
Brian Salomon9530f7e2017-07-11 09:03:10 -0400409 static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
410 GrAAType aaType;
411 do {
412 aaType = kAATypes[random->nextULessThan(SK_ARRAY_COUNT(kAATypes))];
413 } while(GrAAType::kMSAA == aaType && GrFSAAType::kUnifiedMSAA != fsaaType);
bsalomon6663acf2016-05-10 09:14:17 -0700414 GrStyle style;
415 do {
416 GrTest::TestStyle(random, &style);
senorblancof57372d2016-08-31 10:36:19 -0700417 } while (!style.isSimpleFill());
bsalomonee432412016-06-27 07:18:18 -0700418 GrShape shape(path, style);
Robert Phillips7c525e62018-06-12 10:11:12 -0400419 return TessellatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
420 aaType, GrGetRandomStencil(random, context));
joshualitt2fbd4062015-05-07 13:06:41 -0700421}
422
423#endif