blob: a91f7f605cb39b8dd7a5843aeb11cc04e313b3c2 [file] [log] [blame]
ethannicholas1a1b3ac2015-06-10 12:11:17 -07001/*
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 "GrAALinearizingConvexPathRenderer.h"
9
10#include "GrAAConvexTessellator.h"
bsalomon75398562015-08-17 12:55:38 -070011#include "GrBatchFlushState.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070012#include "GrBatchTest.h"
13#include "GrContext.h"
14#include "GrDefaultGeoProcFactory.h"
15#include "GrGeometryProcessor.h"
16#include "GrInvariantOutput.h"
17#include "GrPathUtils.h"
18#include "GrProcessor.h"
bsalomonbb243832016-07-22 07:10:19 -070019#include "GrPipelineBuilder.h"
bsalomon6663acf2016-05-10 09:14:17 -070020#include "GrStyle.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070021#include "SkGeometry.h"
22#include "SkString.h"
23#include "SkTraceEvent.h"
fmalitabd5d7e72015-06-26 07:18:24 -070024#include "SkPathPriv.h"
bsalomon16b99132015-08-13 14:55:50 -070025#include "batches/GrVertexBatch.h"
egdaniele659a582015-11-13 09:55:43 -080026#include "glsl/GrGLSLGeometryProcessor.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070027
fmalitabd5d7e72015-06-26 07:18:24 -070028static const int DEFAULT_BUFFER_SIZE = 100;
29
30// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For
31// the time being, we simply drop back to software rendering above this stroke width.
32static const SkScalar kMaxStrokeWidth = 20.0;
ethannicholas1a1b3ac2015-06-10 12:11:17 -070033
34GrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
35}
36
37///////////////////////////////////////////////////////////////////////////////
38
bsalomon0aff2fa2015-07-31 06:48:27 -070039bool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
40 if (!args.fAntiAlias) {
fmalitabd5d7e72015-06-26 07:18:24 -070041 return false;
42 }
bsalomon8acedde2016-06-24 10:42:16 -070043 if (!args.fShape->knownToBeConvex()) {
fmalitabd5d7e72015-06-26 07:18:24 -070044 return false;
45 }
bsalomon8acedde2016-06-24 10:42:16 -070046 if (args.fShape->style().pathEffect()) {
fmalitabd5d7e72015-06-26 07:18:24 -070047 return false;
48 }
bsalomon8acedde2016-06-24 10:42:16 -070049 if (args.fShape->inverseFilled()) {
bsalomon6663acf2016-05-10 09:14:17 -070050 return false;
51 }
bsalomon8acedde2016-06-24 10:42:16 -070052 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
robertphillips8c170972016-09-22 12:42:30 -070053
54 if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
55 stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
ethannicholasfea77632015-08-19 12:09:12 -070056 if (!args.fViewMatrix->isSimilarity()) {
57 return false;
58 }
bsalomon6663acf2016-05-10 09:14:17 -070059 SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth();
robertphillips8c170972016-09-22 12:42:30 -070060 if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) {
61 return false;
62 }
63 return strokeWidth <= kMaxStrokeWidth &&
bsalomon8acedde2016-06-24 10:42:16 -070064 args.fShape->knownToBeClosed() &&
bsalomon6663acf2016-05-10 09:14:17 -070065 stroke.getJoin() != SkPaint::Join::kRound_Join;
fmalitabd5d7e72015-06-26 07:18:24 -070066 }
bsalomon6663acf2016-05-10 09:14:17 -070067 return stroke.getStyle() == SkStrokeRec::kFill_Style;
ethannicholas1a1b3ac2015-06-10 12:11:17 -070068}
69
70// extract the result vertices and indices from the GrAAConvexTessellator
71static void extract_verts(const GrAAConvexTessellator& tess,
72 void* vertices,
73 size_t vertexStride,
74 GrColor color,
75 uint16_t firstIndex,
76 uint16_t* idxs,
77 bool tweakAlphaForCoverage) {
78 intptr_t verts = reinterpret_cast<intptr_t>(vertices);
79
80 for (int i = 0; i < tess.numPts(); ++i) {
81 *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
82 }
83
84 // Make 'verts' point to the colors
85 verts += sizeof(SkPoint);
86 for (int i = 0; i < tess.numPts(); ++i) {
ethannicholas1a1b3ac2015-06-10 12:11:17 -070087 if (tweakAlphaForCoverage) {
fmalitabd5d7e72015-06-26 07:18:24 -070088 SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
89 unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
ethannicholas1a1b3ac2015-06-10 12:11:17 -070090 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
91 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
92 } else {
93 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
mtklein002c2ce2015-08-26 05:43:22 -070094 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) =
fmalitabd5d7e72015-06-26 07:18:24 -070095 tess.coverage(i);
ethannicholas1a1b3ac2015-06-10 12:11:17 -070096 }
97 }
98
99 for (int i = 0; i < tess.numIndices(); ++i) {
100 idxs[i] = tess.index(i) + firstIndex;
101 }
102}
103
bungeman06ca8ec2016-06-09 08:01:03 -0700104static sk_sp<GrGeometryProcessor> create_fill_gp(bool tweakAlphaForCoverage,
joshualittdf0c5572015-08-03 11:35:28 -0700105 const SkMatrix& viewMatrix,
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700106 bool usesLocalCoords,
107 bool coverageIgnored) {
joshualittdf0c5572015-08-03 11:35:28 -0700108 using namespace GrDefaultGeoProcFactory;
joshualitte494a582015-08-03 09:32:36 -0700109
joshualittdf0c5572015-08-03 11:35:28 -0700110 Color color(Color::kAttribute_Type);
111 Coverage::Type coverageType;
112 // TODO remove coverage if coverage is ignored
113 /*if (coverageIgnored) {
114 coverageType = Coverage::kNone_Type;
115 } else*/ if (tweakAlphaForCoverage) {
116 coverageType = Coverage::kSolid_Type;
117 } else {
118 coverageType = Coverage::kAttribute_Type;
119 }
120 Coverage coverage(coverageType);
121 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type :
122 LocalCoords::kUnused_Type);
bungeman06ca8ec2016-06-09 08:01:03 -0700123 return MakeForDeviceSpace(color, coverage, localCoords, viewMatrix);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700124}
125
bsalomonabd30f52015-08-13 13:34:48 -0700126class AAFlatteningConvexPathBatch : public GrVertexBatch {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700127public:
Brian Salomon25a88092016-12-01 09:36:50 -0500128 DEFINE_OP_CLASS_ID
reed1b55a962015-09-17 20:16:13 -0700129
bsalomon0432dd62016-06-30 07:19:27 -0700130 AAFlatteningConvexPathBatch(GrColor color,
131 const SkMatrix& viewMatrix,
132 const SkPath& path,
133 SkScalar strokeWidth,
robertphillips8c170972016-09-22 12:42:30 -0700134 SkStrokeRec::Style style,
bsalomon0432dd62016-06-30 07:19:27 -0700135 SkPaint::Join join,
136 SkScalar miterLimit) : INHERITED(ClassID()) {
robertphillips8c170972016-09-22 12:42:30 -0700137 fGeoData.emplace_back(Geometry{ color, viewMatrix, path,
138 strokeWidth, style, join, miterLimit });
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700139
bsalomon0432dd62016-06-30 07:19:27 -0700140 // compute bounds
bsalomon88cf17d2016-07-08 06:40:56 -0700141 SkRect bounds = path.getBounds();
bsalomon0432dd62016-06-30 07:19:27 -0700142 SkScalar w = strokeWidth;
143 if (w > 0) {
144 w /= 2;
145 // If the half stroke width is < 1 then we effectively fallback to bevel joins.
146 if (SkPaint::kMiter_Join == join && w > 1.f) {
147 w *= miterLimit;
148 }
bsalomon88cf17d2016-07-08 06:40:56 -0700149 bounds.outset(w, w);
bsalomon0432dd62016-06-30 07:19:27 -0700150 }
bsalomon88cf17d2016-07-08 06:40:56 -0700151 this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700152 }
153
Brian Salomon7c3e7182016-12-01 09:35:30 -0500154 const char* name() const override { return "AAFlatteningConvexBatch"; }
155
156 SkString dumpInfo() const override {
157 SkString string;
158 for (const auto& geo : fGeoData) {
159 string.appendf("Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, "
160 "MiterLimit: %.2f\n",
161 geo.fColor, geo.fStrokeWidth, geo.fStyle, geo.fJoin, geo.fMiterLimit);
162 }
163 string.append(DumpPipelineInfo(*this->pipeline()));
164 string.append(INHERITED::dumpInfo());
165 return string;
166 }
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700167
halcanary9d524f22016-03-29 09:03:52 -0700168 void computePipelineOptimizations(GrInitInvariantOutput* color,
ethannicholasff210322015-11-24 12:10:10 -0800169 GrInitInvariantOutput* coverage,
170 GrBatchToXPOverrides* overrides) const override {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700171 // When this is called on a batch, there is only one geometry bundle
ethannicholasff210322015-11-24 12:10:10 -0800172 color->setKnownFourComponents(fGeoData[0].fColor);
173 coverage->setUnknownSingleComponent();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700174 }
175
bsalomone46f9fe2015-08-18 06:05:14 -0700176private:
ethannicholasff210322015-11-24 12:10:10 -0800177 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700178 // Handle any color overrides
ethannicholasff210322015-11-24 12:10:10 -0800179 if (!overrides.readsColor()) {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700180 fGeoData[0].fColor = GrColor_ILLEGAL;
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700181 }
ethannicholasff210322015-11-24 12:10:10 -0800182 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700183
184 // setup batch properties
ethannicholasff210322015-11-24 12:10:10 -0800185 fBatch.fColorIgnored = !overrides.readsColor();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700186 fBatch.fColor = fGeoData[0].fColor;
ethannicholasff210322015-11-24 12:10:10 -0800187 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
188 fBatch.fCoverageIgnored = !overrides.readsCoverage();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700189 fBatch.fLinesOnly = SkPath::kLine_SegmentMask == fGeoData[0].fPath.getSegmentMasks();
ethannicholasff210322015-11-24 12:10:10 -0800190 fBatch.fCanTweakAlphaForCoverage = overrides.canTweakAlphaForCoverage();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700191 }
192
bsalomon342bfc22016-04-01 06:06:20 -0700193 void draw(GrVertexBatch::Target* target, const GrGeometryProcessor* gp, int vertexCount,
joshualitt144c3c82015-11-30 12:30:13 -0800194 size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700195 if (vertexCount == 0 || indexCount == 0) {
196 return;
197 }
cdalton397536c2016-03-25 12:15:03 -0700198 const GrBuffer* vertexBuffer;
egdaniel0e1853c2016-03-17 11:35:45 -0700199 GrMesh mesh;
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700200 int firstVertex;
mtklein002c2ce2015-08-26 05:43:22 -0700201 void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
bsalomon75398562015-08-17 12:55:38 -0700202 &firstVertex);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700203 if (!verts) {
204 SkDebugf("Could not allocate vertices\n");
205 return;
206 }
207 memcpy(verts, vertices, vertexCount * vertexStride);
208
cdalton397536c2016-03-25 12:15:03 -0700209 const GrBuffer* indexBuffer;
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700210 int firstIndex;
bsalomon75398562015-08-17 12:55:38 -0700211 uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700212 if (!idxs) {
213 SkDebugf("Could not allocate indices\n");
214 return;
215 }
216 memcpy(idxs, indices, indexCount * sizeof(uint16_t));
egdaniel0e1853c2016-03-17 11:35:45 -0700217 mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex,
218 firstIndex, vertexCount, indexCount);
bsalomon342bfc22016-04-01 06:06:20 -0700219 target->draw(gp, mesh);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700220 }
mtklein002c2ce2015-08-26 05:43:22 -0700221
joshualitt144c3c82015-11-30 12:30:13 -0800222 void onPrepareDraws(Target* target) const override {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700223 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
224
joshualittdf0c5572015-08-03 11:35:28 -0700225 // Setup GrGeometryProcessor
bungeman06ca8ec2016-06-09 08:01:03 -0700226 sk_sp<GrGeometryProcessor> gp(create_fill_gp(canTweakAlphaForCoverage,
227 this->viewMatrix(),
228 this->usesLocalCoords(),
229 this->coverageIgnored()));
joshualittdf0c5572015-08-03 11:35:28 -0700230 if (!gp) {
231 SkDebugf("Couldn't create a GrGeometryProcessor\n");
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700232 return;
233 }
234
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700235 size_t vertexStride = gp->getVertexStride();
236
237 SkASSERT(canTweakAlphaForCoverage ?
238 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
239 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
240
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700241 int instanceCount = fGeoData.count();
242
243 int vertexCount = 0;
244 int indexCount = 0;
245 int maxVertices = DEFAULT_BUFFER_SIZE;
246 int maxIndices = DEFAULT_BUFFER_SIZE;
mtklein002c2ce2015-08-26 05:43:22 -0700247 uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride);
248 uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t));
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700249 for (int i = 0; i < instanceCount; i++) {
joshualitt144c3c82015-11-30 12:30:13 -0800250 const Geometry& args = fGeoData[i];
robertphillips8c170972016-09-22 12:42:30 -0700251 GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth,
252 args.fJoin, args.fMiterLimit);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700253
254 if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
255 continue;
256 }
257
258 int currentIndices = tess.numIndices();
259 SkASSERT(currentIndices <= UINT16_MAX);
260 if (indexCount + currentIndices > UINT16_MAX) {
mtklein002c2ce2015-08-26 05:43:22 -0700261 // if we added the current instance, we would overflow the indices we can store in a
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700262 // uint16_t. Draw what we've got so far and reset.
bungeman06ca8ec2016-06-09 08:01:03 -0700263 this->draw(target, gp.get(),
264 vertexCount, vertexStride, vertices, indexCount, indices);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700265 vertexCount = 0;
266 indexCount = 0;
267 }
268 int currentVertices = tess.numPts();
269 if (vertexCount + currentVertices > maxVertices) {
270 maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
mtklein002c2ce2015-08-26 05:43:22 -0700271 vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700272 }
273 if (indexCount + currentIndices > maxIndices) {
274 maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2);
mtklein002c2ce2015-08-26 05:43:22 -0700275 indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t));
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700276 }
277
mtklein002c2ce2015-08-26 05:43:22 -0700278 extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor,
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700279 vertexCount, indices + indexCount, canTweakAlphaForCoverage);
280 vertexCount += currentVertices;
281 indexCount += currentIndices;
282 }
bungeman06ca8ec2016-06-09 08:01:03 -0700283 this->draw(target, gp.get(), vertexCount, vertexStride, vertices, indexCount, indices);
mtklein002c2ce2015-08-26 05:43:22 -0700284 sk_free(vertices);
285 sk_free(indices);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700286 }
287
Brian Salomon25a88092016-12-01 09:36:50 -0500288 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
bsalomonabd30f52015-08-13 13:34:48 -0700289 AAFlatteningConvexPathBatch* that = t->cast<AAFlatteningConvexPathBatch>();
290 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
291 that->bounds(), caps)) {
joshualitt8cab9a72015-07-16 09:13:50 -0700292 return false;
293 }
294
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700295 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
296 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
297 return false;
298 }
299
300 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
301 // not tweaking
302 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) {
303 fBatch.fCanTweakAlphaForCoverage = false;
304 }
305
bsalomon0432dd62016-06-30 07:19:27 -0700306 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
bsalomon88cf17d2016-07-08 06:40:56 -0700307 this->joinBounds(*that);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700308 return true;
309 }
310
311 GrColor color() const { return fBatch.fColor; }
312 bool linesOnly() const { return fBatch.fLinesOnly; }
313 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
314 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
315 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
316 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
317
318 struct BatchTracker {
319 GrColor fColor;
320 bool fUsesLocalCoords;
321 bool fColorIgnored;
322 bool fCoverageIgnored;
323 bool fLinesOnly;
324 bool fCanTweakAlphaForCoverage;
325 };
326
bsalomon0432dd62016-06-30 07:19:27 -0700327 struct Geometry {
328 GrColor fColor;
329 SkMatrix fViewMatrix;
330 SkPath fPath;
331 SkScalar fStrokeWidth;
robertphillips8c170972016-09-22 12:42:30 -0700332 SkStrokeRec::Style fStyle;
bsalomon0432dd62016-06-30 07:19:27 -0700333 SkPaint::Join fJoin;
334 SkScalar fMiterLimit;
335 };
336
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700337 BatchTracker fBatch;
338 SkSTArray<1, Geometry, true> fGeoData;
reed1b55a962015-09-17 20:16:13 -0700339
340 typedef GrVertexBatch INHERITED;
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700341};
342
bsalomon0aff2fa2015-07-31 06:48:27 -0700343bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -0400344 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -0800345 "GrAALinearizingConvexPathRenderer::onDrawPath");
Brian Osman11052242016-10-27 14:47:55 -0400346 SkASSERT(!args.fRenderTargetContext->isUnifiedMultisampled());
bsalomon8acedde2016-06-24 10:42:16 -0700347 SkASSERT(!args.fShape->isEmpty());
robertphillips8c170972016-09-22 12:42:30 -0700348 SkASSERT(!args.fShape->style().pathEffect());
csmartdaltonecbc12b2016-06-08 10:08:43 -0700349
bsalomon0432dd62016-06-30 07:19:27 -0700350 SkPath path;
351 args.fShape->asPath(&path);
bsalomon8acedde2016-06-24 10:42:16 -0700352 bool fill = args.fShape->style().isSimpleFill();
353 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
bsalomon0432dd62016-06-30 07:19:27 -0700354 SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth();
355 SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin();
356 SkScalar miterLimit = stroke.getMiter();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700357
Brian Salomon9afd3712016-12-01 10:59:09 -0500358 sk_sp<GrDrawOp> batch(new AAFlatteningConvexPathBatch(args.fPaint->getColor(),
359 *args.fViewMatrix,
360 path, strokeWidth,
361 stroke.getStyle(),
362 join, miterLimit));
robertphillips976f5f02016-06-03 10:59:20 -0700363
bsalomonbb243832016-07-22 07:10:19 -0700364 GrPipelineBuilder pipelineBuilder(*args.fPaint);
365 pipelineBuilder.setUserStencil(args.fUserStencilSettings);
366
Hal Canary144caf52016-11-07 17:57:18 -0500367 args.fRenderTargetContext->drawBatch(pipelineBuilder, *args.fClip, batch.get());
bsalomonbb243832016-07-22 07:10:19 -0700368
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700369 return true;
370}
371
372///////////////////////////////////////////////////////////////////////////////////////////////////
373
374#ifdef GR_TEST_UTILS
375
bsalomonabd30f52015-08-13 13:34:48 -0700376DRAW_BATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) {
bsalomon0432dd62016-06-30 07:19:27 -0700377 GrColor color = GrRandomColor(random);
378 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
379 SkPath path = GrTest::TestPathConvex(random);
robertphillips8c170972016-09-22 12:42:30 -0700380
381 SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style,
382 SkStrokeRec::kStroke_Style,
383 SkStrokeRec::kStrokeAndFill_Style };
384
385 SkStrokeRec::Style style = styles[random->nextU() % 3];
386
387 SkScalar strokeWidth = -1.f;
bsalomon0432dd62016-06-30 07:19:27 -0700388 SkPaint::Join join = SkPaint::kMiter_Join;
389 SkScalar miterLimit = 0.5f;
robertphillips8c170972016-09-22 12:42:30 -0700390
391 if (SkStrokeRec::kFill_Style != style) {
392 strokeWidth = random->nextRangeF(1.0f, 10.0f);
393 if (random->nextBool()) {
394 join = SkPaint::kMiter_Join;
395 } else {
396 join = SkPaint::kBevel_Join;
397 }
398 miterLimit = random->nextRangeF(0.5f, 2.0f);
399 }
400
401 return new AAFlatteningConvexPathBatch(color, viewMatrix, path, strokeWidth,
402 style, join, miterLimit);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700403}
404
405#endif