blob: 6d7aabb1e08da9fae32f7e31e2b2d2a6351e66f5 [file] [log] [blame]
bsalomon@google.comffca4002011-02-22 20:34:01 +00001#include "GrPathRenderer.h"
2
3#include "GrPoint.h"
4#include "GrDrawTarget.h"
5#include "GrPathIter.h"
6#include "GrMemory.h"
7#include "GrTexture.h"
8
bsalomon@google.comd302f142011-03-03 13:54:13 +00009GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
10 bool stencilWrapOpsSupport)
11 : fSeparateStencil(separateStencilSupport),
12 fStencilWrapOps(stencilWrapOpsSupport) {
bsalomon@google.comffca4002011-02-22 20:34:01 +000013
14}
15
16////////////////////////////////////////////////////////////////////////////////
bsalomon@google.comd302f142011-03-03 13:54:13 +000017// Stencil rules for paths
18
19////// Even/Odd
20
21static const GrStencilSettings gEOStencilPass = {
22 kInvert_StencilOp, kInvert_StencilOp,
23 kKeep_StencilOp, kKeep_StencilOp,
24 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
25 0xffffffff, 0xffffffff,
26 0xffffffff, 0xffffffff,
27 0xffffffff, 0xffffffff
28};
29
30// ok not to check clip b/c stencil pass only wrote inside clip
31static const GrStencilSettings gEOColorPass = {
32 kZero_StencilOp, kZero_StencilOp,
33 kZero_StencilOp, kZero_StencilOp,
34 kNotEqual_StencilFunc, kNotEqual_StencilFunc,
35 0xffffffff, 0xffffffff,
36 0x0, 0x0,
37 0xffffffff, 0xffffffff
38};
39
40// have to check clip b/c outside clip will always be zero.
41static const GrStencilSettings gInvEOColorPass = {
42 kZero_StencilOp, kZero_StencilOp,
43 kZero_StencilOp, kZero_StencilOp,
44 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
45 0xffffffff, 0xffffffff,
46 0x0, 0x0,
47 0xffffffff, 0xffffffff
48};
49
50////// Winding
51
52// when we have separate stencil we increment front faces / decrement back faces
53// when we don't have wrap incr and decr we use the stencil test to simulate
54// them.
55
56static const GrStencilSettings gWindStencilSeparateWithWrap = {
57 kIncWrap_StencilOp, kDecWrap_StencilOp,
58 kKeep_StencilOp, kKeep_StencilOp,
59 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
60 0xffffffff, 0xffffffff,
61 0xffffffff, 0xffffffff,
62 0xffffffff, 0xffffffff
63};
64
65// if inc'ing the max value, invert to make 0
66// if dec'ing zero invert to make all ones.
67// we can't avoid touching the stencil on both passing and
68// failing, so we can't resctrict ourselves to the clip.
69static const GrStencilSettings gWindStencilSeparateNoWrap = {
70 kInvert_StencilOp, kInvert_StencilOp,
71 kIncClamp_StencilOp, kDecClamp_StencilOp,
72 kEqual_StencilFunc, kEqual_StencilFunc,
73 0xffffffff, 0xffffffff,
74 0xffffffff, 0x0,
75 0xffffffff, 0xffffffff
76};
77
78// When there are no separate faces we do two passes to setup the winding rule
79// stencil. First we draw the front faces and inc, then we draw the back faces
80// and dec. These are same as the above two split into the incrementing and
81// decrementing passes.
82static const GrStencilSettings gWindSingleStencilWithWrapInc = {
83 kIncWrap_StencilOp, kIncWrap_StencilOp,
84 kKeep_StencilOp, kKeep_StencilOp,
85 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
86 0xffffffff, 0xffffffff,
87 0xffffffff, 0xffffffff,
88 0xffffffff, 0xffffffff
89};
90static const GrStencilSettings gWindSingleStencilWithWrapDec = {
91 kDecWrap_StencilOp, kDecWrap_StencilOp,
92 kKeep_StencilOp, kKeep_StencilOp,
93 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
94 0xffffffff, 0xffffffff,
95 0xffffffff, 0xffffffff,
96 0xffffffff, 0xffffffff
97};
98static const GrStencilSettings gWindSingleStencilNoWrapInc = {
99 kInvert_StencilOp, kInvert_StencilOp,
100 kIncClamp_StencilOp, kIncClamp_StencilOp,
101 kEqual_StencilFunc, kEqual_StencilFunc,
102 0xffffffff, 0xffffffff,
103 0xffffffff, 0xffffffff,
104 0xffffffff, 0xffffffff
105};
106static const GrStencilSettings gWindSingleStencilNoWrapDec = {
107 kInvert_StencilOp, kInvert_StencilOp,
108 kDecClamp_StencilOp, kDecClamp_StencilOp,
109 kEqual_StencilFunc, kEqual_StencilFunc,
110 0xffffffff, 0xffffffff,
111 0x0, 0x0,
112 0xffffffff, 0xffffffff
113};
114
115static const GrStencilSettings gWindColorPass = {
116 kZero_StencilOp, kZero_StencilOp,
117 kZero_StencilOp, kZero_StencilOp,
118 kNonZeroIfInClip_StencilFunc, kNonZeroIfInClip_StencilFunc,
119 0xffffffff, 0xffffffff,
120 0x0, 0x0,
121 0xffffffff, 0xffffffff
122};
123
124static const GrStencilSettings gInvWindColorPass = {
125 kZero_StencilOp, kZero_StencilOp,
126 kZero_StencilOp, kZero_StencilOp,
127 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
128 0xffffffff, 0xffffffff,
129 0x0, 0x0,
130 0xffffffff, 0xffffffff
131};
132
133////// Normal render to stencil
134
135// Sometimes the default path renderer can draw a path directly to the stencil
136// buffer without having to first resolve the interior / exterior.
137static const GrStencilSettings gDirectToStencil = {
138 kZero_StencilOp, kZero_StencilOp,
139 kIncClamp_StencilOp, kIncClamp_StencilOp,
140 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
141 0xffffffff, 0xffffffff,
142 0x0, 0x0,
143 0xffffffff, 0xffffffff
144};
145
146////////////////////////////////////////////////////////////////////////////////
147// Helpers for drawPath
bsalomon@google.comffca4002011-02-22 20:34:01 +0000148
149#define STENCIL_OFF 0 // Always disable stencil (even when needed)
150static const GrScalar gTolerance = GR_Scalar1;
151
152static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10;
153
154static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) {
155 GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
156 if (d < tol) {
157 return 1;
158 } else {
159 // Each time we subdivide, d should be cut in 4. So we need to
160 // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
161 // points.
162 // 2^(log4(x)) = sqrt(x);
163 d = ceilf(sqrtf(d/tol));
164 return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
165 }
166}
167
168static uint32_t generate_quadratic_points(const GrPoint& p0,
169 const GrPoint& p1,
170 const GrPoint& p2,
171 GrScalar tolSqd,
172 GrPoint** points,
173 uint32_t pointsLeft) {
174 if (pointsLeft < 2 ||
175 (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
176 (*points)[0] = p2;
177 *points += 1;
178 return 1;
179 }
180
181 GrPoint q[] = {
182 GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
183 GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
184 };
185 GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));
186
187 pointsLeft >>= 1;
188 uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft);
189 uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft);
190 return a + b;
191}
192
193static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) {
194 GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
195 points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
196 d = sqrtf(d);
197 if (d < tol) {
198 return 1;
199 } else {
200 d = ceilf(sqrtf(d/tol));
201 return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
202 }
203}
204
205static uint32_t generate_cubic_points(const GrPoint& p0,
206 const GrPoint& p1,
207 const GrPoint& p2,
208 const GrPoint& p3,
209 GrScalar tolSqd,
210 GrPoint** points,
211 uint32_t pointsLeft) {
212 if (pointsLeft < 2 ||
213 (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
214 p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
215 (*points)[0] = p3;
216 *points += 1;
217 return 1;
218 }
219 GrPoint q[] = {
220 GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
221 GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
222 GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))
223 };
224 GrPoint r[] = {
225 GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),
226 GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))
227 };
228 GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));
229 pointsLeft >>= 1;
230 uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
231 uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
232 return a + b;
233}
234
235static int worst_case_point_count(GrPathIter* path,
236 int* subpaths,
237 GrScalar tol) {
238 int pointCount = 0;
239 *subpaths = 1;
240
241 bool first = true;
242
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000243 GrPathCmd cmd;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000244
245 GrPoint pts[4];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000246 while ((cmd = path->next(pts)) != kEnd_PathCmd) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000247
248 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000249 case kLine_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000250 pointCount += 1;
251 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000252 case kQuadratic_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000253 pointCount += quadratic_point_count(pts, tol);
254 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000255 case kCubic_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000256 pointCount += cubic_point_count(pts, tol);
257 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000258 case kMove_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000259 pointCount += 1;
260 if (!first) {
261 ++(*subpaths);
262 }
263 break;
264 default:
265 break;
266 }
267 first = false;
268 }
269 return pointCount;
270}
271
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000272static inline bool single_pass_path(const GrDrawTarget& target,
273 const GrPathIter& path,
274 GrPathFill fill) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000275#if STENCIL_OFF
276 return true;
277#else
278 if (kEvenOdd_PathFill == fill) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000279 GrConvexHint hint = path.convexHint();
280 return hint == kConvex_ConvexHint ||
281 hint == kNonOverlappingConvexPieces_ConvexHint;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000282 } else if (kWinding_PathFill == fill) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000283 GrConvexHint hint = path.convexHint();
284 return hint == kConvex_ConvexHint ||
285 hint == kNonOverlappingConvexPieces_ConvexHint ||
286 (hint == kSameWindingConvexPieces_ConvexHint &&
bsalomon@google.comffca4002011-02-22 20:34:01 +0000287 target.canDisableBlend() && !target.isDitherState());
288
289 }
290 return false;
291#endif
292}
293
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000294bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
295 GrPathIter* path,
296 GrPathFill fill) const {
297 return single_pass_path(*target, *path, fill);
298}
299
bsalomon@google.comd302f142011-03-03 13:54:13 +0000300void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target,
301 GrDrawTarget::StageBitfield stages,
302 GrPathIter* path,
303 GrPathFill fill,
304 const GrPoint* translate,
305 bool stencilOnly) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000306
307 GrDrawTarget::AutoStateRestore asr(target);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000308 bool colorWritesWereDisabled = target->isColorWriteDisabled();
309 // face culling doesn't make sense here
310 GrAssert(GrDrawTarget::kBoth_DrawFace == target->getDrawFace());
bsalomon@google.comffca4002011-02-22 20:34:01 +0000311
312 GrMatrix viewM = target->getViewMatrix();
313 // In order to tesselate the path we get a bound on how much the matrix can
314 // stretch when mapping to screen coordinates.
315 GrScalar stretch = viewM.getMaxStretch();
316 bool useStretch = stretch > 0;
317 GrScalar tol = gTolerance;
318
319 if (!useStretch) {
320 // TODO: deal with perspective in some better way.
321 tol /= 10;
322 } else {
323 GrScalar sinv = GR_Scalar1 / stretch;
324 tol = GrMul(tol, sinv);
325 }
326 GrScalar tolSqd = GrMul(tol, tol);
327
bsalomon@google.comd302f142011-03-03 13:54:13 +0000328 path->rewind();
329
bsalomon@google.comffca4002011-02-22 20:34:01 +0000330 int subpathCnt;
331 int maxPts = worst_case_point_count(path,
332 &subpathCnt,
333 tol);
334
335 GrVertexLayout layout = 0;
336 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
337 if ((1 << s) & stages) {
338 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
339 }
340 }
341
342 // add 4 to hold the bounding rect
343 GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);
344
345 GrPoint* base = (GrPoint*) arg.vertices();
346 GrPoint* vert = base;
347 GrPoint* subpathBase = base;
348
349 GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
350
351 path->rewind();
352
353 // TODO: use primitve restart if available rather than multiple draws
354 GrPrimitiveType type;
355 int passCount = 0;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000356 const GrStencilSettings* passes[3];
357 GrDrawTarget::DrawFace drawFace[3];
bsalomon@google.comffca4002011-02-22 20:34:01 +0000358 bool reverse = false;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000359 bool lastPassIsBounds;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000360
361 if (kHairLine_PathFill == fill) {
362 type = kLineStrip_PrimitiveType;
363 passCount = 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000364 if (stencilOnly) {
365 passes[0] = &gDirectToStencil;
366 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000367 passes[0] = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000368 }
369 lastPassIsBounds = false;
370 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000371 } else {
372 type = kTriangleFan_PrimitiveType;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000373 if (single_pass_path(*target, *path, fill)) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000374 passCount = 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000375 if (stencilOnly) {
376 passes[0] = &gDirectToStencil;
377 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000378 passes[0] = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000379 }
380 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
381 lastPassIsBounds = false;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000382 } else {
383 switch (fill) {
384 case kInverseEvenOdd_PathFill:
385 reverse = true;
386 // fallthrough
387 case kEvenOdd_PathFill:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000388 passes[0] = &gEOStencilPass;
389 if (stencilOnly) {
390 passCount = 1;
391 lastPassIsBounds = false;
392 } else {
393 passCount = 2;
394 lastPassIsBounds = true;
395 if (reverse) {
396 passes[1] = &gInvEOColorPass;
397 } else {
398 passes[1] = &gEOColorPass;
399 }
400 }
401 drawFace[0] = drawFace[1] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000402 break;
403
404 case kInverseWinding_PathFill:
405 reverse = true;
406 // fallthrough
407 case kWinding_PathFill:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000408 if (fSeparateStencil) {
409 if (fStencilWrapOps) {
410 passes[0] = &gWindStencilSeparateWithWrap;
411 } else {
412 passes[0] = &gWindStencilSeparateNoWrap;
413 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000414 passCount = 2;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000415 drawFace[0] = GrDrawTarget::kBoth_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000416 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000417 if (fStencilWrapOps) {
418 passes[0] = &gWindSingleStencilWithWrapInc;
419 passes[1] = &gWindSingleStencilWithWrapDec;
420 } else {
421 passes[0] = &gWindSingleStencilNoWrapInc;
422 passes[1] = &gWindSingleStencilNoWrapDec;
423 }
424 // which is cw and which is ccw is arbitrary.
425 drawFace[0] = GrDrawTarget::kCW_DrawFace;
426 drawFace[1] = GrDrawTarget::kCCW_DrawFace;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000427 passCount = 3;
428 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000429 if (stencilOnly) {
430 lastPassIsBounds = false;
431 --passCount;
432 } else {
433 lastPassIsBounds = true;
434 drawFace[passCount-1] = GrDrawTarget::kBoth_DrawFace;
435 if (reverse) {
436 passes[passCount-1] = &gInvWindColorPass;
437 } else {
438 passes[passCount-1] = &gWindColorPass;
439 }
440 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000441 break;
442 default:
443 GrAssert(!"Unknown path fill!");
444 return;
445 }
446 }
447 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000448
449 GrPoint pts[4];
450
451 bool first = true;
452 int subpath = 0;
453
454 for (;;) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000455 GrPathCmd cmd = path->next(pts);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000456 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000457 case kMove_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000458 if (!first) {
459 subpathVertCount[subpath] = vert-subpathBase;
460 subpathBase = vert;
461 ++subpath;
462 }
463 *vert = pts[0];
464 vert++;
465 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000466 case kLine_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000467 *vert = pts[1];
468 vert++;
469 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000470 case kQuadratic_PathCmd: {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000471 generate_quadratic_points(pts[0], pts[1], pts[2],
472 tolSqd, &vert,
473 quadratic_point_count(pts, tol));
474 break;
475 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000476 case kCubic_PathCmd: {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000477 generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
478 tolSqd, &vert,
479 cubic_point_count(pts, tol));
480 break;
481 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000482 case kClose_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000483 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000484 case kEnd_PathCmd:
bsalomon@google.comffca4002011-02-22 20:34:01 +0000485 subpathVertCount[subpath] = vert-subpathBase;
486 ++subpath; // this could be only in debug
487 goto FINISHED;
488 }
489 first = false;
490 }
491FINISHED:
492 GrAssert(subpath == subpathCnt);
493 GrAssert((vert - base) <= maxPts);
494
495 if (translate) {
496 int count = vert - base;
497 for (int i = 0; i < count; i++) {
498 base[i].offset(translate->fX, translate->fY);
499 }
500 }
501
bsalomon@google.comd302f142011-03-03 13:54:13 +0000502 // if we're stenciling we will follow with a pass that draws
503 // a bounding rect to set the color. We're stenciling when
504 // passCount > 1.
505 const int& boundVertexStart = maxPts;
506 GrPoint* boundsVerts = base + boundVertexStart;
507 if (lastPassIsBounds) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000508 GrRect bounds;
509 if (reverse) {
510 GrAssert(NULL != target->getRenderTarget());
511 // draw over the whole world.
512 bounds.setLTRB(0, 0,
513 GrIntToScalar(target->getRenderTarget()->width()),
514 GrIntToScalar(target->getRenderTarget()->height()));
515 GrMatrix vmi;
516 if (target->getViewInverse(&vmi)) {
517 vmi.mapRect(&bounds);
518 }
519 } else {
520 bounds.setBounds((GrPoint*)base, vert - base);
521 }
522 boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,
523 bounds.fBottom);
524 }
525
526 for (int p = 0; p < passCount; ++p) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000527 target->setDrawFace(drawFace[p]);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000528 if (NULL != passes[p]) {
529 target->setStencil(*passes[p]);
530 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000531
532 if (lastPassIsBounds && (p == passCount-1)) {
533 if (!colorWritesWereDisabled) {
534 target->disableState(GrDrawTarget::kNoColorWrites_StateBit);
535 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000536 target->drawNonIndexed(kTriangleFan_PrimitiveType,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000537 boundVertexStart, 4);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000538
539 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000540 if (passCount > 1) {
541 target->enableState(GrDrawTarget::kNoColorWrites_StateBit);
542 }
bsalomon@google.comffca4002011-02-22 20:34:01 +0000543 int baseVertex = 0;
544 for (int sp = 0; sp < subpathCnt; ++sp) {
545 target->drawNonIndexed(type,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000546 baseVertex,
547 subpathVertCount[sp]);
bsalomon@google.comffca4002011-02-22 20:34:01 +0000548 baseVertex += subpathVertCount[sp];
549 }
550 }
551 }
552}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000553
554void GrDefaultPathRenderer::drawPath(GrDrawTarget* target,
555 GrDrawTarget::StageBitfield stages,
556 GrPathIter* path,
557 GrPathFill fill,
558 const GrPoint* translate) {
559 this->drawPathHelper(target, stages, path, fill, translate, false);
560}
561
562void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target,
563 GrPathIter* path,
564 GrPathFill fill,
565 const GrPoint* translate) {
566 GrAssert(kInverseEvenOdd_PathFill != fill);
567 GrAssert(kInverseWinding_PathFill != fill);
568 this->drawPathHelper(target, 0, path, fill, translate, true);
569 }