blob: ebd0cc142da4bd32e8b51a836fbd1acf623978fc [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.com8f9cbd62011-12-09 15:55:34 +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.com8f9cbd62011-12-09 15:55:34 +0000388 GrMatrix viewM = fTarget->getDrawState().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.com8f9cbd62011-12-09 15:55:34 +0000391 GrDrawState* drawState = fTarget->drawState();
bsalomon@google.com30085192011-08-19 15:42:31 +0000392
bsalomon@google.com30085192011-08-19 15:42:31 +0000393 // FIXME: It's really dumb that we recreate the verts for a new vertex
394 // layout. We only do that because the GrDrawTarget API doesn't allow
395 // us to change the vertex layout after reserveVertexSpace(). We won't
396 // actually change the vertex data when the layout changes since all the
397 // stages reference the positions (rather than having separate tex coords)
398 // and we don't ever have per-vert colors. In practice our call sites
399 // won't change the stages in use inside a setPath / removePath pair. But
400 // it is a silly limitation of the GrDrawTarget design that should be fixed.
401 if (tol != fPreviousSrcTol ||
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000402 stageMask != fPreviousStages) {
403 if (!this->createGeom(tol, stageMask)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000404 return;
405 }
406 }
407
408 GrAssert(NULL != fTarget);
409 GrDrawTarget::AutoStateRestore asr(fTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000410 bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
bsalomon@google.com30085192011-08-19 15:42:31 +0000411 // face culling doesn't make sense here
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000412 GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
bsalomon@google.com30085192011-08-19 15:42:31 +0000413
414 int passCount = 0;
415 const GrStencilSettings* passes[3];
tomhudson@google.com93813632011-10-27 20:21:16 +0000416 GrDrawState::DrawFace drawFace[3];
bsalomon@google.com30085192011-08-19 15:42:31 +0000417 bool reverse = false;
418 bool lastPassIsBounds;
419
420 if (kHairLine_PathFill == fFill) {
421 passCount = 1;
422 if (stencilOnly) {
423 passes[0] = &gDirectToStencil;
424 } else {
425 passes[0] = NULL;
426 }
427 lastPassIsBounds = false;
tomhudson@google.com93813632011-10-27 20:21:16 +0000428 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000429 } else {
430 if (single_pass_path(*fTarget, *fPath, fFill)) {
431 passCount = 1;
432 if (stencilOnly) {
433 passes[0] = &gDirectToStencil;
434 } else {
435 passes[0] = NULL;
436 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000437 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000438 lastPassIsBounds = false;
439 } else {
440 switch (fFill) {
441 case kInverseEvenOdd_PathFill:
442 reverse = true;
443 // fallthrough
444 case kEvenOdd_PathFill:
445 passes[0] = &gEOStencilPass;
446 if (stencilOnly) {
447 passCount = 1;
448 lastPassIsBounds = false;
449 } else {
450 passCount = 2;
451 lastPassIsBounds = true;
452 if (reverse) {
453 passes[1] = &gInvEOColorPass;
454 } else {
455 passes[1] = &gEOColorPass;
456 }
457 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000458 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000459 break;
460
461 case kInverseWinding_PathFill:
462 reverse = true;
463 // fallthrough
464 case kWinding_PathFill:
465 if (fSeparateStencil) {
466 if (fStencilWrapOps) {
467 passes[0] = &gWindStencilSeparateWithWrap;
468 } else {
469 passes[0] = &gWindStencilSeparateNoWrap;
470 }
471 passCount = 2;
tomhudson@google.com93813632011-10-27 20:21:16 +0000472 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000473 } else {
474 if (fStencilWrapOps) {
475 passes[0] = &gWindSingleStencilWithWrapInc;
476 passes[1] = &gWindSingleStencilWithWrapDec;
477 } else {
478 passes[0] = &gWindSingleStencilNoWrapInc;
479 passes[1] = &gWindSingleStencilNoWrapDec;
480 }
481 // which is cw and which is ccw is arbitrary.
tomhudson@google.com93813632011-10-27 20:21:16 +0000482 drawFace[0] = GrDrawState::kCW_DrawFace;
483 drawFace[1] = GrDrawState::kCCW_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000484 passCount = 3;
485 }
486 if (stencilOnly) {
487 lastPassIsBounds = false;
488 --passCount;
489 } else {
490 lastPassIsBounds = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000491 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000492 if (reverse) {
493 passes[passCount-1] = &gInvWindColorPass;
494 } else {
495 passes[passCount-1] = &gWindColorPass;
496 }
497 }
498 break;
499 default:
500 GrAssert(!"Unknown path fFill!");
501 return;
502 }
503 }
504 }
505
506 {
bsalomon@google.com30085192011-08-19 15:42:31 +0000507 for (int p = 0; p < passCount; ++p) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000508 drawState->setDrawFace(drawFace[p]);
bsalomon@google.com30085192011-08-19 15:42:31 +0000509 if (NULL != passes[p]) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000510 *drawState->stencil() = *passes[p];
bsalomon@google.com30085192011-08-19 15:42:31 +0000511 }
512
513 if (lastPassIsBounds && (p == passCount-1)) {
514 if (!colorWritesWereDisabled) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000515 drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000516 }
517 GrRect bounds;
518 if (reverse) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000519 GrAssert(NULL != drawState->getRenderTarget());
bsalomon@google.com30085192011-08-19 15:42:31 +0000520 // draw over the whole world.
521 bounds.setLTRB(0, 0,
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000522 GrIntToScalar(drawState->getRenderTarget()->width()),
523 GrIntToScalar(drawState->getRenderTarget()->height()));
bsalomon@google.com30085192011-08-19 15:42:31 +0000524 GrMatrix vmi;
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000525 // mapRect through persp matrix may not be correct
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000526 if (!drawState->getViewMatrix().hasPerspective() &&
527 drawState->getViewInverse(&vmi)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000528 vmi.mapRect(&bounds);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000529 } else {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000530 if (stageMask) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000531 if (!drawState->getViewInverse(&vmi)) {
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000532 GrPrintf("Could not invert matrix.");
533 return;
534 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000535 drawState->preConcatSamplerMatrices(stageMask, vmi);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000536 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000537 drawState->setViewMatrix(GrMatrix::I());
bsalomon@google.com30085192011-08-19 15:42:31 +0000538 }
539 } else {
540 bounds = fPath->getBounds();
541 bounds.offset(fTranslate);
542 }
543 GrDrawTarget::AutoGeometryPush agp(fTarget);
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000544 fTarget->drawSimpleRect(bounds, NULL, stageMask);
bsalomon@google.com30085192011-08-19 15:42:31 +0000545 } else {
546 if (passCount > 1) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000547 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000548 }
549 if (fUseIndexedDraw) {
550 fTarget->drawIndexed(fPrimitiveType, 0, 0,
551 fVertexCnt, fIndexCnt);
552 } else {
553 int baseVertex = 0;
554 for (int sp = 0; sp < fSubpathCount; ++sp) {
555 fTarget->drawNonIndexed(fPrimitiveType, baseVertex,
556 fSubpathVertCount[sp]);
557 baseVertex += fSubpathVertCount[sp];
558 }
559 }
560 }
561 }
562 }
563}
564
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000565void GrDefaultPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
566 this->onDrawPath(stageMask, false);
bsalomon@google.com30085192011-08-19 15:42:31 +0000567}
568
569void GrDefaultPathRenderer::drawPathToStencil() {
570 GrAssert(kInverseEvenOdd_PathFill != fFill);
571 GrAssert(kInverseWinding_PathFill != fFill);
572 this->onDrawPath(0, true);
573}