blob: 51cbde02cf5347e1aa249410db7b03f6691517e6 [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
bsalomon@google.com30085192011-08-19 15:42:31 +0000165#define STENCIL_OFF 0 // Always disable stencil (even when needed)
166
bsalomon@google.com7d72c452012-01-30 14:02:44 +0000167static inline bool single_pass_path(const GrPath& path, GrPathFill fill) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000168#if STENCIL_OFF
169 return true;
170#else
bsalomon@google.com7d72c452012-01-30 14:02:44 +0000171 if (kEvenOdd_PathFill == fill || kWinding_PathFill == fill) {
172 return path.isConvex();
bsalomon@google.com30085192011-08-19 15:42:31 +0000173 }
174 return false;
175#endif
176}
177
178bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
bsalomon@google.com289533a2011-10-27 12:34:25 +0000179 const GrPath& path,
bsalomon@google.com30085192011-08-19 15:42:31 +0000180 GrPathFill fill) const {
bsalomon@google.com7d72c452012-01-30 14:02:44 +0000181 return !single_pass_path(path, fill);
bsalomon@google.com30085192011-08-19 15:42:31 +0000182}
183
184void GrDefaultPathRenderer::pathWillClear() {
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000185 fSubpathVertCount.reset(0);
bsalomon@google.com30085192011-08-19 15:42:31 +0000186 fTarget->resetVertexSource();
187 if (fUseIndexedDraw) {
188 fTarget->resetIndexSource();
189 }
190 fPreviousSrcTol = -GR_Scalar1;
191 fPreviousStages = -1;
192}
193
194static inline void append_countour_edge_indices(GrPathFill fillType,
195 uint16_t fanCenterIdx,
196 uint16_t edgeV0Idx,
197 uint16_t** indices) {
198 // when drawing lines we're appending line segments along
199 // the contour. When applying the other fill rules we're
200 // drawing triangle fans around fanCenterIdx.
201 if (kHairLine_PathFill != fillType) {
202 *((*indices)++) = fanCenterIdx;
203 }
204 *((*indices)++) = edgeV0Idx;
205 *((*indices)++) = edgeV0Idx + 1;
206}
207
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000208bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol,
209 GrDrawState::StageMask stageMask) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000210 {
211 SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
212
213 GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol);
214 int maxPts = GrPathUtils::worstCasePointCount(*fPath, &fSubpathCount,
215 srcSpaceTol);
216
217 if (maxPts <= 0) {
218 return false;
219 }
220 if (maxPts > ((int)SK_MaxU16 + 1)) {
221 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
222 return false;
223 }
224
225 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000226 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000227 if ((1 << s) & stageMask) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000228 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
229 }
230 }
231
232 fUseIndexedDraw = fSubpathCount > 1;
233
234 int maxIdxs = 0;
235 if (kHairLine_PathFill == fFill) {
236 if (fUseIndexedDraw) {
237 maxIdxs = 2 * maxPts;
238 fPrimitiveType = kLines_PrimitiveType;
239 } else {
240 fPrimitiveType = kLineStrip_PrimitiveType;
241 }
242 } else {
243 if (fUseIndexedDraw) {
244 maxIdxs = 3 * maxPts;
245 fPrimitiveType = kTriangles_PrimitiveType;
246 } else {
247 fPrimitiveType = kTriangleFan_PrimitiveType;
248 }
249 }
250
251 GrPoint* base;
252 if (!fTarget->reserveVertexSpace(layout, maxPts, (void**)&base)) {
253 return false;
254 }
255 GrAssert(NULL != base);
256 GrPoint* vert = base;
257
258 uint16_t* idxBase = NULL;
259 uint16_t* idx = NULL;
260 uint16_t subpathIdxStart = 0;
261 if (fUseIndexedDraw) {
262 if (!fTarget->reserveIndexSpace(maxIdxs, (void**)&idxBase)) {
263 fTarget->resetVertexSource();
264 return false;
265 }
266 GrAssert(NULL != idxBase);
267 idx = idxBase;
268 }
269
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000270 fSubpathVertCount.reset(fSubpathCount);
bsalomon@google.com30085192011-08-19 15:42:31 +0000271
272 GrPoint pts[4];
273
274 bool first = true;
275 int subpath = 0;
276
277 SkPath::Iter iter(*fPath, false);
278
279 for (;;) {
280 GrPathCmd cmd = (GrPathCmd)iter.next(pts);
281 switch (cmd) {
282 case kMove_PathCmd:
283 if (!first) {
284 uint16_t currIdx = (uint16_t) (vert - base);
285 fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
286 subpathIdxStart = currIdx;
287 ++subpath;
288 }
289 *vert = pts[0];
290 vert++;
291 break;
292 case kLine_PathCmd:
293 if (fUseIndexedDraw) {
294 uint16_t prevIdx = (uint16_t)(vert - base) - 1;
295 append_countour_edge_indices(fFill, subpathIdxStart,
296 prevIdx, &idx);
297 }
298 *(vert++) = pts[1];
299 break;
300 case kQuadratic_PathCmd: {
301 // first pt of quad is the pt we ended on in previous step
302 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
303 uint16_t numPts = (uint16_t)
304 GrPathUtils::generateQuadraticPoints(
305 pts[0], pts[1], pts[2],
306 srcSpaceTolSqd, &vert,
307 GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
308 if (fUseIndexedDraw) {
309 for (uint16_t i = 0; i < numPts; ++i) {
310 append_countour_edge_indices(fFill, subpathIdxStart,
311 firstQPtIdx + i, &idx);
312 }
313 }
314 break;
315 }
316 case kCubic_PathCmd: {
317 // first pt of cubic is the pt we ended on in previous step
318 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
319 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
320 pts[0], pts[1], pts[2], pts[3],
321 srcSpaceTolSqd, &vert,
322 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
323 if (fUseIndexedDraw) {
324 for (uint16_t i = 0; i < numPts; ++i) {
325 append_countour_edge_indices(fFill, subpathIdxStart,
326 firstCPtIdx + i, &idx);
327 }
328 }
329 break;
330 }
331 case kClose_PathCmd:
332 break;
333 case kEnd_PathCmd:
334 uint16_t currIdx = (uint16_t) (vert - base);
335 fSubpathVertCount[subpath] = currIdx - subpathIdxStart;
336 goto FINISHED;
337 }
338 first = false;
339 }
340FINISHED:
341 GrAssert((vert - base) <= maxPts);
342 GrAssert((idx - idxBase) <= maxIdxs);
343
344 fVertexCnt = vert - base;
345 fIndexCnt = idx - idxBase;
346
347 if (fTranslate.fX || fTranslate.fY) {
348 int count = vert - base;
349 for (int i = 0; i < count; i++) {
350 base[i].offset(fTranslate.fX, fTranslate.fY);
351 }
352 }
353 }
354 // set these at the end so if we failed on first drawPath inside a
355 // setPath/clearPath block we won't assume geom was created on a subsequent
356 // drawPath in the same block.
357 fPreviousSrcTol = srcSpaceTol;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000358 fPreviousStages = stageMask;
bsalomon@google.com30085192011-08-19 15:42:31 +0000359 return true;
360}
361
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000362void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
bsalomon@google.com30085192011-08-19 15:42:31 +0000363 bool stencilOnly) {
364
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000365 GrMatrix viewM = fTarget->getDrawState().getViewMatrix();
bsalomon@google.com181e9bd2011-09-07 18:42:30 +0000366 GrScalar tol = GR_Scalar1;
bsalomon@google.com38396322011-09-09 19:32:04 +0000367 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000368 GrDrawState* drawState = fTarget->drawState();
bsalomon@google.com30085192011-08-19 15:42:31 +0000369
bsalomon@google.com30085192011-08-19 15:42:31 +0000370 // FIXME: It's really dumb that we recreate the verts for a new vertex
371 // layout. We only do that because the GrDrawTarget API doesn't allow
372 // us to change the vertex layout after reserveVertexSpace(). We won't
373 // actually change the vertex data when the layout changes since all the
374 // stages reference the positions (rather than having separate tex coords)
375 // and we don't ever have per-vert colors. In practice our call sites
376 // won't change the stages in use inside a setPath / removePath pair. But
377 // it is a silly limitation of the GrDrawTarget design that should be fixed.
378 if (tol != fPreviousSrcTol ||
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000379 stageMask != fPreviousStages) {
380 if (!this->createGeom(tol, stageMask)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000381 return;
382 }
383 }
384
385 GrAssert(NULL != fTarget);
386 GrDrawTarget::AutoStateRestore asr(fTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000387 bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
bsalomon@google.com30085192011-08-19 15:42:31 +0000388 // face culling doesn't make sense here
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000389 GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
bsalomon@google.com30085192011-08-19 15:42:31 +0000390
391 int passCount = 0;
392 const GrStencilSettings* passes[3];
tomhudson@google.com93813632011-10-27 20:21:16 +0000393 GrDrawState::DrawFace drawFace[3];
bsalomon@google.com30085192011-08-19 15:42:31 +0000394 bool reverse = false;
395 bool lastPassIsBounds;
396
397 if (kHairLine_PathFill == fFill) {
398 passCount = 1;
399 if (stencilOnly) {
400 passes[0] = &gDirectToStencil;
401 } else {
402 passes[0] = NULL;
403 }
404 lastPassIsBounds = false;
tomhudson@google.com93813632011-10-27 20:21:16 +0000405 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000406 } else {
bsalomon@google.com7d72c452012-01-30 14:02:44 +0000407 if (single_pass_path(*fPath, fFill)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000408 passCount = 1;
409 if (stencilOnly) {
410 passes[0] = &gDirectToStencil;
411 } else {
412 passes[0] = NULL;
413 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000414 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000415 lastPassIsBounds = false;
416 } else {
417 switch (fFill) {
418 case kInverseEvenOdd_PathFill:
419 reverse = true;
420 // fallthrough
421 case kEvenOdd_PathFill:
422 passes[0] = &gEOStencilPass;
423 if (stencilOnly) {
424 passCount = 1;
425 lastPassIsBounds = false;
426 } else {
427 passCount = 2;
428 lastPassIsBounds = true;
429 if (reverse) {
430 passes[1] = &gInvEOColorPass;
431 } else {
432 passes[1] = &gEOColorPass;
433 }
434 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000435 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000436 break;
437
438 case kInverseWinding_PathFill:
439 reverse = true;
440 // fallthrough
441 case kWinding_PathFill:
442 if (fSeparateStencil) {
443 if (fStencilWrapOps) {
444 passes[0] = &gWindStencilSeparateWithWrap;
445 } else {
446 passes[0] = &gWindStencilSeparateNoWrap;
447 }
448 passCount = 2;
tomhudson@google.com93813632011-10-27 20:21:16 +0000449 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000450 } else {
451 if (fStencilWrapOps) {
452 passes[0] = &gWindSingleStencilWithWrapInc;
453 passes[1] = &gWindSingleStencilWithWrapDec;
454 } else {
455 passes[0] = &gWindSingleStencilNoWrapInc;
456 passes[1] = &gWindSingleStencilNoWrapDec;
457 }
458 // which is cw and which is ccw is arbitrary.
tomhudson@google.com93813632011-10-27 20:21:16 +0000459 drawFace[0] = GrDrawState::kCW_DrawFace;
460 drawFace[1] = GrDrawState::kCCW_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000461 passCount = 3;
462 }
463 if (stencilOnly) {
464 lastPassIsBounds = false;
465 --passCount;
466 } else {
467 lastPassIsBounds = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000468 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000469 if (reverse) {
470 passes[passCount-1] = &gInvWindColorPass;
471 } else {
472 passes[passCount-1] = &gWindColorPass;
473 }
474 }
475 break;
476 default:
477 GrAssert(!"Unknown path fFill!");
478 return;
479 }
480 }
481 }
482
483 {
bsalomon@google.com30085192011-08-19 15:42:31 +0000484 for (int p = 0; p < passCount; ++p) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000485 drawState->setDrawFace(drawFace[p]);
bsalomon@google.com30085192011-08-19 15:42:31 +0000486 if (NULL != passes[p]) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000487 *drawState->stencil() = *passes[p];
bsalomon@google.com30085192011-08-19 15:42:31 +0000488 }
489
490 if (lastPassIsBounds && (p == passCount-1)) {
491 if (!colorWritesWereDisabled) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000492 drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000493 }
494 GrRect bounds;
495 if (reverse) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000496 GrAssert(NULL != drawState->getRenderTarget());
bsalomon@google.com30085192011-08-19 15:42:31 +0000497 // draw over the whole world.
498 bounds.setLTRB(0, 0,
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000499 GrIntToScalar(drawState->getRenderTarget()->width()),
500 GrIntToScalar(drawState->getRenderTarget()->height()));
bsalomon@google.com30085192011-08-19 15:42:31 +0000501 GrMatrix vmi;
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000502 // mapRect through persp matrix may not be correct
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000503 if (!drawState->getViewMatrix().hasPerspective() &&
504 drawState->getViewInverse(&vmi)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000505 vmi.mapRect(&bounds);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000506 } else {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000507 if (stageMask) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000508 if (!drawState->getViewInverse(&vmi)) {
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000509 GrPrintf("Could not invert matrix.");
510 return;
511 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000512 drawState->preConcatSamplerMatrices(stageMask, vmi);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000513 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000514 drawState->setViewMatrix(GrMatrix::I());
bsalomon@google.com30085192011-08-19 15:42:31 +0000515 }
516 } else {
517 bounds = fPath->getBounds();
518 bounds.offset(fTranslate);
519 }
520 GrDrawTarget::AutoGeometryPush agp(fTarget);
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000521 fTarget->drawSimpleRect(bounds, NULL, stageMask);
bsalomon@google.com30085192011-08-19 15:42:31 +0000522 } else {
523 if (passCount > 1) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000524 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000525 }
526 if (fUseIndexedDraw) {
527 fTarget->drawIndexed(fPrimitiveType, 0, 0,
528 fVertexCnt, fIndexCnt);
529 } else {
530 int baseVertex = 0;
531 for (int sp = 0; sp < fSubpathCount; ++sp) {
532 fTarget->drawNonIndexed(fPrimitiveType, baseVertex,
533 fSubpathVertCount[sp]);
534 baseVertex += fSubpathVertCount[sp];
535 }
536 }
537 }
538 }
539 }
540}
541
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000542void GrDefaultPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
543 this->onDrawPath(stageMask, false);
bsalomon@google.com30085192011-08-19 15:42:31 +0000544}
545
546void GrDefaultPathRenderer::drawPathToStencil() {
547 GrAssert(kInverseEvenOdd_PathFill != fFill);
548 GrAssert(kInverseWinding_PathFill != fFill);
549 this->onDrawPath(0, true);
550}