blob: 6ea04591cdd7070671a0d18b470bf21cd66d9519 [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
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000044GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
45 kInvert_StencilOp,
46 kKeep_StencilOp,
47 kAlwaysIfInClip_StencilFunc,
48 0xffff,
49 0xffff,
50 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000051
52// ok not to check clip b/c stencil pass only wrote inside clip
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000053GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
54 kZero_StencilOp,
55 kZero_StencilOp,
56 kNotEqual_StencilFunc,
57 0xffff,
58 0x0000,
59 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000060
61// have to check clip b/c outside clip will always be zero.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000062GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
63 kZero_StencilOp,
64 kZero_StencilOp,
65 kEqualIfInClip_StencilFunc,
66 0xffff,
67 0x0000,
68 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000069
70////// Winding
71
72// when we have separate stencil we increment front faces / decrement back faces
73// when we don't have wrap incr and decr we use the stencil test to simulate
74// them.
75
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000076GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
bsalomon@google.com30085192011-08-19 15:42:31 +000077 kIncWrap_StencilOp, kDecWrap_StencilOp,
78 kKeep_StencilOp, kKeep_StencilOp,
79 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000080 0xffff, 0xffff,
81 0xffff, 0xffff,
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000082 0xffff, 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000083
84// if inc'ing the max value, invert to make 0
85// if dec'ing zero invert to make all ones.
86// we can't avoid touching the stencil on both passing and
87// failing, so we can't resctrict ourselves to the clip.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000088GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
bsalomon@google.com30085192011-08-19 15:42:31 +000089 kInvert_StencilOp, kInvert_StencilOp,
90 kIncClamp_StencilOp, kDecClamp_StencilOp,
91 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000092 0xffff, 0xffff,
93 0xffff, 0x0000,
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000094 0xffff, 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000095
96// When there are no separate faces we do two passes to setup the winding rule
97// stencil. First we draw the front faces and inc, then we draw the back faces
98// and dec. These are same as the above two split into the incrementing and
99// decrementing passes.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000100GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
101 kIncWrap_StencilOp,
102 kKeep_StencilOp,
103 kAlwaysIfInClip_StencilFunc,
104 0xffff,
105 0xffff,
106 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000107
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000108GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
109 kDecWrap_StencilOp,
110 kKeep_StencilOp,
111 kAlwaysIfInClip_StencilFunc,
112 0xffff,
113 0xffff,
114 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000115
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000116GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
117 kInvert_StencilOp,
118 kIncClamp_StencilOp,
119 kEqual_StencilFunc,
120 0xffff,
121 0xffff,
122 0xffff);
123
124GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
125 kInvert_StencilOp,
126 kDecClamp_StencilOp,
127 kEqual_StencilFunc,
128 0xffff,
129 0x0000,
130 0xffff);
131
132// Color passes are the same whether we use the two-sided stencil or two passes
133
134GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
135 kZero_StencilOp,
136 kZero_StencilOp,
137 kNonZeroIfInClip_StencilFunc,
138 0xffff,
139 0x0000,
140 0xffff);
141
142GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
143 kZero_StencilOp,
144 kZero_StencilOp,
145 kEqualIfInClip_StencilFunc,
146 0xffff,
147 0x0000,
148 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000149
150////// Normal render to stencil
151
152// Sometimes the default path renderer can draw a path directly to the stencil
153// buffer without having to first resolve the interior / exterior.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000154GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
155 kZero_StencilOp,
156 kIncClamp_StencilOp,
157 kAlwaysIfInClip_StencilFunc,
158 0xffff,
159 0x0000,
160 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000161
162////////////////////////////////////////////////////////////////////////////////
163// Helpers for drawPath
164
165static GrConvexHint getConvexHint(const SkPath& path) {
166 return path.isConvex() ? kConvex_ConvexHint : kConcave_ConvexHint;
167}
168
169#define STENCIL_OFF 0 // Always disable stencil (even when needed)
170
171static inline bool single_pass_path(const GrDrawTarget& target,
172 const GrPath& path,
173 GrPathFill fill) {
174#if STENCIL_OFF
175 return true;
176#else
177 if (kEvenOdd_PathFill == fill) {
178 GrConvexHint hint = getConvexHint(path);
179 return hint == kConvex_ConvexHint ||
180 hint == kNonOverlappingConvexPieces_ConvexHint;
181 } else if (kWinding_PathFill == fill) {
182 GrConvexHint hint = getConvexHint(path);
183 return hint == kConvex_ConvexHint ||
184 hint == kNonOverlappingConvexPieces_ConvexHint ||
185 (hint == kSameWindingConvexPieces_ConvexHint &&
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000186 !target.drawWillReadDst() &&
187 !target.getDrawState().isDitherState());
bsalomon@google.com30085192011-08-19 15:42:31 +0000188
189 }
190 return false;
191#endif
192}
193
194bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
bsalomon@google.com289533a2011-10-27 12:34:25 +0000195 const GrPath& path,
bsalomon@google.com30085192011-08-19 15:42:31 +0000196 GrPathFill fill) const {
197 return !single_pass_path(*target, path, fill);
198}
199
200void GrDefaultPathRenderer::pathWillClear() {
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000201 fSubpathVertCount.reset(0);
bsalomon@google.com30085192011-08-19 15:42:31 +0000202 fTarget->resetVertexSource();
203 if (fUseIndexedDraw) {
204 fTarget->resetIndexSource();
205 }
206 fPreviousSrcTol = -GR_Scalar1;
207 fPreviousStages = -1;
208}
209
210static inline void append_countour_edge_indices(GrPathFill fillType,
211 uint16_t fanCenterIdx,
212 uint16_t edgeV0Idx,
213 uint16_t** indices) {
214 // when drawing lines we're appending line segments along
215 // the contour. When applying the other fill rules we're
216 // drawing triangle fans around fanCenterIdx.
217 if (kHairLine_PathFill != fillType) {
218 *((*indices)++) = fanCenterIdx;
219 }
220 *((*indices)++) = edgeV0Idx;
221 *((*indices)++) = edgeV0Idx + 1;
222}
223
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000224bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
225 GrDrawState::StageMask stageMask) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000226 {
227 SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
228
229 GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol);
230 int maxPts = GrPathUtils::worstCasePointCount(*fPath, &fSubpathCount,
231 srcSpaceTol);
232
233 if (maxPts <= 0) {
234 return false;
235 }
236 if (maxPts > ((int)SK_MaxU16 + 1)) {
237 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
238 return false;
239 }
240
241 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000242 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000243 if ((1 << s) & stageMask) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000244 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
245 }
246 }
247
248 fUseIndexedDraw = fSubpathCount > 1;
249
250 int maxIdxs = 0;
251 if (kHairLine_PathFill == fFill) {
252 if (fUseIndexedDraw) {
253 maxIdxs = 2 * maxPts;
254 fPrimitiveType = kLines_PrimitiveType;
255 } else {
256 fPrimitiveType = kLineStrip_PrimitiveType;
257 }
258 } else {
259 if (fUseIndexedDraw) {
260 maxIdxs = 3 * maxPts;
261 fPrimitiveType = kTriangles_PrimitiveType;
262 } else {
263 fPrimitiveType = kTriangleFan_PrimitiveType;
264 }
265 }
266
267 GrPoint* base;
268 if (!fTarget->reserveVertexSpace(layout, maxPts, (void**)&base)) {
269 return false;
270 }
271 GrAssert(NULL != base);
272 GrPoint* vert = base;
273
274 uint16_t* idxBase = NULL;
275 uint16_t* idx = NULL;
276 uint16_t subpathIdxStart = 0;
277 if (fUseIndexedDraw) {
278 if (!fTarget->reserveIndexSpace(maxIdxs, (void**)&idxBase)) {
279 fTarget->resetVertexSource();
280 return false;
281 }
282 GrAssert(NULL != idxBase);
283 idx = idxBase;
284 }
285
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000286 fSubpathVertCount.reset(fSubpathCount);
bsalomon@google.com30085192011-08-19 15:42:31 +0000287
288 GrPoint pts[4];
289
290 bool first = true;
291 int subpath = 0;
292
293 SkPath::Iter iter(*fPath, false);
294
295 for (;;) {
296 GrPathCmd cmd = (GrPathCmd)iter.next(pts);
297 switch (cmd) {
298 case kMove_PathCmd:
299 if (!first) {
300 uint16_t currIdx = (uint16_t) (vert - base);
301 fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
302 subpathIdxStart = currIdx;
303 ++subpath;
304 }
305 *vert = pts[0];
306 vert++;
307 break;
308 case kLine_PathCmd:
309 if (fUseIndexedDraw) {
310 uint16_t prevIdx = (uint16_t)(vert - base) - 1;
311 append_countour_edge_indices(fFill, subpathIdxStart,
312 prevIdx, &idx);
313 }
314 *(vert++) = pts[1];
315 break;
316 case kQuadratic_PathCmd: {
317 // first pt of quad is the pt we ended on in previous step
318 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
319 uint16_t numPts = (uint16_t)
320 GrPathUtils::generateQuadraticPoints(
321 pts[0], pts[1], pts[2],
322 srcSpaceTolSqd, &vert,
323 GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
324 if (fUseIndexedDraw) {
325 for (uint16_t i = 0; i < numPts; ++i) {
326 append_countour_edge_indices(fFill, subpathIdxStart,
327 firstQPtIdx + i, &idx);
328 }
329 }
330 break;
331 }
332 case kCubic_PathCmd: {
333 // first pt of cubic is the pt we ended on in previous step
334 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
335 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
336 pts[0], pts[1], pts[2], pts[3],
337 srcSpaceTolSqd, &vert,
338 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
339 if (fUseIndexedDraw) {
340 for (uint16_t i = 0; i < numPts; ++i) {
341 append_countour_edge_indices(fFill, subpathIdxStart,
342 firstCPtIdx + i, &idx);
343 }
344 }
345 break;
346 }
347 case kClose_PathCmd:
348 break;
349 case kEnd_PathCmd:
350 uint16_t currIdx = (uint16_t) (vert - base);
351 fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
352 goto FINISHED;
353 }
354 first = false;
355 }
356FINISHED:
357 GrAssert((vert - base) <= maxPts);
358 GrAssert((idx - idxBase) <= maxIdxs);
359
360 fVertexCnt = vert - base;
361 fIndexCnt = idx - idxBase;
362
363 if (fTranslate.fX || fTranslate.fY) {
364 int count = vert - base;
365 for (int i = 0; i < count; i++) {
366 base[i].offset(fTranslate.fX, fTranslate.fY);
367 }
368 }
369 }
370 // set these at the end so if we failed on first drawPath inside a
371 // setPath/clearPath block we won't assume geom was created on a subsequent
372 // drawPath in the same block.
373 fPreviousSrcTol = srcSpaceTol;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000374 fPreviousStages = stageMask;
bsalomon@google.com30085192011-08-19 15:42:31 +0000375 return true;
376}
377
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000378void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
bsalomon@google.com30085192011-08-19 15:42:31 +0000379 bool stencilOnly) {
380
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000381 GrMatrix viewM = fTarget->getDrawState().getViewMatrix();
bsalomon@google.com181e9bd2011-09-07 18:42:30 +0000382 GrScalar tol = GR_Scalar1;
bsalomon@google.com38396322011-09-09 19:32:04 +0000383 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000384 GrDrawState* drawState = fTarget->drawState();
bsalomon@google.com30085192011-08-19 15:42:31 +0000385
bsalomon@google.com30085192011-08-19 15:42:31 +0000386 // FIXME: It's really dumb that we recreate the verts for a new vertex
387 // layout. We only do that because the GrDrawTarget API doesn't allow
388 // us to change the vertex layout after reserveVertexSpace(). We won't
389 // actually change the vertex data when the layout changes since all the
390 // stages reference the positions (rather than having separate tex coords)
391 // and we don't ever have per-vert colors. In practice our call sites
392 // won't change the stages in use inside a setPath / removePath pair. But
393 // it is a silly limitation of the GrDrawTarget design that should be fixed.
394 if (tol != fPreviousSrcTol ||
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000395 stageMask != fPreviousStages) {
396 if (!this->createGeom(tol, stageMask)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000397 return;
398 }
399 }
400
401 GrAssert(NULL != fTarget);
402 GrDrawTarget::AutoStateRestore asr(fTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000403 bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
bsalomon@google.com30085192011-08-19 15:42:31 +0000404 // face culling doesn't make sense here
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000405 GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
bsalomon@google.com30085192011-08-19 15:42:31 +0000406
407 int passCount = 0;
408 const GrStencilSettings* passes[3];
tomhudson@google.com93813632011-10-27 20:21:16 +0000409 GrDrawState::DrawFace drawFace[3];
bsalomon@google.com30085192011-08-19 15:42:31 +0000410 bool reverse = false;
411 bool lastPassIsBounds;
412
413 if (kHairLine_PathFill == fFill) {
414 passCount = 1;
415 if (stencilOnly) {
416 passes[0] = &gDirectToStencil;
417 } else {
418 passes[0] = NULL;
419 }
420 lastPassIsBounds = false;
tomhudson@google.com93813632011-10-27 20:21:16 +0000421 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000422 } else {
423 if (single_pass_path(*fTarget, *fPath, fFill)) {
424 passCount = 1;
425 if (stencilOnly) {
426 passes[0] = &gDirectToStencil;
427 } else {
428 passes[0] = NULL;
429 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000430 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000431 lastPassIsBounds = false;
432 } else {
433 switch (fFill) {
434 case kInverseEvenOdd_PathFill:
435 reverse = true;
436 // fallthrough
437 case kEvenOdd_PathFill:
438 passes[0] = &gEOStencilPass;
439 if (stencilOnly) {
440 passCount = 1;
441 lastPassIsBounds = false;
442 } else {
443 passCount = 2;
444 lastPassIsBounds = true;
445 if (reverse) {
446 passes[1] = &gInvEOColorPass;
447 } else {
448 passes[1] = &gEOColorPass;
449 }
450 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000451 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000452 break;
453
454 case kInverseWinding_PathFill:
455 reverse = true;
456 // fallthrough
457 case kWinding_PathFill:
458 if (fSeparateStencil) {
459 if (fStencilWrapOps) {
460 passes[0] = &gWindStencilSeparateWithWrap;
461 } else {
462 passes[0] = &gWindStencilSeparateNoWrap;
463 }
464 passCount = 2;
tomhudson@google.com93813632011-10-27 20:21:16 +0000465 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000466 } else {
467 if (fStencilWrapOps) {
468 passes[0] = &gWindSingleStencilWithWrapInc;
469 passes[1] = &gWindSingleStencilWithWrapDec;
470 } else {
471 passes[0] = &gWindSingleStencilNoWrapInc;
472 passes[1] = &gWindSingleStencilNoWrapDec;
473 }
474 // which is cw and which is ccw is arbitrary.
tomhudson@google.com93813632011-10-27 20:21:16 +0000475 drawFace[0] = GrDrawState::kCW_DrawFace;
476 drawFace[1] = GrDrawState::kCCW_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000477 passCount = 3;
478 }
479 if (stencilOnly) {
480 lastPassIsBounds = false;
481 --passCount;
482 } else {
483 lastPassIsBounds = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000484 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000485 if (reverse) {
486 passes[passCount-1] = &gInvWindColorPass;
487 } else {
488 passes[passCount-1] = &gWindColorPass;
489 }
490 }
491 break;
492 default:
493 GrAssert(!"Unknown path fFill!");
494 return;
495 }
496 }
497 }
498
499 {
bsalomon@google.com30085192011-08-19 15:42:31 +0000500 for (int p = 0; p < passCount; ++p) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000501 drawState->setDrawFace(drawFace[p]);
bsalomon@google.com30085192011-08-19 15:42:31 +0000502 if (NULL != passes[p]) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000503 *drawState->stencil() = *passes[p];
bsalomon@google.com30085192011-08-19 15:42:31 +0000504 }
505
506 if (lastPassIsBounds && (p == passCount-1)) {
507 if (!colorWritesWereDisabled) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000508 drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000509 }
510 GrRect bounds;
511 if (reverse) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000512 GrAssert(NULL != drawState->getRenderTarget());
bsalomon@google.com30085192011-08-19 15:42:31 +0000513 // draw over the whole world.
514 bounds.setLTRB(0, 0,
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000515 GrIntToScalar(drawState->getRenderTarget()->width()),
516 GrIntToScalar(drawState->getRenderTarget()->height()));
bsalomon@google.com30085192011-08-19 15:42:31 +0000517 GrMatrix vmi;
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000518 // mapRect through persp matrix may not be correct
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000519 if (!drawState->getViewMatrix().hasPerspective() &&
520 drawState->getViewInverse(&vmi)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000521 vmi.mapRect(&bounds);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000522 } else {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000523 if (stageMask) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000524 if (!drawState->getViewInverse(&vmi)) {
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000525 GrPrintf("Could not invert matrix.");
526 return;
527 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000528 drawState->preConcatSamplerMatrices(stageMask, vmi);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000529 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000530 drawState->setViewMatrix(GrMatrix::I());
bsalomon@google.com30085192011-08-19 15:42:31 +0000531 }
532 } else {
533 bounds = fPath->getBounds();
534 bounds.offset(fTranslate);
535 }
536 GrDrawTarget::AutoGeometryPush agp(fTarget);
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000537 fTarget->drawSimpleRect(bounds, NULL, stageMask);
bsalomon@google.com30085192011-08-19 15:42:31 +0000538 } else {
539 if (passCount > 1) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000541 }
542 if (fUseIndexedDraw) {
543 fTarget->drawIndexed(fPrimitiveType, 0, 0,
544 fVertexCnt, fIndexCnt);
545 } else {
546 int baseVertex = 0;
547 for (int sp = 0; sp < fSubpathCount; ++sp) {
548 fTarget->drawNonIndexed(fPrimitiveType, baseVertex,
549 fSubpathVertCount[sp]);
550 baseVertex += fSubpathVertCount[sp];
551 }
552 }
553 }
554 }
555 }
556}
557
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000558void GrDefaultPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
559 this->onDrawPath(stageMask, false);
bsalomon@google.com30085192011-08-19 15:42:31 +0000560}
561
562void GrDefaultPathRenderer::drawPathToStencil() {
563 GrAssert(kInverseEvenOdd_PathFill != fFill);
564 GrAssert(kInverseWinding_PathFill != fFill);
565 this->onDrawPath(0, true);
566}