blob: cd4e4296422718bba42be6af04ef1fb793d87853 [file] [log] [blame]
bsalomon@google.com30085192011-08-19 15:42:31 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "GrDefaultPathRenderer.h"
10
11#include "GrContext.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000012#include "GrDrawState.h"
bsalomon@google.com30085192011-08-19 15:42:31 +000013#include "GrPathUtils.h"
tomhudson@google.comdd5f7442011-08-30 15:13:55 +000014#include "SkString.h"
bsalomon@google.com30085192011-08-19 15:42:31 +000015#include "SkTrace.h"
16
17
18GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
19 bool stencilWrapOpsSupport)
20 : fSeparateStencil(separateStencilSupport)
21 , fStencilWrapOps(stencilWrapOpsSupport)
22 , fSubpathCount(0)
23 , fSubpathVertCount(0)
24 , fPreviousSrcTol(-GR_Scalar1)
25 , fPreviousStages(-1) {
26 fTarget = NULL;
27}
28
bsalomon@google.com289533a2011-10-27 12:34:25 +000029bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
30 const SkPath& path,
31 GrPathFill fill,
32 bool antiAlias) const {
33 // this class can draw any path with any fill but doesn't do any
34 // anti-aliasing.
35 return !antiAlias;
36}
37
38
bsalomon@google.com30085192011-08-19 15:42:31 +000039////////////////////////////////////////////////////////////////////////////////
40// Stencil rules for paths
41
42////// Even/Odd
43
44static const GrStencilSettings gEOStencilPass = {
45 kInvert_StencilOp, kInvert_StencilOp,
46 kKeep_StencilOp, kKeep_StencilOp,
47 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000048 0xffff, 0xffff,
49 0xffff, 0xffff,
50 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +000051};
52
53// ok not to check clip b/c stencil pass only wrote inside clip
54static const GrStencilSettings gEOColorPass = {
55 kZero_StencilOp, kZero_StencilOp,
56 kZero_StencilOp, kZero_StencilOp,
57 kNotEqual_StencilFunc, kNotEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000058 0xffff, 0xffff,
59 0x0000, 0x0000,
60 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +000061};
62
63// have to check clip b/c outside clip will always be zero.
64static const GrStencilSettings gInvEOColorPass = {
65 kZero_StencilOp, kZero_StencilOp,
66 kZero_StencilOp, kZero_StencilOp,
67 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000068 0xffff, 0xffff,
69 0x0000, 0x0000,
70 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +000071};
72
73////// Winding
74
75// when we have separate stencil we increment front faces / decrement back faces
76// when we don't have wrap incr and decr we use the stencil test to simulate
77// them.
78
79static const GrStencilSettings gWindStencilSeparateWithWrap = {
80 kIncWrap_StencilOp, kDecWrap_StencilOp,
81 kKeep_StencilOp, kKeep_StencilOp,
82 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000083 0xffff, 0xffff,
84 0xffff, 0xffff,
85 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +000086};
87
88// if inc'ing the max value, invert to make 0
89// if dec'ing zero invert to make all ones.
90// we can't avoid touching the stencil on both passing and
91// failing, so we can't resctrict ourselves to the clip.
92static const GrStencilSettings gWindStencilSeparateNoWrap = {
93 kInvert_StencilOp, kInvert_StencilOp,
94 kIncClamp_StencilOp, kDecClamp_StencilOp,
95 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000096 0xffff, 0xffff,
97 0xffff, 0x0000,
98 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +000099};
100
101// When there are no separate faces we do two passes to setup the winding rule
102// stencil. First we draw the front faces and inc, then we draw the back faces
103// and dec. These are same as the above two split into the incrementing and
104// decrementing passes.
105static const GrStencilSettings gWindSingleStencilWithWrapInc = {
106 kIncWrap_StencilOp, kIncWrap_StencilOp,
107 kKeep_StencilOp, kKeep_StencilOp,
108 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000109 0xffff, 0xffff,
110 0xffff, 0xffff,
111 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000112};
113static const GrStencilSettings gWindSingleStencilWithWrapDec = {
114 kDecWrap_StencilOp, kDecWrap_StencilOp,
115 kKeep_StencilOp, kKeep_StencilOp,
116 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000117 0xffff, 0xffff,
118 0xffff, 0xffff,
119 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000120};
121static const GrStencilSettings gWindSingleStencilNoWrapInc = {
122 kInvert_StencilOp, kInvert_StencilOp,
123 kIncClamp_StencilOp, kIncClamp_StencilOp,
124 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000125 0xffff, 0xffff,
126 0xffff, 0xffff,
127 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000128};
129static const GrStencilSettings gWindSingleStencilNoWrapDec = {
130 kInvert_StencilOp, kInvert_StencilOp,
131 kDecClamp_StencilOp, kDecClamp_StencilOp,
132 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000133 0xffff, 0xffff,
134 0x0000, 0x0000,
135 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000136};
137
138static const GrStencilSettings gWindColorPass = {
139 kZero_StencilOp, kZero_StencilOp,
140 kZero_StencilOp, kZero_StencilOp,
141 kNonZeroIfInClip_StencilFunc, kNonZeroIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000142 0xffff, 0xffff,
143 0x0000, 0x0000,
144 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000145};
146
147static const GrStencilSettings gInvWindColorPass = {
148 kZero_StencilOp, kZero_StencilOp,
149 kZero_StencilOp, kZero_StencilOp,
150 kEqualIfInClip_StencilFunc, kEqualIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000151 0xffff, 0xffff,
152 0x0000, 0x0000,
153 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000154};
155
156////// Normal render to stencil
157
158// Sometimes the default path renderer can draw a path directly to the stencil
159// buffer without having to first resolve the interior / exterior.
160static const GrStencilSettings gDirectToStencil = {
161 kZero_StencilOp, kZero_StencilOp,
162 kIncClamp_StencilOp, kIncClamp_StencilOp,
163 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000164 0xffff, 0xffff,
165 0x0000, 0x0000,
166 0xffff, 0xffff
bsalomon@google.com30085192011-08-19 15:42:31 +0000167};
168
169////////////////////////////////////////////////////////////////////////////////
170// Helpers for drawPath
171
172static GrConvexHint getConvexHint(const SkPath& path) {
173 return path.isConvex() ? kConvex_ConvexHint : kConcave_ConvexHint;
174}
175
176#define STENCIL_OFF 0 // Always disable stencil (even when needed)
177
178static inline bool single_pass_path(const GrDrawTarget& target,
179 const GrPath& path,
180 GrPathFill fill) {
181#if STENCIL_OFF
182 return true;
183#else
184 if (kEvenOdd_PathFill == fill) {
185 GrConvexHint hint = getConvexHint(path);
186 return hint == kConvex_ConvexHint ||
187 hint == kNonOverlappingConvexPieces_ConvexHint;
188 } else if (kWinding_PathFill == fill) {
189 GrConvexHint hint = getConvexHint(path);
190 return hint == kConvex_ConvexHint ||
191 hint == kNonOverlappingConvexPieces_ConvexHint ||
192 (hint == kSameWindingConvexPieces_ConvexHint &&
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000193 !target.drawWillReadDst() &&
194 !target.getDrawState().isDitherState());
bsalomon@google.com30085192011-08-19 15:42:31 +0000195
196 }
197 return false;
198#endif
199}
200
201bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
bsalomon@google.com289533a2011-10-27 12:34:25 +0000202 const GrPath& path,
bsalomon@google.com30085192011-08-19 15:42:31 +0000203 GrPathFill fill) const {
204 return !single_pass_path(*target, path, fill);
205}
206
207void GrDefaultPathRenderer::pathWillClear() {
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000208 fSubpathVertCount.reset(0);
bsalomon@google.com30085192011-08-19 15:42:31 +0000209 fTarget->resetVertexSource();
210 if (fUseIndexedDraw) {
211 fTarget->resetIndexSource();
212 }
213 fPreviousSrcTol = -GR_Scalar1;
214 fPreviousStages = -1;
215}
216
217static inline void append_countour_edge_indices(GrPathFill fillType,
218 uint16_t fanCenterIdx,
219 uint16_t edgeV0Idx,
220 uint16_t** indices) {
221 // when drawing lines we're appending line segments along
222 // the contour. When applying the other fill rules we're
223 // drawing triangle fans around fanCenterIdx.
224 if (kHairLine_PathFill != fillType) {
225 *((*indices)++) = fanCenterIdx;
226 }
227 *((*indices)++) = edgeV0Idx;
228 *((*indices)++) = edgeV0Idx + 1;
229}
230
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000231bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
232 GrDrawState::StageMask stageMask) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000233 {
234 SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
235
236 GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol);
237 int maxPts = GrPathUtils::worstCasePointCount(*fPath, &fSubpathCount,
238 srcSpaceTol);
239
240 if (maxPts <= 0) {
241 return false;
242 }
243 if (maxPts > ((int)SK_MaxU16 + 1)) {
244 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
245 return false;
246 }
247
248 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000249 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000250 if ((1 << s) & stageMask) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000251 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
252 }
253 }
254
255 fUseIndexedDraw = fSubpathCount > 1;
256
257 int maxIdxs = 0;
258 if (kHairLine_PathFill == fFill) {
259 if (fUseIndexedDraw) {
260 maxIdxs = 2 * maxPts;
261 fPrimitiveType = kLines_PrimitiveType;
262 } else {
263 fPrimitiveType = kLineStrip_PrimitiveType;
264 }
265 } else {
266 if (fUseIndexedDraw) {
267 maxIdxs = 3 * maxPts;
268 fPrimitiveType = kTriangles_PrimitiveType;
269 } else {
270 fPrimitiveType = kTriangleFan_PrimitiveType;
271 }
272 }
273
274 GrPoint* base;
275 if (!fTarget->reserveVertexSpace(layout, maxPts, (void**)&base)) {
276 return false;
277 }
278 GrAssert(NULL != base);
279 GrPoint* vert = base;
280
281 uint16_t* idxBase = NULL;
282 uint16_t* idx = NULL;
283 uint16_t subpathIdxStart = 0;
284 if (fUseIndexedDraw) {
285 if (!fTarget->reserveIndexSpace(maxIdxs, (void**)&idxBase)) {
286 fTarget->resetVertexSource();
287 return false;
288 }
289 GrAssert(NULL != idxBase);
290 idx = idxBase;
291 }
292
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000293 fSubpathVertCount.reset(fSubpathCount);
bsalomon@google.com30085192011-08-19 15:42:31 +0000294
295 GrPoint pts[4];
296
297 bool first = true;
298 int subpath = 0;
299
300 SkPath::Iter iter(*fPath, false);
301
302 for (;;) {
303 GrPathCmd cmd = (GrPathCmd)iter.next(pts);
304 switch (cmd) {
305 case kMove_PathCmd:
306 if (!first) {
307 uint16_t currIdx = (uint16_t) (vert - base);
308 fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
309 subpathIdxStart = currIdx;
310 ++subpath;
311 }
312 *vert = pts[0];
313 vert++;
314 break;
315 case kLine_PathCmd:
316 if (fUseIndexedDraw) {
317 uint16_t prevIdx = (uint16_t)(vert - base) - 1;
318 append_countour_edge_indices(fFill, subpathIdxStart,
319 prevIdx, &idx);
320 }
321 *(vert++) = pts[1];
322 break;
323 case kQuadratic_PathCmd: {
324 // first pt of quad is the pt we ended on in previous step
325 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
326 uint16_t numPts = (uint16_t)
327 GrPathUtils::generateQuadraticPoints(
328 pts[0], pts[1], pts[2],
329 srcSpaceTolSqd, &vert,
330 GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
331 if (fUseIndexedDraw) {
332 for (uint16_t i = 0; i < numPts; ++i) {
333 append_countour_edge_indices(fFill, subpathIdxStart,
334 firstQPtIdx + i, &idx);
335 }
336 }
337 break;
338 }
339 case kCubic_PathCmd: {
340 // first pt of cubic is the pt we ended on in previous step
341 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
342 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
343 pts[0], pts[1], pts[2], pts[3],
344 srcSpaceTolSqd, &vert,
345 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
346 if (fUseIndexedDraw) {
347 for (uint16_t i = 0; i < numPts; ++i) {
348 append_countour_edge_indices(fFill, subpathIdxStart,
349 firstCPtIdx + i, &idx);
350 }
351 }
352 break;
353 }
354 case kClose_PathCmd:
355 break;
356 case kEnd_PathCmd:
357 uint16_t currIdx = (uint16_t) (vert - base);
358 fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
359 goto FINISHED;
360 }
361 first = false;
362 }
363FINISHED:
364 GrAssert((vert - base) <= maxPts);
365 GrAssert((idx - idxBase) <= maxIdxs);
366
367 fVertexCnt = vert - base;
368 fIndexCnt = idx - idxBase;
369
370 if (fTranslate.fX || fTranslate.fY) {
371 int count = vert - base;
372 for (int i = 0; i < count; i++) {
373 base[i].offset(fTranslate.fX, fTranslate.fY);
374 }
375 }
376 }
377 // set these at the end so if we failed on first drawPath inside a
378 // setPath/clearPath block we won't assume geom was created on a subsequent
379 // drawPath in the same block.
380 fPreviousSrcTol = srcSpaceTol;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000381 fPreviousStages = stageMask;
bsalomon@google.com30085192011-08-19 15:42:31 +0000382 return true;
383}
384
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000385void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
bsalomon@google.com30085192011-08-19 15:42:31 +0000386 bool stencilOnly) {
387
bsalomon@google.com30085192011-08-19 15:42:31 +0000388 GrMatrix viewM = fTarget->getViewMatrix();
bsalomon@google.com181e9bd2011-09-07 18:42:30 +0000389 GrScalar tol = GR_Scalar1;
bsalomon@google.com38396322011-09-09 19:32:04 +0000390 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
bsalomon@google.com30085192011-08-19 15:42:31 +0000391
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000392 GrDrawState* drawState = fTarget->drawState();
393
bsalomon@google.com30085192011-08-19 15:42:31 +0000394 // FIXME: It's really dumb that we recreate the verts for a new vertex
395 // layout. We only do that because the GrDrawTarget API doesn't allow
396 // us to change the vertex layout after reserveVertexSpace(). We won't
397 // actually change the vertex data when the layout changes since all the
398 // stages reference the positions (rather than having separate tex coords)
399 // and we don't ever have per-vert colors. In practice our call sites
400 // won't change the stages in use inside a setPath / removePath pair. But
401 // it is a silly limitation of the GrDrawTarget design that should be fixed.
402 if (tol != fPreviousSrcTol ||
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000403 stageMask != fPreviousStages) {
404 if (!this->createGeom(tol, stageMask)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000405 return;
406 }
407 }
408
409 GrAssert(NULL != fTarget);
410 GrDrawTarget::AutoStateRestore asr(fTarget);
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000411 bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
bsalomon@google.com30085192011-08-19 15:42:31 +0000412 // face culling doesn't make sense here
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000413 GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
bsalomon@google.com30085192011-08-19 15:42:31 +0000414
415 int passCount = 0;
416 const GrStencilSettings* passes[3];
tomhudson@google.com93813632011-10-27 20:21:16 +0000417 GrDrawState::DrawFace drawFace[3];
bsalomon@google.com30085192011-08-19 15:42:31 +0000418 bool reverse = false;
419 bool lastPassIsBounds;
420
421 if (kHairLine_PathFill == fFill) {
422 passCount = 1;
423 if (stencilOnly) {
424 passes[0] = &gDirectToStencil;
425 } else {
426 passes[0] = NULL;
427 }
428 lastPassIsBounds = false;
tomhudson@google.com93813632011-10-27 20:21:16 +0000429 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000430 } else {
431 if (single_pass_path(*fTarget, *fPath, fFill)) {
432 passCount = 1;
433 if (stencilOnly) {
434 passes[0] = &gDirectToStencil;
435 } else {
436 passes[0] = NULL;
437 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000438 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000439 lastPassIsBounds = false;
440 } else {
441 switch (fFill) {
442 case kInverseEvenOdd_PathFill:
443 reverse = true;
444 // fallthrough
445 case kEvenOdd_PathFill:
446 passes[0] = &gEOStencilPass;
447 if (stencilOnly) {
448 passCount = 1;
449 lastPassIsBounds = false;
450 } else {
451 passCount = 2;
452 lastPassIsBounds = true;
453 if (reverse) {
454 passes[1] = &gInvEOColorPass;
455 } else {
456 passes[1] = &gEOColorPass;
457 }
458 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000459 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000460 break;
461
462 case kInverseWinding_PathFill:
463 reverse = true;
464 // fallthrough
465 case kWinding_PathFill:
466 if (fSeparateStencil) {
467 if (fStencilWrapOps) {
468 passes[0] = &gWindStencilSeparateWithWrap;
469 } else {
470 passes[0] = &gWindStencilSeparateNoWrap;
471 }
472 passCount = 2;
tomhudson@google.com93813632011-10-27 20:21:16 +0000473 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000474 } else {
475 if (fStencilWrapOps) {
476 passes[0] = &gWindSingleStencilWithWrapInc;
477 passes[1] = &gWindSingleStencilWithWrapDec;
478 } else {
479 passes[0] = &gWindSingleStencilNoWrapInc;
480 passes[1] = &gWindSingleStencilNoWrapDec;
481 }
482 // which is cw and which is ccw is arbitrary.
tomhudson@google.com93813632011-10-27 20:21:16 +0000483 drawFace[0] = GrDrawState::kCW_DrawFace;
484 drawFace[1] = GrDrawState::kCCW_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000485 passCount = 3;
486 }
487 if (stencilOnly) {
488 lastPassIsBounds = false;
489 --passCount;
490 } else {
491 lastPassIsBounds = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000492 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000493 if (reverse) {
494 passes[passCount-1] = &gInvWindColorPass;
495 } else {
496 passes[passCount-1] = &gWindColorPass;
497 }
498 }
499 break;
500 default:
501 GrAssert(!"Unknown path fFill!");
502 return;
503 }
504 }
505 }
506
507 {
bsalomon@google.com30085192011-08-19 15:42:31 +0000508 for (int p = 0; p < passCount; ++p) {
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000509 drawState->setDrawFace(drawFace[p]);
bsalomon@google.com30085192011-08-19 15:42:31 +0000510 if (NULL != passes[p]) {
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000511 drawState->setStencil(*passes[p]);
bsalomon@google.com30085192011-08-19 15:42:31 +0000512 }
513
514 if (lastPassIsBounds && (p == passCount-1)) {
515 if (!colorWritesWereDisabled) {
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000516 drawState->disableState(
517 GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000518 }
519 GrRect bounds;
520 if (reverse) {
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000521 GrAssert(NULL != drawState->getRenderTarget());
bsalomon@google.com30085192011-08-19 15:42:31 +0000522 // draw over the whole world.
523 bounds.setLTRB(0, 0,
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000524 GrIntToScalar(drawState->getRenderTarget()->width()),
525 GrIntToScalar(drawState->getRenderTarget()->height()));
bsalomon@google.com30085192011-08-19 15:42:31 +0000526 GrMatrix vmi;
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000527 // mapRect through persp matrix may not be correct
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000528 if (!drawState->getViewMatrix().hasPerspective() &&
529 drawState->getViewInverse(&vmi)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000530 vmi.mapRect(&bounds);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000531 } else {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000532 if (stageMask) {
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000533 if (!drawState->getViewInverse(&vmi)) {
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000534 GrPrintf("Could not invert matrix.");
535 return;
536 }
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000537 drawState->preConcatSamplerMatrices(stageMask, vmi);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000538 }
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000539 drawState->setViewMatrix(GrMatrix::I());
bsalomon@google.com30085192011-08-19 15:42:31 +0000540 }
541 } else {
542 bounds = fPath->getBounds();
543 bounds.offset(fTranslate);
544 }
545 GrDrawTarget::AutoGeometryPush agp(fTarget);
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000546 fTarget->drawSimpleRect(bounds, NULL, stageMask);
bsalomon@google.com30085192011-08-19 15:42:31 +0000547 } else {
548 if (passCount > 1) {
bsalomon@google.com0fec61d2011-12-08 15:53:53 +0000549 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000550 }
551 if (fUseIndexedDraw) {
552 fTarget->drawIndexed(fPrimitiveType, 0, 0,
553 fVertexCnt, fIndexCnt);
554 } else {
555 int baseVertex = 0;
556 for (int sp = 0; sp < fSubpathCount; ++sp) {
557 fTarget->drawNonIndexed(fPrimitiveType, baseVertex,
558 fSubpathVertCount[sp]);
559 baseVertex += fSubpathVertCount[sp];
560 }
561 }
562 }
563 }
564 }
565}
566
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000567void GrDefaultPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
568 this->onDrawPath(stageMask, false);
bsalomon@google.com30085192011-08-19 15:42:31 +0000569}
570
571void GrDefaultPathRenderer::drawPathToStencil() {
572 GrAssert(kInverseEvenOdd_PathFill != fFill);
573 GrAssert(kInverseWinding_PathFill != fFill);
574 this->onDrawPath(0, true);
575}