blob: b565838e1594777a38ce06b8efd065ee8fcb75ef [file] [log] [blame]
bsalomon@google.comffca4002011-02-22 20:34:01 +00001#include "GrPathRenderer.h"
2
3#include "GrPoint.h"
4#include "GrDrawTarget.h"
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +00005#include "GrPathUtils.h"
bsalomon@google.comffca4002011-02-22 20:34:01 +00006#include "GrMemory.h"
7#include "GrTexture.h"
8
tomhudson@google.com278cbb42011-06-30 19:37:01 +00009#include "SkString.h"
10#include SK_USER_TRACE_INCLUDE_FILE
11
tomhudson@google.comd22b6e42011-06-24 15:53:40 +000012GrPathRenderer::GrPathRenderer()
13 : fCurveTolerance (GR_Scalar1) {
14
15}
16
bsalomon@google.comd302f142011-03-03 13:54:13 +000017GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
18 bool stencilWrapOpsSupport)
tomhudson@google.comd22b6e42011-06-24 15:53:40 +000019 : fSeparateStencil(separateStencilSupport)
20 , fStencilWrapOps(stencilWrapOpsSupport) {
bsalomon@google.comffca4002011-02-22 20:34:01 +000021
22}
23
24////////////////////////////////////////////////////////////////////////////////
bsalomon@google.comd302f142011-03-03 13:54:13 +000025// Stencil rules for paths
26
27////// Even/Odd
28
29static const GrStencilSettings gEOStencilPass = {
30 kInvert_StencilOp, kInvert_StencilOp,
31 kKeep_StencilOp, kKeep_StencilOp,
32 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
33 0xffffffff, 0xffffffff,
34 0xffffffff, 0xffffffff,
35 0xffffffff, 0xffffffff
36};
37
38// ok not to check clip b/c stencil pass only wrote inside clip
39static const GrStencilSettings gEOColorPass = {
40 kZero_StencilOp, kZero_StencilOp,
41 kZero_StencilOp, kZero_StencilOp,
42 kNotEqual_StencilFunc, kNotEqual_StencilFunc,
43 0xffffffff, 0xffffffff,
44 0x0, 0x0,
45 0xffffffff, 0xffffffff
46};
47
48// have to check clip b/c outside clip will always be zero.
49static const GrStencilSettings gInvEOColorPass = {
50 kZero_StencilOp, kZero_StencilOp,
51 kZero_StencilOp, kZero_StencilOp,
52 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
53 0xffffffff, 0xffffffff,
54 0x0, 0x0,
55 0xffffffff, 0xffffffff
56};
57
58////// Winding
59
60// when we have separate stencil we increment front faces / decrement back faces
61// when we don't have wrap incr and decr we use the stencil test to simulate
62// them.
63
64static const GrStencilSettings gWindStencilSeparateWithWrap = {
65 kIncWrap_StencilOp, kDecWrap_StencilOp,
66 kKeep_StencilOp, kKeep_StencilOp,
67 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
68 0xffffffff, 0xffffffff,
69 0xffffffff, 0xffffffff,
70 0xffffffff, 0xffffffff
71};
72
73// if inc'ing the max value, invert to make 0
74// if dec'ing zero invert to make all ones.
75// we can't avoid touching the stencil on both passing and
76// failing, so we can't resctrict ourselves to the clip.
77static const GrStencilSettings gWindStencilSeparateNoWrap = {
78 kInvert_StencilOp, kInvert_StencilOp,
79 kIncClamp_StencilOp, kDecClamp_StencilOp,
80 kEqual_StencilFunc, kEqual_StencilFunc,
81 0xffffffff, 0xffffffff,
82 0xffffffff, 0x0,
83 0xffffffff, 0xffffffff
84};
85
86// When there are no separate faces we do two passes to setup the winding rule
87// stencil. First we draw the front faces and inc, then we draw the back faces
88// and dec. These are same as the above two split into the incrementing and
89// decrementing passes.
90static const GrStencilSettings gWindSingleStencilWithWrapInc = {
91 kIncWrap_StencilOp, kIncWrap_StencilOp,
92 kKeep_StencilOp, kKeep_StencilOp,
93 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
94 0xffffffff, 0xffffffff,
95 0xffffffff, 0xffffffff,
96 0xffffffff, 0xffffffff
97};
98static const GrStencilSettings gWindSingleStencilWithWrapDec = {
99 kDecWrap_StencilOp, kDecWrap_StencilOp,
100 kKeep_StencilOp, kKeep_StencilOp,
101 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
102 0xffffffff, 0xffffffff,
103 0xffffffff, 0xffffffff,
104 0xffffffff, 0xffffffff
105};
106static const GrStencilSettings gWindSingleStencilNoWrapInc = {
107 kInvert_StencilOp, kInvert_StencilOp,
108 kIncClamp_StencilOp, kIncClamp_StencilOp,
109 kEqual_StencilFunc, kEqual_StencilFunc,
110 0xffffffff, 0xffffffff,
111 0xffffffff, 0xffffffff,
112 0xffffffff, 0xffffffff
113};
114static const GrStencilSettings gWindSingleStencilNoWrapDec = {
115 kInvert_StencilOp, kInvert_StencilOp,
116 kDecClamp_StencilOp, kDecClamp_StencilOp,
117 kEqual_StencilFunc, kEqual_StencilFunc,
118 0xffffffff, 0xffffffff,
119 0x0, 0x0,
120 0xffffffff, 0xffffffff
121};
122
123static const GrStencilSettings gWindColorPass = {
124 kZero_StencilOp, kZero_StencilOp,
125 kZero_StencilOp, kZero_StencilOp,
126 kNonZeroIfInClip_StencilFunc, kNonZeroIfInClip_StencilFunc,
127 0xffffffff, 0xffffffff,
128 0x0, 0x0,
129 0xffffffff, 0xffffffff
130};
131
132static const GrStencilSettings gInvWindColorPass = {
133 kZero_StencilOp, kZero_StencilOp,
134 kZero_StencilOp, kZero_StencilOp,
135 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
136 0xffffffff, 0xffffffff,
137 0x0, 0x0,
138 0xffffffff, 0xffffffff
139};
140
141////// Normal render to stencil
142
143// Sometimes the default path renderer can draw a path directly to the stencil
144// buffer without having to first resolve the interior / exterior.
145static const GrStencilSettings gDirectToStencil = {
146 kZero_StencilOp, kZero_StencilOp,
147 kIncClamp_StencilOp, kIncClamp_StencilOp,
148 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
149 0xffffffff, 0xffffffff,
150 0x0, 0x0,
151 0xffffffff, 0xffffffff
152};
153
154////////////////////////////////////////////////////////////////////////////////
155// Helpers for drawPath
bsalomon@google.comffca4002011-02-22 20:34:01 +0000156
reed@google.com07f3ee12011-05-16 17:21:57 +0000157static GrConvexHint getConvexHint(const SkPath& path) {
158 return path.isConvex() ? kConvex_ConvexHint : kConcave_ConvexHint;
159}
160
bsalomon@google.comffca4002011-02-22 20:34:01 +0000161#define STENCIL_OFF 0 // Always disable stencil (even when needed)
bsalomon@google.comffca4002011-02-22 20:34:01 +0000162
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000163static inline bool single_pass_path(const GrDrawTarget& target,
reed@google.com07f3ee12011-05-16 17:21:57 +0000164 const GrPath& path,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000165 GrPathFill fill) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000166#if STENCIL_OFF
167 return true;
168#else
169 if (kEvenOdd_PathFill == fill) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000170 GrConvexHint hint = getConvexHint(path);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000171 return hint == kConvex_ConvexHint ||
172 hint == kNonOverlappingConvexPieces_ConvexHint;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000173 } else if (kWinding_PathFill == fill) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000174 GrConvexHint hint = getConvexHint(path);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000175 return hint == kConvex_ConvexHint ||
176 hint == kNonOverlappingConvexPieces_ConvexHint ||
177 (hint == kSameWindingConvexPieces_ConvexHint &&
bsalomon@google.comffca4002011-02-22 20:34:01 +0000178 target.canDisableBlend() && !target.isDitherState());
179
180 }
181 return false;
182#endif
183}
184
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000185bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
reed@google.com07f3ee12011-05-16 17:21:57 +0000186 const GrPath& path,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000187 GrPathFill fill) const {
reed@google.com07f3ee12011-05-16 17:21:57 +0000188 return !single_pass_path(*target, path, fill);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000189}
190
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000191void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
192 GrDrawTarget::StageBitfield stages,
reed@google.com07f3ee12011-05-16 17:21:57 +0000193 const GrPath& path,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000194 GrPathFill fill,
195 const GrPoint* translate,
196 bool stencilOnly) {
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000197 SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath",
198 "points", SkStringPrintf("%i", path.countPoints()).c_str());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000199
200 GrDrawTarget::AutoStateRestore asr(target);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000201 bool colorWritesWereDisabled = target->isColorWriteDisabled();
202 // face culling doesn't make sense here
203 GrAssert(GrDrawTarget::kBoth_DrawFace == target->getDrawFace());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000204
205 GrMatrix viewM = target->getViewMatrix();
206 // In order to tesselate the path we get a bound on how much the matrix can
207 // stretch when mapping to screen coordinates.
208 GrScalar stretch = viewM.getMaxStretch();
209 bool useStretch = stretch > 0;
tomhudson@google.comd22b6e42011-06-24 15:53:40 +0000210 GrScalar tol = fCurveTolerance;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000211
212 if (!useStretch) {
213 // TODO: deal with perspective in some better way.
214 tol /= 10;
215 } else {
bungeman@google.com8c5753e2011-05-20 19:11:50 +0000216 tol = GrScalarDiv(tol, stretch);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000217 }
218 GrScalar tolSqd = GrMul(tol, tol);
219
220 int subpathCnt;
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000221 int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000222
223 GrVertexLayout layout = 0;
224 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
225 if ((1 << s) & stages) {
226 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
227 }
228 }
229
230 // add 4 to hold the bounding rect
231 GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);
232
233 GrPoint* base = (GrPoint*) arg.vertices();
234 GrPoint* vert = base;
235 GrPoint* subpathBase = base;
236
237 GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
238
bsalomon@google.comffca4002011-02-22 20:34:01 +0000239 // TODO: use primitve restart if available rather than multiple draws
240 GrPrimitiveType type;
241 int passCount = 0;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000242 const GrStencilSettings* passes[3];
243 GrDrawTarget::DrawFace drawFace[3];
bsalomon@google.comffca4002011-02-22 20:34:01 +0000244 bool reverse = false;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000245 bool lastPassIsBounds;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000246
247 if (kHairLine_PathFill == fill) {
248 type = kLineStrip_PrimitiveType;
249 passCount = 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000250 if (stencilOnly) {
251 passes[0] = &gDirectToStencil;
252 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000253 passes[0] = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000254 }
255 lastPassIsBounds = false;
256 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000257 } else {
258 type = kTriangleFan_PrimitiveType;
reed@google.com07f3ee12011-05-16 17:21:57 +0000259 if (single_pass_path(*target, path, fill)) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000260 passCount = 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000261 if (stencilOnly) {
262 passes[0] = &gDirectToStencil;
263 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000264 passes[0] = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000265 }
266 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
267 lastPassIsBounds = false;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000268 } else {
269 switch (fill) {
270 case kInverseEvenOdd_PathFill:
271 reverse = true;
272 // fallthrough
273 case kEvenOdd_PathFill:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000274 passes[0] = &gEOStencilPass;
275 if (stencilOnly) {
276 passCount = 1;
277 lastPassIsBounds = false;
278 } else {
279 passCount = 2;
280 lastPassIsBounds = true;
281 if (reverse) {
282 passes[1] = &gInvEOColorPass;
283 } else {
284 passes[1] = &gEOColorPass;
285 }
286 }
287 drawFace[0] = drawFace[1] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000288 break;
289
290 case kInverseWinding_PathFill:
291 reverse = true;
292 // fallthrough
293 case kWinding_PathFill:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000294 if (fSeparateStencil) {
295 if (fStencilWrapOps) {
296 passes[0] = &gWindStencilSeparateWithWrap;
297 } else {
298 passes[0] = &gWindStencilSeparateNoWrap;
299 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000300 passCount = 2;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000301 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000302 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000303 if (fStencilWrapOps) {
304 passes[0] = &gWindSingleStencilWithWrapInc;
305 passes[1] = &gWindSingleStencilWithWrapDec;
306 } else {
307 passes[0] = &gWindSingleStencilNoWrapInc;
308 passes[1] = &gWindSingleStencilNoWrapDec;
309 }
310 // which is cw and which is ccw is arbitrary.
311 drawFace[0] = GrDrawTarget::kCW_DrawFace;
312 drawFace[1] = GrDrawTarget::kCCW_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000313 passCount = 3;
314 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000315 if (stencilOnly) {
316 lastPassIsBounds = false;
317 --passCount;
318 } else {
319 lastPassIsBounds = true;
320 drawFace[passCount-1] = GrDrawTarget::kBoth_DrawFace;
321 if (reverse) {
322 passes[passCount-1] = &gInvWindColorPass;
323 } else {
324 passes[passCount-1] = &gWindColorPass;
325 }
326 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000327 break;
328 default:
329 GrAssert(!"Unknown path fill!");
330 return;
331 }
332 }
333 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000334
335 GrPoint pts[4];
336
337 bool first = true;
338 int subpath = 0;
339
reed@google.com07f3ee12011-05-16 17:21:57 +0000340 SkPath::Iter iter(path, false);
341
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000342 {
343 SK_TRACE_EVENT0("GrDefaultPathRenderer::onDrawPath::assembleVerts");
bsalomon@google.comffca4002011-02-22 20:34:01 +0000344 for (;;) {
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000345
reed@google.com07f3ee12011-05-16 17:21:57 +0000346 GrPathCmd cmd = (GrPathCmd)iter.next(pts);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000347 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000348 case kMove_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000349 if (!first) {
350 subpathVertCount[subpath] = vert-subpathBase;
351 subpathBase = vert;
352 ++subpath;
353 }
354 *vert = pts[0];
355 vert++;
356 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000357 case kLine_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000358 *vert = pts[1];
359 vert++;
360 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000361 case kQuadratic_PathCmd: {
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000362 GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
363 tolSqd, &vert,
364 GrPathUtils::quadraticPointCount(pts, tol));
bsalomon@google.comffca4002011-02-22 20:34:01 +0000365 break;
366 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000367 case kCubic_PathCmd: {
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000368 GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
369 tolSqd, &vert,
370 GrPathUtils::cubicPointCount(pts, tol));
bsalomon@google.comffca4002011-02-22 20:34:01 +0000371 break;
372 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000373 case kClose_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000374 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000375 case kEnd_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000376 subpathVertCount[subpath] = vert-subpathBase;
377 ++subpath; // this could be only in debug
378 goto FINISHED;
379 }
380 first = false;
381 }
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000382 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000383FINISHED:
384 GrAssert(subpath == subpathCnt);
385 GrAssert((vert - base) <= maxPts);
386
387 if (translate) {
388 int count = vert - base;
389 for (int i = 0; i < count; i++) {
390 base[i].offset(translate->fX, translate->fY);
391 }
392 }
393
bsalomon@google.comd302f142011-03-03 13:54:13 +0000394 // if we're stenciling we will follow with a pass that draws
395 // a bounding rect to set the color. We're stenciling when
396 // passCount > 1.
397 const int& boundVertexStart = maxPts;
398 GrPoint* boundsVerts = base + boundVertexStart;
399 if (lastPassIsBounds) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000400 GrRect bounds;
401 if (reverse) {
402 GrAssert(NULL != target->getRenderTarget());
403 // draw over the whole world.
404 bounds.setLTRB(0, 0,
405 GrIntToScalar(target->getRenderTarget()->width()),
406 GrIntToScalar(target->getRenderTarget()->height()));
407 GrMatrix vmi;
408 if (target->getViewInverse(&vmi)) {
409 vmi.mapRect(&bounds);
410 }
411 } else {
412 bounds.setBounds((GrPoint*)base, vert - base);
413 }
414 boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,
415 bounds.fBottom);
416 }
417
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000418 {
419 SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath::renderPasses",
420 "verts", SkStringPrintf("%i", vert - base).c_str());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000421 for (int p = 0; p < passCount; ++p) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000422 target->setDrawFace(drawFace[p]);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000423 if (NULL != passes[p]) {
424 target->setStencil(*passes[p]);
425 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000426
427 if (lastPassIsBounds && (p == passCount-1)) {
428 if (!colorWritesWereDisabled) {
429 target->disableState(GrDrawTarget::kNoColorWrites_StateBit);
430 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000431 target->drawNonIndexed(kTriangleFan_PrimitiveType,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000432 boundVertexStart, 4);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000433
434 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000435 if (passCount > 1) {
436 target->enableState(GrDrawTarget::kNoColorWrites_StateBit);
437 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000438 int baseVertex = 0;
439 for (int sp = 0; sp < subpathCnt; ++sp) {
440 target->drawNonIndexed(type,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000441 baseVertex,
442 subpathVertCount[sp]);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000443 baseVertex += subpathVertCount[sp];
444 }
445 }
446 }
tomhudson@google.com278cbb42011-06-30 19:37:01 +0000447 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000448}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000449
450void GrDefaultPathRenderer::drawPath(GrDrawTarget* target,
451 GrDrawTarget::StageBitfield stages,
reed@google.com07f3ee12011-05-16 17:21:57 +0000452 const GrPath& path,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000453 GrPathFill fill,
454 const GrPoint* translate) {
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000455 this->onDrawPath(target, stages, path, fill, translate, false);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000456}
457
458void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target,
reed@google.com07f3ee12011-05-16 17:21:57 +0000459 const GrPath& path,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000460 GrPathFill fill,
461 const GrPoint* translate) {
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000462 GrAssert(kInverseEvenOdd_PathFill != fill);
463 GrAssert(kInverseWinding_PathFill != fill);
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000464 this->onDrawPath(target, 0, path, fill, translate, true);
senorblanco@chromium.org9d18b782011-03-28 20:47:09 +0000465}